Files
h5-uniapp/pages/asset/transfer.vue
T
li 86d0f9da49 feat: 转账页面合约账户支持 + 实时汇率显示
1. 合约账户作为转账选项(原FTKbot改为Contract)
2. BTC/ETH↔合约时显示USDT等值转换提示
3. 合约→现货时显示合约USDT可用余额
2026-03-31 10:46:20 +08:00

375 lines
11 KiB
Vue

<template>
<view :style="'background-color: '+theme.bg+';color: '+theme.text" style="height: 100vh;">
<myNav :title="i18n.assets.transfer.title" :isRight="true" righturl="/static/imgs/asset/zhuanhuanjilu@2x.png"
@Jump="router.push('/pages/asset/record')"></myNav>
<view class="padding-w-30">
<view class="borderBox" :style="'background-color: '+theme.fu_bg">
<view class="height-260 padding-22 flex align-center justify-between">
<view class="flex-1">
<view @click="showPoup='accountL'"
:class="[animationName?'animation-slide-bottom':'']"
class="width-100b height-110 flex align-center">
<i class="cuIcon-title color-00C481"></i>
<text class="font-32 color-D1D3D8 margin-w-10">{{i18n.assets.transfer.from}}</text>
<text class="font-32">{{leftObj.name}}</text>
</view>
<view class="width-100b height-2 margin-c-4" style="background-color: #D1D3D8;"> </view>
<view @click="showPoup='accountR'"
:class="[animationName?'animation-slide-top':'']"
class="width-100b height-110 flex align-center">
<i class="cuIcon-title color-FF4040"></i>
<text class="font-32 color-D1D3D8 margin-w-10">{{i18n.assets.transfer.to}}</text>
<text class="font-32">{{rightObj.name}}</text>
</view>
</view>
<image @click="exchange" :class="animationName" class="width-62 height-62 margin-l-30"
src="/static/imgs/asset/qiehuan@2x.png" mode=""></image>
</view>
</view>
<view class="borderBox" :style="'background-color: '+theme.fu_bg">
<view @click="showPoup='currency',currType=true" class="padding-22">
<view class="height-65 flex align-center">
<text class="font-32">{{i18n.assets.transfer.curr}}</text>
</view>
<view class="height-65 flex align-center">
<text v-if="selectCurr.curr_id != undefined"
class="font-32 numbold-font">{{selectCurr.name}}</text>
<text v-else class="font-32 color-0165EE">{{i18n.assets.transfer.subtit}}</text>
</view>
</view>
</view>
<view class="borderBox" :style="'background-color: '+theme.fu_bg">
<view class="padding-22">
<view class="height-65 flex align-center">
<text class="font-32">{{i18n.assets.transfer.num}}</text>
</view>
<view class="height-65 flex align-center justify-between">
<input class="height-65 font-26 numbold-font" type="number" v-model="inputNum"
:placeholder="i18n.assets.transfer.inputNum" />
<view class="height-65 line-height-65">
<text @click="allIn" class="font-26 bold-font color-0165EE">{{i18n.assets.transfer.all}}</text>
</view>
</view>
</view>
</view>
<view class="borderBox" :style="'background-color: '+theme.fu_bg">
<view class="padding-22">
<view class="height-65 flex align-center justify-between">
<text class="font-30">{{i18n.assets.transfer.pay_pwd}}</text>
<input class="height-65 font-30 numbold-font text-right" type="text" v-model="pay_pwd" password
:placeholder="i18n.assets.transfer.inputPWD" />
</view>
</view>
</view>
<view v-if="selectCurr.name" class="flex align-center">
<text class="font-26">{{i18n.assets.transfer.usable}}</text>
<u-count-to fontSize="26" :color="theme.text" :endVal="available_num" :decimals="4" :duration="400"></u-count-to>
<text class="font-26">{{showConvertUnit}}</text>
</view>
<!-- 合约转换提示 -->
<view v-if="needConversion && inputNum > 0" class="margin-t-10 padding-w-22">
<text class="font-24 color-00C481"> {{convertedDisplay}}</text>
</view>
<!-- <p class="font-26 color-333333">可用 {{available_num}} USDT</p> -->
<view class="borderBox" :style="'background-color: '+theme.fu_bg">
<view class="padding-22" v-html="transfer_text">
</view>
</view>
<view class="width-600 margin-50-auto">
<button @click="transfer" class="cu-btn loginBtn">{{i18n.assets.transfer.sure}}</button>
</view>
</view>
<u-picker @confirm="select" v-model="currType" mode="selector" :range="count_obj" range-key="name"
:confirm-text="i18n.assets.transfer.confirm" :cancel-text="i18n.assets.transfer.cancel"></u-picker>
</view>
</template>
<script>
export default {
data() {
return {
inputNum: '',
pay_pwd: '',
zhuanghu: [],
leftObj: {
id: 1,
name: '现货账户'
},
rightObj: {
id: 1,
name: '现货账户'
},
currList: [],
selectCurr: '',
selectIndex: '',
showPoup: '',
currType: false,
transfer_text: '',
animationName: '',
flag: true,
theme: '',
}
},
onLoad(e) {
console.log(e)
if(e.id){
if(e.id==1||e.id==0){
this.leftObj.id = 1
this.leftObj.name = this.i18n.assets.transfer.xh
this.rightObj.id = 2
this.rightObj.name = this.i18n.assets.transfer.fb
}
if(e.id==2){
this.leftObj.id = e.id
this.leftObj.name = this.i18n.assets.transfer.fb
this.rightObj.id = 1
this.rightObj.name = this.i18n.assets.transfer.xh
}
if(e.id==3){
this.leftObj.id = e.id
this.leftObj.name = this.i18n.assets.transfer.lh
this.rightObj.id = 1
this.rightObj.name = this.i18n.assets.transfer.xh
}
if(e.id==4){
this.leftObj.id = e.id
this.leftObj.name = this.i18n.assets.transfer.qq
this.rightObj.id = 1
this.rightObj.name = this.i18n.assets.transfer.xh
}
}
if(e.rightid){
this.leftObj.id = 1
this.leftObj.name = this.i18n.assets.transfer.xh
this.rightObj.id = e.rightid
this.rightObj.name = this.i18n.assets.transfer.qq
}
},
onShow() {
if (uni.getStorageSync("theme") == "dark") {
this.theme = this.$store.state.darkTheme
} else {
this.theme = this.$store.state.lightTheme
}
this.get_transfer()
},
computed: {
i18n() {
return this.$t('message');
},
// 是否涉及合约账户且非USDT(需要汇率转换)
needConversion() {
if (!this.selectCurr || !this.selectCurr.name) return false
const isContract = this.leftObj.id == 3 || this.rightObj.id == 3
const isUSDT = this.selectCurr.curr_id == 1 || (this.selectCurr.name || '').toUpperCase() === 'USDT'
return isContract && !isUSDT
},
// 可用余额 — 合约→现货时显示合约USDT余额
available_num() {
if (this.needConversion && this.leftObj.id == 3) {
// 从合约转出:显示合约USDT余额
let usdtItem = this.currList.find(c => c.curr_id == 1 || (c.name || '').toUpperCase() === 'USDT')
return usdtItem ? (usdtItem.num_lh || 0) : 0
}
if(this.leftObj.id==1){
return this.selectCurr.num || 0
}else if(this.leftObj.id==2){
return this.selectCurr.num_fb || 0
}else if(this.leftObj.id==3){
return this.selectCurr.num_lh || 0
}else if(this.leftObj.id==4){
return this.selectCurr.num_qq || 0
}else{
return 0;
}
},
// 显示可用余额的单位
showConvertUnit() {
if (this.needConversion && this.leftObj.id == 3) {
return 'USDT'
}
return this.selectCurr.name || ''
},
// 转换后显示
convertedDisplay() {
if (!this.needConversion || !this.inputNum || this.inputNum <= 0) return ''
let rate = parseFloat(this.selectCurr.exchange) || 0
if (rate <= 0) return ''
if (this.rightObj.id == 3) {
// 现货→合约:输入BTC/ETH数量,显示USDT等值
return (this.inputNum * rate).toFixed(2) + ' USDT (合约)'
} else {
// 合约→现货:输入USDT数量,显示BTC/ETH等值
return (this.inputNum / rate).toFixed(8) + ' ' + this.selectCurr.name + ' (现货)'
}
},
count_obj() {
let obj = [];
var that = this
switch (this.showPoup) {
case 'currency':
obj = that.currList
break;
case 'accountL':
obj = that.zhuanghu.filter((item) => {
return item.id != that.rightObj.id&&item.id != that.leftObj.id
})
break;
case 'accountR':
obj = that.zhuanghu.filter((item) => {
return item.id != that.leftObj.id&&item.id != that.rightObj.id
})
break;
default:
obj = that.currList
break;
}
return obj
},
},
methods: {
get_transfer() {
this.post('/wallet/get_transfer').then((res) => {
console.log('划转内容', res)
if (res.code == 1) {
let currData = res.data.curr || []
// 确保 BTC 和 ETH 始终出现在币种列表中
let names = currData.map(c => (c.name || '').toUpperCase())
if (!names.includes('BTC')) {
currData.push({ curr_id: 'btc_static', name: 'BTC', num: 0, num_fb: 0, num_lh: 0, num_qq: 0 })
}
if (!names.includes('ETH')) {
currData.push({ curr_id: 'eth_static', name: 'ETH', num: 0, num_fb: 0, num_lh: 0, num_qq: 0 })
}
this.currList = currData
this.transfer_text = res.data.transfer_text
this.zhuanghu = res.data.zhuanghu
if (this.selectIndex) {
this.selectCurr = this.currList[this.selectIndex]
}
}
})
},
allIn() {
if (this.selectCurr.curr_id != undefined) {
this.inputNum = this.available_num
} else {
this.tos(this.i18n.assets.transfer.p0)
}
},
// 划转
transfer() {
if (!this.flag) return
console.log(this.selectCurr.curr_id)
if (this.selectCurr.curr_id == undefined) {
this.tos(this.i18n.assets.transfer.p0)
return
}
if (this.inputNum == '') {
this.tos(this.i18n.assets.transfer.inputNum)
return
}
if (Number(this.inputNum) > Number(this.available_num)) {
this.tos(this.i18n.assets.transfer.maxNum + this.available_num)
return
}
if (this.pay_pwd == '') {
this.tos(this.i18n.assets.transfer.inputPWD)
return
}
uni.showLoading({
title: this.i18n.assets.transfer.loading,
mask:true
})
this.flag = false
this.post('/wallet/transfer_sub', {
left_id: this.leftObj.id,
right_id: this.rightObj.id,
curr_id: this.selectCurr.curr_id,
num: this.inputNum,
pay_pwd: this.pay_pwd,
}).then((res) => {
console.log('划转提交', res)
this.flag = true
uni.hideLoading()
if (res.code == 1) {
this.tos(res.msg)
this.pay_pwd = ''
this.inputNum = ''
setTimeout(() => {
uni.navigateTo({
url: '/pages/asset/record'
})
}, 500)
}
})
},
exchange() {
if (this.animationName) return
this.animationName = 'XZ180'
this.inputNum = ''
let temp = this.leftObj
this.leftObj = this.rightObj
this.rightObj = temp
setTimeout(() => {
this.animationName = ''
}, 500)
},
select(index) {
if (this.showPoup == 'accountL') {
this.leftObj = this.count_obj[index]
console.log(this.leftObj.name)
}
if (this.showPoup == 'accountR') {
this.rightObj = this.count_obj[index]
console.log(this.rightObj.name)
}
if (this.showPoup == 'currency') {
this.selectIndex = index
this.selectCurr = this.currList[index]
this.inputNum = ''
console.log(this.selectCurr)
}
},
}
}
</script>
<style lang="scss">
.borderBox {
width: 690rpx;
// height: 260rpx;
margin: 22rpx auto;
// background: #FFFFFF;
box-shadow: 0rpx 3rpx 6rpx rgba(200, 200, 200, 0.16);
border-radius: 10rpx;
}
.XZ180 {
transition: all 0.5s;
transform: rotate(180deg);
}
.loginBtn {
width: 600rpx;
height: 96rpx;
background: #06C38D !important;
border-radius: 12rpx;
line-height: 96rpx;
color: #FFFFFF;
font-size: 32rpx;
text-align: center;
}
</style>