Compare commits

...

51 Commits

Author SHA1 Message Date
ZhangYong 3b3537ed77 退款执行上传图片提示 10 hours ago
ZhangYong 4ee3a62df6 收款执行修改精网号问题 10 hours ago
ZhangYong 1133741ea7 金币退款单位翻译 2 days ago
ZhangYong 05f63ef288 英所属英文地区 2 days ago
ZhangYong f21fa9bc98 资金流水账导出传市场id以及字段映射 2 days ago
ZhangYong 09ae2d6f1b 执行人退款币种改 id 2 days ago
ZhangYong c4f2fab06e iPay88 统一 3 days ago
ZhangYong 465f15a6ec 业绩归属导出 3 days ago
ZhangYong 5c84db4d0f 退款展示币种问题 4 days ago
ZhangYong 4ed46899bc 资金流水提示词 4 days ago
ZhangYong f1b6494db8 业绩归属市场名转id 4 days ago
ZhangYong ab88e2bbc3 补一下多语言 4 days ago
ZhangYong c71c077581 Merge branch 'zhangyong/feature-20260402144402-现金4期' into milestone-20260402-现金4期 4 days ago
ZhangYong 814dd1f3a8 filterMenu取消工具类按照id升序 4 days ago
jiangcheng f44a2af9e3 金额调整 4 days ago
ZhangYong 5ea50dea13 新增收款软件产品加一下钱包 4 days ago
jiangcheng 4141aa527f Merge branch 'milestone-20260402-现金4期' of http://39.101.133.168:8807/huangqizhen/gold-vue into milestone-20260402-现金4期 5 days ago
jiangcheng 08de72d47c 合并 5 days ago
ZhangYong 4a5cd54897 业绩调整提示词 5 days ago
ZhangYong a1b7e6fb9d 表格高度问题 5 days ago
jiangcheng 4c416f4506 退款bug修改 5 days ago
jiangcheng d70a3f5fcc 合并 5 days ago
jiangcheng 46f3e862b4 Merge branch 'milestone-20260402-现金4期' of http://39.101.133.168:8807/huangqizhen/gold-vue into milestone-20260402-现金4期 5 days ago
jiangcheng 64a557bd22 活动多语言配置、资金流水账字段优化 5 days ago
ZhangYong ecc395d2ab 多语言以及业绩归属字段 5 days ago
ZhangYong 9639662f8e 权限控制 5 days ago
ZhangYong 5c5ea5b385 加业绩字段 5 days ago
ZhangYong e31953d76e 多语言合并问题 6 days ago
ZhangYong 0fb98e0466 Merge branch 'zhangyong/feature-20260402144402-现金4期' into milestone-20260402-现金4期 6 days ago
ZhangYong d7371d40cb 地区问题 6 days ago
jiangcheng b5110ef05e Merge branch 'jiangcheng/feature-20260402142510-现金四期' into milestone-20260402-现金4期 6 days ago
jiangcheng b298d7eb50 资金流水账 6 days ago
ZhangYong 69e6df9bab 钱包界面字段修改 6 days ago
ZhangYong 718ad7c915 修改 1 week ago
ZhangYong 3742632ec8 钱包二级界面 1 week ago
ZhangYong a3e10d9273 删掉原钱包入口 1 week ago
ZhangYong 098a3823f3 业绩编辑 1 week ago
ZhangYong 24ca0519c6 钱包组件创建 1 week ago
ZhangYong efac84b68d 权限完毕 1 week ago
ZhangYong 9758497195 Merge branch 'milestone-20260402-现金4期' into zhangyong/feature-20260402144402-现金4期 1 week ago
ZhangYong 6f9037d0a9 加权限 1 week ago
ZhangYong caae87cfd3 加了界面 2 weeks ago
ZhangYong 7065fe4507 Merge branch 'hotfix-stript2' into milestone-20260402-现金4期 2 weeks ago
ZhangYong 083e4b9efc 执行加上stripe2 2 weeks ago
ZhangYong 0257c28de5 Merge branch 'milestone-20260402-现金4期' of http://39.101.133.168:8807/huangqizhen/gold-vue into milestone-20260402-现金4期 2 weeks ago
ZhangYong 6551fee088 配置文件 2 weeks ago
ZhangYong b55089dbcb 配置文件 2 weeks ago
ZhangYong 90697620f4 工作台:px->vw 2 weeks ago
jiangcheng 1d49c7b2cd Merge branch 'milestone-20260402-现金4期' of http://39.101.133.168:8807/huangqizhen/gold-vue into milestone-20260402-现金4期 2 weeks ago
jiangcheng f8c1261777 活动操作修改及多语言配置 2 weeks ago
ZhangYong 99b4336a67 保留 2 weeks ago
  1. 22
      .env.development
  2. 2
      .gitignore
  3. 10
      src/api/cash/cash.js
  4. 9
      src/api/cash/financialAccount.js
  5. 27
      src/assets/SvgIcons/wallet_management.svg
  6. 79
      src/components/locales/lang/en.js
  7. 116
      src/components/locales/lang/zh-CN.js
  8. 50
      src/components/workspace/CashManagement.vue
  9. 114
      src/components/workspace/GoldManagement.vue
  10. 90
      src/router/index.js
  11. 0
      src/static/common.js
  12. 3
      src/utils/menuTreePermission.js
  13. 17
      src/utils/menuUtils.js
  14. 6
      src/views/activityManage/activity.vue
  15. 1
      src/views/home.vue
  16. 7
      src/views/moneyManage/executor/executor.vue
  17. 753
      src/views/moneyManage/financialAccount/cashFlow.vue
  18. 375
      src/views/moneyManage/financialAccount/performanceAttribution.vue
  19. 51
      src/views/moneyManage/receiveDetail/receiveService.vue
  20. 15
      src/views/usergold/gold/clientCount.vue
  21. 913
      src/views/walletManage/WalletBalance.vue
  22. 472
      src/views/walletManage/components/WalletDetailTemplate.vue
  23. 10
      src/views/walletManage/walletDetail/BJWallet.vue
  24. 10
      src/views/walletManage/walletDetail/CAWallet.vue
  25. 12
      src/views/walletManage/walletDetail/HKWallet.vue
  26. 10
      src/views/walletManage/walletDetail/MyWallet.vue
  27. 10
      src/views/walletManage/walletDetail/SGWalletCM.vue
  28. 10
      src/views/walletManage/walletDetail/SGWalletHC.vue
  29. 10
      src/views/walletManage/walletDetail/THWalletHA.vue
  30. 10
      src/views/walletManage/walletDetail/THWalletHS.vue
  31. 10
      src/views/walletManage/walletDetail/VNWallet.vue

22
.env.development

@ -0,0 +1,22 @@
VITE_API_BASE='https://hwjb.homilychart.com/dev/admin/'
# 测试环境
# VITE_API_BASE='http://54.255.212.181:10704/'
# 正式环境
# VITE_API_BASE='http://54.255.212.181:10705/'
VITE_UPLOAD_URL=http://39.101.133.168:8828/hljw/api/aws/upload
# sunjiabei
# VITE_API_BASE='http://192.168.9.28:8081/'
# VITE_API_BASE='http://192.168.5.92:8081/'
# 张勇
# VITE_API_BASE='http://192.168.40.72:8081/'
# 本地
# VITE_API_BASE='http://localhost:8081/'
# 孙加倍
# VITE_API_BASE='http://192.168.40.12:8081'
# 黄其振
# VITE_API_BASE='http://192.168.40.17:8081'
# Lijianlin
# VITE_API_BASE='http://192.168.40.9:8081/'
# VITE_API_BASE='http://localhost:8081/'
# 汪国瑞
# VITE_API_BASE='http://192.168.40.30:8081/'

2
.gitignore

@ -25,5 +25,5 @@ dist-ssr
*.sw?
# 忽略
stats.html
.env.development
# .env.development

10
src/api/cash/cash.js

@ -0,0 +1,10 @@
import http from '@/util/http.js'
// 查询钱包记录
export const selectWalletRecords = (data) => {
return http({
method: 'POST',
url: '/cashCollection/selectWalletRecords',
data
})
}

9
src/api/cash/financialAccount.js

@ -44,3 +44,12 @@ export const exportFunds = (data) => {
data
})
}
// 业绩调整
export const adjustment = (data) => {
return http({
method: 'POST',
url: '/cashCollection/adjust',
data
})
}

27
src/assets/SvgIcons/wallet_management.svg

@ -0,0 +1,27 @@
<svg width="31" height="31" viewBox="0 0 31 31" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.74612 0.375959C11.6259 0.0545255 15.0739 -0.278254 20.0466 0.375959C25.0192 1.03017 28.1825 3.79754 29.2367 7.13376C30.2909 10.47 30.2144 16.9942 29.826 20.258C29.507 24.1645 27.2331 28.7886 21.7954 29.5942C16.3576 30.3997 9.67485 30.1849 6.99417 29.2304C4.3135 28.2758 0.763355 26.2434 0.299165 20.5505C-0.165026 14.8577 -0.471763 7.2173 2.42497 4.11929C4.43352 1.73288 7.86631 0.697393 9.74612 0.375959Z" fill="#FFE2F4"/>
<g filter="url(#filter0_d_2049_43228)">
<path d="M22.1043 26.6488H7.99325C7.54074 26.649 7.09261 26.5594 6.67449 26.3852C6.25636 26.211 5.87643 25.9555 5.55638 25.6334C5.23634 25.3113 4.98246 24.9288 4.80924 24.5079C4.63603 24.0869 4.54687 23.6358 4.54688 23.1801V6.90912C4.54687 6.45348 4.63603 6.00231 4.80924 5.58137C4.98246 5.16044 5.23634 4.77799 5.55638 4.45587C5.87643 4.13376 6.25636 3.87828 6.67449 3.70405C7.09261 3.52982 7.54074 3.44024 7.99325 3.44043H20.2205L25.5449 8.73726V23.1801C25.5446 24.0992 25.1821 24.9806 24.5371 25.6309C23.892 26.2812 23.0171 26.6473 22.1043 26.6488Z" fill="url(#paint0_linear_2049_43228)"/>
</g>
<path d="M21.0781 12.1216H9.74479C9.3766 12.1216 9.07812 12.4201 9.07812 12.7882V20.1216C9.07812 20.4898 9.3766 20.7882 9.74479 20.7882H21.0781C21.4463 20.7882 21.7448 20.4898 21.7448 20.1216V12.7882C21.7448 12.4201 21.4463 12.1216 21.0781 12.1216Z" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21.7422 14.4546H15.7422V18.1213H21.7422V14.4546Z" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21.7422 13.7881V18.7881" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M18.0781 12.1216C18.0781 10.4549 16.9115 10.1216 16.4115 10.1216C15.3004 10.1216 12.7781 10.1216 11.5781 10.1216C10.3781 10.1216 10.0781 11.0768 10.0781 11.5544V12.1216" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M18.5781 16.7881C18.8543 16.7881 19.0781 16.5642 19.0781 16.2881C19.0781 16.0119 18.8543 15.7881 18.5781 15.7881C18.302 15.7881 18.0781 16.0119 18.0781 16.2881C18.0781 16.5642 18.302 16.7881 18.5781 16.7881Z" fill="white"/>
<path d="M20.0195 3.44043V7.76966C20.0195 8.08702 20.1465 8.39137 20.3726 8.61577C20.5987 8.84017 20.9053 8.96624 21.2251 8.96624H25.5453V8.85939L20.0195 3.44043Z" fill="#EED2FF"/>
<defs>
<filter id="filter0_d_2049_43228" x="3.54688" y="2.44043" width="23" height="25.2085" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.74902 0 0 0 0 0.52549 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2049_43228"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2049_43228" result="shape"/>
</filter>
<linearGradient id="paint0_linear_2049_43228" x1="36.044" y1="15.0446" x2="12.9513" y2="-5.84872" gradientUnits="userSpaceOnUse">
<stop stop-color="#4C02B3"/>
<stop offset="1" stop-color="#E992FF"/>
</linearGradient>
</defs>
</svg>

79
src/components/locales/lang/en.js

@ -4,12 +4,15 @@ export default {
// Common Group (Filters, Buttons, Units)
common: {
// Filters
market: "Market",
marketPlaceholder: "Select market",
name: "Name",
none: "None",
selectedValue: "Selected Value",
pleaseInputName: "Enter name",
customerName: "Customer",
customerNamePlaceholder: "Enter customer name",
customer: "Customer",
jwcode: "Homily ID",
jwcodePlaceholder: "Enter Homily ID",
activityName: "Activity",
@ -23,8 +26,8 @@ export default {
payModelPlaceholder: "Select payment method",
refundType: "Refund Type",
refundTypePlaceholder: "Select refund type",
market: "Region",
marketPlaceholder: "Select region",
performanceByRegion: "Performance By Region",
performanceByRegionPlaceholder: "Select Performance By Region",
position: "Position",
positionPlaceholder: "Select position",
roleName: "Role",
@ -107,6 +110,7 @@ export default {
add: "Add",
addUser: "Add User",
addRole: "Add Role",
addCashFlow:"Add Cash Flow",
save: "Save",
saving: "Saving...",
addActivity: "Add Activity",
@ -202,6 +206,7 @@ export default {
refreshFailed: 'Refresh failed: {msg}',
unknownError: 'Unknown error',
refreshError: 'Refresh error, try again',
refundagain:'Refund submitted. Please do not submit again',
logoutSuccess: 'Logged out',
staffHidden: 'Staff data hidden',
staffShown: 'Staff data shown',
@ -405,6 +410,7 @@ export default {
activityLoadFailed: "Activity load failed",
activityDataLoadFailed: "Activity data error",
getDataFailed: "Get data failed",
networkError:"Network Error",
exportWalletDetailError: "Export wallet detail error",
selectCompanyWallet: "Please select company wallet",
getDetailFailed: "Get detail failed",
@ -422,6 +428,7 @@ export default {
// Common List Fields
common_list: {
marketName: "Region",
id: "No.",
originalChinese: "Chinese",
english: "English",
@ -438,6 +445,7 @@ export default {
hongKong: "Hong Kong",
companyWallet: "Company Wallet",
companyWalletPlaceholder: "Select Company Wallet",
marketPlaceholder: "Select Region",
position: "Position",
roleName: "Role",
departmentPermission: "Dept Perm",
@ -467,7 +475,11 @@ export default {
refundSuccess: "Refund Success",
refundReason: "Refund Reason",
activity: "Activity",
businessBelong: "Region",
performanceMarket: "Performance by region",
receiveArea: "Receive Area",
receiveType:"Receive Type",
paymentMethod:"Payment Method",
nums:"Number",
startTime: "Start Time",
endTime: "End Time",
status: "Status",
@ -534,6 +546,7 @@ export default {
pending: "Pending",
fee: "Fee",
transferVoucher: "Transfer IMG",
noTransferVoucher: "No Voucher",
payVoucher: "Payment IMG",
refund: "Refund",
normal: "Normal",
@ -934,6 +947,7 @@ export default {
other: "Other",
currentBalance: "Current Balance",
transactionType: "Type",
transactionCurrency: "Currency",
transactionDesc: "Desc",
transactionOrderNo: "Order No.",
transactionStatus: "Status",
@ -1292,6 +1306,65 @@ export default {
ThailandHSWallet: "Thailand HS Wallet",
VietnamHCMWallet: "VietnamHCM Wallet",
BeijingWallet: "Beijing Company Wallet"
},
cashFlow:{
otherIncome:"Other Income",
addFee:"Add Fee",
performanceMarket: "Performance Market",
performanceMarketPlaceholder: "Please select performance market",
incomeCategory: "Income Category",
incomeCategoryPlaceholder: "Please select income category",
investmentIncome:"Investment Income",
taxRefund:"Tax Refund",
governmentSubsidy:"Government Subsidy",
localIntercompany:"Local Intercompany",
corporateIntercompany:"Corporate Intercompany",
otherIncomeNon:"Other Income-Nonperformance ",
otherIncomeYes:"Other Income-Performance",
quantity: "Quantity",
quantityPlaceholder: "Please enter quantity",
payType: "Payment Method",
payTypePlaceholder: "Please select payment method",
paymentCurrency: "Payment Currency",
paymentCurrencyPlaceholder: "Please select payment currency",
paymentAmount: "Payment Amount",
paymentAmountPlaceholder: "Please enter payment amount",
paymentTime: "Payment Time",
paymentTimePlaceholder: "Select payment time",
bankHandlingFee: "Bank Handling Fee",
bankHandlingFeePlaceholder: "Please enter bank handling fee",
remarks: "Remarks",
remarksPlaceholder: "Please enter remarks (optional, limit 100 characters)",
remarkPlaceholderDate:"Need to fill in the handling fee settlement period (e.g. 'March 12, 2026 Ipay88 handling fee')",
cancel: "Cancel",
submit: "Submit",
ipay88:"Ipay88",
cardPayment:"Card Payment",
fixedProcessingFee:"Fixed Processing Fee",
settlementRegion:"Settlement Region",
Malaysia:"Malaysia",
processingFee:"Processing Fee",
processingFeePlaceholder:"Processing Fee Placeholder",
quantityMustBeNumber:"Quantity Must Be Number",
invalidFormat:"Invalid amount format. Maximum 2 decimal places allowed.",
paymentMust:"Payment amount must be 0",
remarksexceed:"Please enter remarks",
marketConsumption:"Market Consumption Gold Performance Adjustment",
time:"Select Time",
coefficient:"Coefficient Adjustment",
coefficientPlaceholder:"Please enter coefficient adjustment",
adjustment:"Transfer In",
adjustmentOut:"Transfer Out",
marketTeam:"Market Team",
total:"Total",
performanceAdjustment:"Performance Adjustment",
payTime:"Payment Time",
orderCode:"System Transaction No.",
receivedMarketName:"Received Market",
performanceMarket:"Performance Market",
goodsName:"Income Category",
goodNum:"Quantity",
payType:"Payment Method",
}
},

116
src/components/locales/lang/zh-CN.js

@ -4,12 +4,15 @@ export default {
// 通用组 (筛选,按钮,币种计量)
common: {
// 筛选
market:'所属地区',
marketPlaceholder:'请选择所属地区',
name: "姓名",
none: "无",
selectedValue: "当前选中",
pleaseInputName: "请输入姓名",
customerName: "客户姓名",
customerNamePlaceholder: "请输入客户姓名",
customer: "客户",
jwcode: "精网号",
jwcodePlaceholder: "请输入精网号",
activityName: "活动名称",
@ -23,8 +26,8 @@ export default {
payModelPlaceholder: "请选择支付方式",
refundType: "退款类型",
refundTypePlaceholder: "请选择退款类型",
market: "所属地区",
marketPlaceholder: "请选择所属地区",
performanceByRegion: "业绩归属地区",
performanceByRegionPlaceholder: "请选择业绩归属地区",
position: "职位名称",
positionPlaceholder: "请选择职位名称",
roleName: "角色名称",
@ -107,6 +110,7 @@ export default {
add: "添加",
addUser: "新增用户",
addRole: "新增角色",
addCashFlow: "新增流水",
save: "保存",
saving: "保存中...",
addActivity: "新增活动",
@ -172,7 +176,7 @@ export default {
all: "全部",
unknownSubmitter: "未知提交人",
noAuditorRecorded: "未记录审核人",
noExecutorRecorded: "未记录执行人"
noExecutorRecorded: "未记录执行人",
},
// 权限模块
@ -182,10 +186,11 @@ export default {
changeRoleConfirmContent1: "确认修改权限角色?<br>您正在将【",
changeRoleConfirmContent2: "】的权限角色从【",
changeRoleConfirmContent3: "】修改为【",
changeRoleConfirmContent4: "】<br>变更后,该用户的可操作权限将同步更新为新角色配置,涉及数据访问、功能操作等权限变化,请谨慎确认。",
changeRoleConfirmContent4:
"】<br>变更后,该用户的可操作权限将同步更新为新角色配置,涉及数据访问、功能操作等权限变化,请谨慎确认。",
changeRoleSuccessContent1: "用户",
changeRoleSuccessContent2: "的权限角色已更改为【",
roleRegionNote: "此地区无实际意义,仅用于各分部负责人查看其地区角色"
roleRegionNote: "此地区无实际意义,仅用于各分部负责人查看其地区角色",
},
// 提示信息组
elmessage: {
@ -208,6 +213,7 @@ export default {
jumpSuccess: "跳转成功",
jumpFailed: "跳转失败",
refundFailed: "退款失败",
refundagain:"已提交退款,请勿重复提交",
oldPasswordError: "原密码错误,请重新输入",
addSuccess: "添加成功", // 大写是添加成功,小写是新增
addsuccess: "新增成功",
@ -406,6 +412,7 @@ export default {
activityLoadFailed: "活动列表加载失败,请稍后重试",
activityDataLoadFailed: "活动数据加载异常,请稍后重试",
getDataFailed: "获取数据失败",
networkError: "网络错误",
exportWalletDetailError: "导出钱包明细出错",
selectCompanyWallet: "请选择公司钱包",
// 权限
@ -422,6 +429,7 @@ export default {
// 通用列表字段组
common_list: {
marketName: "所属地区",
id: "序号",
originalChinese: "原始中文",
english: "英文",
@ -438,6 +446,7 @@ export default {
hongKong: "香港",
companyWallet: "公司钱包",
companyWalletPlaceholder: "请选择公司钱包",
marketPlaceholder: "请选择所属地区",
position: "职位",
roleName: "角色名称",
departmentPermission: "部门权限",
@ -467,7 +476,11 @@ export default {
refundSuccess: "退款成功",
refundReason: "退款理由",
activity: "活动名称",
businessBelong: "业绩归属地",
receiveArea: "到账地区",
performanceMarket: "业绩归属地区",
receiveType: "收入类别",
paymentMethod: "付款方式",
nums: "个数",
startTime: "开始时间",
endTime: "结束时间",
status: "状态",
@ -534,13 +547,14 @@ export default {
pending: "待处理",
fee: "手续费",
transferVoucher: "转账凭证",
noTransferVoucher: "无转账凭证",
payVoucher: "支付凭证",
refund: "退款",
normal: "正常",
activityStatus: {
notStarted: "未开始",
inProgress: "进行中",
ended: "已结束"
ended: "已结束",
},
operation: "操作",
configTime: "配置时间",
@ -688,7 +702,7 @@ export default {
similarCosumeRecords: "检测到该用户近期有相似消耗记录",
rechargePermanentGold: "充值永久金币",
buy: "购买",
orderStatus:'订单状态',
orderStatus: "订单状态",
operator: "操作人",
submitter: "提交人",
continueOperation: "是否继续操作?",
@ -941,9 +955,10 @@ export default {
other: "其他",
currentBalance: "当前余额",
transactionType: "交易类型",
transactionCurrency: "交易币种",
transactionDesc: "交易说明",
transactionOrderNo: "交易单号",
transactionStatus: "交易状态",
transactionStatus: "状态",
exceptionData: "异常数据",
time: "时间",
market: {
@ -1058,8 +1073,8 @@ export default {
placeholder: "请选择语言",
options: {
zhCN: "中文(简体)",
en: "English"
}
en: "English",
},
},
showStaffData: "显示员工数据",
hideStaffData: "隐藏员工数据",
@ -1094,7 +1109,7 @@ export default {
againPasswordPlaceholder: "请再次输入新密码",
tips: {
lengthAndChars: "密码由8-16位数字、字母或符号组成",
complexity: "至少含2种以上字符"
complexity: "至少含2种以上字符",
},
rules: {
allowedChars: "密码只能包含数字、字母或符号",
@ -1103,15 +1118,15 @@ export default {
complexity: "密码至少包含两种类型(数字、字母或符号)",
notMatch: "两次输入密码不一致",
newPasswordRequired: "新密码不能为空",
againPasswordRequired: "请再次输入新密码"
againPasswordRequired: "请再次输入新密码",
},
submitting: "修改中..."
submitting: "修改中...",
},
difftime: {
minuteAgo: "分钟前",
hourAgo: "小时前",
yesterday: "昨天",
}
},
},
// 现金管理
@ -1151,9 +1166,9 @@ export default {
paymentAsia: "PaymentAsia",
transfer: "E-Transfer",
iotPay: "IOT Pay",
stripe3:'Stripe3',
paysolution:'paysolution',
stripe2:'Stripe2',
stripe3: "Stripe3",
paysolution: "paysolution",
stripe2: "Stripe2",
},
statusList: {
submitted: "已提交",
@ -1302,7 +1317,7 @@ export default {
refundConfirmTitle: "退款确认",
refundConfirmContent: "确定要对订单 {orderNo} 进行退款吗?",
//钱包
wallet:{
wallet: {
HongKongWallet: "香港钱包",
MalaysiaWallet: "马来西亚钱包",
CanadaWallet: "加拿大钱包",
@ -1311,8 +1326,67 @@ export default {
ThailandHAWallet: "泰国HA钱包",
ThailandHSWallet: "泰国HS钱包",
VietnamHCMWallet: "越南钱包",
BeijingWallet: "北京公司钱包"
}
BeijingWallet: "北京公司钱包",
},
cashFlow: {
otherIncome:"其他收入",
addFee:"手续费补充",
performanceMarket:"业绩归属地区",
performanceMarketPlaceholder:"请选择业绩归属地区",
incomeCategory:"收入类别",
incomeCategoryPlaceholder:"请选择收入类别",
investmentIncome:"理财收入",
taxRefund:"退税",
governmentSubsidy:"政府补贴",
localIntercompany:"本地往来",
corporateIntercompany:"公司往来",
otherIncomeNon:"其他收入-非业绩",
otherIncomeYes:"其他收入-算业绩",
quantity:"个数",
quantityPlaceholder:"请输入个数",
payType:"付款方式",
payTypePlaceholder:"请选择付款方式",
paymentCurrency:"币种",
paymentCurrencyPlaceholder:"请选择币种",
paymentAmount:"付款金额",
paymentAmountPlaceholder:"请输入付款金额",
paymentTime:"付款时间",
paymentTimePlaceholder:"选择付款时间",
bankHandlingFee:"银行手续费",
bankHandlingFeePlaceholder:"请输入银行手续费",
remarks:"备注",
remarksPlaceholder:"请输入备注 (选填,限制100字)",
remarkPlaceholderDate:"需填写手续费结算周期(如“2026年3月12日Ipay88手续费”)",
cancel: "取消",
submit: "提交",
ipay88: "Ipay88",
cardPayment: "刷卡",
fixedProcessingFee: "固定手续费",
settlementRegion: "到账地区",
Malaysia: "马来西亚",
processingFee: "手续费",
processingFeePlaceholder: "请输入手续费",
quantityMustBeNumber: "个数必须为数字",
invalidFormat: "金额格式不正确,最多两位小数",
paymentMust: "付款金额必须为0",
remarksexceed: "请输入备注",
marketConsumption: "市场消耗金币业绩调整",
time: "选择时间",
coefficient: "系数调整",
coefficientPlaceholder: "请输入系数调整",
adjustment: "调入",
adjustmentOut: "调出",
marketTeam: "市场团队",
total: "合计",
performanceAdjustment: "业绩调整",
payTime: "付款时间",
orderCode: "系统交易号",
receivedMarketName: "到账地区",
performanceMarket: "业绩归属地区",
goodsName: "收入类别",
goodNum: "个数",
payType: "付款方式",
},
},
// 消息

50
src/components/workspace/CashManagement.vue

@ -17,9 +17,9 @@
<el-icon
class="service-icon"
style="
margin-left: 5px;
margin-left: .2604vw;
cursor: pointer;
font-size: 16px;
font-size: .8333vw;
transition: all 0.3s ease;">
<Warning/>
</el-icon>
@ -270,12 +270,12 @@ onMounted( async() => {
<style scoped>
/* 保留你原来的样式 */
.cash-management {
margin: 10px 5px;
margin: .5208vw .2604vw;
width: 100%;
height: 550px;
border-radius: 8px;
height: 28.6458vw;
border-radius: .4167vw;
background: #E7F4FD;
box-shadow: 0 2px 2px 0 #00000040;
box-shadow: 0 .1042vw .1042vw 0 #00000040;
display: flex;
flex-direction: column;
align-items: center;
@ -285,9 +285,9 @@ onMounted( async() => {
width: 100%;
height: 5vh;
flex-shrink: 0;
border-radius: 8px;
border-radius: .4167vw;
background: linear-gradient(90deg, #E4F0FC 0%, #C6ADFF 50%, #E4F0FC 100%);
box-shadow: 0 2px 2px 0 #00152940;
box-shadow: 0 .1042vw .1042vw 0 #00152940;
display: flex;
align-items: center;
justify-content: center;
@ -296,25 +296,25 @@ onMounted( async() => {
.text1 {
color: #040a2d;
font-family: "PingFang SC";
font-size: 28px;
font-size: 1.4583vw;
font-weight: 900;
}
.text1-update-time {
margin-left: 10px;
margin-left: .5208vw;
color: #040a2d;
font-size: 20px;
font-size: 1.0417vw;
font-weight: 700;
}
.text2 {
margin: 13px;
margin: .6771vw;
width: 95%;
height: 10vh;
border-radius: 8px;
border-radius: .4167vw;
background: linear-gradient(90deg, #E4F0FC 0%, #C1DCF8 50%, #E4F0FC 100%);
box-shadow: 0 2px 2px 0 #00152940;
box-shadow: 0 .1042vw .1042vw 0 #00152940;
display: flex;
align-items: center;
justify-content: center;
@ -322,7 +322,7 @@ onMounted( async() => {
.text2-income {
color: #040a2d;
font-size: 40px;
font-size: 2.0833vw;
font-weight: 900;
}
@ -331,17 +331,17 @@ onMounted( async() => {
align-items: center;
width: 100%;
height: 100%;
padding: 10px;
padding: .5208vw;
}
.market-data {
display: flex;
width: 265px;
width: 13.8021vw;
flex-direction: column;
align-items: flex-start;
gap: 20px;
padding: 10px;
margin-left: 20px;
gap: 1.0417vw;
padding: .5208vw;
margin-left: 1.0417vw;
}
.market-item {
@ -349,18 +349,18 @@ onMounted( async() => {
justify-content: space-between;
width: 100%;
font-family: "PingFang SC";
font-size: 16px;
font-size: .8333vw;
color: #040a2d;
white-space: nowrap; /* 禁止换行 */
overflow: hidden; /* 隐藏溢出内容 */
text-overflow: ellipsis; /* 溢出显示省略号 */
margin-bottom: 8px; /* 增加项间距,提升可读性 */
margin-bottom: .4167vw; /* 增加项间距,提升可读性 */
cursor: pointer;
}
.market-name {
flex: 0 0 auto; /* 名称部分自适应宽度 */
margin-right: 16px; /* 与金额保持距离 */
margin-right: .8333vw; /* 与金额保持距离 */
}
.market-value {
@ -370,9 +370,9 @@ onMounted( async() => {
.chart {
flex: 1;
height: 300px;
height: 15.625vw;
width: auto;
margin-top: 10px;
margin-top: .5208vw;
}
</style>

114
src/components/workspace/GoldManagement.vue

@ -20,13 +20,13 @@
}}</span>&nbsp;&nbsp;&nbsp;&nbsp;{{ t('workbench.compareToPreviousDay') }}
{{ dailyChange / 100 }}&nbsp;
<template v-if="dailyChange > 0">
<el-image :src="upArrow" style="width: 14px;"/>
<el-image :src="upArrow" style="width: .7292vw;"/>
</template>
<template v-else-if="dailyChange < 0">
<el-image :src="downArrow" style="width: 14px;"/>
<el-image :src="downArrow" style="width: .7292vw;"/>
</template>
<template v-else>
<el-image :src="pingArrow" style="width: 14px; padding-top: 12px"/>
<el-image :src="pingArrow" style="width: .7292vw; padding-top: .625vw"/>
</template>
</div>
<div>
@ -50,8 +50,8 @@
</el-col>
<!-- 右边图表 -->
<el-col :span="12">
<!-- <div ref="goldTypeChart" style="width: 100%; height: 100px;"></div>-->
<div style="width: 100%; height: 60px;">&nbsp;</div>
<!-- <div ref="goldTypeChart" style="width: 100%; height: 5.2083vw;"></div>-->
<div style="width: 100%; height: 3.125vw;">&nbsp;</div>
<div class="margin-bottom">
[{{ t('workbench.goldExpireIn12Months')}}{{ currentFreeDecember / 100 }}]
</div>
@ -68,12 +68,12 @@
<el-row>
<el-col :span="12">
<div class="center-card">{{ t('workbench.convertedSGDCumulativeAmount') }}</div>
<el-image :src="svg1" style="width: 88px; display: block;margin: 0 auto;"/>
<el-image :src="svg1" style="width: 4.5833vw; display: block;margin: 0 auto;"/>
<div class="center-card">{{ yearlyMoney / 100 }}{{ t('workbench.SGD') }}</div>
</el-col>
<el-col :span="12" style="border-left: 2px solid #CFE6FE; height: 160px">
<el-col :span="12" style="border-left: .1042vw solid #CFE6FE; height: 8.3333vw">
<div class="center-card" style="white-space: nowrap;">{{ t('workbench.yesterdayNew')}}{{ recharge / 100 }}</div>
<div ref="rechargeGoldChart" style="width: 88px; height: 88px; display: block;margin: 0 auto;"></div>
<div ref="rechargeGoldChart" style="width: 4.5833vw; height: 4.5833vw; display: block;margin: 0 auto;"></div>
<div class="center-card" style="white-space: nowrap;">{{ t('workbench.wherePermanentGold')}}{{ money / 100 }}</div>
</el-col>
</el-row>
@ -87,7 +87,7 @@
<!-- 第三个卡片 -->
<div class="card-item">
<div class="card-title">{{ t('workbench.annualCumulativeConsume')}}{{ yearlyReduce / 100 }}</div>
<el-row style="height: 200px;">
<el-row style="height: 10.4167vw;">
<el-col :span="12">
<div ref="consumeChart" style="width:100%; height: 88%;"></div>
</el-col>
@ -101,21 +101,21 @@
<!-- 第四个卡片 -->
<div class="card-item" >
<div class="card-title">{{ t('workbench.annualCumulativeRechargePeople')}}{{ yearlyRechargeNum }}</div>
<el-row style="height: 200px;">
<el-col :span="12" style="border-right: 2px solid #CFE6FE; height: 200px">
<el-row style="height: 10.4167vw;">
<el-col :span="12" style="border-right: .1042vw solid #CFE6FE; height: 10.4167vw">
<div class="chart5">
<el-image :src="svg2" style="width: 88px; display: block;margin: 0 auto;"/>
<el-image :src="svg2" style="width: 4.5833vw; display: block;margin: 0 auto;"/>
<div class="margin-bottom">
<div style="display: flex; gap: 10px; font-size: 16px;">{{ t('workbench.weekYearOnYear')}}{{ sumWow }}%
<el-image v-if="sumWow > 0" :src="upArrow" style="width: 10px;"/>
<el-image v-else-if="sumWow < 0" :src="downArrow" style="width: 10px;"/>
<el-image v-else :src="pingArrow" style="width: 10px;"/>
<div style="display: flex; gap: .5208vw; font-size: .8333vw;">{{ t('workbench.weekYearOnYear')}}{{ sumWow }}%
<el-image v-if="sumWow > 0" :src="upArrow" style="width: .5208vw;"/>
<el-image v-else-if="sumWow < 0" :src="downArrow" style="width: .5208vw;"/>
<el-image v-else :src="pingArrow" style="width: .5208vw;"/>
</div>
<div style="display: flex; gap: 10px; font-size: 16px;">
<div style="display: flex; gap: .5208vw; font-size: .8333vw;">
{{ t('workbench.dayYearOnYear')}}{{ sumDaily }}%
<el-image v-if="sumDaily > 0" :src="upArrow" style="width: 10px;"/>
<el-image v-else-if="sumDaily < 0" :src="downArrow" style="width: 10px;"/>
<el-image v-else :src="pingArrow" style="width: 10px; "/>
<el-image v-if="sumDaily > 0" :src="upArrow" style="width: .5208vw;"/>
<el-image v-else-if="sumDaily < 0" :src="downArrow" style="width: .5208vw;"/>
<el-image v-else :src="pingArrow" style="width: .5208vw; "/>
</div>
</div>
@ -570,46 +570,46 @@ onMounted(async () => {
}
.card-item-row1 {
height: 200px;
height: 10.4167vw;
width: auto;
background: #E4F0FC;
box-shadow: 0 0 4px 0 #00000040;
border-radius: 10px;
margin-top: 20px;
margin-left: 5px;
margin-right: 5px;
margin-bottom: -5px;
padding-bottom: 10px;
box-shadow: 0 0 .2083vw 0 #00000040;
border-radius: .5208vw;
margin-top: 1.0417vw;
margin-left: .2604vw;
margin-right: .2604vw;
margin-bottom: -0.2604vw;
padding-bottom: .5208vw;
}
.card-item {
height: 240px;
height: 12.5vw;
width: auto;
background: #E4F0FC;
box-shadow: 0 0 4px 0 #00000040;
border-radius: 10px;
margin-top: 20px;
margin-left: 5px;
margin-right: 5px;
margin-bottom: -5px;
padding-bottom: 10px;
box-shadow: 0 0 .2083vw 0 #00000040;
border-radius: .5208vw;
margin-top: 1.0417vw;
margin-left: .2604vw;
margin-right: .2604vw;
margin-bottom: -0.2604vw;
padding-bottom: .5208vw;
}
.card-title {
font-weight: bold;
height: 36px;
font-size: 17px;
height: 1.875vw;
font-size: .8854vw;
width: 100%;
flex-shrink: 0;
border-radius: 8px;
border-radius: .4167vw;
background: linear-gradient(90deg, #E4F0FC 0%, #C1DCF8 50%, #E4F0FC 100%);
box-shadow: 0 0 2px 0 #00152940;
box-shadow: 0 0 .1042vw 0 #00152940;
display: flex;
align-items: center;
justify-content: center;
margin-top: -5px;
margin-bottom: 10px;
margin-top: -0.2604vw;
margin-bottom: .5208vw;
}
.card-item .el-col {
@ -631,9 +631,9 @@ onMounted(async () => {
width: 100%;
height: 5vh;
flex-shrink: 0;
border-radius: 8px;
border-radius: .4167vw;
background: linear-gradient(90deg, #E4F0FC 0%, #FFF178 50%, #E4F0FC 100%);
box-shadow: 0 2px 2px 0 #00152940;
box-shadow: 0 .1042vw .1042vw 0 #00152940;
display: flex;
align-items: center;
justify-content: center;
@ -642,47 +642,47 @@ onMounted(async () => {
.text1 {
color: #040a2d;
font-family: " PingFang SC ";
font-size: 28px;
font-size: 1.4583vw;
font-style: normal;
font-weight: 900;
line-height: 31.79px;
line-height: 1.6557vw;
}
.text1-update-time {
width: 100%;
height: 26px;
height: 1.3542vw;
flex-shrink: 0;
color: #040a2d;
font-family: "PingFang SC";
font-size: 20px;
font-size: 1.0417vw;
font-style: normal;
font-weight: 700;
line-height: 31.79px;
line-height: 1.6557vw;
}
/* 背景卡片大小 */
.gold-management {
margin: 10px 5px;
margin: .5208vw .2604vw;
width: 100%;
height: 550px;
height: 28.6458vw;
flex-shrink: 0;
border-radius: 8px;
border-radius: .4167vw;
background: #E7F4FD;
box-shadow: 0 2px 2px 0 #00000040;
box-shadow: 0 .1042vw .1042vw 0 #00000040;
flex-direction: column;
align-items: center;
}
.margin-bottom {
padding-left: 20px;
padding-left: 1.0417vw;
}
.chart5 {
margin-top: 15px;
margin-top: .7813vw;
.margin-bottom {
margin-top: 10px;
padding-left: 20px;
margin-top: .5208vw;
padding-left: 1.0417vw;
}
}
</style>

90
src/router/index.js

@ -413,6 +413,92 @@ const routes = [
}
]
},
// 钱包管理
{
path: 'walletManage',
name: 'walletManage',
meta: {permissionId: 150},
children: [
// 钱包余额
{
path: 'walletBalance',
name: "walletBalance",
component: () => import("../views/walletManage/WalletBalance.vue"),
meta: {permissionId: 151}
},
// 钱包明细
{
path: 'walletDetail',
name: "walletDetail",
meta: {permissionId: 152},
children: [
// 香港钱包
{
path: 'hkWallet',
name: "hkWallet",
component: () => import("../views/walletManage/walletDetail/HKWallet.vue"),
meta: {permissionId: 153}
},
//新加坡HC钱包
{
path: 'sgWalletHC',
name: "sgWalletHC",
component: () => import("../views/walletManage/walletDetail/SGWalletHC.vue"),
meta: {permissionId: 154}
},
//马来钱包
{
path: 'myWallet',
name: "myWallet",
component: () => import("../views/walletManage/walletDetail/MyWallet.vue"),
meta: {permissionId: 155}
},
// 新加坡CM钱包
{
path: 'sgWalletCM',
name: "sgWalletCM",
component: () => import("../views/walletManage/walletDetail/SGWalletCM.vue"),
meta: {permissionId: 156}
},
// 加拿大钱包
{
path: 'caWallet',
name: "caWallet",
component: () => import("../views/walletManage/walletDetail/CAWallet.vue"),
meta: {permissionId: 157}
},
//泰国HS钱包
{
path: 'thWalletHS',
name: "thWalletHS",
component: () => import("../views/walletManage/walletDetail/THWalletHS.vue"),
meta: {permissionId: 158}
},
//泰国HA钱包
{
path: 'thWalletHA',
name: "thWalletHA",
component: () => import("../views/walletManage/walletDetail/THWalletHA.vue"),
meta: {permissionId: 159}
},
//越南钱包
{
path: 'vnWallet',
name: "vnWallet",
component: () => import("../views/walletManage/walletDetail/VNWallet.vue"),
meta: {permissionId: 160}
},
//北京钱包
{
path: 'bjWallet',
name: "bjWallet",
component: () => import("../views/walletManage/walletDetail/BJWallet.vue"),
meta: {permissionId: 161}
},
]
},
]
},
// 频道管理
{
path: 'channelManage',
@ -542,8 +628,8 @@ router.beforeEach(async (to, from, next) => {
const requiresPermission = to.meta && to.meta.permissionId;
if (requiresPermission) {
const hasPermission = Array.isArray(requiresPermission)
? requiresPermission.some(id => userPermissionIds.includes(id))
: userPermissionIds.includes(requiresPermission);
? requiresPermission.some(id => userPermissionIds.some(uid => String(uid) === String(id)))
: userPermissionIds.some(uid => String(uid) === String(requiresPermission));
if (!hasPermission) {
next('/noPermission');

0
src/static/common.js

3
src/utils/menuTreePermission.js

@ -175,6 +175,9 @@ export const permissionMapping = {
financial_accounting: 147, // 财务核算
cash_flow_ledger: 148, // 资金流水账
performance_attribution_accounting: 149, // 业绩归属台账
new_transaction_flow: 162, // 新增流水
performance_adjustment: 163, // 业绩调整
}
// 递归查找菜单中是否存在目标id

17
src/utils/menuUtils.js

@ -7,7 +7,8 @@ export function filterMenu(menuList) {
...menu,
children: menu.children ? filterMenu(menu.children) : []
}))
.sort((a, b) => a.id - b.id); // 按 id 升序
// 按 id 升序
// .sort((a, b) => a.id - b.id);
}
// 过滤 只获得第三级的菜单
@ -86,7 +87,19 @@ export const getRoutePath = (menu) => {
"149": "/moneyManage/financialAccount/performanceAttribution", // 业绩归属账(财务核算子菜单)
"125": "/channelManage/reward", // 打赏管理(频道管理子菜单)
"126": "/channelManage/fans", // 铁粉管理(频道管理子菜单)
"127": "/channelManage/cart" // 小黄车管理(频道管理子菜单)
"127": "/channelManage/cart", // 小黄车管理(频道管理子菜单)
"150": "/walletManage", // 钱包管理
"151": "/walletManage/walletBalance", // 钱包余额
"152": "/walletManage/walletDetail", // 钱包明细
"153": "/walletManage/walletDetail/hkWallet", // 香港钱包
"154": "/walletManage/walletDetail/sgWalletHC", // 新加坡HC钱包
"156": "/walletManage/walletDetail/sgWalletCM", // 新加坡CM钱包
"155": "/walletManage/walletDetail/myWallet", // 马来西亚钱包
"157": "/walletManage/walletDetail/caWallet", // 加拿大钱包
"158": "/walletManage/walletDetail/thWalletHS", // 泰国HS钱包
"159": "/walletManage/walletDetail/thWalletHA", // 泰国HA钱包
"160": "/walletManage/walletDetail/vnWallet", // 越南钱包
"161": "/walletManage/walletDetail/bjWallet" // 北京钱包
};
// 从映射表中匹配路由,无匹配时返回无权限页面路径

6
src/views/activityManage/activity.vue

@ -45,7 +45,7 @@
</template>
</el-table-column>
<el-table-column prop="activityName" :label="t('common_list.activity')" width="150px" show-overflow-tooltip />
<el-table-column prop="businessBelong" :label="t('common_list.businessBelong')" width="150px" />
<el-table-column prop="businessBelong" :label="t('common_add.businessBelong')" width="150px" />
<el-table-column prop="areaName" :label="t('common_list.market')" width="150px" />
<el-table-column prop="startTime" :label="t('common_list.startTime')" width="200px">
<template #default="scope">
@ -67,8 +67,8 @@
<el-table-column prop="creatorName" :label="t('common_list.creator')" width="150px" />
<el-table-column prop="operation" :label="t('common_list.operation')" width="220px">
<template #default="scope">
<el-button type="primary" text @click="editOpen(scope.row)">{{ t('common.edit') }}</el-button>
<!-- <el-button type="danger" text @click="openDel(scope.row)">删除</el-button> -->
<!-- <el-button type="primary" text @click="editOpen(scope.row)">{{ t('common.edit') }}</el-button> -->
<el-button type="danger" text @click="openDel(scope.row)">{{t('common.delete')}}</el-button>
</template>
</el-table-column>
</el-table>

1
src/views/home.vue

@ -33,6 +33,7 @@ const menuNameMap = {
'124': 'channel-management', //
'128': 'permission-management', //
'146': 'mutiple-language', //
'150': 'wallet_management', //
}
const getIconPath = (menuNameId) => {

7
src/views/moneyManage/executor/executor.vue

@ -423,7 +423,7 @@ const submitRefund = async function () {
refundTime: editForm.value.refundTime ? dayjs(editForm.value.refundTime).format('YYYY-MM-DD HH:mm:ss') : "",
refundRemark: editForm.value.refundRemark,
id: editRow.value.id,
refundCurrency: editForm.value.refundCurrency,
refundCurrency: CurrencyForId(editForm.value.refundCurrency),
refundAmount: editForm.value.refundAmount,
refundChannels: editForm.value.refundChannels,
status: 41,
@ -515,6 +515,7 @@ const channelOptions = ref([
t('cash.payMethods.transfer'),
t('cash.payMethods.iotPay'),
t('cash.payMethods.stripe3'),
t('cash.payMethods.stripe2'),
t('cash.payMethods.paypal'),
])
@ -633,9 +634,9 @@ const customUpload = async (options) => {
})
if (response.code === 200 && response.data) {
editForm.value.imageUrl = response.data.url
ElMessage.success(response.msg || t('elmessage.uploadSuccess'))
ElMessage.success( t('elmessage.uploadSuccess'))
} else {
ElMessage.error(response.msg || t('elmessage.uploadFailed'))
ElMessage.error( t('elmessage.uploadFailed'))
}
} catch (error) {
console.error('上传错误:', error)

753
src/views/moneyManage/financialAccount/cashFlow.vue

@ -1,5 +1,5 @@
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue'
import { ref, reactive, onMounted, nextTick, toRaw } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/util/http.js'
@ -9,10 +9,14 @@ import { Moneyfunds, refundOnline, exportFunds } from '@/api/cash/financialAccou
import { useAdminStore } from '@/store/index.js'
import { storeToRefs } from 'pinia'
import _ from 'lodash';
import { normalizePayType } from '@/views/moneyManage/receiveDetail/utils/staticData.js'
import { normalizePayType,MarketNameForId, CurrencyForId, } from '@/views/moneyManage/receiveDetail/utils/staticData.js'
import { isTemplate } from 'element-plus/es/utils/index.mjs'
import { Row } from 'vxe-pc-ui'
import CashManagement from '@/components/workspace/CashManagement.vue'
import { permissionMapping, hasMenuPermission } from "@/utils/menuTreePermission.js"
const adminStore = useAdminStore()
const { adminData } = storeToRefs(adminStore)
const { adminData, menuTree,flag } = storeToRefs(adminStore)
const { t } = useI18n()
const route = useRoute()
@ -35,12 +39,30 @@ const paytypeList = [
t('cash.payMethods.check'), //
]
//
const hasNewTransactionFlow = ref(false)
//
const initPermissions = async () => {
if (!menuTree.value || !menuTree.value.length) return;
//
hasNewTransactionFlow.value = hasMenuPermission(menuTree.value, permissionMapping.new_transaction_flow);
};
const payPlatformOptions = ref([...paytypeList])
const statusOptions = [
{ label: t('common_list.received'), value: 4 },
{ label: t('common_list.refunded'), value: 6 }
]
const marketFilter = (value) => {
const map = {
4: t('cash.markets.Singapore'),
5: t('cash.markets.Malaysia'),
13:t('cash.markets.HongKong'),
24016: t('cash.markets.Canada'),
24018:t('cash.markets.Thailand'),
24022:t('cash.markets.VietnamHCM'),
24033:t('cash.markets.Beijing'),
};
return map[value] || '-';
};
//
const marketOptions = ref([])
@ -49,12 +71,13 @@ const marketOptions = ref([])
const queryParams = reactive({
jwcode: '',
markets: [], //
performanceMarkets:[],
timeRange: [], // [startTime, endTime]
payType: '',
orderCode: '',
statuses: [],
pageNum: 1,
pageSize: 20
pageSize: 20,
platformSelection: []
})
const total = ref(0)
@ -104,28 +127,96 @@ const formatStatuses = (statuses) => {
// 3
return statuses;
};
const performanceMarket = ref([
t('cash.markets.Malaysia'), // 西
t('cash.markets.HongKong'), //
t('cash.markets.Singapore'), //
t('cash.markets.Thailand'), //
t('cash.markets.VietnamHCM'), // HCM
t('cash.markets.Canada'), //
t('cash.markets.Beijing') //
])
const getPayPlatformOptions = async () => {
try {
const res = await request({
url: '/market/getAreaPayTypeTree',
method: 'POST'
})
if (res.code === 200) {
payPlatformOptionsList.value = res.data
console.log('支付平台数据加载成功:', payPlatformOptionsList.value)
} else {
ElMessage.error(res.msg || t('elmessage.getDataFailed'))
}
} catch (error) {
console.error('请求支付平台数据出错:', error)
ElMessage.error(t('elmessage.networkError'))
}
}
//
const fetchData = async () => {
loading.value = true
try {
//
//areaPayTypeList
const areaPayTypeList = [];
const options = toRaw(payPlatformOptionsList.value);
const selectedPaths = queryParams.platformSelection;
if (selectedPaths.length > 0 && options.length > 0) {
selectedPaths.forEach(path => {
const areaId = path[0];
const payMethodId = path[path.length - 1];
if (path.length === 1) {
const countryNode = options.find(c => c.id === areaId);
if (countryNode && countryNode.children) {
countryNode.children.forEach(child => {
areaPayTypeList.push({
areaId: areaId,
payType: child.name
});
});
}
}
else {
const countryNode = options.find(c => c.id === areaId);
if (countryNode && countryNode.children) {
const methodNode = countryNode.children.find(m => m.id === payMethodId);
if (methodNode) {
areaPayTypeList.push({
areaId: areaId,
payType: methodNode.name
});
}
}
}
});
}
//performanceMarket
let performanceMarkets = [];
const selectedNames = queryParams.performanceMarket;
if (Array.isArray(selectedNames) && selectedNames.length > 0) {
performanceMarkets = selectedNames
.map(name => {
if (!name) return null;
const id = MarketNameForId(name);
return id;
})
.filter(id => id !== null && id !== 'null'); //
}
const params = {
pageNum: queryParams.pageNum,
pageSize: queryParams.pageSize,
fundsDTO: {
jwcode: queryParams.jwcode,
localMarket: queryParams.markets,
performanceMarkets:performanceMarkets,
areaPayTypeList: areaPayTypeList,
startTime: queryParams.timeRange?.[0] ? dayjs(queryParams.timeRange[0]).format('YYYY-MM-DD HH:mm:ss') : '',
endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '',
payType: normalizePayType(queryParams.payType || ''),
orderCode: queryParams.orderCode,
statuses: formatStatuses(queryParams.statuses),
markets: [],
}
}
console.log('查询参数:', params)
const res = await Moneyfunds(params)
if (res.code == 200) {
@ -152,11 +243,11 @@ const handleSearch = () => {
const handleReset = () => {
queryParams.jwcode = ''
queryParams.markets = []
queryParams.performanceMarket = ''
queryParams.timeRange = null
queryParams.payType = ''
queryParams.orderCode = ''
queryParams.statuses = []
queryParams.platformSelection=[]
handleSearch()
}
@ -171,22 +262,21 @@ const handleCurrentChange = (val) => {
}
// 退
const openRefundConfirm = (row) => {
const openRefundConfirm = () => {
showDetail.value=false
textContent.value = t('common.willRefundOrder') + '?'
refundConfirmDialog.value = true
refundFormData.value = {
...row,
oldpermanentGold: row.permanentGold || row.gold || 0,//退
oldfreeGold: row.freeGold || row.free || 0,//退
...formDataRow.value,
oldpermanentGold: formDataRow.value.permanentGold || formDataRow.value.gold || 0,//退
oldfreeGold: formDataRow.value.freeGold || formDataRow.value.free || 0,//退
permanentGold: null,
freeGold: null,
}
console.log(row);
}
const openRefundDialog = () => {
refundDialog.value = true
closeConfirmRefund()
}
const closeConfirmRefund = () => {
@ -197,8 +287,6 @@ const refundConfirmDialog = ref(false)
const textContent = ref('')
const refundDialog = ref(false)
const refundFormData = ref({})
const resetRefund = () => {
refundFormData.value.refundModel = ''
refundFormData.value.refundReason = ''
@ -208,6 +296,10 @@ const resetRefund = () => {
}
const handleRefund = async () => {
try {
if(refundFormData.value.status == 6){
ElMessage.error(t('elmessage.refundagain'))
return
}
if (refundFormData.value.refundModel == 1) {
if (Number(refundFormData.value.permanentGold || 0) > Number(refundFormData.value.oldpermanentGold || 0)) {
ElMessage.error(t('elmessage.limitRefundGoldNotExceedOriginal'))
@ -244,6 +336,7 @@ const handleRefund = async () => {
const res = await refundOnline(params)
if (res.code == 200) {
ElMessage.success(t('elmessage.submitSuccess'))
refundDialog.value = false
fetchData()
} else {
@ -254,6 +347,10 @@ const handleRefund = async () => {
}
}
const payPlatformOptionsList = ref([])
// ==================== ====================
const exportListVisible = ref(false)
@ -276,6 +373,17 @@ const handleExport = async () => {
return statuses;
};
try {
let performanceMarkets = [];
const selectedNames = queryParams.performanceMarket;
if (Array.isArray(selectedNames) && selectedNames.length > 0) {
performanceMarkets = selectedNames
.map(name => {
if (!name) return null;
const id = MarketNameForId(name);
return id;
})
.filter(id => id !== null && id !== 'null'); //
}
const params = {
pageNum: queryParams.pageNum,
pageSize: queryParams.pageSize,
@ -286,11 +394,11 @@ const handleExport = async () => {
endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '',
payType: normalizePayType(queryParams.payType || ''),
orderCode: queryParams.orderCode,
performanceMarkets: performanceMarkets,
statuses: formatStatuses(queryParams.statuses),
markets: [],
}
}
// TODO: URL
const res = await exportFunds(params)
if (res.code == 200) {
@ -390,9 +498,204 @@ const findValueByLabel = (options, label) => {
return null
}
//
const formDataRow = ref({
jwcode:'',
marketName:'',
goodsName:'',
paymentCurrencyName:'',
paymentAmount:'',
payTime:'',
voucher:'',
name:'',
activity:'',
payType:'',
receivedCurrencyName:'',
receivedAmount:'',
receivedTime:'',
handlingCharge:'',
remark:'',
});
//
const showDetail=ref(false)
const showRecordDetail = async (row) => {
showDetail.value=true
formDataRow.value={
...row,
handlingCharge:row.handlingCharge || 0
}
}
const paymentCurrency = ref([
t('cash.currency.usd'), // (USD)
t('cash.currency.hkd'), // (HKD)
t('cash.currency.sgd'), // (SGD)
t('cash.currency.myr'), // (MYR)
t('cash.currency.thb'), // (THB)
t('cash.currency.cad'), // (CAD)
t('cash.currency.vnd'), // (VND)
t('cash.currency.krw'), // (KRW)
t('cash.currency.rmb'), // (CNY)
])
//
const showAddDetail=ref(false)
const type = ref('other')
const addCashFlow=(s)=>{
showAddDetail.value=true
type.value=s
}
const selectAddType= (s) => {
otherFormRef.value?.resetFields?.();
ipay88FormRef.value?.resetFields?.();
type.value=s
}
const otherFormRef = ref(null);
const addOtherForm=ref({
performanceMarket:"", //
goodsName:"", //
goodNum:"", //
payType:"", //
paymentCurrency:"", //
paymentAmount:"", //
payTime:"", //
handlingCharge:"", //
remark:"", //
isPerformance:'',
submitterId: adminData.value?.id || '', // ID
submitterMarket: adminData.value?.markets || [] //
})
const otherRules = {
performanceMarket: [
{ required: true, message: t('common.performanceByRegionPlaceholder'), trigger: 'change' }
],
goodsName: [
{ required: true, message: t('cash.cashFlow.incomeCategoryPlaceholder'), trigger: 'change' }
],
goodNum: [
{ type: 'number', message: t('cash.cashFlow.quantityMustBeNumber'), trigger: 'blur' }
],
payType: [
{ required: true, message: t('elmessage.checkPayModel'), trigger: 'change' }
],
paymentCurrency: [
{ required: true, message: t('common.payCurrencyPlaceholder'), trigger: 'change' }
],
paymentAmount: [
{ required: true, message: t('common_add.payAmountPlaceholder'), trigger: 'blur' },
{ pattern: /^-?[0-9]+(\.[0-9]{1,2})?$/, message: t('cash.cashFlow.invalidFormat'), trigger: 'blur' }
],
payTime: [
{ required: true, message: t('common_add.payTimePlaceholder'), trigger: 'change' }
],
handlingCharge: [
{ pattern: /^[0-9]+(\.[0-9]{1,2})?$/, message: t('cash.cashFlow.invalidFormat'), trigger: 'blur' }
]
};
const handleOther=async ()=>{
if (!otherFormRef.value) return;
try {
await otherFormRef.value.validate();
if(addOtherForm.value.goodsName=== t('cash.cashFlow.localIntercompany') ||
addOtherForm.value.goodsName=== t('cash.cashFlow.corporateIntercompany') ||
addOtherForm.value.goodsName=== t('cash.cashFlow.otherIncomeNon') ){
addOtherForm.value.isPerformance='0'
}else{
addOtherForm.value.isPerformance='1'
}
const submitData={
performanceMarket:String(MarketNameForId(addOtherForm.value.performanceMarket)),
goodsName:addOtherForm.value.goodsName,
goodNum:String(addOtherForm.value.goodNum),
payType:addOtherForm.value.payType,
paymentCurrency:String(CurrencyForId(addOtherForm.value.paymentCurrency)),
paymentAmount:addOtherForm.value.paymentAmount*100,
payTime:addOtherForm.value.payTime,
handlingCharge:addOtherForm.value.handlingCharge*100,
remark:addOtherForm.value.remark,
isPerformance:addOtherForm.value.isPerformance,
submitterId: addOtherForm.value.submitterId,
submitterMarket: addOtherForm.value.submitterMarket,
}
const handle =await request({
url:'/cashCollection/addExFund',
data:submitData
})
console.log('提交的数据:', submitData);
if (handle.code == 200 || handle.status == 200) {
ElMessage.success(t('elmessage.submitSuccess'));
otherFormRef.value?.resetFields?.();
showAddDetail.value = false;
fetchData()
}
} catch (error) {
console.log('校验失败', error);
}
};
const ipay88FormRef = ref(null);
const addIpay88Form=ref({
performanceMarket:"", //
payType:"", //
paymentCurrency:"", //
handlingCharge:"", //
remark:"", //
submitterId: adminData.value?.id || '', // ID
submitterMarket: adminData.value?.markets || [] //
})
const ipay88Rules = {
performanceMarket: [{ required: true, message: t('common.performanceByRegionPlaceholder'), trigger: 'change' } ],
goodsName: [{ required: true, message: t('cash.cashFlow.incomeCategoryPlaceholder'), trigger: 'change' }],
payType: [ { required: true, message: t('common.payModelPlaceholder'), trigger: 'change' } ],
paymentCurrency: [{ required: true, message: t('common.payCurrencyPlaceholder'), trigger: 'change' }],
payTime: [{ required: true, message: t('common_add.payTimePlaceholder'), trigger: 'change' }],
handlingCharge: [
{ required: true, message: t("common_add.feePlaceholder"),trigger: 'change'},
{ pattern: /^[0-9]+(\.[0-9]{1,2})?$/, message: t('cash.cashFlow.invalidFormat'),trigger: 'change' } ],
remark: [ {required: true, max: 100, message: t('cash.cashFlow.remarksexceed'), trigger: 'change' }]
};
const handleIpay88 =async () =>{
if (!ipay88FormRef.value) return;
try {
await ipay88FormRef.value.validate();
const Data={
performanceMarket:String(MarketNameForId(addIpay88Form.value.performanceMarket)),
payType:addIpay88Form.value.payType,
paymentCurrency:String(CurrencyForId(addIpay88Form.value.paymentCurrency)),
handlingCharge:addIpay88Form.value.handlingCharge*100,
remark:addIpay88Form.value.remark,
submitterId: addIpay88Form.value.submitterId,
submitterMarket: addIpay88Form.value.submitterMarket,
}
const handle =await request({
url:'/cashCollection/addiPay88Fee',
data:Data
})
console.log('提交的数据:', Data);
if (handle.code == 200 || handle.status == 200) {
ElMessage.success(t('elmessage.submitSuccess'));
ipay88FormRef.value?.resetFields?.();
showAddDetail.value = false;
fetchData()
}
} catch (error) {
console.log('校验失败', error);
}
}
// handleCancel
const handleCancel = () => {
otherFormRef.value?.resetFields?.();
ipay88FormRef.value?.resetFields?.();
showAddDetail.value = false;
};
const previewVisible=ref(false)
const handlePreviewClick=()=>{
if(previewVisible.value){
previewVisible.value=false
}
}
onMounted(async () => {
await initPermissions()
await getMarket()
await getPayPlatformOptions()
//
// URL?region=a&region=b keyrouter['a','b'], ID
const regionName = Array.isArray(route.query.region) ? route.query.region[0] : route.query.region
@ -420,29 +723,35 @@ onMounted(async () => {
<el-input v-model="queryParams.jwcode" :placeholder="t('common.jwcodePlaceholder')" clearable />
</div>
<div class="search-item">
<span class="label">{{ t('common.market') }}</span>
<span class="label">{{ t('cash.cashFlow.performanceMarket') }}</span>
<el-select v-model="queryParams.performanceMarket"
:placeholder="t('cash.cashFlow.performanceMarketPlaceholder')"
clearable :multiple="true"
style="width: 220px;"
:prop="performanceMarket"
collapse-tags >
<el-option v-for="item in performanceMarket" :key="item" :label="item" :value="item" />
</el-select>
<!-- <span class="label">{{ t('common.performanceByRegion') }}</span> -->
<!-- 下拉多选使用 el-cascader 匹配地区树结构 -->
<el-cascader v-model="queryParams.markets" :options="marketOptions"
<!-- <el-cascader v-model="queryParams.markets" :options="marketOptions"
:props="{ multiple: true, emitPath: false }" collapse-tags collapse-tags-tooltip
:placeholder="t('common.marketPlaceholder')" clearable style="width: 220px;" />
:placeholder="t('common.performanceByRegionPlaceholder')" clearable style="width: 240px;" /> -->
</div>
<!-- 选择平台二级表单 -->
<div class="search-item">
<span class="label">{{ t('common.payPlatform1') }}</span>
<el-select v-model="queryParams.payType" :placeholder="t('common.payPlatformPlaceholder1')" clearable>
<el-option v-for="item in payPlatformOptions" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="search-item">
<span class="label">{{ t('common.status') }}</span>
<el-select v-model="queryParams.statuses[0]" :placeholder="t('common.statusPlaceholder')" clearable>
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-cascader v-model="queryParams.platformSelection" :options="payPlatformOptionsList"
:props="{ multiple: true ,value:'id',label:'name'}"
collapse-tags collapse-tags-tooltip :placeholder="t('common.payPlatformPlaceholder1')" clearable
style="width: 220px;"
/>
</div>
<div class="search-item">
<span class="label">{{ t('common.orderNo') }}</span>
<el-input v-model="queryParams.orderCode" :placeholder="t('common.orderNoPlaceholder')" clearable />
</div>
<div class="search-item" style="width: auto;">
<span class="label">{{ t('common.payTime2') }}</span>
<el-date-picker v-model="queryParams.timeRange" type="datetimerange" :range-separator="t('common.to')"
@ -455,82 +764,59 @@ onMounted(async () => {
<el-button type="primary" @click="openExportList">{{ t('common.viewExportList') }}</el-button>
<el-button type="success" @click="handleReset">{{ t('common.reset') }}</el-button>
</div>
<div class="newAdd">
<el-button v-if="hasNewTransactionFlow" class="newAdd_btn" @click="addCashFlow('other')">{{ t('common.addCashFlow') }}</el-button>
</div>
</div>
</div>
</el-card>
<!-- 表格区域 -->
<el-card class="table-card">
<el-card class="table-card" >
<el-table ref="tableRef" :data="tableData" v-loading="loading" style="width: 100%; flex: 1;"
:cell-style="{ textAlign: 'center' }"
:header-cell-style="{ background: '#F3FAFE', color: '#333', textAlign: 'center' }">
:header-cell-style="{ background: '#F3FAFE', color: '#333', textAlign: 'center' }"
@row-click="showRecordDetail" >
<el-table-column type="index" :label="t('common_list.id')" width="60" align="center" fixed="left">
<template #default="scope">
<span>{{ scope.$index + 1 + (queryParams.pageNum - 1) * queryParams.pageSize }}</span>
</template>
</el-table-column>
<el-table-column prop="jwcode" :label="t('common_list.jwcode')" width="120" fixed="left" />
<el-table-column prop="name" :label="t('common_list.name')" width="150" show-overflow-tooltip />
<el-table-column prop="marketName" :label="t('common_list.market')" width="120" show-overflow-tooltip />
<el-table-column prop="payTime" :label="t('common_list.payTime2')" width="180" align="center" />
<el-table-column prop="orderCode" :label="t('common_list.orderCode')" width="280" show-overflow-tooltip />
<el-table-column prop="paymentAmount" :label="t('common_list.payAmount')" width="150" align="right">
<!-- <template #default="{ row }">
{{ row.paymentAmount }} {{ row.paymentCurrency }}
</template> -->
<el-table-column prop="receivedMarket" :label="t('common_list.receiveArea')" width="280" show-overflow-tooltip >
<template #default="{ row }">
{{ row.receivedMarket }}
</template>
</el-table-column>
<el-table-column prop="paymentCurrencyName" :label="t('common_list.payCurrency')" width="120"
show-overflow-tooltip />
<el-table-column prop="receivedAmount" :label="t('common_list.receiveAmount')" width="150" align="right">
<!-- <template #default="{ row }">
{{ row.receivedAmount }} {{ row.receivedCurrency }}
</template> -->
<el-table-column prop="performanceMarket" :label="t('common_list.performanceMarket')" width="120" show-overflow-tooltip >
<template #default="{ row }">
{{ row.performanceMarket }}
</template></el-table-column>
<el-table-column prop="name" :label="t('common_list.name')" width="150" show-overflow-tooltip />
<el-table-column prop="jwcode" :label="t('common_list.jwcode')" width="120" />
<el-table-column prop="goodsName" :label="t('common_list.receiveType')" width="120" >
<template #default="{ row }">{{ row.goodsName || '-' }}</template>
</el-table-column>
<el-table-column prop="remark" :label="t('common_list.remark')" width="120" />
<el-table-column prop="goodNum" :label="t('common_list.nums')" width="120" />
<el-table-column prop="payType" :label="t('common_list.paymentMethod')" width="120" />
<el-table-column prop="receivedCurrencyName" :label="t('common_list.receiveCurrency')" width="120"
show-overflow-tooltip />
<el-table-column prop="handlingCharge" :label="t('common_list.fee')" width="100" align="right" />
<el-table-column prop="payType" :label="t('common_list.payModel')" width="120" align="center" />
<el-table-column prop="payTime" :label="t('common_list.payTime2')" width="180" align="center" />
<el-table-column prop="status" :label="t('common_list.status')" width="120" align="center" fixed="right">
<template #default="{ row }">
<div style="display: flex; align-items: center;">
<el-tag :type="row.status === 4 ? 'success' : 'warning'" effect="plain">
{{ row.status === 4 ? t('common_list.received') : t('common_list.refunded') }}
</el-tag>
<el-popover trigger="hover" placement="top" popper-class="refund-popover" width="auto"
v-if="row.status === 6">
<div class="popover-content">
<div class="popover-title">{{ t('common_list.refundDetail') }}</div>
<div class="popover-item">
<span class="label">{{ t('common_list.refundAmount') }}</span>
<span class="value">{{ row.refundAmount || '-' }}</span>
</div>
<div class="popover-item">
<span class="label">{{ t('common_list.refundCurrency') }}</span>
<span class="value">{{ row.refundCurrency || '-' }}</span>
</div>
</div>
<template #reference>
<img @click.stop src="@/assets/SvgIcons/consume.svg"
style="width: 15px; height: 15px; margin-left: 5px; cursor: pointer; display: inline-block;">
</template>
</el-popover>
</div>
</template>
<el-table-column prop="paymentAmount" :label="t('common_list.payAmount')" width="150" align="right">
</el-table-column>
<el-table-column :label="t('common_list.operation')" width="100" fixed="right" align="center">
<el-table-column prop="handlingCharge" :label="t('common_list.fee')" width="100" align="right" >
<template #default="{ row }">{{ row.handlingCharge || 0 }}</template>
</el-table-column>
<el-table-column prop="receivedAmount" :label="t('common_list.receiveAmount')" width="150" align="right">
</el-table-column>
<!-- <el-table-column :label="t('common_list.operation')" width="100" fixed="right" align="center">
<template #default="{ row }">
<el-button v-if="row.orderCode.slice(0, 4) == 'GOLD' && row.status === 4" type="danger" link size="small"
@click="openRefundConfirm(row)">
{{ t('common_list.refund') }}
</el-button>
</template>
</el-table-column>
</el-table-column> -->
</el-table>
<!-- 分页 -->
@ -541,6 +827,210 @@ onMounted(async () => {
</div>
</el-card>
<!-- 详情显示页 -->
<el-dialog class="detailDialog" v-model="showDetail" :title="t('common_add.originalOrderInfo')" width="700px" destroy-on-close>
<el-form :model="formDataRow" label-width="100px" class="detail-form" disabled>
<div style="display: flex;">
<div class="left">
<div class="add-item">
<el-form-item :label="t('common_list.jwcode')">
<el-input v-model="formDataRow.jwcode" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.market')">
<el-input v-model="formDataRow.marketName" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.productName')">
<el-input v-model="formDataRow.goodsName" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.payCurrency')">
<el-input v-model="formDataRow.paymentCurrencyName" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.payAmount')">
<el-input v-model="formDataRow.paymentAmount" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.payTime2')">
<el-input v-model="formDataRow.payTime" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.transferVoucher')">
<div v-if="formDataRow.voucher" class="voucher-container">
<el-image :src="formDataRow.voucher" :preview-src-list="[formDataRow.voucher]"
fit="cover" class="voucher-img" v-model:preview-visible="previewVisible"
@click="handlePreviewClick"/>
</div>
<div v-else class="no-voucher">{{ t('common_list.noTransferVoucher') }}</div>
</el-form-item>
</div>
</div>
<div class="right">
<div class="add-item">
<el-form-item :label="t('common_list.customerName')">
<el-input v-model="formDataRow.name" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.activity')">
<el-input v-model="formDataRow.activityName" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.payModel')">
<el-input v-model="formDataRow.payType" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_add.receiveCurrency')">
<el-input v-model="formDataRow.receivedCurrencyName" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.receiveAmount')">
<el-input v-model="formDataRow.receivedAmount" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.receiveTime')">
<el-input v-model="formDataRow.receivedTime" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.fee')">
<el-input v-model="formDataRow.handlingCharge" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.submitter')">
<el-input v-model="adminData.adminName" />
</el-form-item>
</div>
<div class="add-item">
<el-form-item :label="t('common_list.remark')">
<el-input v-model="formDataRow.remark" type="textarea" :rows="2" />
</el-form-item>
</div>
</div>
</div>
</el-form>
<div style="display:flex;justify-content: center;margin-top: 5vh;" class="btnDiv">
<el-button type="default" style="background-color: #7E91FF;" @click="showDetail = false">{{t('common.cancel')}}</el-button>
<el-button v-show="formDataRow.orderCode.slice(0, 4) == 'GOLD' && formDataRow.status === 4 " type="primary" style="background-color: #2741DE; margin-left: 2.5vw;" @click="openRefundConfirm">{{ t('common.refund') }}</el-button>
</div>
</el-dialog>
<!-- 新增流水页面 -->
<el-dialog class="adddialog" v-model="showAddDetail" style="width: 400px;">
<div style="width: fit-content; height: fit-content;margin-bottom: 20px; ">
<el-button
class="btnItem"
:style="{backgroundColor: type === 'other' ? '#2741DE' : '#E5EBFE', color: type === 'other' ? 'white' : '#666' }"
@click="selectAddType('other')" >{{ t('cash.cashFlow.otherIncome') }}</el-button>
<el-button
class="btnItem"
:style="{ backgroundColor: type === 'ipay88' ? '#2741DE' : '#E5EBFE', color: type === 'ipay88' ? 'white' : '#666' }"
@click="selectAddType('ipay88')" >{{ t('cash.cashFlow.addFee') }}</el-button>
</div>
<!-- 其他收入填写表单 -->
<div v-if="type === 'other'" >
<el-form :model="addOtherForm" :rules="otherRules" ref="otherFormRef" label-width="120px" label-position="left">
<el-form-item :label=" t('cash.cashFlow.performanceMarket')" prop="performanceMarket">
<el-select v-model="addOtherForm.performanceMarket" :placeholder="t('cash.cashFlow.performanceMarketPlaceholder')" >
<el-option v-for="item in performanceMarket" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.incomeCategory')" prop="goodsName">
<el-select v-model="addOtherForm.goodsName" :placeholder="t('cash.cashFlow.incomeCategoryPlaceholder')" >
<el-option :value="t('cash.cashFlow.investmentIncome')" />
<el-option :value="t('cash.cashFlow.taxRefund')" />
<el-option :value="t('cash.cashFlow.governmentSubsidy')" />
<el-option :value="t('cash.cashFlow.localIntercompany')" />
<el-option :value="t('cash.cashFlow.corporateIntercompany')" />
<el-option :value="t('cash.cashFlow.otherIncomeNon')" />
<el-option :value="t('cash.cashFlow.otherIncomeYes')" />
</el-select>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.quantity')" prop="goodNum">
<el-input v-model.number="addOtherForm.goodNum" :placeholder="t('cash.cashFlow.quantityPlaceholder')" />
</el-form-item>
<el-form-item :label="t('cash.cashFlow.payType')" prop="payType">
<el-select v-model="addOtherForm.payType" :placeholder="t('cash.cashFlow.payTypePlaceholder')" >
<el-option v-for="item in paytypeList" :key="item" :value="item" :label="item"/>
</el-select>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.paymentCurrency')" prop="paymentCurrency">
<el-select v-model="addOtherForm.paymentCurrency" :placeholder="t('cash.cashFlow.paymentCurrencyPlaceholder')" >
<el-option v-for="item in paymentCurrency" :key="item" :label="item" :value="item"/>
</el-select>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.paymentAmount')" prop="paymentAmount">
<el-input v-model="addOtherForm.paymentAmount" :placeholder="t('cash.cashFlow.paymentAmountPlaceholder')" />
</el-form-item>
<el-form-item :label="t('cash.cashFlow.paymentTime')" prop="payTime">
<el-date-picker v-model="addOtherForm.payTime" type="datetime" :placeholder="t('cash.cashFlow.paymentTimePlaceholder')" value-format="YYYY-MM-DD HH:mm:ss"/>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.bankHandlingFee')" prop="handlingCharge">
<el-input v-model="addOtherForm.handlingCharge" :placeholder="t('cash.cashFlow.bankHandlingFeePlaceholder')" />
</el-form-item>
<el-form-item :label="t('cash.cashFlow.remarks')" prop="remark">
<el-input v-model="addOtherForm.remark" type="textarea" :rows="3" :placeholder="t('cash.cashFlow.remarksPlaceholder')" :maxlength="100" show-word-limit />
</el-form-item>
</el-form>
<div class="btnDiv" >
<el-button type="default" style="background-color: #7E91FF;" @click="handleCancel">{{t('cash.cashFlow.cancel')}}</el-button>
<el-button type="primary" style="background-color: #2741DE; margin-left: 2.5vw;" @click="handleOther">{{t('cash.cashFlow.submit')}}</el-button>
</div>
</div>
<!-- ipay88手续费填写表单 -->
<div v-if="type === 'ipay88'" >
<el-form :model="addIpay88Form" :rules="ipay88Rules" ref="ipay88FormRef" label-width="120px" label-position="left">
<el-form-item :label="t('cash.cashFlow.payType')" prop="payType">
<el-select v-model="addIpay88Form.payType" :placeholder="t('cash.cashFlow.payTypePlaceholder')" >
<el-option :value="t('cash.cashFlow.ipay88')" :label="t('cash.cashFlow.ipay88')"/>
<el-option :value="t('cash.cashFlow.cardPayment')" :label="t('cash.cashFlow.cardPayment')"/>
</el-select>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.performanceMarket')" prop="performanceMarket">
<el-select v-model="addIpay88Form.performanceMarket" :placeholder="t('cash.cashFlow.performanceMarketPlaceholder')" >
<el-option v-for="item in performanceMarket" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.incomeCategory')">
<el-input disabled :value="t('cash.cashFlow.fixedProcessingFee')"></el-input>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.settlementRegion')">
<el-input disabled :value="t('cash.cashFlow.Malaysia')"></el-input>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.paymentCurrency')" prop="paymentCurrency">
<el-select v-model="addIpay88Form.paymentCurrency" :placeholder="t('cash.cashFlow.paymentCurrencyPlaceholder')">
<el-option v-for="item in paymentCurrency" :key="item" :label="item" :value="item"/>
</el-select>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.paymentAmount')" prop="paymentAmount">
<el-input disabled v-model="addIpay88Form.paymentAmount" :placeholder="t('cash.cashFlow.paymentAmountPlaceholder')" value="0"/>
</el-form-item>
<el-form-item :label="t('cash.cashFlow.processingFee')" prop="handlingCharge">
<el-input v-model="addIpay88Form.handlingCharge" :placeholder="t('cash.cashFlow.processingFeePlaceholder')" />
</el-form-item>
<el-form-item :label="t('cash.cashFlow.remarks')" prop="remark">
<el-input v-model="addIpay88Form.remark" type="textarea" :rows="3" :placeholder="t('cash.cashFlow.remarkPlaceholderDate')" :maxlength="100" show-word-limit/>
</el-form-item>
</el-form>
<div class="btnDiv">
<el-button type="default" style="background-color: #7E91FF;" @click="handleCancel">{{t('cash.cashFlow.cancel')}}</el-button>
<el-button type="primary" style="background-color: #2741DE; margin-left: 2.5vw;" @click="handleIpay88">{{t('cash.cashFlow.submit')}}</el-button>
</div>
</div>
</el-dialog>
<!-- 导出列表弹窗 -->
<el-dialog v-model="exportListVisible" :title="t('common_export.exportList')" width="80%">
<el-table :data="exportList" style="width: 100% ;height: 60vh;" :loading="exportListLoading">
@ -606,7 +1096,7 @@ onMounted(async () => {
</div>
<div class="add-item">
<el-text style="width:4vw;">{{ t('common_add.activity') }}</el-text>
<el-input v-model="refundFormData.activity" style="width:10vw;" disabled />
<el-input v-model="refundFormData.activityName" style="width:10vw;" disabled />
</div>
<div class="add-item">
<el-text style="width:4vw;">{{ t('common_add.productName') }}</el-text>
@ -627,7 +1117,7 @@ onMounted(async () => {
</div>
<div class="add-item">
<el-text style="width:4vw;">{{ t('common_add.payCurrency') }}</el-text>
<el-input v-model="refundFormData.paymentCurrency" style="width:10vw;" disabled />
<el-input v-model="refundFormData.paymentCurrencyName" style="width:10vw;" disabled />
</div>
<div class="add-item">
<el-text style="width:4vw;">{{ t('common_add.payAmount') }}</el-text>
@ -697,8 +1187,6 @@ onMounted(async () => {
</div>
</template>
<style lang="scss">
.refund-popover {
background-color: #EEF5FE !important;
@ -715,6 +1203,68 @@ onMounted(async () => {
}
</style>
<style scoped lang="scss">
:deep(.detailDialog) {
background: #F3FAFE !important;
.left {
width: 50%;
height: 60vh;
min-height: 400px;
.add-item {
display: flex;
align-items: center;
margin-bottom: 1vh;
}
.image {
width: 4vw !important;
height: 4vw !important;
}
}
.right {
width: 50%;
height: 60vh;
.add-item {
display: flex;
align-items: center;
margin-bottom: 1vh;
}
}
.voucher-img {
width: 100px; /* 限制宽度 */
height: 100px; /* 限制高度 */
border-radius: 4px;
cursor: pointer; /* 鼠标放上去显示手型,提示可点击预览 */
}
.no-voucher {
color: #909399;
font-size: 14px;
}
}
:deep(.adddialog .el-form-item__label) {
min-width: 120px;
width: auto;
font-weight: 800;
padding-bottom: 15px;
}
.btnItem {
margin-left: 10px;
border-radius: 5px;
}
.btnDiv{
text-align: center;
margin-top: 30px;
}
:deep(.adddialog) {
min-width: 400px;
background-color: #F3FAFE !important;
margin-top: 8vh;
border-radius: 8px;
}
.popover-content {
.popover-title {
color: #409EFF;
@ -798,6 +1348,17 @@ onMounted(async () => {
gap: 10px;
}
.newAdd {
margin-left: auto;
display: flex;
width: 240px;
justify-content: flex-end;
}
.newAdd_btn{
background-color: blueviolet;
color: white;
}
.table-card {
background: #E7F4FD;
flex: 1;

375
src/views/moneyManage/financialAccount/performanceAttribution.vue

@ -1,13 +1,17 @@
<script setup>
import { ref, reactive, onMounted, toRefs, nextTick } from 'vue'
import { ref, reactive, onMounted, toRefs, nextTick, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/util/http.js'
import dayjs from 'dayjs'
import { useI18n } from 'vue-i18n'
import { refundOnline,performanceSelect,exportPerformance } from '@/api/cash/financialAccount.js'
import { refundOnline, performanceSelect, exportPerformance, adjustment } from '@/api/cash/financialAccount.js'
import { getUserInfo } from '@/api/common/common.js'
import { useAdminStore } from '@/store/index.js'
import { permissionMapping, hasMenuPermission } from "@/utils/menuTreePermission.js"
import { storeToRefs } from 'pinia'
const adminStore = useAdminStore()
const { menuTree, flag } = storeToRefs(adminStore)
const adminData = ref({})
@ -29,6 +33,16 @@ const paytypeList = [
t('cash.payMethods.paypal'),
]
const hasperformanceAdjustment = ref(false)
//
const initPermissions = async () => {
if (!menuTree.value || !menuTree.value.length) return;
//
hasperformanceAdjustment.value = hasMenuPermission(menuTree.value, permissionMapping.performance_adjustment);
console.log('业绩调整权限', hasperformanceAdjustment.value);
};
const payPlatformOptions = ref([...paytypeList])
const statusOptions = [
@ -85,18 +99,35 @@ const getMarket = async () => {
}
}
// ID
const findIdsByNames = (nodes, names, resultIds) => {
if (!nodes || nodes.length === 0) return;
nodes.forEach(node => {
if (names.includes(node.label)) {
resultIds.push(node.value);
}
if (node.children) {
findIdsByNames(node.children, names, resultIds);
}
});
};
//
const fetchData = async () => {
loading.value = true
try {
// adminData ID
const adminMarketNames = adminData.value.marketName?.split(',').map(item => item.trim()).filter(Boolean) || [];
const adminMarketIds = [];
findIdsByNames(marketOptions.value, adminMarketNames, adminMarketIds);
//
console.log('adminData.value.markets:', adminData.value.markets)
const params = {
pageNum: queryParams.pageNum,
pageSize: queryParams.pageSize,
performanceDTO:{
performanceDTO: {
jwcode: queryParams.jwcode,
adminMarket: adminData.value.marketName.split(',').filter(item => item.trim() !== '') || [],
adminMarket: adminMarketIds,
customerMarket: queryParams.customerMarket,
startTime: queryParams.timeRange?.[0] ? dayjs(queryParams.timeRange[0]).format('YYYY-MM-DD HH:mm:ss') : '',
endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '',
@ -157,6 +188,7 @@ const handleCurrentChange = (val) => {
fetchData()
}
// 退
const handleRefund = (row) => {
ElMessageBox.confirm(t('elmessage.refundConfirmContent', { orderNo: row.systemTradeNo }), t('elmessage.refundConfirmTitle'), {
@ -167,7 +199,7 @@ const handleRefund = (row) => {
ElMessage.success(t('elmessage.refundSubmitSuccess'))
//
fetchData()
}).catch(() => {})
}).catch(() => { })
}
// ==================== ====================
@ -179,12 +211,15 @@ const exportListLoading = ref(false)
// Excel
const handleExport = async () => {
try {
const adminMarketNames = adminData.value.marketName?.split(',').map(item => item.trim()).filter(Boolean) || [];
const adminMarketIds = [];
findIdsByNames(marketOptions.value, adminMarketNames, adminMarketIds);
const params = {
pageNum: queryParams.pageNum,
pageSize: queryParams.pageSize,
performanceDTO:{
performanceDTO: {
jwcode: queryParams.jwcode,
adminMarket: adminData.value.marketName.split(',').filter(item => item.trim() !== '') || [],
adminMarket: adminMarketIds,
customerMarket: queryParams.customerMarket,
startTime: queryParams.timeRange?.[0] ? dayjs(queryParams.timeRange[0]).format('YYYY-MM-DD HH:mm:ss') : '',
endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '',
@ -193,7 +228,7 @@ const handleExport = async () => {
// TODO: URL
const res = await exportPerformance(params)
if(res.code == 200){
if (res.code == 200) {
console.log('导出参数', params)
ElMessage.success(t('elmessage.exportSuccess'))
@ -264,9 +299,114 @@ const getTagText = (state) => {
}
}
onMounted( async() => {
// ==================== ====================
const adjustVisible = ref(false)
const adjustTime = ref('')
const adjustCoefficient = ref('')
const matrixMarkets = computed(() => [
{ key: 'sg', label: t('cash.markets.Singapore') },
{ key: 'my', label: t('cash.markets.Malaysia') },
{ key: 'hk', label: t('cash.markets.HongKong') },
{ key: 'th', label: t('cash.markets.Thailand') },
{ key: 'vn', label: t('clientCount.market.vnGold') },
{ key: 'ca', label: t('cash.markets.Canada') }
])
const adjustData = ref([])
const initAdjustData = () => {
adjustData.value = matrixMarkets.value.map(rowMarket => {
const row = { inMarket: rowMarket.label + t('common.customer') }
matrixMarkets.value.forEach(colMarket => {
row[colMarket.key] = '' //
})
return row
})
}
const handleAdjustment = () => {
adjustTime.value = dayjs().format('YYYY-MM-DD HH:mm:ss')
adjustCoefficient.value = ''
initAdjustData()
adjustVisible.value = true
}
const computedAdjustData = computed(() => {
const data = [...adjustData.value]
const sumRow = { inMarket: t('cash.cashFlow.total'), isSum: true }
matrixMarkets.value.forEach(colMarket => {
let colSum = 0
adjustData.value.forEach(row => {
const val = parseFloat(row[colMarket.key])
if (!isNaN(val)) colSum += val
})
sumRow[colMarket.key] = colSum
})
data.push(sumRow)
return data
})
const getRowTotal = (row) => {
let sum = 0
matrixMarkets.value.forEach(colMarket => {
const val = parseFloat(row[colMarket.key])
if (!isNaN(val)) sum += val
})
return sum
}
const formatNumber = (val) => {
if (val === '' || val === '-' || val === undefined || val === null) return val;
val = String(val);
let formatted = val.replace(/[^\d.-]/g, ''); //
formatted = formatted.replace(/(?!^)-/g, ''); //
formatted = formatted.replace(/(\..*?)\..*/g, '$1'); //
return formatted;
}
const submitAdjustment = async () => {
if (!adjustTime.value) {
ElMessage.warning(t('cash.cashFlow.time'))
return
}
if (!adjustCoefficient.value) {
ElMessage.warning(t('cash.cashFlow.coefficientPlaceholder'))
return
}
// matrix (66)
// 0
const matrix = adjustData.value.map(row => {
return matrixMarkets.value.map(colMarket => {
const val = parseFloat(row[colMarket.key])
return isNaN(val) ? 0 : val
})
})
//
const payload = {
matrix: matrix,
weight: parseFloat(adjustCoefficient.value), //
time: adjustTime.value,
submitterId: adminData.value.id || 1000063, // adminData
submitterMarket: adminData.value.marketName || '总部' //
}
console.log('提交的封装数据:', JSON.stringify(payload, null, 2))
await adjustment(payload)
ElMessage.success(t('elmessage.submitSuccess'))
adjustVisible.value = false
fetchData()
}
onMounted(async () => {
await initPermissions()
await handleAdminInfo()
getMarket()
await getMarket()
await fetchData()
})
</script>
@ -283,83 +423,66 @@ onMounted( async() => {
<el-input v-model="queryParams.jwcode" :placeholder="t('common.jwcodePlaceholder')" clearable />
</div>
<div class="search-item">
<span class="label">{{ t('common.market') }}</span>
<span class="label">{{ t('common_list.market') }}</span>
<!-- 下拉多选使用 el-cascader 匹配地区树结构 -->
<el-cascader
v-model="queryParams.customerMarket"
:options="marketOptions"
:props="{ multiple: true, emitPath: false }"
collapse-tags
collapse-tags-tooltip
:placeholder="t('common.marketPlaceholder')"
clearable
style="width: 8vw;"
/>
<el-cascader v-model="queryParams.customerMarket" :options="marketOptions"
:props="{ multiple: true, emitPath: false }" collapse-tags collapse-tags-tooltip
:placeholder="t('common_list.marketPlaceholder')" clearable style="width: 8vw;" />
</div>
<div class="search-item" style="width: auto;">
<span class="label">{{ t('common.payTime2') }}</span>
<el-date-picker
v-model="queryParams.timeRange"
type="datetimerange"
:range-separator="t('common.to')"
:start-placeholder="t('common.startTime')"
:end-placeholder="t('common.endTime')"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
style="width: 18vw;"
/>
<el-date-picker v-model="queryParams.timeRange" type="datetimerange" :range-separator="t('common.to')"
:start-placeholder="t('common.startTime')" :end-placeholder="t('common.endTime')"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]" style="width: 18vw;" />
</div>
</div>
<div class="search-row">
<el-button type="primary" @click="handleSearch">{{ t('common.search') }}</el-button>
<el-button type="primary" @click="handleExport">{{ t('common.exportExcel') }}</el-button>
<el-button type="primary" @click="openExportList">{{ t('common.viewExportList') }}</el-button>
<el-button type="success" @click="handleReset">{{ t('common.reset') }}</el-button>
<button v-if="hasperformanceAdjustment" class="adjust-btn" @click="handleAdjustment">{{
t('cash.cashFlow.performanceAdjustment') }}</button>
</div>
</div>
</el-card>
<!-- 表格区域 -->
<el-card class="table-card">
<el-table ref="tableRef" :data="tableData" v-loading="loading" style="width: 100%; flex: 1;" :cell-style="{ textAlign: 'center' }" :header-cell-style="{ background: '#F3FAFE', color: '#333',textAlign: 'center' }">
<el-table-column type="index" :label="t('common_list.id')" min-width="60" align="center" fixed="left" >
<el-table ref="tableRef" :data="tableData" v-loading="loading" style="width: 100%; flex: 1;"
:cell-style="{ textAlign: 'center' }"
:header-cell-style="{ background: '#F3FAFE', color: '#333', textAlign: 'center' }">
<el-table-column type="index" :label="t('common_list.id')" min-width="60" align="center" fixed="left">
<template #default="scope">
<span>{{ scope.$index + 1 + (queryParams.pageNum - 1) * queryParams.pageSize }}</span>
</template>
</el-table-column>
<el-table-column prop="jwcode" :label="t('common_list.jwcode')" min-width="120" fixed="left" />
<el-table-column prop="payTime" :label="t('cash.cashFlow.payTime')" min-width="180" />
<el-table-column prop="orderCode" :label="t('cash.cashFlow.orderCode')" min-width="350" show-overflow-tooltip />
<el-table-column prop="receivedMarketName" :label="t('cash.cashFlow.receivedMarketName')" min-width="120"
show-overflow-tooltip />
<el-table-column prop="performanceMarketName" :label="t('cash.cashFlow.performanceMarket')" min-width="120"
show-overflow-tooltip />
<el-table-column prop="name" :label="t('common_list.name')" min-width="150" show-overflow-tooltip />
<el-table-column prop="marketName" :label="t('common_list.market')" min-width="120" show-overflow-tooltip />
<el-table-column prop="orderCode" :label="t('common_list.orderCode')" min-width="280" show-overflow-tooltip />
<el-table-column prop="paymentAmount" :label="t('common_list.payAmount')" min-width="150" align="right">
<!-- <template #default="{ row }">
{{ row.paymentAmount }} {{ row.paymentCurrency }}
</template> -->
</el-table-column>
<el-table-column prop="paymentCurrency" :label="t('common_list.payCurrency')" min-width="180" show-overflow-tooltip />
<el-table-column prop="receivedAmount" :label="t('common_list.receiveAmount')" min-width="150" align="right">
<!-- <template #default="{ row }">
{{ row.receivedAmount }} {{ row.receivedCurrency }}
</template> -->
</el-table-column>
<el-table-column prop="receivedCurrency" :label="t('common_list.receiveCurrency')" min-width="180" show-overflow-tooltip />
<el-table-column prop="handlingCharge" :label="t('common_list.fee')" min-width="100" align="right" />
<el-table-column prop="jwcode" :label="t('common_list.jwcode')" min-width="120" />
<el-table-column prop="goodsName" :label="t('cash.cashFlow.goodsName')" min-width="120" show-overflow-tooltip />
<el-table-column prop="remark" :label="t('common_list.remark')" min-width="120" show-overflow-tooltip />
<el-table-column prop="goodNum" :label="t('cash.cashFlow.goodNum')" min-width="120" show-overflow-tooltip />
<el-table-column prop="payType" :label="t('cash.cashFlow.payType')" min-width="120" show-overflow-tooltip />
<el-table-column prop="receivedCurrency" :label="t('common_list.receiveCurrency')" min-width="180"
show-overflow-tooltip />
<el-table-column prop="paymentAmount" :label="t('common_list.payAmount')" min-width="150" />
<el-table-column prop="handlingCharge" :label="t('common_list.fee')" min-width="100" />
<el-table-column prop="receivedAmount" :label="t('common_list.receiveAmount')" min-width="150" />
</el-table>
<!-- 分页 -->
<div class="pagination-container">
<el-pagination
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
:current-page="queryParams.pageNum"
:page-size="queryParams.pageSize"
:page-sizes="[10, 20, 50, 100]"
@size-change="handlePageSizeChange"
@current-change="handleCurrentChange"
/>
<el-pagination background layout="total, sizes, prev, pager, next, jumper" :total="total"
:current-page="queryParams.pageNum" :page-size="queryParams.pageSize" :page-sizes="[10, 20, 50, 100]"
@size-change="handlePageSizeChange" @current-change="handleCurrentChange" />
</div>
</el-card>
@ -394,6 +517,65 @@ onMounted( async() => {
</div>
</template>
</el-dialog>
<!-- 业绩调整弹窗 -->
<el-dialog v-model="adjustVisible" :title="t('cash.cashFlow.marketConsumption')" width="80%" top="5vh" align-center
class="custom-adjust-dialog">
<template #header="{ titleId, titleClass }">
<div style="text-align: center; font-weight: bold; font-size: 18px;" :id="titleId" :class="titleClass">{{
t('cash.cashFlow.marketConsumption') }}</div>
</template>
<div style="display: flex; gap: 40px; margin-bottom: 20px; align-items: center;">
<div style="display: flex; align-items: center;">
<span style="margin-right: 10px; font-weight: bold;">{{ t('cash.cashFlow.time') }}</span>
<el-date-picker v-model="adjustTime" type="datetime" :placeholder="t('cash.cashFlow.time')"
value-format="YYYY-MM-DD HH:mm:ss" />
</div>
<div style="display: flex; align-items: center;">
<span style="margin-right: 10px; font-weight: bold;">{{ t('cash.cashFlow.coefficient') }}</span>
<el-input v-model="adjustCoefficient" :placeholder="t('cash.cashFlow.coefficientPlaceholder')"
style="width: 200px;" @input="adjustCoefficient = formatNumber(adjustCoefficient)" />
</div>
</div>
<el-table :data="computedAdjustData" border style="width: 100%" :cell-style="{ textAlign: 'center' }"
:header-cell-style="{ background: '#F3FAFE', color: '#333', textAlign: 'center', padding: '0' }">
<el-table-column width="150" align="center" fixed="left">
<template #header>
<div class="diagonal-header">
<span class="top-right">{{ t('cash.cashFlow.adjustment') }}</span>
<span class="bottom-left">{{ t('cash.cashFlow.adjustmentOut') }}</span>
</div>
</template>
<template #default="{ row }">
<span style="font-weight: bold;">{{ row.inMarket }}</span>
</template>
</el-table-column>
<el-table-column v-for="col in matrixMarkets" :key="col.key"
:label="col.label + ' ' + t('cash.cashFlow.marketTeam')" min-width="120" align="center">
<template #default="{ row }">
<span v-if="row.isSum">{{ row[col.key] }}</span>
<el-input v-else v-model="row[col.key]" @input="row[col.key] = formatNumber($event)" placeholder=""
class="seamless-input" />
</template>
</el-table-column>
<el-table-column :label="t('cash.cashFlow.total')" min-width="120" align="center" fixed="right">
<template #default="{ row }">
{{ getRowTotal(row) }}
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer" style="text-align: center;">
<el-button type="primary" plain @click="adjustVisible = false" style="width: 100px;">{{ t('common.cancel')
}}</el-button>
<el-button type="primary" @click="submitAdjustment" style="width: 100px;">{{ t('common.submit') }}</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
@ -440,7 +622,8 @@ onMounted( async() => {
text-align: right;
}
.el-input, .el-select {
.el-input,
.el-select {
width: 8vw;
}
}
@ -451,6 +634,16 @@ onMounted( async() => {
gap: 10px;
}
.adjust-btn {
color: #fff;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
border: none;
background-color: #7349ad;
margin-left: auto;
}
.table-card {
background: #E7F4FD;
flex: 1;
@ -484,4 +677,60 @@ onMounted( async() => {
:deep(.el-table__row:hover > .el-table__cell) {
background-color: #E5EBFE !important;
}
.diagonal-header {
position: relative;
width: 100%;
height: 50px;
/* Set a fixed height to make diagonal line work well */
background: linear-gradient(to top right, transparent 49.5%, #dcdfe6 49.5%, #dcdfe6 50.5%, transparent 50.5%);
}
.diagonal-header .top-right {
position: absolute;
top: 5px;
right: 15px;
font-weight: bold;
}
.diagonal-header .bottom-left {
position: absolute;
bottom: 5px;
left: 15px;
font-weight: bold;
}
/* 业绩调整弹窗全局样式 */
:deep(.custom-adjust-dialog) {
background-color: #f3fafe !important;
/* 统一淡蓝色背景 */
border-radius: 8px;
}
:deep(.custom-adjust-dialog .el-dialog__header) {
padding-bottom: 20px;
border-bottom: 1px solid #EBEEF5;
margin-right: 0;
}
:deep(.custom-adjust-dialog .el-dialog__body) {
padding-top: 20px;
}
/* 无缝输入框样式(去除边框和背景) */
.seamless-input :deep(.el-input__wrapper) {
box-shadow: none !important;
background-color: transparent !important;
padding: 0;
}
.seamless-input :deep(.el-input__inner) {
text-align: center;
font-size: 14px;
height: 100%;
}
.seamless-input :deep(.el-input__inner:focus) {
outline: none;
}
</style>

51
src/views/moneyManage/receiveDetail/receiveService.vue

@ -270,7 +270,7 @@
@change="handleMarketChange($event)">
</CurrencySelect>
</el-form-item>
<el-form-item :label="t('common_add.receiveWallet')" required prop="receivedWallet" v-if="isGold">
<el-form-item :label="t('common_add.receiveWallet')" required prop="receivedWallet" >
<CurrencySelect v-model="addFormData.receivedWallet" :items="MoneyWalletOptions"
:placeholder="t('common_add.receiveWalletPlaceholder')" :disabled="!selectWallet || isGroup"
@update:modelValue="handleFieldInput('receivedWallet')"
@ -411,12 +411,12 @@
<div class="add-item"
v-show="refundFormData.goodsName === t('cash.coinRecharge') && refundFormData.refundModel === '1'">
<el-text style="width:4vw;">{{ t('common_add.permanentGold') }}</el-text>
<el-input v-model="refundFormData.partRefundGold" style="width:5vw;" />&nbsp;&nbsp;
<el-input v-model="refundFormData.partRefundGold" style="width:5vw;" />&nbsp;&nbsp;{{ t('cash.unit') }}
</div>
<div class="add-item"
v-show="refundFormData.goodsName === t('cash.coinRecharge') && refundFormData.refundModel === '1'">
<el-text style="width:4vw;">{{ t('common_add.freeGold') }}</el-text>
<el-input v-model="refundFormData.partRefundFree" style="width:5vw;" />&nbsp;&nbsp;
<el-input v-model="refundFormData.partRefundFree" style="width:5vw;" />&nbsp;&nbsp;{{ t('cash.unit') }}
</div>
<div class="add-item">
<el-text style="width:4vw;">{{ t('common_add.refundReason') }}</el-text>
@ -804,11 +804,12 @@ const handleJwcodeBlur = () => {
//
const jwcodeQuerying = ref(false)
let jwcodeQueryPromise = null
//
const lastSearchedJwcode = ref('')
const jwcodeSeachMarket = async () => {
try {
if (jwcodeQuerying.value && jwcodeQueryPromise) {
await jwcodeQueryPromise
return
return await jwcodeQueryPromise
}
const jwcode = String(addFormData.value.jwcode ?? '').replace(/\s/g, '')
addFormData.value.jwcode = jwcode
@ -824,6 +825,12 @@ const jwcodeSeachMarket = async () => {
ElMessage.error(t('elmessage.limitJwcodeLength'))
return
}
//
if (lastSearchedJwcode.value === jwcode && addFormData.value.name && addFormData.value.market) {
return { code: 200, data: { market: addFormData.value.market, marketName: addFormData.value.marketName, name: addFormData.value.name } }
}
jwcodeQuerying.value = true
jwcodeQueryPromise = request({
url: '/cashCollection/getNameAndMarket',
@ -835,25 +842,32 @@ const jwcodeSeachMarket = async () => {
addFormData.value.market = result.data.market
addFormData.value.marketName = result.data.marketName
addFormData.value.name = result.data.name
lastSearchedJwcode.value = jwcode //
if (addFormRef.value) {
addFormRef.value.validateField('name');
addFormRef.value.validateField('market');
}
return result; // 便
} else if (result.code == 0) {
lastSearchedJwcode.value = '' //
const region = result.data && result.data.market
if (region) {
ElMessage.info({
message: t('elmessage.userRegionHint', { region }),
customClass: 'custom-blue-message'
})
return
}
ElMessage.error(t('elmessage.customerNotExist'))
return result; // code0便
} else {
lastSearchedJwcode.value = '' //
ElMessage.error(t('elmessage.customerNotExist'))
return result; //
}
} catch (error) {
console.log(error);
lastSearchedJwcode.value = ''
return { code: 500 }; //
} finally {
jwcodeQuerying.value = false
jwcodeQueryPromise = null
@ -862,8 +876,9 @@ const jwcodeSeachMarket = async () => {
const waitJwcodeQuery = async () => {
if (jwcodeQuerying.value && jwcodeQueryPromise) {
await jwcodeQueryPromise
return await jwcodeQueryPromise
}
return null
}
const LastGoodsName = ref('')
@ -935,7 +950,9 @@ const testGold = () => {
//
const handleAddForm = async () => {
try {
await waitJwcodeQuery()
// null
const waitResult = await waitJwcodeQuery()
await addFormRef.value.validate();
if (!testGold().valid) {
ElMessage.error(testGold().message);
@ -976,6 +993,19 @@ const handleAddForm = async () => {
}
ifAddDone.value = true
//
let jwcodeResult = waitResult
if (!jwcodeResult) {
jwcodeResult = await jwcodeSeachMarket()
}
// code=0 退
if (!jwcodeResult || jwcodeResult.code === 0 || jwcodeResult.code === 500) {
ifAddDone.value = false;
return;
}
const result = await request({
url: '/cashCollection/add',
data: {
@ -990,9 +1020,10 @@ const handleAddForm = async () => {
receivedMarket: MarketNameForId(addFormData.value.receivedMarket) || '',
paymentAmount: (addFormData.value.paymentAmount) * 100,
submitterMarket: normalizeSubmitterMarket(adminData.value.markets),
...(isGold.value ? {
isPerformance: 1,
...( {
walletId: WalletForId(addFormData.value.receivedWallet)
} : {})
} )
}
})
if (result.code == 200) {

15
src/views/usergold/gold/clientCount.vue

@ -21,14 +21,6 @@
>
{{ $t('clientCount.clientCountBalance') }}
</el-button>
<el-button
class="no-active-btn"
:class="{ 'active-btn': activeTab === 'clientCountWallet' }"
@click="navigateTo('clientCountWallet')"
:disabled="!hasWallet" v-if="hasWallet"
>
{{ $t('clientCount.clientCountWallet') }}
</el-button>
</el-button-group>
<!-- 渲染子路由组件 -->
</div>
@ -56,7 +48,6 @@ const {menuTree} = storeToRefs(adminStore);
const activeTab = ref('');
const hasDetail = ref(false);
const hasBalance = ref(false);
const hasWallet = ref(false);
//
const navigateTo = (name) => {
activeTab.value = name;
@ -69,7 +60,6 @@ const initPermissions = () => {
if (!menuTree.value || !menuTree.value.length) return;
hasDetail.value = hasMenuPermission(menuTree.value, permissionMapping.gold_coin_customer_bill);
hasBalance.value = hasMenuPermission(menuTree.value, permissionMapping.gold_coin_customer_balance);
hasWallet.value = hasMenuPermission(menuTree.value, permissionMapping.wallet);
};
//
@ -77,14 +67,13 @@ const getDefaultAuditRoute = () => {
initPermissions();
if (hasDetail.value) return 'clientCountDetail';
if (hasBalance.value) return 'clientCountBalance';
if (hasWallet.value) return 'clientCountWallet';
return 'clientCountDetail';
};
//
watch(() => route.name, (newName) => {
initPermissions()
if (newName === 'clientCountDetail' || newName === 'clientCountBalance' || newName === 'clientCountWallet') {
if (newName === 'clientCountDetail' || newName === 'clientCountBalance') {
activeTab.value = newName;
} else if (newName === 'usergold') {
// 访 /coinConsume
@ -101,7 +90,7 @@ onMounted(() => {
navigateTo(defaultRoute);
} else {
//
if (route.name === 'clientCountDetail' || route.name === 'clientCountBalance' || route.name === 'clientCountWallet') {
if (route.name === 'clientCountDetail' || route.name === 'clientCountBalance') {
activeTab.value = route.name;
}
}

913
src/views/walletManage/WalletBalance.vue

@ -0,0 +1,913 @@
<script setup>
//
import { useAdminStore } from "@/store/index.js"
import { storeToRefs } from "pinia"
import { findMenuById, permissionMapping } from "@/utils/menuTreePermission.js"
const adminStore = useAdminStore()
const { adminData, menuTree, flag } = storeToRefs(adminStore)
// flag()
watch(flag, (newFlag, oldFlag) => {
// flag
if (newFlag !== oldFlag) {
console.log('员工数据flag状态改变,重新加载数据', newFlag)
get()
}
})
import { onMounted, ref, watch, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import moment from 'moment'
import API from '@/util/http.js'
import { reverseMarketMapping } from "@/utils/marketMap.js";
//
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
//
const dialogVisible = ref(false)
//
const markets = ref([])
//
// tableData
const tableData = ref([]);
const walletMap = {
1: 'historyGold',
2: 'hkGold',
3: 'sgHcGold',
4: 'myGold',
5: 'sgGold',
6: 'caGold',
7: 'thHsGold',
8: 'thHaGold',
9: 'vnGold',
10: 'bjGold'
};
const propToWalletId = {
historyGold: 1,
hkGold: 2,
sgHcGold: 3,
myGold: 4,
sgGold: 5,
caGold: 6,
thHsGold: 7,
thHaGold: 8,
vnGold: 9,
bjGold: 10
};
const tableRef = ref(null)
const scrollTableTop = () => {
tableRef.value?.setScrollTop?.(0)
}
//
const userInfo = ref({})
// ===========================================
//
const total = ref(100)
//
const getTime = ref([])
// User
const selectData = ref({
jwcode: '',
markets: [],
})
//
const getAllObj = ref({})
//
const getObj = ref({
pageNum: 1,
pageSize: 50
})
//
const sortField = ref('')
const sortOrder = ref('')
const sortWalletId = ref('')
//
// ===========================================================================
//
const get = async function (val) {
try {
//
if (typeof val === 'number') {
getObj.value.pageNum = val
}
if (selectData.value.jwcode) {
//
const numberRegex = /^\d{1,9}$/;
//
if (!numberRegex.test(selectData.value.jwcode)) {
ElMessage.error(t('elmessage.checkJwcodeFormat'))
return
}
}
console.log('搜索参数', getObj.value, selectData.value)
//
const params = {
pageNum: getObj.value.pageNum,
pageSize: getObj.value.pageSize
}
//
if (selectData.value.jwcode) {
params.jwcode = Number(selectData.value.jwcode)
}
if (selectData.value.markets && selectData.value.markets.length > 0) {
//
params.market = String(selectData.value.markets[0])
}
if (sortField.value) {
params.sortField = sortField.value
}
if (sortOrder.value) {
params.sortOrder = sortOrder.value
}
if (sortWalletId.value !== '') {
params.sortWalletId = sortWalletId.value
}
console.log('最终请求参数', params)
const result = await API({
url: '/cashCollection/selectUserWallets',
method: 'post',
data: params
})
console.log('响应数据', result)
if (result.code === 200) {
tableData.value = result.data.list.map(item => {
const row = {
historyGold: 0,
name: item.userName,
jwcode: item.jwcode,
market: item.marketName,
hkGold: 0,
sgHcGold: 0,
myGold: 0,
sgGold: 0,
caGold: 0,
thHsGold: 0,
thHaGold: 0,
vnGold: 0,
bjGold: 0
};
if (item.walletList && Array.isArray(item.walletList)) {
item.walletList.forEach(wallet => {
const prop = walletMap[wallet.walletId];
if (prop) {
row[prop] = wallet.currentPermanentGold;
}
});
}
return row;
});
total.value = result.data.total;
} else {
ElMessage.error(result.msg || t('elmessage.getDataFailed'));
}
} catch (error) {
console.log('请求失败', error)
}
}
// selectData putExcel jwcode
const trimJwCode = () => {
if (selectData.value.jwcode) {
selectData.value.jwcode = selectData.value.jwcode.replace(/\s/g, '');
}
}
//
const search = function () {
trimJwCode();
getObj.value.pageNum = 1
get()
}
//
const reset = function () {
selectData.value = {
jwcode: '',
markets: [],
}
sortField.value = ''
sortOrder.value = ''
sortWalletId.value = ''
selectedMarketPath.value = []
//
getObj.value.pageNum = 1
get()
}
const cellClick = function (row, column) {
console.log('cellClick', column)
const walletId = propToWalletId[column.property];
const propToMarketName = {
historyGold: t('clientCount.market.historyGold'),
hkGold: t('clientCount.market.hkGold'),
sgHcGold: t('clientCount.market.sgHcGold'),
myGold: t('clientCount.market.myGold'),
sgGold: t('clientCount.market.sgCmGold'),
caGold: t('clientCount.market.caGold'),
thHsGold: t('clientCount.market.thHsGold'),
thHaGold: t('clientCount.market.thHaGold'),
vnGold: t('clientCount.market.vnGold'),
bjGold: t('clientCount.market.bjGold')
}
const marketName = propToMarketName[column.property]
if (marketName && walletId) {
currentWalletInfo.value = {
userName: row.name,
jwcode: row.jwcode,
marketName: row.market, //
walletName: marketName + t('clientCount.wallet'), //
currentBalance: row[column.property] || 0,
walletId: walletId
}
walletDetailQuery.value.pageNum = 1
getWalletDetail()
walletDetailVisible.value = true
}
}
//
const walletDetailVisible = ref(false)
const walletDetailList = ref([])
const walletDetailTotal = ref(0)
const walletDetailLoading = ref(false)
const currentWalletInfo = ref({})
const walletDetailQuery = ref({
pageNum: 1,
pageSize: 20
})
const getWalletRecordTypeText = (item) => {
const type = Number(item.type)
if (type === 0) {
return t('clientCount.recharge')
}
if (type === 1) {
return t('clientCount.consume')
}
if (type === 2) {
return t('clientCount.refund')
}
return item.typeText || t('clientCount.other')
}
const getWalletDetail = async () => {
walletDetailLoading.value = true
try {
const params = {
pageNum: walletDetailQuery.value.pageNum,
pageSize: walletDetailQuery.value.pageSize,
userWalletRecord: {
jwcode: Number(currentWalletInfo.value.jwcode),
walletId: currentWalletInfo.value.walletId
}
}
const result = await API({
url: '/cashCollection/selectWalletRecords',
method: 'post',
data: params
})
if (result.code === 200) {
walletDetailList.value = result.data.list.map(item => ({
time: moment(item.createTime).format('YYYY-MM-DD HH:mm:ss'),
type: getWalletRecordTypeText(item),
amount: Number(item.amount) || 0,
desc: item.description || '',
orderNo: item.orderCode,
status: item.status === 0 ? 1 : 2
}))
walletDetailTotal.value = result.data.total
} else {
ElMessage.error(result.msg || t('elmessage.getDetailFailed'))
}
} catch (error) {
console.error(error)
} finally {
walletDetailLoading.value = false
}
}
const handleWalletDetailSizeChange = (val) => {
walletDetailQuery.value.pageSize = val
walletDetailQuery.value.pageNum = 1
getWalletDetail()
}
const handleWalletDetailCurrentChange = (val) => {
walletDetailQuery.value.pageNum = val
getWalletDetail()
}
//
const handleSortChange = (column) => {
console.log('排序字段:', column.prop)
console.log('排序方式:', column.order)
if (!column.prop || !column.order) {
sortField.value = ''
sortOrder.value = ''
sortWalletId.value = ''
getObj.value.pageNum = 1
get()
return
}
if (propToWalletId[column.prop]) {
sortField.value = 'currentPermanentGold'
sortWalletId.value = propToWalletId[column.prop]
}
sortOrder.value = column.order === 'ascending' ? 'ASC' : 'DESC'
getObj.value.pageNum = 1
get()
}
//
onMounted(async function () {
await get()
await getMarket()
await getExportList()
})
const handlePageSizeChange = function (val) {
getObj.value.pageSize = val
getObj.value.pageNum = 1
get()
}
const handleCurrentChange = function (val) {
getObj.value.pageNum = val
get()
}
const exportExcel = async function () {
const params = {
pageNum: 1, //
pageSize: 10000, //
}
//
if (selectData.value.jwcode) {
params.jwcode = Number(selectData.value.jwcode)
}
if (selectData.value.markets && selectData.value.markets.length > 0) {
//
params.market = String(selectData.value.markets[0])
}
const res = await API({
url: '/export/exportUserWallet',
method: 'post',
data: params
})
if (res.code === 200) {
ElMessage.success(t('elmessage.exportSuccess'))
//
} else {
ElMessage.error(res.msg || t('elmessage.exportFailed'))
}
}
const exportWalletDetail = async () => {
const params = {
pageNum: walletDetailQuery.value.pageNum,
pageSize: walletDetailQuery.value.pageSize,
userWalletRecord: {
jwcode: Number(currentWalletInfo.value.jwcode),
walletId: currentWalletInfo.value.walletId
}
}
try {
const res = await API({
url: '/export/exportUserWalletRecord',
method: 'post',
data: params
})
if (res.code === 200) {
ElMessage.success(t('elmessage.exportSuccess'))
} else {
ElMessage.error(res.msg || t('elmessage.exportFailed'))
}
} catch (error) {
console.error('导出钱包明细出错:', error)
ElMessage.error(t('elmessage.exportWalletDetailError'))
}
}
const selectWallet = async function () {
selectWalletVisible.value = true
}
const exportExcelOnlyOne = async function () {
if (!selectWalletForm.value.companyWalletId) {
ElMessage.error(t('elmessage.selectCompanyWallet'))
return
}
const params = {
pageNum: 1, //
pageSize: 10000, //
userWalletRecord: {
walletId: selectWalletForm.value.companyWalletId,
jwcode: selectData.value.jwcode ? Number(selectData.value.jwcode) : null
}
}
try {
const res = await API({
url: '/export/exportUserWalletRecord',
method: 'post',
data: params
})
if (res.code === 200) {
ElMessage.success(t('elmessage.exportSuccess'))
openExportList() //
} else {
ElMessage.error(res.msg || t('elmessage.exportFailed'))
}
} catch (error) {
console.error('导出失败:', error)
ElMessage.error(t('elmessage.exportFailed'))
} finally {
selectWalletVisible.value = false
}
}
const exportListVisible = ref(false)
const selectWalletVisible = ref(false)
const selectWalletFormRef = ref(null)
const selectWalletRules = {
companyWalletId: [
{ required: true, message: t('common_list.companyWalletPlaceholder'), trigger: 'change' }
]
}
//
const closeSelectWallet = () => {
//
selectWalletFormRef.value.resetFields()
selectWalletForm.value = {}
selectWalletVisible.value = false
}
const selectWalletForm = ref({})
const companyWalletList = ref([
{
id: 2,
name: t('clientCount.market.hkGold') + t('clientCount.wallet')
},
{
id: 3,
name: t('clientCount.market.sgHcGold')
},
{
id: 4,
name: t('clientCount.market.myGold')
},
{
id: 5,
name: t('clientCount.market.sgCmGold')
},
{
id: 6,
name: t('clientCount.market.caGold')
},
{
id: 7,
name: t('clientCount.market.thHsGold')
},
{
id: 8,
name: t('clientCount.market.thHaGold')
},
{
id: 9,
name: t('clientCount.market.vnGold')
},
{
id: 10,
name: t('clientCount.market.bjGold')
}
])
//
const openExportList = () => {
getExportList()
exportListVisible.value = true
}
//
const exportList = ref([])
//
const exportListLoading = ref(false)
//
const getExportList = async () => {
exportListLoading.value = true
try {
const result = await API({ url: '/export/export' })
if (result.code === 200) {
// type1617
const filteredData = result.data.filter(item => {
return item.type === 16 || item.type === 17;
});
exportList.value = filteredData
} else {
ElMessage.error(result.msg || t('elmessage.getExportListError'))
}
} catch (error) {
console.error('获取导出列表出错:', error)
ElMessage.error(t('elmessage.getExportListError'))
} finally {
exportListLoading.value = false
}
}
//
const downloadExportFile = (item) => {
if (item.state === 2) {
const link = document.createElement('a')
link.href = item.url
link.download = item.fileName
link.click()
} else {
ElMessage.warning(t('elmessage.exportingInProgress'))
}
}
//
const getTagType = (state) => {
switch (state) {
case 0:
return 'info';
case 1:
return 'primary';
case 2:
return 'success';
case 3:
return 'danger';
default:
return 'info';
}
}
//
const getTagText = (state) => {
switch (state) {
case 0:
return t('elmessage.pendingExecution');
case 1:
return t('elmessage.executing');
case 2:
return t('elmessage.executed');
case 3:
return t('elmessage.errorExecution');
default:
return t('elmessage.unknownStatus');
}
}
//
const selectedMarketPath = ref([])
const handleMarketChange = (value) => {
if (value && value.length > 0) {
const lastValue = value[value.length - 1];
//
const marketValue = reverseMarketMapping[lastValue];
selectData.value.markets = Array.isArray(marketValue) ? marketValue : [marketValue];
} else {
// []
selectData.value.markets = [];
}
};
//
const getMarket = async function () {
try {
// POST
const result = await API({
url: '/market/selectMarket',
});
//
console.log('请求成功', result)
//
const transformTree = (nodes) => {
//
const allChildren = nodes.flatMap(node => node.children || []);
return allChildren.map(child => {
const grandchildren = child.children && child.children.length
? transformTree([child]) //
: null;
return {
value: child.name,
label: child.name,
children: grandchildren
};
});
};
//
markets.value = transformTree(result.data)
console.log('转换后的地区树==============', markets.value)
} catch (error) {
console.log('请求失败', error)
}
}
const format3 = (num) => {
//
return num.toLocaleString('en-US')
}
</script>
<template>
<div style="display: flex; flex-direction: column; height: 95vh;">
<el-card class="card1" style="margin-bottom: 1vh;">
<div class="head-card">
<div class="head-card-element">
<el-text class="mx-1" size="large">{{ $t('common.jwcode') }}</el-text>
<el-input v-model="selectData.jwcode" style="width: 160px" :placeholder="$t('common.jwcodePlaceholder')"
clearable />
</div>
<div class="head-card-element">
<el-text class="mx-1" size="large">{{ $t('common_list.market') }}</el-text>
<el-cascader v-model="selectedMarketPath" :options="markets" :placeholder="$t('common_list.marketPlaceholder')"
clearable style="width:180px" @change="handleMarketChange" />
</div>
<div class="head-card-element">
<!-- <el-checkbox v-model="showEmployeeData" @change="search()">员工数据</el-checkbox> -->
</div>
<el-button type="primary" @click="search()">{{ $t('common.search') }}</el-button>
<el-button @click="reset" type="success">{{ $t('common.reset') }}</el-button>
<el-button type="primary" @click="exportExcel()">{{ $t('common.exportExcel') }}</el-button>
<!-- <el-button type="primary" @click="selectWallet()">{{ $t('common.exportCompanyWalletDetail') }}</el-button> -->
<el-button type="primary" @click="openExportList">{{ $t('common.viewExportList') }}</el-button>
</div>
<!-- </div> -->
</el-card>
<el-card class="card2">
<!-- 设置表格容器的高度和滚动样式 -->
<div style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
<el-table ref="tableRef" :data="tableData" @cellClick="cellClick" style="width: 100%; flex: 1"
@sort-change="handleSortChange" :row-style="{ height: '50px' }">
<el-table-column type="index" :label="$t('common_list.id')" width="100px" fixed="left">
<template #default="scope">
<span>{{
scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
}}</span>
</template>
</el-table-column>
<el-table-column prop="name" :label="$t('common_list.name')" width="140" />
<el-table-column prop="jwcode" :label="$t('common_list.jwcode')" width="140" />
<el-table-column prop="market" :label="$t('common_list.market')" width="140" />
<el-table-column prop="historyGold" :label="$t('clientCount.market.historyGold')" sortable="custom"
min-width="140">
<template #default="scope">
<span>{{ (scope.row.historyGold || 0) }}</span>
</template>
</el-table-column>
<el-table-column prop="hkGold" :label="$t('clientCount.market.hkGold')" sortable="custom" min-width="140">
<template #default="scope">
<span>{{ (scope.row.hkGold || 0) }}</span>
</template>
</el-table-column>
<el-table-column prop="sgHcGold" :label="$t('clientCount.market.sgHcGold')" sortable="custom" min-width="150">
<template #default="scope">
<span>{{ (scope.row.sgHcGold || 0) }}</span>
</template>
</el-table-column>
<el-table-column prop="myGold" :label="$t('clientCount.market.myGold')" sortable="custom" min-width="120">
<template #default="scope">
<span>{{ (scope.row.myGold || 0) }}</span>
</template>
</el-table-column>
<el-table-column prop="sgGold" :label="$t('clientCount.market.sgCmGold')" sortable="custom" min-width="150">
<template #default="scope">
<span>{{ (scope.row.sgGold || 0) }}</span>
</template>
</el-table-column>
<el-table-column prop="caGold" :label="$t('clientCount.market.caGold')" sortable="custom" min-width="120">
<template #default="scope">
<span>{{ (scope.row.caGold || 0) }}</span>
</template>
</el-table-column>
<el-table-column prop="thHsGold" :label="$t('clientCount.market.thHsGold')" sortable="custom" min-width="140">
<template #default="scope">
<span>{{ (scope.row.thHsGold || 0) }}</span>
</template>
</el-table-column>
<el-table-column prop="thHaGold" :label="$t('clientCount.market.thHaGold')" sortable="custom" min-width="140">
<template #default="scope">
<span>{{ (scope.row.thHaGold || 0) }}</span>
</template>
</el-table-column>
<el-table-column prop="vnGold" :label="$t('clientCount.market.vnGold')" sortable="custom" min-width="120">
<template #default="scope">
<span>{{ (scope.row.vnGold || 0) }}</span>
</template>
</el-table-column>
<el-table-column prop="bjGold" :label="$t('clientCount.market.bjGold')" sortable="custom" min-width="120">
<template #default="scope">
<span>{{ (scope.row.bjGold || 0) }}</span>
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div class="pagination" style="margin-top: 20px">
<el-pagination background :current-page="getObj.pageNum" :page-size="getObj.pageSize"
:page-sizes="[5, 10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper" :total="total"
@size-change="handlePageSizeChange" @current-change="handleCurrentChange"></el-pagination>
</div>
</el-card>
</div>
<el-dialog v-model="exportListVisible" :title="$t('common_export.exportList')" width="80%">
<el-table :data="exportList" style="width: 100% ;height: 60vh;" :loading="exportListLoading">
<el-table-column prop="fileName" :label="$t('common_export.fileName')" />
<el-table-column prop="state" :label="$t('common_export.status')">
<template #default="scope">
<el-tag :type="getTagType(scope.row.state)" :effect="scope.row.state === 3 ? 'light' : 'plain'">
{{ getTagText(scope.row.state) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('common_export.createTime')">
<template #default="scope">
{{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
</template>
</el-table-column>
<el-table-column :label="$t('common_export.operation')">
<template #default="scope">
<el-button type="primary" size="small" @click="downloadExportFile(scope.row)"
:disabled="scope.row.state !== 2">
{{ $t('common_export.download') }}
</el-button>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button text @click="exportListVisible = false">{{ $t('common_export.close') }}</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="selectWalletVisible" width="30%" top="20%" :before-close="closeSelectWallet">
<el-form :model="selectWalletForm" :rules="selectWalletRules" ref="selectWalletFormRef" label-width="120px">
<el-form-item :label="$t('common_list.companyWallet')" prop="companyWalletId" style="margin-top: 30px;">
<el-select v-model="selectWalletForm.companyWalletId" :placeholder="$t('common_list.companyWalletPlaceholder')"
style="width: 80%;">
<el-option v-for="item in companyWalletList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div style="display: flex; justify-content: flex-end;">
<el-button type="primary" @click="exportExcelOnlyOne()">{{ $t('common.confirm') }}</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="walletDetailVisible" width="70%" top="20vh">
<template #header>
<div class="wallet-detail-header"
style="display: flex; gap: 40px; justify-content: space-between; align-items: center; font-size: 16px;">
<span style="font-weight: bold; color: #F56C6C;">* {{ currentWalletInfo.walletName }}</span>
<span><span style="color: #F56C6C;">*</span> {{ $t('clientCount.user') }}: {{ currentWalletInfo.userName }} (ID:
{{ currentWalletInfo.jwcode }})</span>
<span><span style="color: #F56C6C;">*</span> {{ $t('common.market') }}: {{ currentWalletInfo.marketName
}}</span>
</div>
<div style="margin-top: 15px; font-size: 16px;">
<span style="color: #F56C6C; font-weight: bold;">* {{ $t('clientCount.currentBalance') }}: {{
format3(currentWalletInfo.currentBalance || 0) }} {{ $t('common.goldCoin') }}</span>
</div>
</template>
<el-table :data="walletDetailList" v-loading="walletDetailLoading"
style="width: 100%; height: 50vh; overflow-y: auto;" border stripe>
<el-table-column prop="time" :label="$t('clientCount.time')" align="center" width="180">
<template #default="scope">{{ scope.row.time }}</template>
</el-table-column>
<el-table-column prop="type" :label="$t('clientCount.transactionType')" align="center" width="120" />
<el-table-column prop="amount" :label="$t('common_list.money')" align="center" width="120">
<template #default="scope">
<span :style="{ color: scope.row.amount >= 0 ? '#67C23A' : '#F56C6C', fontWeight: 'bold' }">
{{ scope.row.amount > 0 ? '+' + format3(scope.row.amount) : format3(scope.row.amount) }}
</span>
</template>
</el-table-column>
<el-table-column prop="desc" :label="$t('clientCount.transactionDesc')" align="center" />
<el-table-column prop="orderNo" :label="$t('clientCount.transactionOrderNo')" align="center" width="220" />
<el-table-column prop="status" :label="$t('clientCount.transactionStatus')" align="center" width="220"
fixed="right">
<template #default="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : scope.row.status === 2 ? 'danger' : 'info'"
:effect="scope.row.status === 1 ? 'light' : 'plain'">
{{ scope.row.status === 1 ? t('common_list.normal') : scope.row.status === 2 ? t('common_list.refunded') :
t('clientCount.exceptionData') }}
</el-tag>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer" style="display: flex; justify-content: space-between; align-items: center;">
<div class="pagination-container">
<el-pagination background :current-page="walletDetailQuery.pageNum" :page-size="walletDetailQuery.pageSize"
:page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper" :total="walletDetailTotal"
@size-change="handleWalletDetailSizeChange" @current-change="handleWalletDetailCurrentChange" />
</div>
<div>
<el-button type="primary" @click="exportWalletDetail">{{ $t('common.exportExcel') }}</el-button>
<el-button text @click="walletDetailVisible = false">{{ $t('common_export.close') }}</el-button>
</div>
</div>
</template>
</el-dialog>
</template>
<style scoped lang="scss">
//
.card1 {
background: #F3FAFE;
}
//
.card2 {
background: #E7F4FD;
flex: 1;
display: flex;
flex-direction: column;
:deep(.el-card__body) {
padding: 20px;
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
}
//
:deep(.el-table__header-wrapper),
:deep(.el-table__body-wrapper),
:deep(.el-table__cell),
/* 表格 */
:deep(.el-table__body td) {
background-color: #F3FAFE !important;
}
/* 表头 */
:deep(.el-table__header th) {
background-color: #F3FAFE !important;
}
/* 鼠标悬停 */
:deep(.el-table__row:hover > .el-table__cell) {
background-color: #E5EBFE !important;
}
.pagination {
display: flex;
}
.status {
display: flex;
}
.head-card {
display: flex;
}
.head-card-element {
margin-right: 20px;
}
.head-card-btn {
margin-left: auto;
}
.custom-box {
display: flex;
flex-wrap: wrap;
row-gap: 5px;
div:nth-child(1) {
flex: 1 0 100%;
}
div {
margin-right: 20px;
}
}
</style>

472
src/views/walletManage/components/WalletDetailTemplate.vue

@ -0,0 +1,472 @@
<script setup>
import { ref, watch, nextTick, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import API from '@/util/http.js'
import moment from 'moment'
import { useI18n } from 'vue-i18n'
import { useAdminStore } from "@/store/index.js"
import { storeToRefs } from "pinia"
import { selectWalletRecords } from "@/api/cash/cash.js"
const props = defineProps({
type: {
type: Number,
required: true
}
})
const { t } = useI18n()
const route = useRoute()
const adminStore = useAdminStore()
const { flag } = storeToRefs(adminStore)
const tableData = ref([])
const total = ref(0)
const loading = ref(false)
const marketLists = ref([])
const selectedMarketPath = ref([])
const selectData = ref({
jwcode: '',
walletId: '',
market: ''
})
const getObj = ref({
pageNum: 1,
pageSize: 20
})
const tableRef = ref(null)
const scrollTableTop = () => {
tableRef.value?.setScrollTop?.(0)
}
//
const trimJwCode = () => {
if (selectData.value.jwcode) {
selectData.value.jwcode = selectData.value.jwcode.replace(/\s/g, '');
}
}
//
const getWalletRecordTypeText = (item) => {
const type = Number(item.type)
if (type === 0) {
return t('clientCount.recharge')
}
if (type === 1) {
return t('clientCount.consume')
}
if (type === 2) {
return t('clientCount.refund')
}
return item.typeText || t('clientCount.other')
}
//
const format3 = (num) => {
return num.toLocaleString('en-US')
}
//
const getWalletData = async () => {
console.log('walletId:', selectData.value.walletId)
if (!selectData.value.walletId) return;
if (selectData.value.jwcode) {
const numberRegex = /^\d{1,9}$/;
if (!numberRegex.test(selectData.value.jwcode)) {
ElMessage.error(t('elmessage.checkJwcodeFormat'))
return
}
}
loading.value = true
try {
const params = {
pageNum: getObj.value.pageNum,
pageSize: getObj.value.pageSize,
userWalletRecord: {
walletId: selectData.value.walletId,
market: selectData.value.market,
jwcode: selectData.value.jwcode
}
}
const result = await selectWalletRecords(params)
if (result.code === 200) {
tableData.value = result.data.list.map(item => ({
...item,
time: moment(item.createTime).format('YYYY-MM-DD HH:mm:ss'),
typeText: getWalletRecordTypeText(item),
amount: Number(item.amount) || 0,
desc: item.description || '',
orderNo: item.orderCode,
status: item.status === 0 ? 1 : 2,
userName: item.userName || '-',
jwcode: item.jwcode || '-'
}))
total.value = result.data.total
await nextTick()
scrollTableTop()
} else {
ElMessage.error(result.msg || t('elmessage.getDataFailed'))
}
} catch (error) {
console.error('获取钱包明细失败:', error)
} finally {
loading.value = false
}
}
//
const search = function () {
trimJwCode()
getObj.value.pageNum = 1
getWalletData()
}
//
const reset = function () {
selectData.value.jwcode = ''
selectData.value.market = ''
selectedMarketPath.value = []
getObj.value.pageNum = 1
getWalletData()
}
//
const handlePageSizeChange = function (val) {
getObj.value.pageSize = val
getWalletData()
}
const handleCurrentChange = function (val) {
getObj.value.pageNum = val
getWalletData()
}
// flag
watch(flag, (newFlag, oldFlag) => {
if (newFlag !== oldFlag) {
getWalletData()
}
})
// props
watch(
() => props.type,
(newType) => {
if (newType) {
selectData.value.walletId = newType
getObj.value.pageNum = 1
getWalletData()
}
},
{ immediate: true }
)
// ==================== ====================
const exportListVisible = ref(false)
const exportList = ref([])
const exportListLoading = ref(false)
const exportExcelOnlyOne = async function () {
if (!selectData.value.walletId) {
ElMessage.error(t('elmessage.selectCompanyWallet'))
return
}
const params = {
pageNum: 1, //
pageSize: 10000, //
userWalletRecord: {
walletId: selectData.value.walletId,
jwcode: selectData.value.jwcode ? Number(selectData.value.jwcode) : null
}
}
try {
const res = await API({
url: '/export/exportUserWalletRecord',
method: 'post',
data: params
})
if (res.code === 200) {
ElMessage.success(t('elmessage.exportSuccess'))
} else {
ElMessage.error(res.msg || t('elmessage.exportFailed'))
}
} catch (error) {
console.error('导出失败:', error)
ElMessage.error(t('elmessage.exportFailed'))
}
}
//
const openExportList = () => {
getExportList()
exportListVisible.value = true
}
//
const getExportList = async () => {
exportListLoading.value = true
try {
const result = await API({ url: '/export/export' })
if (result.code === 200) {
// type 16 17 WalletBalance
const filteredData = result.data.filter(item => {
return item.type === 16 || item.type === 17;
});
exportList.value = filteredData
} else {
ElMessage.error(result.msg || t('elmessage.getExportListError'))
}
} catch (error) {
console.error('获取导出列表出错:', error)
ElMessage.error(t('elmessage.getExportListError'))
} finally {
exportListLoading.value = false
}
}
//
const downloadExportFile = (item) => {
if (item.state === 2) {
const link = document.createElement('a')
link.href = item.url
link.download = item.fileName
link.click()
} else {
ElMessage.warning(t('elmessage.exportingInProgress'))
}
}
//
const getTagType = (state) => {
switch (state) {
case 0: return 'info';
case 1: return 'primary';
case 2: return 'success';
case 3: return 'danger';
default: return 'info';
}
}
//
const getTagText = (state) => {
switch (state) {
case 0: return t('elmessage.pendingExecution');
case 1: return t('elmessage.executing');
case 2: return t('elmessage.executed');
case 3: return t('elmessage.errorExecution');
default: return t('elmessage.unknownStatus');
}
}
const transformTree = (nodes) => {
//
const allChildren = nodes.flatMap(node => node.children || []);
return allChildren.map(child => {
const grandchildren = child.children && child.children.length
? transformTree([child]) //
: null;
return {
value: child.id,
label: child.name,
children: grandchildren
};
});
};
const selectMarket = async function () {
try {
const selectMarketResult = await API({ url: '/market/selectMarket' });
marketLists.value = transformTree(selectMarketResult.data)
console.log('转换后的地区树==============:', marketLists.value);
} catch (error) {
console.error('获取地区树失败:', error);
return {};
}
};
const handleMarketChange = (value) => {
if (value && value.length > 0) {
// id id
const lastValueId = value[value.length - 1];
selectData.value.market = lastValueId;
} else {
selectData.value.market = '';
}
};
onMounted(() => {
selectData.value.walletId = props.type
selectMarket()
})
</script>
<template>
<div style="display: flex; flex-direction: column; height: 95vh;">
<el-card class="card1" style="margin-bottom: 1vh;">
<div class="head-card">
<div class="head-card-element">
<el-text class="mx-1" size="large">{{ $t('common_list.jwcode') }}</el-text>
<el-input v-model="selectData.jwcode" style="width: 12.5vw" :placeholder="$t('common.jwcodePlaceholder')" clearable />
</div>
<div class="head-card-element">
<el-text class="mx-1" size="large">{{ $t('common_list.market') }}</el-text>
<el-cascader v-model="selectedMarketPath" :options="marketLists" :placeholder="$t('common_list.marketPlaceholder')"
clearable style="width:180px" @change="handleMarketChange" />
</div>
<div class="head-card-btn">
<el-button type="success" @click="reset">{{ $t('common.reset') }}</el-button>
<el-button type="primary" @click="search">{{ $t('common.search') }}</el-button>
<el-button type="primary" @click="exportExcelOnlyOne">{{ $t('common.exportExcel') }}</el-button>
<el-button type="primary" @click="openExportList">{{ $t('common.viewExportList') }}</el-button>
</div>
</div>
</el-card>
<el-card class="card2">
<div style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
<el-table ref="tableRef" :data="tableData" v-loading="loading" style="width: 100%; flex: 1"
:row-style="{ height: '50px' }">
<el-table-column type="index" :label="$t('common_list.id')" width="80px" fixed="left">
<template #default="scope">
<span>{{ scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize }}</span>
</template>
</el-table-column>
<el-table-column prop="jwcode" :label="$t('common_list.jwcode')" width="140" />
<el-table-column prop="userName" :label="$t('common_list.name')" width="140" />
<el-table-column prop="marketName" :label="$t('common_list.marketName')" width="140" />
<el-table-column prop="typeText" :label="$t('clientCount.transactionType')" align="center" width="120" />
<el-table-column prop="transactionCurrency" :label="$t('clientCount.transactionCurrency')" align="center"
width="120" />
<el-table-column prop="amount" :label="$t('common_list.money')" align="center" width="120">
<template #default="scope">
<span :style="{ color: scope.row.amount >= 0 ? '#67C23A' : '#F56C6C', fontWeight: 'bold' }">
{{ scope.row.amount > 0 ? '+' + format3(scope.row.amount) : format3(scope.row.amount) }}
</span>
</template>
</el-table-column>
<el-table-column prop="orderNo" :label="$t('clientCount.transactionOrderNo')" align="center" min-width="320" />
<el-table-column prop="desc" :label="$t('clientCount.transactionDesc')" align="center" min-width="150" />
<el-table-column prop="status" :label="$t('clientCount.transactionStatus')" align="center" width="150">
<template #default="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : scope.row.status === 2 ? 'danger' : 'info'"
:effect="scope.row.status === 1 ? 'light' : 'plain'">
{{ scope.row.status === 1 ? t('common_list.normal') : scope.row.status === 2 ? t('common_list.refunded')
: t('clientCount.exceptionData') }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="time" :label="$t('clientCount.time')" align="center" width="180">
<template #default="scope">{{ scope.row.time }}</template>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div class="pagination" style="margin-top: 20px">
<el-pagination background :current-page="getObj.pageNum" :page-size="getObj.pageSize"
:page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper" :total="total"
@size-change="handlePageSizeChange" @current-change="handleCurrentChange"></el-pagination>
</div>
</el-card>
<!-- 导出列表弹窗 -->
<el-dialog v-model="exportListVisible" :title="$t('common_export.exportList')" width="80%">
<el-table :data="exportList" style="width: 100% ;height: 60vh;" :loading="exportListLoading">
<el-table-column prop="fileName" :label="$t('common_export.fileName')" />
<el-table-column prop="state" :label="$t('common_export.status')">
<template #default="scope">
<el-tag :type="getTagType(scope.row.state)" :effect="scope.row.state === 3 ? 'light' : 'plain'">
{{ getTagText(scope.row.state) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('common_export.createTime')">
<template #default="scope">
{{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
</template>
</el-table-column>
<el-table-column :label="$t('common_export.operation')">
<template #default="scope">
<el-button type="primary" size="small" @click="downloadExportFile(scope.row)"
:disabled="scope.row.state !== 2">
{{ $t('common_export.download') }}
</el-button>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button text @click="exportListVisible = false">{{ $t('common_export.close') }}</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<style scoped lang="scss">
.card1 {
background: #F3FAFE;
}
.card2 {
background: #E7F4FD;
flex: 1;
display: flex;
flex-direction: column;
:deep(.el-card__body) {
padding: 20px;
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
}
:deep(.el-table__header-wrapper),
:deep(.el-table__body-wrapper),
:deep(.el-table__cell),
:deep(.el-table__body td) {
background-color: #F3FAFE !important;
}
:deep(.el-table__header th) {
background-color: #F3FAFE !important;
}
:deep(.el-table__row:hover > .el-table__cell) {
background-color: #E5EBFE !important;
}
.pagination {
display: flex;
}
.head-card {
display: flex;
}
.head-card-element {
margin-right: 20px;
white-space: nowrap;
.mx-1 {
font-size: 16px;
margin: 0 10px;
}
}
.head-card-btn {
margin-left: 100px;
}
</style>

10
src/views/walletManage/walletDetail/BJWallet.vue

@ -0,0 +1,10 @@
<!-- 北京钱包界面 -->
<template>
<div>
<WalletDetailTemplate :type="10" />
</div>
</template>
<script setup>
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue'
</script>
<style scoped></style>

10
src/views/walletManage/walletDetail/CAWallet.vue

@ -0,0 +1,10 @@
<!-- 加拿大钱包界面 -->
<template>
<div>
<WalletDetailTemplate :type="6" />
</div>
</template>
<script setup>
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue'
</script>
<style scoped></style>

12
src/views/walletManage/walletDetail/HKWallet.vue

@ -0,0 +1,12 @@
<!-- 初始界面 -->
<template>
<div>
<WalletDetailTemplate :type="2" />
</div>
</template>
<script setup>
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue'
</script>
<style scoped>
</style>

10
src/views/walletManage/walletDetail/MyWallet.vue

@ -0,0 +1,10 @@
<!-- 马来钱包界面 -->
<template>
<div>
<WalletDetailTemplate :type="4" />
</div>
</template>
<script setup>
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue'
</script>
<style scoped></style>

10
src/views/walletManage/walletDetail/SGWalletCM.vue

@ -0,0 +1,10 @@
<!-- 新加坡CM钱包界面 -->
<template>
<div>
<WalletDetailTemplate :type="5" />
</div>
</template>
<script setup>
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue'
</script>
<style scoped></style>

10
src/views/walletManage/walletDetail/SGWalletHC.vue

@ -0,0 +1,10 @@
<!-- 新加坡HC钱包界面 -->
<template>
<div>
<WalletDetailTemplate :type="3" />
</div>
</template>
<script setup>
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue'
</script>
<style scoped></style>

10
src/views/walletManage/walletDetail/THWalletHA.vue

@ -0,0 +1,10 @@
<!-- 泰国HA钱包界面 -->
<template>
<div>
<WalletDetailTemplate :type="8" />
</div>
</template>
<script setup>
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue'
</script>
<style scoped></style>

10
src/views/walletManage/walletDetail/THWalletHS.vue

@ -0,0 +1,10 @@
<!-- 泰国HS钱包界面 -->
<template>
<div>
<WalletDetailTemplate :type="7" />
</div>
</template>
<script setup>
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue'
</script>
<style scoped></style>

10
src/views/walletManage/walletDetail/VNWallet.vue

@ -0,0 +1,10 @@
<!-- 越南钱包界面 -->
<template>
<div>
<WalletDetailTemplate :type="9" />
</div>
</template>
<script setup>
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue'
</script>
<style scoped></style>
Loading…
Cancel
Save