|
|
@@ -0,0 +1,305 @@
|
|
|
+<template>
|
|
|
+ <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
|
|
|
+ <cwg-header :title="t('Ib.Report.Tit4')" />
|
|
|
+ <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>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ <template #profit="{ row }">
|
|
|
+ <view class="symbol-cell">
|
|
|
+ <text :class="getProfitColorClass(row.profit)">{{ row.profit || 0 }}</text>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ </cwg-tabel>
|
|
|
+ </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
|
|
|
+})
|
|
|
+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 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 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'
|
|
|
+ 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)
|
|
|
+ }
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+@import "@/uni.scss";
|
|
|
+
|
|
|
+.avatar {
|
|
|
+ width: px2rpx(60);
|
|
|
+ height: px2rpx(60);
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.content-title {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ font-size: px2rpx(20);
|
|
|
+ font-weight: 500;
|
|
|
+
|
|
|
+ .content-title-btns {
|
|
|
+ margin: px2rpx(8) 0;
|
|
|
+
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: px2rpx(12);
|
|
|
+
|
|
|
+ .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);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-primary:active {
|
|
|
+ background-color: var(--color-navy-700);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.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;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.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);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.is-sell,
|
|
|
+.is-loss {
|
|
|
+ color: #eb483f;
|
|
|
+}
|
|
|
+
|
|
|
+.is-buy,
|
|
|
+.is-profit {
|
|
|
+ color: #46cd7c;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+.search-bar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-start;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: px2rpx(16);
|
|
|
+ margin: px2rpx(16) 0;
|
|
|
+
|
|
|
+ .cwg-combox,
|
|
|
+ .uni-easyinput,
|
|
|
+ .uni-date {
|
|
|
+ width: px2rpx(240) !important;
|
|
|
+ flex: none;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|