|
|
@@ -1,305 +1,250 @@
|
|
|
<template>
|
|
|
<cwg-page-wrapper class="create-page" :isHeaderFixed="true">
|
|
|
<cwg-header :title="t('wallet.item62')" />
|
|
|
- <view class="info-card">
|
|
|
- <cwg-complex-search :fields="filterFields" v-model="searchParams" @search="handleSearch"
|
|
|
- @reset="handleReset" />
|
|
|
- <cwg-tabel ref="tableRef" :columns="columns" :immediate="false" :mobilePrimaryFields="mobilePrimaryFields"
|
|
|
- :queryParams="search" :api="listApi" :show-operation="false">
|
|
|
- <template #symbol="{ row }">
|
|
|
- <view class="symbol-cell">
|
|
|
- <view class="pair">{{ getSymbolParts(row.symbol)[0] }}/{{ getSymbolParts(row.symbol)[1]
|
|
|
- }}</view>
|
|
|
- <view class="desc">{{ row.openPrice }}
|
|
|
- <text :class="getCmdColorClass(row.cmdName)">{{ formatCmdName(row.cmdName) }}{{ row.volume
|
|
|
- }}{{ t('Label.Lot') }}</text>
|
|
|
+ <view id="custom_WalletTransfer" class="transfer-page">
|
|
|
+ <view class="main-content">
|
|
|
+ <view class="box box-step2">
|
|
|
+ <view class="b-card">
|
|
|
+ <view class="card-top">
|
|
|
+ <uni-forms ref="formRef" :model="form" :rules="rules" label-position="top"
|
|
|
+ validate-trigger="submit">
|
|
|
+
|
|
|
+ <view class="card-row card-tit">
|
|
|
+ <view class="title-wrapper">
|
|
|
+ <view class="tit">
|
|
|
+ <text class="iconfont icon-caret-right"></text>
|
|
|
+ <span>{{ t('wallet.item63') }}</span>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="card-row">
|
|
|
+ <uni-forms-item name="walletbalance">
|
|
|
+ <uni-easyinput v-model="walletbalanceDisplay" disabled class="disabled-input" />
|
|
|
+ </uni-forms-item>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="card-row card-tit">
|
|
|
+ <view class="title-wrapper">
|
|
|
+ <view class="tit">
|
|
|
+ <text class="iconfont icon-caret-right"></text>
|
|
|
+ <span>{{ t('Custom.Transfer.IntoAccount') }}</span>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="card-row">
|
|
|
+ <uni-forms-item name="login">
|
|
|
+ <cwg-combox v-model:value="form.login" :clearable="false"
|
|
|
+ :options="toOptionsDisplay" :placeholder="t('placeholder.choose')" />
|
|
|
+ </uni-forms-item>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="card-row card-tit">
|
|
|
+ <view class="title-wrapper">
|
|
|
+ <view class="tit">
|
|
|
+ <text class="iconfont icon-caret-right"></text>
|
|
|
+ <span>{{ t('Label.Currency') }}</span>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="card-row">
|
|
|
+ <uni-forms-item name="currency">
|
|
|
+ <cwg-combox v-model:value="form.currency" :clearable="false"
|
|
|
+ :options="currencyOptions" :placeholder="t('placeholder.choose')" />
|
|
|
+ </uni-forms-item>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="card-row card-tit">
|
|
|
+ <view class="title-wrapper">
|
|
|
+ <view class="tit">
|
|
|
+ <text class="iconfont icon-caret-right"></text>
|
|
|
+ <span>{{ t('Label.Amount') }}</span>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="card-row">
|
|
|
+ <uni-forms-item name="amount">
|
|
|
+ <uni-easyinput v-model="form.amount" :placeholder="t('placeholder.input')" />
|
|
|
+ </uni-forms-item>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-row">
|
|
|
+ <button class="s-btn reselect" type="primary" @click="toTransfer">{{ t('Btn.Submit') }}</button>
|
|
|
+ </view>
|
|
|
+ </uni-forms>
|
|
|
</view>
|
|
|
</view>
|
|
|
- </template>
|
|
|
- <template #profit="{ row }">
|
|
|
- <view class="symbol-cell">
|
|
|
- <text :class="getProfitColorClass(row.profit)">{{ row.profit || 0 }}</text>
|
|
|
- </view>
|
|
|
- </template>
|
|
|
- </cwg-tabel>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <!-- 失败弹窗 -->
|
|
|
+ <cwg-error-popup v-model:visible="dialogError" @confirm="closeDia" :responseMessage="RES" />
|
|
|
+ <!-- 成功弹窗 -->
|
|
|
+ <cwg-success-popup v-model:visible="dialogSuccess" @confirm="closeDia" />
|
|
|
+ <!-- 等待弹窗 -->
|
|
|
+ <cwg-wait-popup v-model:visible="dialogCheckWait" type="center" :mask-click="false" :showFooters="false" />
|
|
|
</view>
|
|
|
</cwg-page-wrapper>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { computed, ref, nextTick, reactive } from 'vue';
|
|
|
-import { useI18n } from 'vue-i18n';
|
|
|
-const { t, locale } = useI18n();
|
|
|
-import { onLoad } from '@dcloudio/uni-app'
|
|
|
-import { customApi } from '@/service/custom';
|
|
|
-import { useAccountOptions } from '@/composables/useAccountOptions'
|
|
|
-const { loginOptions, isLoaded, isSuccess } = useAccountOptions()
|
|
|
-const search = reactive({
|
|
|
- login: null
|
|
|
+import { ref, reactive, computed, onMounted } from 'vue'
|
|
|
+import { useI18n } from 'vue-i18n'
|
|
|
+import { customApi } from '@/service/custom'
|
|
|
+import { drawApi } from '@/service/draw'
|
|
|
+import Config from '@/config/index'
|
|
|
+
|
|
|
+const { Code } = Config
|
|
|
+const { t } = useI18n()
|
|
|
+
|
|
|
+const loading = ref(false)
|
|
|
+const flag = ref(false)
|
|
|
+const RES = ref('')
|
|
|
+const walletbalance = ref('0')
|
|
|
+const toOptions = ref([])
|
|
|
+
|
|
|
+const form = reactive({
|
|
|
+ currency: 'USD',
|
|
|
+ login: null,
|
|
|
+ amount: ''
|
|
|
})
|
|
|
-const typeMap = computed(() => ([
|
|
|
- { value: null, text: t('Custom.PaymentHistory.All') },
|
|
|
- { value: 1, text: t('Custom.PaymentHistory.Deposit') },
|
|
|
- { value: 2, text: t('Custom.PaymentHistory.Withdrawals') }
|
|
|
-]));
|
|
|
-const orderStatusMap = computed(() => ([
|
|
|
- { value: null, text: t('Custom.PaymentHistory.All') },
|
|
|
- { value: 1, text: t('State.ToBeProcessed') },
|
|
|
- { value: 2, text: t('State.Completed') },
|
|
|
- { value: 3, text: t('State.InTheProcessing') },
|
|
|
- { value: 4, text: t('State.Refused') },
|
|
|
- { value: 5, text: t('State.expireTime') },
|
|
|
- { value: 6, text: t('State.Cancelled') },
|
|
|
-]));
|
|
|
-
|
|
|
-// 表格列配置
|
|
|
-const columns = computed(() => [
|
|
|
- {
|
|
|
- prop: 'symbol',
|
|
|
- label: t('Label.Varieties'), // 交易品种
|
|
|
- align: 'left'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'cmdName',
|
|
|
- label: t('Label.Type'), // 类型
|
|
|
- align: 'left'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'openTime',
|
|
|
- label: t('Label.OpenTime'), // 开仓时间(协调世界时)
|
|
|
- align: 'left'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'volume',
|
|
|
- label: t('Label.Volume'), // 手
|
|
|
- formatter: ({ row }) => `${row.volume || 0} ${t('Label.Lot')}`,
|
|
|
- align: 'right'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'openPrice',
|
|
|
- label: t('Label.OpenPrice'), // 开仓价
|
|
|
- align: 'right'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'tp',
|
|
|
- label: t('Label.EP'), // 止盈
|
|
|
- align: 'right'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'sl',
|
|
|
- label: t('Label.EL'), // 止损
|
|
|
- align: 'right'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'profit',
|
|
|
- label: t('Label.ProfitLoss') + '(USD)', // 利润, USD
|
|
|
- slot: 'profit',
|
|
|
- align: 'right'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'comment',
|
|
|
- label: t('Label.Note'),
|
|
|
- align: 'right',
|
|
|
- isTabel: false
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'more',
|
|
|
- type: 'more',
|
|
|
- width: 20,
|
|
|
- align: 'right'
|
|
|
- },
|
|
|
-])
|
|
|
-
|
|
|
-const mobilePrimaryFields = computed(() => [
|
|
|
- {
|
|
|
- prop: 'symbol',
|
|
|
- label: t('Label.Varieties'), // 交易品种
|
|
|
- align: 'left',
|
|
|
- slot: 'symbol'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'profit',
|
|
|
- label: t('Label.ProfitLoss') + '(USD)', // 利润, USD
|
|
|
- slot: 'profit',
|
|
|
- align: 'right'
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'more',
|
|
|
- type: 'more',
|
|
|
- width: 20,
|
|
|
- align: 'right'
|
|
|
- },
|
|
|
-])
|
|
|
|
|
|
-// 动态传入筛选字段配置
|
|
|
-const filterFields = computed(() => [
|
|
|
- isLoaded.value && isSuccess.value && { key: 'login', type: 'select', label: t('Custom.PaymentHistory.TradingAccount'), placeholder: t('placeholder.login'), options: loginOptions || [], defaultValue: search.login || undefined },
|
|
|
- { key: 'date', label: t('placeholder.Start') + ' - ' + t('placeholder.End'), type: 'daterange' }
|
|
|
-])
|
|
|
-const searchParams = ref({})
|
|
|
-const tableRef = ref(null)
|
|
|
-const handleSearch = (params) => {
|
|
|
- Object.assign(search, params)
|
|
|
- search.login = Number(params.login)
|
|
|
- search.platform = loginOptions.find(item => item.value === params.login)?.platform || ''
|
|
|
- if(!search.platform) return
|
|
|
- nextTick(() => {
|
|
|
- tableRef.value.refreshTable()
|
|
|
- })
|
|
|
-}
|
|
|
+const currencyOptions = [{ text: 'USD', value: 'USD' }]
|
|
|
|
|
|
-const handleReset = (params) => {
|
|
|
- Object.assign(search, params)
|
|
|
- search.platform = loginOptions.find(item => item.value === params.login)?.platform || ''
|
|
|
- if(!search.platform) return
|
|
|
- nextTick(() => {
|
|
|
- tableRef.value.refreshTable()
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-const listApi = ref(null)
|
|
|
-listApi.value = customApi.tradePosition
|
|
|
+const walletbalanceDisplay = computed(() => `$ ${walletbalance.value}`)
|
|
|
|
|
|
-const getSymbolParts = (sym: string) => {
|
|
|
- if (!sym) return ['', '']
|
|
|
- const s = String(sym).toUpperCase()
|
|
|
- if (s.includes('/')) {
|
|
|
- const [base, quote] = s.split('/')
|
|
|
- return [base, quote]
|
|
|
- }
|
|
|
- const base = s.slice(0, 3)
|
|
|
- const quote = s.slice(3)
|
|
|
- return [base, quote]
|
|
|
-}
|
|
|
-const formatCmdName = (cmd: string) => {
|
|
|
- const v = String(cmd || '').toLowerCase()
|
|
|
- if (v.includes('sell')) return '卖出'
|
|
|
- if (v.includes('buy')) return '买入'
|
|
|
- return cmd || ''
|
|
|
-}
|
|
|
-const getCmdColorClass = (cmd: string) => {
|
|
|
- const v = String(cmd || '').toLowerCase()
|
|
|
- if (v.includes('sell')) return 'is-sell'
|
|
|
- if (v.includes('buy')) return 'is-buy'
|
|
|
+const groupTypeName = (type) => {
|
|
|
+ if (type == '1') return t("AccountType.ClassicAccount")
|
|
|
+ if (type == '2') return t("AccountType.SeniorAccount")
|
|
|
+ if (type == '5') return t("AccountType.SpeedAccount")
|
|
|
+ if (type == '6') return t("AccountType.SpeedAccount")
|
|
|
+ if (type == '7') return t("AccountType.StandardAccount")
|
|
|
+ if (type == '8') return t("AccountType.CentAccount")
|
|
|
return ''
|
|
|
}
|
|
|
-const getProfitColorClass = (profit: any) => {
|
|
|
- const n = Number(profit)
|
|
|
- if (!Number.isFinite(n) || n === 0) return ''
|
|
|
- return n > 0 ? 'is-profit' : 'is-loss'
|
|
|
-}
|
|
|
|
|
|
-onLoad((e) => {
|
|
|
- if (e.login) {
|
|
|
- search.login = Number(e.login)
|
|
|
- }
|
|
|
+const toOptionsDisplay = computed(() => {
|
|
|
+ return toOptions.value.map(item => ({
|
|
|
+ text: `${item.login} - ${item.platform} - ${groupTypeName(item.type)}`,
|
|
|
+ value: item.login
|
|
|
+ }))
|
|
|
})
|
|
|
-</script>
|
|
|
|
|
|
-<style scoped lang="scss">
|
|
|
-@import "@/uni.scss";
|
|
|
+const dialogCheck = ref(false)
|
|
|
+const dialogVisible = ref(false)
|
|
|
+const dialogCheckWait = ref(false)
|
|
|
|
|
|
-.avatar {
|
|
|
- width: px2rpx(60);
|
|
|
- height: px2rpx(60);
|
|
|
- border-radius: 4px;
|
|
|
-}
|
|
|
+const dialogSuccess = computed(() => dialogCheck.value && dialogVisible.value)
|
|
|
+const dialogError = computed(() => dialogCheck.value && !dialogVisible.value)
|
|
|
|
|
|
-.content-title {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- font-size: px2rpx(20);
|
|
|
- font-weight: 500;
|
|
|
+const rules = {
|
|
|
+ login: {
|
|
|
+ rules: [{ required: true, errorMessage: t('vaildate.select.empty') }]
|
|
|
+ },
|
|
|
+ currency: {
|
|
|
+ rules: [{ required: true, errorMessage: t('vaildate.select.empty') }]
|
|
|
+ },
|
|
|
+ amount: {
|
|
|
+ rules: [
|
|
|
+ { required: true, errorMessage: t('vaildate.amount.format') },
|
|
|
+ {
|
|
|
+ validateFunction: (rule, value, data, callback) => {
|
|
|
+ if (!value) {
|
|
|
+ callback(t('vaildate.amount.format'))
|
|
|
+ } else if (!/^[0-9]+([.]{1}[0-9]{1,2})?$/.test(value)) {
|
|
|
+ callback(t('vaildate.amount.format'))
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- .content-title-btns {
|
|
|
- margin: px2rpx(8) 0;
|
|
|
+const formRef = ref(null)
|
|
|
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- gap: px2rpx(12);
|
|
|
+const closeDia = () => {
|
|
|
+ if (formRef.value) {
|
|
|
+ form.amount = ''
|
|
|
+ form.login = null
|
|
|
+ formRef.value.clearValidate()
|
|
|
+ }
|
|
|
+ dialogCheck.value = false
|
|
|
+ dialogVisible.value = false
|
|
|
+}
|
|
|
|
|
|
- .btn-primary {
|
|
|
- min-width: px2rpx(120);
|
|
|
- background-color: var(--color-error);
|
|
|
- color: white;
|
|
|
- padding: 0 px2rpx(12);
|
|
|
- border: none;
|
|
|
- font-size: px2rpx(14);
|
|
|
- text-align: center;
|
|
|
- cursor: pointer;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- gap: px2rpx(8);
|
|
|
+const toTransfer = async () => {
|
|
|
+ try {
|
|
|
+ await formRef.value.validate()
|
|
|
+
|
|
|
+ if (walletbalance.value == '0' || Number(walletbalance.value) < Number(form.amount)) {
|
|
|
+ uni.showToast({ title: t('wallet.item64'), icon: 'none' })
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
- .btn-primary:active {
|
|
|
- background-color: var(--color-navy-700);
|
|
|
+ if (flag.value) return
|
|
|
+ flag.value = true
|
|
|
+ dialogCheckWait.value = true
|
|
|
+
|
|
|
+ let res = await customApi.walletTransferApply({ ...form })
|
|
|
+
|
|
|
+ if (res.code == Code.StatusOK) {
|
|
|
+ dialogCheck.value = true
|
|
|
+ dialogVisible.value = true
|
|
|
+ flag.value = false
|
|
|
+ getWalletList() // refresh balance after success
|
|
|
+ } else {
|
|
|
+ RES.value = res.msg
|
|
|
+ dialogCheck.value = true
|
|
|
+ dialogVisible.value = false
|
|
|
+ flag.value = false
|
|
|
}
|
|
|
+ dialogCheckWait.value = false
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.operation-btn {
|
|
|
- :deep(span) {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- gap: px2rpx(4);
|
|
|
- cursor: pointer;
|
|
|
- background-color: var(--color-slate-150);
|
|
|
- padding: px2rpx(8) 0;
|
|
|
+const getToDateList = async () => {
|
|
|
+ try {
|
|
|
+ let res = await customApi.CustomDropdown({})
|
|
|
+ if (res.code == Code.StatusOK) {
|
|
|
+ toOptions.value = res.data || []
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: res.msg, icon: 'none' })
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.operation-btn.disabled {
|
|
|
- cursor: not-allowed;
|
|
|
- opacity: 0.5;
|
|
|
-}
|
|
|
-
|
|
|
-.symbol-cell {
|
|
|
- display: inline-flex;
|
|
|
- align-items: flex-start;
|
|
|
- gap: 0.25rem;
|
|
|
- flex-direction: column;
|
|
|
-
|
|
|
- .pair {
|
|
|
- font-weight: 600;
|
|
|
- color: var(--color-slate-900);
|
|
|
- }
|
|
|
-
|
|
|
- .desc {
|
|
|
- color: var(--color-slate-600);
|
|
|
+const getWalletList = async () => {
|
|
|
+ try {
|
|
|
+ let res = await drawApi.walletbalance({})
|
|
|
+ if (res.code == Code.StatusOK) {
|
|
|
+ walletbalance.value = res.data != null ? res.data : '0'
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: res.msg, icon: 'none' })
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.is-sell,
|
|
|
-.is-loss {
|
|
|
- color: #eb483f;
|
|
|
-}
|
|
|
-
|
|
|
-.is-buy,
|
|
|
-.is-profit {
|
|
|
- color: #46cd7c;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+onMounted(() => {
|
|
|
+ getToDateList()
|
|
|
+ getWalletList()
|
|
|
+})
|
|
|
+</script>
|
|
|
|
|
|
-.search-bar {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: flex-start;
|
|
|
- flex-wrap: wrap;
|
|
|
- gap: px2rpx(16);
|
|
|
- margin: px2rpx(16) 0;
|
|
|
+<style scoped lang="scss">
|
|
|
+@import "@/uni.scss";
|
|
|
+@import "@/pages/customer/transfer.scss";
|
|
|
|
|
|
- .cwg-combox,
|
|
|
- .uni-easyinput,
|
|
|
- .uni-date {
|
|
|
- width: px2rpx(240) !important;
|
|
|
- flex: none;
|
|
|
+:deep(.disabled-input) {
|
|
|
+ .uni-easyinput__content {
|
|
|
+ background-color: #f5f7fa !important;
|
|
|
+ input {
|
|
|
+ color: #c0c4cc !important;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</style>
|