Compare commits
merge into: huangqizhen:master
huangqizhen:0919test
huangqizhen:dev
huangqizhen:huangqizheng/feature-20250702164103-登录页面退出登录
huangqizhen:huangqizheng/feature-20251213090502-现金退款多语言
huangqizhen:jiangcheng/feature-20260226111316-test
huangqizhen:jiangcheng/feature-20260306102603-钱包体系
huangqizhen:jiangcheng/feature-20260326164657-金币日常优化3.0
huangqizhen:jiangcheng/feature-20260402142510-现金四期
huangqizhen:lihui/feature-20250623144029-金币前端lihui
huangqizhen:lihui/feature-20250711103624-金币二期
huangqizhen:lihui/feature-20250728114233-金币前端三期
huangqizhen:lihui/feature-20250815155204-金币优化
huangqizhen:lihui/feature-20250915101448-现金管理
huangqizhen:lihui/feature-20250915101448-紧急
huangqizhen:lihui/feature-20251104165712-现金二期
huangqizhen:lihuilin/feature-20251104102812-现金二期
huangqizhen:lihuilin/feature-20251212182509-多语言二期
huangqizhen:lihuilin/feature-20260121173255-多语言二期2合并
huangqizhen:master
huangqizhen:milestone-20250623-金币前端
huangqizhen:milestone-20250711-金币前端二期
huangqizhen:milestone-20250728-金币前端三期
huangqizhen:milestone-20250815-金币优化
huangqizhen:milestone-20250913-现金管理
huangqizhen:milestone-20250917-重构工作台
huangqizhen:milestone-20251104-现金二期
huangqizhen:milestone-20251125-多语言
huangqizhen:milestone-20251209-多语言二期
huangqizhen:milestone-20251215-多语言二期2
huangqizhen:milestone-20251215-现金管理三期
huangqizhen:milestone-20251217-红包
huangqizhen:milestone-20260128-日常优化1.0
huangqizhen:milestone-20260212-日常优化2.0
huangqizhen:milestone-20260304-钱包体系
huangqizhen:milestone-20260328-金币日常优化3.0
huangqizhen:milestone-20260402-现金4期
huangqizhen:youhua/chongzhi
huangqizhen:zhangrenyuan/feature-20250623164058-金币前端
huangqizhen:zhangrenyuan/feature-20250714163943-金币前端二期
huangqizhen:zhangrenyuan/feature-20250728113353-金币前端三期
huangqizhen:zhangrenyuan/feature-20250817091555-金币优化
huangqizhen:zhangrenyuan/feature-20250917134308-现金管理
huangqizhen:zhangrenyuan/feature-20251104133449-现金管理二期
huangqizhen:zhangrenyuan/feature-20251125114759-多语言
huangqizhen:zhangrenyuan/feature-20251209163007-多语言二期
huangqizhen:zhangrenyuan/feature-20251215114424-现金管理三期
huangqizhen:zhangrenyuan/feature-20260113104415-现金重构
huangqizhen:zhangrenyuan/feature-20260119112612-红包
huangqizhen:zhangrenyuan/feature-20260128093451-日常优化1.0
huangqizhen:zhangrenyuan/feature-20260211101424-日常优化2.0
huangqizhen:zhangrenyuan/feature-20260305110430-钱包体系
huangqizhen:zhangrenyuan/feature-20260326164720-日常优化3.0
huangqizhen:zhangyong/feature-20250716164232-金币前端
huangqizhen:zhangyong/feature-20250815160302-金币优化
huangqizhen:zhangyong/feature-20260113094820-现金重构
huangqizhen:zhangyong/feature-20260211100322-日常优化2.0
huangqizhen:zhangyong/feature-20260402144402-现金4期
huangqizhen:zhangyong/milestone-20250913-现金管理
huangqizhen:zhangyong/milestone-20250913-现金管理二期
pull from: huangqizhen:milestone-20260402-现金4期
huangqizhen:0919test
huangqizhen:dev
huangqizhen:huangqizheng/feature-20250702164103-登录页面退出登录
huangqizhen:huangqizheng/feature-20251213090502-现金退款多语言
huangqizhen:jiangcheng/feature-20260226111316-test
huangqizhen:jiangcheng/feature-20260306102603-钱包体系
huangqizhen:jiangcheng/feature-20260326164657-金币日常优化3.0
huangqizhen:jiangcheng/feature-20260402142510-现金四期
huangqizhen:lihui/feature-20250623144029-金币前端lihui
huangqizhen:lihui/feature-20250711103624-金币二期
huangqizhen:lihui/feature-20250728114233-金币前端三期
huangqizhen:lihui/feature-20250815155204-金币优化
huangqizhen:lihui/feature-20250915101448-现金管理
huangqizhen:lihui/feature-20250915101448-紧急
huangqizhen:lihui/feature-20251104165712-现金二期
huangqizhen:lihuilin/feature-20251104102812-现金二期
huangqizhen:lihuilin/feature-20251212182509-多语言二期
huangqizhen:lihuilin/feature-20260121173255-多语言二期2合并
huangqizhen:master
huangqizhen:milestone-20250623-金币前端
huangqizhen:milestone-20250711-金币前端二期
huangqizhen:milestone-20250728-金币前端三期
huangqizhen:milestone-20250815-金币优化
huangqizhen:milestone-20250913-现金管理
huangqizhen:milestone-20250917-重构工作台
huangqizhen:milestone-20251104-现金二期
huangqizhen:milestone-20251125-多语言
huangqizhen:milestone-20251209-多语言二期
huangqizhen:milestone-20251215-多语言二期2
huangqizhen:milestone-20251215-现金管理三期
huangqizhen:milestone-20251217-红包
huangqizhen:milestone-20260128-日常优化1.0
huangqizhen:milestone-20260212-日常优化2.0
huangqizhen:milestone-20260304-钱包体系
huangqizhen:milestone-20260328-金币日常优化3.0
huangqizhen:milestone-20260402-现金4期
huangqizhen:youhua/chongzhi
huangqizhen:zhangrenyuan/feature-20250623164058-金币前端
huangqizhen:zhangrenyuan/feature-20250714163943-金币前端二期
huangqizhen:zhangrenyuan/feature-20250728113353-金币前端三期
huangqizhen:zhangrenyuan/feature-20250817091555-金币优化
huangqizhen:zhangrenyuan/feature-20250917134308-现金管理
huangqizhen:zhangrenyuan/feature-20251104133449-现金管理二期
huangqizhen:zhangrenyuan/feature-20251125114759-多语言
huangqizhen:zhangrenyuan/feature-20251209163007-多语言二期
huangqizhen:zhangrenyuan/feature-20251215114424-现金管理三期
huangqizhen:zhangrenyuan/feature-20260113104415-现金重构
huangqizhen:zhangrenyuan/feature-20260119112612-红包
huangqizhen:zhangrenyuan/feature-20260128093451-日常优化1.0
huangqizhen:zhangrenyuan/feature-20260211101424-日常优化2.0
huangqizhen:zhangrenyuan/feature-20260305110430-钱包体系
huangqizhen:zhangrenyuan/feature-20260326164720-日常优化3.0
huangqizhen:zhangyong/feature-20250716164232-金币前端
huangqizhen:zhangyong/feature-20250815160302-金币优化
huangqizhen:zhangyong/feature-20260113094820-现金重构
huangqizhen:zhangyong/feature-20260211100322-日常优化2.0
huangqizhen:zhangyong/feature-20260402144402-现金4期
huangqizhen:zhangyong/milestone-20250913-现金管理
huangqizhen:zhangyong/milestone-20250913-现金管理二期
51 Commits
master
...
milestone-
31 changed files with 2964 additions and 338 deletions
-
22.env.development
-
2.gitignore
-
10src/api/cash/cash.js
-
9src/api/cash/financialAccount.js
-
27src/assets/SvgIcons/wallet_management.svg
-
79src/components/locales/lang/en.js
-
116src/components/locales/lang/zh-CN.js
-
50src/components/workspace/CashManagement.vue
-
114src/components/workspace/GoldManagement.vue
-
90src/router/index.js
-
0src/static/common.js
-
3src/utils/menuTreePermission.js
-
17src/utils/menuUtils.js
-
6src/views/activityManage/activity.vue
-
1src/views/home.vue
-
7src/views/moneyManage/executor/executor.vue
-
755src/views/moneyManage/financialAccount/cashFlow.vue
-
431src/views/moneyManage/financialAccount/performanceAttribution.vue
-
51src/views/moneyManage/receiveDetail/receiveService.vue
-
15src/views/usergold/gold/clientCount.vue
-
913src/views/walletManage/WalletBalance.vue
-
472src/views/walletManage/components/WalletDetailTemplate.vue
-
10src/views/walletManage/walletDetail/BJWallet.vue
-
10src/views/walletManage/walletDetail/CAWallet.vue
-
12src/views/walletManage/walletDetail/HKWallet.vue
-
10src/views/walletManage/walletDetail/MyWallet.vue
-
10src/views/walletManage/walletDetail/SGWalletCM.vue
-
10src/views/walletManage/walletDetail/SGWalletHC.vue
-
10src/views/walletManage/walletDetail/THWalletHA.vue
-
10src/views/walletManage/walletDetail/THWalletHS.vue
-
10src/views/walletManage/walletDetail/VNWallet.vue
@ -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/' |
|||
@ -0,0 +1,10 @@ |
|||
import http from '@/util/http.js' |
|||
|
|||
// 查询钱包记录
|
|||
export const selectWalletRecords = (data) => { |
|||
return http({ |
|||
method: 'POST', |
|||
url: '/cashCollection/selectWalletRecords', |
|||
data |
|||
}) |
|||
} |
|||
@ -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> |
|||
@ -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) { |
|||
// 过滤只显示type为16和17的导出记录 |
|||
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> |
|||
@ -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> |
|||
@ -0,0 +1,10 @@ |
|||
<!-- 北京钱包界面 --> |
|||
<template> |
|||
<div> |
|||
<WalletDetailTemplate :type="10" /> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue' |
|||
</script> |
|||
<style scoped></style> |
|||
@ -0,0 +1,10 @@ |
|||
<!-- 加拿大钱包界面 --> |
|||
<template> |
|||
<div> |
|||
<WalletDetailTemplate :type="6" /> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue' |
|||
</script> |
|||
<style scoped></style> |
|||
@ -0,0 +1,12 @@ |
|||
<!-- 初始界面 --> |
|||
<template> |
|||
<div> |
|||
<WalletDetailTemplate :type="2" /> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue' |
|||
</script> |
|||
<style scoped> |
|||
|
|||
</style> |
|||
@ -0,0 +1,10 @@ |
|||
<!-- 马来钱包界面 --> |
|||
<template> |
|||
<div> |
|||
<WalletDetailTemplate :type="4" /> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue' |
|||
</script> |
|||
<style scoped></style> |
|||
@ -0,0 +1,10 @@ |
|||
<!-- 新加坡CM钱包界面 --> |
|||
<template> |
|||
<div> |
|||
<WalletDetailTemplate :type="5" /> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue' |
|||
</script> |
|||
<style scoped></style> |
|||
@ -0,0 +1,10 @@ |
|||
<!-- 新加坡HC钱包界面 --> |
|||
<template> |
|||
<div> |
|||
<WalletDetailTemplate :type="3" /> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue' |
|||
</script> |
|||
<style scoped></style> |
|||
@ -0,0 +1,10 @@ |
|||
<!-- 泰国HA钱包界面 --> |
|||
<template> |
|||
<div> |
|||
<WalletDetailTemplate :type="8" /> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue' |
|||
</script> |
|||
<style scoped></style> |
|||
@ -0,0 +1,10 @@ |
|||
<!-- 泰国HS钱包界面 --> |
|||
<template> |
|||
<div> |
|||
<WalletDetailTemplate :type="7" /> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue' |
|||
</script> |
|||
<style scoped></style> |
|||
@ -0,0 +1,10 @@ |
|||
<!-- 越南钱包界面 --> |
|||
<template> |
|||
<div> |
|||
<WalletDetailTemplate :type="9" /> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import WalletDetailTemplate from '../components/WalletDetailTemplate.vue' |
|||
</script> |
|||
<style scoped></style> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue