Kaynağa Gözat

Merge branch 'admin_dev' of http://112.213.107.185:3000/cwg-crm/gypsy-crm-frontend-vu into admin_dev

zhb 1 ay önce
ebeveyn
işleme
dc021aeaca

+ 9 - 9
components/cwg-complex-search.vue

@@ -200,9 +200,9 @@ const initFormData = () => {
         else if (field.type === 'date' || field.type === 'daterange') {
             initial[field.key] = getDefaultDateValue(field)
         }
-        // 4. select 类型字段特殊处理:如果没有默认值,默认选第一个选项
-        else if (field.type === 'select' && field.options && field.options.length > 0) {
-            initial[field.key] = field.options[0].value
+        // 4. select 类型字段如果没有默认值,默认置空,不强制选第一个
+        else if (field.type === 'select') {
+            initial[field.key] = null
         }
         // 5. 其他字段默认为空字符串
         else {
@@ -295,9 +295,9 @@ const resetForm = () => {
         else if (field.type === 'date' || field.type === 'daterange') {
             empty[field.key] = getDefaultDateValue(field)
         }
-        // select 类型字段特殊处理:如果没有默认值,默认选择第一个选项
-        else if (field.type === 'select' && field.options && field.options.length > 0) {
-            empty[field.key] = field.options[0].value
+        // select 类型字段如果没有默认值,置空
+        else if (field.type === 'select') {
+            empty[field.key] = null
         }
         // 无默认值 → 清空
         else {
@@ -334,9 +334,9 @@ const resetTempForm = () => {
         else if (field.type === 'date' || field.type === 'daterange') {
             empty[field.key] = getDefaultDateValue(field)
         }
-        // select 类型字段特殊处理:如果没有默认值,默认选择第一个选项
-        else if (field.type === 'select' && field.options && field.options.length > 0) {
-            empty[field.key] = field.options[0].value
+        // select 类型字段如果没有默认值,置空
+        else if (field.type === 'select') {
+            empty[field.key] = null
         }
         // 无默认值 → 清空
         else {

+ 1 - 1
components/cwg-tabel.vue

@@ -503,7 +503,7 @@ const handleSort = (column) => {
     }
     sortState.value = { prop: newOrder ? column.prop : '', order: newOrder }
     emit('sort-change', { prop: sortState.value.prop, order: sortState.value.order })
-    refreshTable()
+    // refreshTable()
 }
 // 展开行切换
 const toggleRowExpand = (rowIndex) => {

+ 1 - 0
composables/useMenuSplit.ts

@@ -290,6 +290,7 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
             icon: 'crm-newspaper',
             children: [
                 { path: '/pages/ib/report', label: 'Home.page_ib.item3', icon: 'icon-withdrawal' },
+                { path: '/pages/ib/complexReport', label: 'Home.page_ib.item11', icon: 'icon-withdrawal' },
             ],
         },
     ])

+ 16 - 4
locale/cn.json

@@ -1077,7 +1077,15 @@
       "item15": "美股",
       "item16": "港股",
       "item17": "期初净值",
-      "item18": "期末净值"
+      "item18": "期末净值",
+      "item19": "客户姓名",
+      "item20": "账户类型",
+      "item21": "入金",
+      "item22": "出金",
+      "item23": "净入金",
+      "item24": "交易量",
+      "item25": "佣金",
+      "item26": "库存费"
     }
   },
   "Home": {
@@ -1100,7 +1108,8 @@
       "item7": "申请历史",
       "item8": "佣金模板",
       "item9": "代理内转",
-      "item10": "账户管理"
+      "item10": "账户管理",
+      "item11": "综合报告"
     },
     "page_shop": {
       "item1": "商城首页",
@@ -2241,7 +2250,9 @@
     "item2": "请选择商品类型",
     "item3": "去支付",
     "item4": "如果您无法点击上面的按钮,请复制下方完整的URL地址,粘贴到您的浏览器的地址栏中然后按回车键,跳转至支付界面进行付款操作",
-    "Or": "或"
+    "Or": "或",
+    "MarginLevel": "爆仓比",
+    "RegDate": "注册日期"
   },
   "AccountType": {
     "ClassicAccount": "经典账户",
@@ -2250,7 +2261,8 @@
     "ProfessionalAccount": "专业账户",
     "StandardAccount": "标准账户",
     "CentAccount": "美分账户",
-    "SpeedAccount": "极速账户"
+    "SpeedAccount": "极速账户",
+    "NewSpeedAccount": "极速账户"
   },
   "ApplicationDialog": {
     "Des43": "申请PAMM账户失败",

+ 7 - 0
pages.json

@@ -268,6 +268,13 @@
         "navigationStyle": "custom"
       }
     },
+    {
+      "path": "pages/ib/complexReport",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
     {
       "path": "pages/ib/transfer",
       "style": {

+ 283 - 0
pages/ib/complexReport.vue

@@ -0,0 +1,283 @@
+<template>
+  <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
+    <cwg-header :title="t('Home.page_ib.item11')" />
+
+    <view class="account-content">
+      <view class="search-content">
+        <view class="search-bar">
+          <cwg-complex-search :fields="filterFields" v-model="searchParams" @search="handleSearch" @reset="handleReset" />
+        </view>
+      </view>
+      <cwg-tabel
+        ref="tableRef"
+        :columns="columns"
+        :mobilePrimaryFields="mobilePrimaryFields"
+        :queryParams="search"
+        :api="listApi"
+        :show-operation="true"
+        :showPagination="true"
+        :showSummary="true"
+        @sort-change="handleSortChange"
+      >
+        <template #action="{ row }">
+          <cwg-dropdown :menu-list="menuList(row)" @menuClick="handleMenuClick">
+            <view class="pc-header-btn">
+              <cwg-icon name="crm-ellipsis" :size="24" />
+            </view>
+          </cwg-dropdown>
+        </template>
+      </cwg-tabel>
+    </view>
+  </cwg-page-wrapper>
+</template>
+
+<script setup lang="ts">
+  // 账户管理
+  import { ref, nextTick, computed, reactive } from 'vue'
+  import { useI18n } from 'vue-i18n'
+  import { ibApi } from '@/service/ib'
+  import { useFilters } from '@/composables/useFilters'
+
+  const { numberFormat } = useFilters()
+  const { t } = useI18n()
+
+  const searchParams = ref({})
+  const search = reactive({
+    cId: '',
+    customName: '',
+    login: '',
+    groupType: 0,
+    platform: null,
+    date: null
+  })
+
+  const listApi = ref(ibApi.ComplexReport)
+  const tableRef = ref<any>(null)
+  const platformOptions = [
+    { text: 'MT4', value: 'MT4' },
+    { text: 'MT5', value: 'MT5' },
+  ]
+
+  const filterFields = computed(() => [
+    { key: 'platform', type: 'select', label: t('Label.Platform'), placeholder: t('placeholder.choose'), options: platformOptions,defaultValue: null, clearable: true },
+    { key: 'cId', type: 'input', label: t('Label.CidAccount'), placeholder: t('Label.CidAccount'), defaultValue: '' },
+    { key: 'customName', type: 'input', label: t('Documentary.Report.item19'), placeholder: t('Documentary.Report.item19'), defaultValue: '' },
+    { key: 'login', type: 'input', label: t('Label.TradingAccount'), placeholder: t('Label.TradingAccount'), defaultValue: '' },
+    { 
+      key: 'groupType', 
+      type: 'select', 
+      label: t('Documentary.Report.item20'),
+      placeholder: t('Documentary.Report.item20'),
+      options: [
+        { text: t('State.All'), value: 0 },
+        { text: t('AccountType.SeniorAccount'), value: 2 },
+        { text: t('AccountType.NewSpeedAccount'), value: 6 },
+        { text: t('AccountType.StandardAccount'), value: 7 },
+        { text: t('AccountType.CentAccount'), value: 8 },
+      ],
+      defaultValue: 0,
+      clearable: true
+    },
+    { key: 'date', label: t('placeholder.Start') + ' - ' + t('placeholder.End'), type: 'daterange' },
+  ])
+  // 表格列配置
+  const columns = computed(() => [
+    {
+      prop: 'cId',
+      label: t('Label.CidAccount'),
+      align: 'center',
+    },
+    {
+      prop: 'customName',
+      label: t('Documentary.Report.item19'),
+      align: 'center',
+      formatter: ({ row }: any) => row.customName || '--',
+    },
+    {
+      prop: 'login',
+      label: t('Label.TradingAccount'),
+      align: 'center',
+      formatter: ({ row }: any) => row.login || '--',
+    },
+    {
+      prop: 'groupType',
+      type: 'tag',
+      label: t('Documentary.Report.item20'),
+      align: 'center',
+      tagMap: {
+        1: t('AccountType.ClassicAccount'),
+        2: t('AccountType.SeniorAccount'),
+        5: t('AccountType.SpeedAccount'),
+        6: t('AccountType.NewSpeedAccount'),
+        7: t('AccountType.StandardAccount'),
+        8: t('AccountType.CentAccount'),
+      },
+    },
+    {
+      prop: 'ibNo',
+      label: t('Label.AgentNumber'),
+      align: 'center',
+      formatter: ({ row }: any) => row.ibNo || '--',
+    },
+    {
+      prop: 'salesNo',
+      label: t('Label.Encode'),
+      align: 'center',
+      formatter: ({ row }: any) => row.salesNo || '--',
+    },
+    {
+      prop: 'salesName',
+      label: '销售姓名',
+      align: 'center',
+      formatter: ({ row }: any) => row.salesName || '--',
+    },
+    {
+      prop: 'deposit',
+      label: t('Documentary.Report.item21'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.deposit ? parseFloat(row.deposit).toFixed(2) : '0.00',
+    },
+    {
+      prop: 'withdrawal',
+      label: t('Documentary.Report.item22'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.withdrawal ? parseFloat(row.withdrawal).toFixed(2) : '0.00',
+    },
+    {
+      prop: 'netDeposit',
+      label: t('Documentary.Report.item23'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.netDeposit ? parseFloat(row.netDeposit).toFixed(2) : '0.00',
+    },
+    {
+      prop: 'volume',
+      label: t('Documentary.Report.item24'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.volume ? parseFloat(row.volume).toFixed(2) : '0.00',
+    },
+    {
+      prop: 'sumRebate',
+      label: t('Documentary.Report.item25'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.sumRebate ? parseFloat(row.sumRebate).toFixed(2) : '0.00',
+    },
+    {
+      prop: 'storage',
+      label: t('Documentary.Report.item26'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.storage ? parseFloat(row.storage).toFixed(2) : '0.00',
+    },
+    {
+      prop: 'balance',
+      label: t('Label.Balance'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.balance != null && row.balance !== '' ? parseFloat(row.balance).toFixed(2) : '--',
+    },
+    {
+      prop: 'equity',
+      label: t('Label.equity'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.equity != null && row.equity !== '' ? parseFloat(row.equity).toFixed(2) : '--',
+    },
+    {
+      prop: 'profit',
+      label: '盈亏',
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.profit ? parseFloat(row.profit).toFixed(2) : '0.00',
+    },
+    {
+      prop: 'marginLevel',
+      label: t('Label.MarginLevel'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.marginLevel || '--',
+    },
+    {
+      prop: 'credit',
+      label: t('Label.Credit'),
+      align: 'center',
+      sortable: 'custom',
+      formatter: ({ row }: any) => row.credit != null && row.credit !== '' ? parseFloat(row.credit).toFixed(2) : '--',
+    },
+    {
+      prop: 'regDate',
+      label: t('Label.RegDate'),
+      align: 'center',
+      formatter: ({ row }: any) => row.regDate || '--',
+    },
+  ])
+
+  const mobilePrimaryFields = computed(()=>[
+    {
+      prop: 'cId',
+      label: t('Label.CidAccount'),
+      align: 'center',
+    },
+    {
+      prop: 'customName',
+      label: '客户姓名',
+      align: 'center',
+      formatter: ({ row }: any) => row.customName || '--',
+    },
+    {
+      prop: 'login',
+      label: t('Label.TradingAccount'),
+      align: 'center',
+      formatter: ({ row }: any) => row.login || '--',
+    },
+    {
+      prop: 'more',
+      type: 'more',
+      width: 20,
+      align: 'right',
+    },
+  ])
+
+
+
+  const handleSearch = (params: any) => {
+    Object.assign(search, params)
+    nextTick(() => {
+      tableRef.value?.refreshTable?.()
+    })
+  }
+
+  const handleReset = (params: any) => {
+    Object.assign(search, {
+      ...params,
+      platform: null,
+      groupType: 0,
+    })
+    nextTick(() => {
+      tableRef.value?.refreshTable?.()
+    })
+  }
+
+  const handleSortChange = (params: any) => {
+    Object.assign(search, {
+      orderColumn: params.prop,
+      orderType: params.order,
+    })
+    nextTick(() => {
+      tableRef.value?.refreshTable?.()
+    })
+  }
+
+</script>
+<style lang="scss" scoped>
+  @import "@/uni.scss";
+
+  .search-content {
+    display: flex;
+    justify-content: space-between;
+  }
+</style>

+ 2 - 0
service/ib.ts

@@ -35,6 +35,8 @@ export const ibApi = {
   TradePosition: (params = {}) => post('/trade/position', params, 'Host90'),
   /** 交易历史 */
   TradeHistory: (params = {}) => post('/trade/sharding/history', params, 'Host90'),
+  /** 综合报告 */
+  ComplexReport: (params = {}) => post('/trade/account/summary', params, 'Host90'),
   /** 内转 */
   agentBalanceTransfer: (params = {}) => post('/agent/balance/transfer/add/imd', params, 'Host90'),
   /** 转出账户信息 */

+ 11 - 10
uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue

@@ -139,11 +139,11 @@ export default {
 		},
 		value: {
 			type: [String, Number, Array],
-			default: ''
+			default: undefined
 		},
 		modelValue: {
 			type: [String, Number, Array],
-			default: ''
+			default: undefined
 		},
 		label: {
 			type: String,
@@ -231,8 +231,9 @@ export default {
 				common
 		},
 		valueCom() {
-			if (this.value === '') return this.modelValue
-			if (this.modelValue === '') return this.value
+			if (this.value === undefined && this.modelValue !== undefined) return this.modelValue
+			if (this.modelValue === undefined && this.value !== undefined) return this.value
+			if (this.value === undefined && this.modelValue === undefined) return undefined
 			return this.value
 		},
 		textShow() {
@@ -370,8 +371,8 @@ export default {
 			}
 		},
 		initDefVal() {
-			let defValue = this.multiple ? [] : ''
-			if ((this.valueCom || this.valueCom === 0) && !this.isDisabled(this.valueCom)) {
+			let defValue = this.multiple ? [] : undefined
+			if ((this.valueCom !== undefined && this.valueCom !== null) && !this.isDisabled(this.valueCom)) {
 				defValue = this.valueCom
 			} else {
 				let strogeValue
@@ -381,23 +382,23 @@ export default {
 				if (strogeValue || strogeValue === 0) {
 					defValue = strogeValue
 				} else {
-					let defItem = this.multiple ? [] : ''
+					let defItem = this.multiple ? [] : undefined
 					if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) {
 						defItem = this.multiple ? [this.mixinDatacomResData[this.defItem - 1].value] : this.mixinDatacomResData[this.defItem - 1].value
 					}
 					defValue = defItem
 				}
-				if (defValue || defValue === 0 || (this.multiple && Array.isArray(defValue) && defValue.length > 0)) {
+				if (defValue !== '' && defValue !== undefined && defValue !== null && (!this.multiple || (Array.isArray(defValue) && defValue.length > 0))) {
 					this.emit(defValue)
 				}
 			}
 
 			if (this.multiple) {
-				const selectedValues = Array.isArray(defValue) ? defValue : (defValue ? [defValue] : []);
+				const selectedValues = Array.isArray(defValue) ? defValue : (defValue !== undefined ? [defValue] : []);
 				const selectedItems = this.mixinDatacomResData.filter(item => selectedValues.includes(item.value));
 				this.current = selectedItems.map(item => this.formatItemName(item));
 			} else {
-				const def = this.mixinDatacomResData.find(item => item.value === defValue)
+				const def = defValue !== undefined ? this.mixinDatacomResData.find(item => item.value === defValue) : null
 				this.current = def ? this.formatItemName(def) : ''
 			}
 		},