You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

913 lines
28 KiB

2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
  1. <script setup>
  2. // 这是客户钱包页面
  3. import { useAdminStore } from "@/store/index.js"
  4. import { storeToRefs } from "pinia"
  5. import { findMenuById, permissionMapping } from "@/utils/menuTreePermission.js"
  6. const adminStore = useAdminStore()
  7. const { adminData, menuTree, flag } = storeToRefs(adminStore)
  8. // 监听全局flag状态变化(员工数据的)
  9. watch(flag, (newFlag, oldFlag) => {
  10. // 当flag状态改变时,重新发送请求
  11. if (newFlag !== oldFlag) {
  12. console.log('员工数据flag状态改变,重新加载数据', newFlag)
  13. get()
  14. }
  15. })
  16. import { onMounted, ref, watch, nextTick } from 'vue'
  17. import { ElMessage } from 'element-plus'
  18. import moment from 'moment'
  19. import API from '@/util/http.js'
  20. import { reverseMarketMapping } from "@/utils/marketMap.js";
  21. // 国际化
  22. import { useI18n } from 'vue-i18n'
  23. const { t } = useI18n()
  24. // 变量
  25. const dialogVisible = ref(false)
  26. // 定义加载状态,获取地区数据
  27. const markets = ref([])
  28. // 充值明细表格
  29. // 替换你代码中的 tableData 初始化部分
  30. const tableData = ref([]);
  31. const walletMap = {
  32. 1: 'historyGold',
  33. 2: 'hkGold',
  34. 3: 'sgHcGold',
  35. 4: 'myGold',
  36. 5: 'sgGold',
  37. 6: 'caGold',
  38. 7: 'thHsGold',
  39. 8: 'thHaGold',
  40. 9: 'vnGold',
  41. 10: 'bjGold'
  42. };
  43. const propToWalletId = {
  44. historyGold: 1,
  45. hkGold: 2,
  46. sgHcGold: 3,
  47. myGold: 4,
  48. sgGold: 5,
  49. caGold: 6,
  50. thHsGold: 7,
  51. thHaGold: 8,
  52. vnGold: 9,
  53. bjGold: 10
  54. };
  55. const tableRef = ref(null)
  56. const scrollTableTop = () => {
  57. tableRef.value?.setScrollTop?.(0)
  58. }
  59. //客户消费记录
  60. const userInfo = ref({})
  61. // 搜索===========================================
  62. //分页总条目
  63. const total = ref(100)
  64. // 搜索对象时间
  65. const getTime = ref([])
  66. // 搜索User
  67. const selectData = ref({
  68. jwcode: '',
  69. markets: [],
  70. })
  71. // 不分页的搜索对象
  72. const getAllObj = ref({})
  73. // 搜索对象
  74. const getObj = ref({
  75. pageNum: 1,
  76. pageSize: 50
  77. })
  78. // 新增排序字段和排序方式
  79. const sortField = ref('')
  80. const sortOrder = ref('')
  81. const sortWalletId = ref('')
  82. // 方法
  83. // 搜索===========================================================================
  84. // 搜索方法
  85. const get = async function (val) {
  86. try {
  87. // 搜索参数页码赋值
  88. if (typeof val === 'number') {
  89. getObj.value.pageNum = val
  90. }
  91. if (selectData.value.jwcode) {
  92. // 纯数字
  93. const numberRegex = /^\d{1,9}$/;
  94. // 检查是否不是数字
  95. if (!numberRegex.test(selectData.value.jwcode)) {
  96. ElMessage.error(t('elmessage.checkJwcodeFormat'))
  97. return
  98. }
  99. }
  100. console.log('搜索参数', getObj.value, selectData.value)
  101. // 构建请求参数
  102. const params = {
  103. pageNum: getObj.value.pageNum,
  104. pageSize: getObj.value.pageSize
  105. }
  106. // 只有当有值时才加入参数,且转换类型
  107. if (selectData.value.jwcode) {
  108. params.jwcode = Number(selectData.value.jwcode)
  109. }
  110. if (selectData.value.markets && selectData.value.markets.length > 0) {
  111. // 确保市场代码也是正确类型(根据示例是字符串)
  112. params.market = String(selectData.value.markets[0])
  113. }
  114. if (sortField.value) {
  115. params.sortField = sortField.value
  116. }
  117. if (sortOrder.value) {
  118. params.sortOrder = sortOrder.value
  119. }
  120. if (sortWalletId.value !== '') {
  121. params.sortWalletId = sortWalletId.value
  122. }
  123. console.log('最终请求参数', params)
  124. const result = await API({
  125. url: '/cashCollection/selectUserWallets',
  126. method: 'post',
  127. data: params
  128. })
  129. console.log('响应数据', result)
  130. if (result.code === 200) {
  131. tableData.value = result.data.list.map(item => {
  132. const row = {
  133. historyGold: 0,
  134. name: item.userName,
  135. jwcode: item.jwcode,
  136. market: item.marketName,
  137. hkGold: 0,
  138. sgHcGold: 0,
  139. myGold: 0,
  140. sgGold: 0,
  141. caGold: 0,
  142. thHsGold: 0,
  143. thHaGold: 0,
  144. vnGold: 0,
  145. bjGold: 0
  146. };
  147. if (item.walletList && Array.isArray(item.walletList)) {
  148. item.walletList.forEach(wallet => {
  149. const prop = walletMap[wallet.walletId];
  150. if (prop) {
  151. row[prop] = wallet.currentPermanentGold;
  152. }
  153. });
  154. }
  155. return row;
  156. });
  157. total.value = result.data.total;
  158. } else {
  159. ElMessage.error(result.msg || t('elmessage.getDataFailed'));
  160. }
  161. } catch (error) {
  162. console.log('请求失败', error)
  163. }
  164. }
  165. // 精网号去空格,同时处理 selectData 和 putExcel 中的 jwcode
  166. const trimJwCode = () => {
  167. if (selectData.value.jwcode) {
  168. selectData.value.jwcode = selectData.value.jwcode.replace(/\s/g, '');
  169. }
  170. }
  171. // 搜索
  172. const search = function () {
  173. trimJwCode();
  174. getObj.value.pageNum = 1
  175. get()
  176. }
  177. // 重置
  178. const reset = function () {
  179. selectData.value = {
  180. jwcode: '',
  181. markets: [],
  182. }
  183. sortField.value = ''
  184. sortOrder.value = ''
  185. sortWalletId.value = ''
  186. selectedMarketPath.value = []
  187. // 重置页码
  188. getObj.value.pageNum = 1
  189. get()
  190. }
  191. const cellClick = function (row, column) {
  192. console.log('cellClick', column)
  193. const walletId = propToWalletId[column.property];
  194. const propToMarketName = {
  195. historyGold: t('clientCount.market.historyGold'),
  196. hkGold: t('clientCount.market.hkGold'),
  197. sgHcGold: t('clientCount.market.sgHcGold'),
  198. myGold: t('clientCount.market.myGold'),
  199. sgGold: t('clientCount.market.sgCmGold'),
  200. caGold: t('clientCount.market.caGold'),
  201. thHsGold: t('clientCount.market.thHsGold'),
  202. thHaGold: t('clientCount.market.thHaGold'),
  203. vnGold: t('clientCount.market.vnGold'),
  204. bjGold: t('clientCount.market.bjGold')
  205. }
  206. const marketName = propToMarketName[column.property]
  207. if (marketName && walletId) {
  208. currentWalletInfo.value = {
  209. userName: row.name,
  210. jwcode: row.jwcode,
  211. marketName: row.market, // 用户所属地区
  212. walletName: marketName + t('clientCount.wallet'), // 钱包名称
  213. currentBalance: row[column.property] || 0,
  214. walletId: walletId
  215. }
  216. walletDetailQuery.value.pageNum = 1
  217. getWalletDetail()
  218. walletDetailVisible.value = true
  219. }
  220. }
  221. // 钱包明细弹窗相关
  222. const walletDetailVisible = ref(false)
  223. const walletDetailList = ref([])
  224. const walletDetailTotal = ref(0)
  225. const walletDetailLoading = ref(false)
  226. const currentWalletInfo = ref({})
  227. const walletDetailQuery = ref({
  228. pageNum: 1,
  229. pageSize: 20
  230. })
  231. const getWalletRecordTypeText = (item) => {
  232. const type = Number(item.type)
  233. if (type === 0) {
  234. return t('clientCount.recharge')
  235. }
  236. if (type === 1) {
  237. return t('clientCount.consume')
  238. }
  239. if (type === 2) {
  240. return t('clientCount.refund')
  241. }
  242. return item.typeText || t('clientCount.other')
  243. }
  244. const getWalletDetail = async () => {
  245. walletDetailLoading.value = true
  246. try {
  247. const params = {
  248. pageNum: walletDetailQuery.value.pageNum,
  249. pageSize: walletDetailQuery.value.pageSize,
  250. userWalletRecord: {
  251. jwcode: Number(currentWalletInfo.value.jwcode),
  252. walletId: currentWalletInfo.value.walletId
  253. }
  254. }
  255. const result = await API({
  256. url: '/cashCollection/selectWalletRecords',
  257. method: 'post',
  258. data: params
  259. })
  260. if (result.code === 200) {
  261. walletDetailList.value = result.data.list.map(item => ({
  262. time: moment(item.createTime).format('YYYY-MM-DD HH:mm:ss'),
  263. type: getWalletRecordTypeText(item),
  264. amount: Number(item.amount) || 0,
  265. desc: item.description || '',
  266. orderNo: item.orderCode,
  267. status: item.status === 0 ? 1 : 2
  268. }))
  269. walletDetailTotal.value = result.data.total
  270. } else {
  271. ElMessage.error(result.msg || t('elmessage.getDetailFailed'))
  272. }
  273. } catch (error) {
  274. console.error(error)
  275. } finally {
  276. walletDetailLoading.value = false
  277. }
  278. }
  279. const handleWalletDetailSizeChange = (val) => {
  280. walletDetailQuery.value.pageSize = val
  281. walletDetailQuery.value.pageNum = 1
  282. getWalletDetail()
  283. }
  284. const handleWalletDetailCurrentChange = (val) => {
  285. walletDetailQuery.value.pageNum = val
  286. getWalletDetail()
  287. }
  288. // 处理排序事件
  289. const handleSortChange = (column) => {
  290. console.log('排序字段:', column.prop)
  291. console.log('排序方式:', column.order)
  292. if (!column.prop || !column.order) {
  293. sortField.value = ''
  294. sortOrder.value = ''
  295. sortWalletId.value = ''
  296. getObj.value.pageNum = 1
  297. get()
  298. return
  299. }
  300. if (propToWalletId[column.prop]) {
  301. sortField.value = 'currentPermanentGold'
  302. sortWalletId.value = propToWalletId[column.prop]
  303. }
  304. sortOrder.value = column.order === 'ascending' ? 'ASC' : 'DESC'
  305. getObj.value.pageNum = 1
  306. get()
  307. }
  308. // 挂载
  309. onMounted(async function () {
  310. await get()
  311. await getMarket()
  312. await getExportList()
  313. })
  314. const handlePageSizeChange = function (val) {
  315. getObj.value.pageSize = val
  316. getObj.value.pageNum = 1
  317. get()
  318. }
  319. const handleCurrentChange = function (val) {
  320. getObj.value.pageNum = val
  321. get()
  322. }
  323. const exportExcel = async function () {
  324. const params = {
  325. pageNum: 1, // 导出通常从第一页开始
  326. pageSize: 10000, // 导出所有数据
  327. }
  328. // 只有当有值时才加入参数,且转换类型
  329. if (selectData.value.jwcode) {
  330. params.jwcode = Number(selectData.value.jwcode)
  331. }
  332. if (selectData.value.markets && selectData.value.markets.length > 0) {
  333. // 确保市场代码也是正确类型
  334. params.market = String(selectData.value.markets[0])
  335. }
  336. const res = await API({
  337. url: '/export/exportUserWallet',
  338. method: 'post',
  339. data: params
  340. })
  341. if (res.code === 200) {
  342. ElMessage.success(t('elmessage.exportSuccess'))
  343. // 不需要立即打开导出列表
  344. } else {
  345. ElMessage.error(res.msg || t('elmessage.exportFailed'))
  346. }
  347. }
  348. const exportWalletDetail = async () => {
  349. const params = {
  350. pageNum: walletDetailQuery.value.pageNum,
  351. pageSize: walletDetailQuery.value.pageSize,
  352. userWalletRecord: {
  353. jwcode: Number(currentWalletInfo.value.jwcode),
  354. walletId: currentWalletInfo.value.walletId
  355. }
  356. }
  357. try {
  358. const res = await API({
  359. url: '/export/exportUserWalletRecord',
  360. method: 'post',
  361. data: params
  362. })
  363. if (res.code === 200) {
  364. ElMessage.success(t('elmessage.exportSuccess'))
  365. } else {
  366. ElMessage.error(res.msg || t('elmessage.exportFailed'))
  367. }
  368. } catch (error) {
  369. console.error('导出钱包明细出错:', error)
  370. ElMessage.error(t('elmessage.exportWalletDetailError'))
  371. }
  372. }
  373. const selectWallet = async function () {
  374. selectWalletVisible.value = true
  375. }
  376. const exportExcelOnlyOne = async function () {
  377. if (!selectWalletForm.value.companyWalletId) {
  378. ElMessage.error(t('elmessage.selectCompanyWallet'))
  379. return
  380. }
  381. const params = {
  382. pageNum: 1, // 导出通常从第一页开始
  383. pageSize: 10000, // 导出大量数据,或者不传让后端处理全部?通常传大值
  384. userWalletRecord: {
  385. walletId: selectWalletForm.value.companyWalletId,
  386. jwcode: selectData.value.jwcode ? Number(selectData.value.jwcode) : null
  387. }
  388. }
  389. try {
  390. const res = await API({
  391. url: '/export/exportUserWalletRecord',
  392. method: 'post',
  393. data: params
  394. })
  395. if (res.code === 200) {
  396. ElMessage.success(t('elmessage.exportSuccess'))
  397. openExportList() // 导出成功后打开导出列表
  398. } else {
  399. ElMessage.error(res.msg || t('elmessage.exportFailed'))
  400. }
  401. } catch (error) {
  402. console.error('导出失败:', error)
  403. ElMessage.error(t('elmessage.exportFailed'))
  404. } finally {
  405. selectWalletVisible.value = false
  406. }
  407. }
  408. const exportListVisible = ref(false)
  409. const selectWalletVisible = ref(false)
  410. const selectWalletFormRef = ref(null)
  411. const selectWalletRules = {
  412. companyWalletId: [
  413. { required: true, message: t('common_list.companyWalletPlaceholder'), trigger: 'change' }
  414. ]
  415. }
  416. // 关闭选择公司钱包弹窗
  417. const closeSelectWallet = () => {
  418. // 重置表单
  419. selectWalletFormRef.value.resetFields()
  420. selectWalletForm.value = {}
  421. selectWalletVisible.value = false
  422. }
  423. const selectWalletForm = ref({})
  424. const companyWalletList = ref([
  425. {
  426. id: 2,
  427. name: t('clientCount.market.hkGold') + t('clientCount.wallet')
  428. },
  429. {
  430. id: 3,
  431. name: t('clientCount.market.sgHcGold')
  432. },
  433. {
  434. id: 4,
  435. name: t('clientCount.market.myGold')
  436. },
  437. {
  438. id: 5,
  439. name: t('clientCount.market.sgCmGold')
  440. },
  441. {
  442. id: 6,
  443. name: t('clientCount.market.caGold')
  444. },
  445. {
  446. id: 7,
  447. name: t('clientCount.market.thHsGold')
  448. },
  449. {
  450. id: 8,
  451. name: t('clientCount.market.thHaGold')
  452. },
  453. {
  454. id: 9,
  455. name: t('clientCount.market.vnGold')
  456. },
  457. {
  458. id: 10,
  459. name: t('clientCount.market.bjGold')
  460. }
  461. ])
  462. // 打开导出列表弹窗
  463. const openExportList = () => {
  464. getExportList()
  465. exportListVisible.value = true
  466. }
  467. // 导出列表数据
  468. const exportList = ref([])
  469. // 导出列表加载状态
  470. const exportListLoading = ref(false)
  471. // 获取导出列表
  472. const getExportList = async () => {
  473. exportListLoading.value = true
  474. try {
  475. const result = await API({ url: '/export/export' })
  476. if (result.code === 200) {
  477. // 过滤只显示type为16和17的导出记录
  478. const filteredData = result.data.filter(item => {
  479. return item.type === 16 || item.type === 17;
  480. });
  481. exportList.value = filteredData
  482. } else {
  483. ElMessage.error(result.msg || t('elmessage.getExportListError'))
  484. }
  485. } catch (error) {
  486. console.error('获取导出列表出错:', error)
  487. ElMessage.error(t('elmessage.getExportListError'))
  488. } finally {
  489. exportListLoading.value = false
  490. }
  491. }
  492. // 下载导出文件
  493. const downloadExportFile = (item) => {
  494. if (item.state === 2) {
  495. const link = document.createElement('a')
  496. link.href = item.url
  497. link.download = item.fileName
  498. link.click()
  499. } else {
  500. ElMessage.warning(t('elmessage.exportingInProgress'))
  501. }
  502. }
  503. //根据状态返回对应的标签类型
  504. const getTagType = (state) => {
  505. switch (state) {
  506. case 0:
  507. return 'info';
  508. case 1:
  509. return 'primary';
  510. case 2:
  511. return 'success';
  512. case 3:
  513. return 'danger';
  514. default:
  515. return 'info';
  516. }
  517. }
  518. //根据状态返回对应的标签文案
  519. const getTagText = (state) => {
  520. switch (state) {
  521. case 0:
  522. return t('elmessage.pendingExecution');
  523. case 1:
  524. return t('elmessage.executing');
  525. case 2:
  526. return t('elmessage.executed');
  527. case 3:
  528. return t('elmessage.errorExecution');
  529. default:
  530. return t('elmessage.unknownStatus');
  531. }
  532. }
  533. // 存储地区选择变化
  534. const selectedMarketPath = ref([])
  535. const handleMarketChange = (value) => {
  536. if (value && value.length > 0) {
  537. const lastValue = value[value.length - 1];
  538. // 确保返回值是数组,如果不是则包装成数组
  539. const marketValue = reverseMarketMapping[lastValue];
  540. selectData.value.markets = Array.isArray(marketValue) ? marketValue : [marketValue];
  541. } else {
  542. // 保持[]格式
  543. selectData.value.markets = [];
  544. }
  545. };
  546. // 获取地区,修改为级联下拉框
  547. const getMarket = async function () {
  548. try {
  549. // 发送POST请求
  550. const result = await API({
  551. url: '/market/selectMarket',
  552. });
  553. // 将响应结果存储到响应式数据中
  554. console.log('请求成功', result)
  555. // 递归转换树形结构为级联选择器需要的格式(跳过第一级节点)
  556. const transformTree = (nodes) => {
  557. // 直接处理第一级节点的子节点
  558. const allChildren = nodes.flatMap(node => node.children || []);
  559. return allChildren.map(child => {
  560. const grandchildren = child.children && child.children.length
  561. ? transformTree([child]) // 递归处理子节点
  562. : null;
  563. return {
  564. value: child.name,
  565. label: child.name,
  566. children: grandchildren
  567. };
  568. });
  569. };
  570. // 存储地区信息
  571. markets.value = transformTree(result.data)
  572. console.log('转换后的地区树==============', markets.value)
  573. } catch (error) {
  574. console.log('请求失败', error)
  575. }
  576. }
  577. const format3 = (num) => {
  578. // 每三位添加逗号
  579. return num.toLocaleString('en-US')
  580. }
  581. </script>
  582. <template>
  583. <div style="display: flex; flex-direction: column; height: 95vh;">
  584. <el-card class="card1" style="margin-bottom: 1vh;">
  585. <div class="head-card">
  586. <div class="head-card-element">
  587. <el-text class="mx-1" size="large">{{ $t('common.jwcode') }}</el-text>
  588. <el-input v-model="selectData.jwcode" style="width: 160px" :placeholder="$t('common.jwcodePlaceholder')"
  589. clearable />
  590. </div>
  591. <div class="head-card-element">
  592. <el-text class="mx-1" size="large">{{ $t('common_list.market') }}</el-text>
  593. <el-cascader v-model="selectedMarketPath" :options="markets" :placeholder="$t('common_list.marketPlaceholder')"
  594. clearable style="width:180px" @change="handleMarketChange" />
  595. </div>
  596. <div class="head-card-element">
  597. <!-- <el-checkbox v-model="showEmployeeData" @change="search()">员工数据</el-checkbox> -->
  598. </div>
  599. <el-button type="primary" @click="search()">{{ $t('common.search') }}</el-button>
  600. <el-button @click="reset" type="success">{{ $t('common.reset') }}</el-button>
  601. <el-button type="primary" @click="exportExcel()">{{ $t('common.exportExcel') }}</el-button>
  602. <!-- <el-button type="primary" @click="selectWallet()">{{ $t('common.exportCompanyWalletDetail') }}</el-button> -->
  603. <el-button type="primary" @click="openExportList">{{ $t('common.viewExportList') }}</el-button>
  604. </div>
  605. <!-- </div> -->
  606. </el-card>
  607. <el-card class="card2">
  608. <!-- 设置表格容器的高度和滚动样式 -->
  609. <div style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
  610. <el-table ref="tableRef" :data="tableData" @cellClick="cellClick" style="width: 100%; flex: 1"
  611. @sort-change="handleSortChange" :row-style="{ height: '50px' }">
  612. <el-table-column type="index" :label="$t('common_list.id')" width="100px" fixed="left">
  613. <template #default="scope">
  614. <span>{{
  615. scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
  616. }}</span>
  617. </template>
  618. </el-table-column>
  619. <el-table-column prop="name" :label="$t('common_list.name')" width="140" />
  620. <el-table-column prop="jwcode" :label="$t('common_list.jwcode')" width="140" />
  621. <el-table-column prop="market" :label="$t('common_list.market')" width="140" />
  622. <el-table-column prop="historyGold" :label="$t('clientCount.market.historyGold')" sortable="custom"
  623. min-width="140">
  624. <template #default="scope">
  625. <span>{{ (scope.row.historyGold || 0) }}</span>
  626. </template>
  627. </el-table-column>
  628. <el-table-column prop="hkGold" :label="$t('clientCount.market.hkGold')" sortable="custom" min-width="140">
  629. <template #default="scope">
  630. <span>{{ (scope.row.hkGold || 0) }}</span>
  631. </template>
  632. </el-table-column>
  633. <el-table-column prop="sgHcGold" :label="$t('clientCount.market.sgHcGold')" sortable="custom" min-width="150">
  634. <template #default="scope">
  635. <span>{{ (scope.row.sgHcGold || 0) }}</span>
  636. </template>
  637. </el-table-column>
  638. <el-table-column prop="myGold" :label="$t('clientCount.market.myGold')" sortable="custom" min-width="120">
  639. <template #default="scope">
  640. <span>{{ (scope.row.myGold || 0) }}</span>
  641. </template>
  642. </el-table-column>
  643. <el-table-column prop="sgGold" :label="$t('clientCount.market.sgCmGold')" sortable="custom" min-width="150">
  644. <template #default="scope">
  645. <span>{{ (scope.row.sgGold || 0) }}</span>
  646. </template>
  647. </el-table-column>
  648. <el-table-column prop="caGold" :label="$t('clientCount.market.caGold')" sortable="custom" min-width="120">
  649. <template #default="scope">
  650. <span>{{ (scope.row.caGold || 0) }}</span>
  651. </template>
  652. </el-table-column>
  653. <el-table-column prop="thHsGold" :label="$t('clientCount.market.thHsGold')" sortable="custom" min-width="140">
  654. <template #default="scope">
  655. <span>{{ (scope.row.thHsGold || 0) }}</span>
  656. </template>
  657. </el-table-column>
  658. <el-table-column prop="thHaGold" :label="$t('clientCount.market.thHaGold')" sortable="custom" min-width="140">
  659. <template #default="scope">
  660. <span>{{ (scope.row.thHaGold || 0) }}</span>
  661. </template>
  662. </el-table-column>
  663. <el-table-column prop="vnGold" :label="$t('clientCount.market.vnGold')" sortable="custom" min-width="120">
  664. <template #default="scope">
  665. <span>{{ (scope.row.vnGold || 0) }}</span>
  666. </template>
  667. </el-table-column>
  668. <el-table-column prop="bjGold" :label="$t('clientCount.market.bjGold')" sortable="custom" min-width="120">
  669. <template #default="scope">
  670. <span>{{ (scope.row.bjGold || 0) }}</span>
  671. </template>
  672. </el-table-column>
  673. </el-table>
  674. </div>
  675. <!-- 分页 -->
  676. <div class="pagination" style="margin-top: 20px">
  677. <el-pagination background :current-page="getObj.pageNum" :page-size="getObj.pageSize"
  678. :page-sizes="[5, 10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper" :total="total"
  679. @size-change="handlePageSizeChange" @current-change="handleCurrentChange"></el-pagination>
  680. </div>
  681. </el-card>
  682. </div>
  683. <el-dialog v-model="exportListVisible" :title="$t('common_export.exportList')" width="80%">
  684. <el-table :data="exportList" style="width: 100% ;height: 60vh;" :loading="exportListLoading">
  685. <el-table-column prop="fileName" :label="$t('common_export.fileName')" />
  686. <el-table-column prop="state" :label="$t('common_export.status')">
  687. <template #default="scope">
  688. <el-tag :type="getTagType(scope.row.state)" :effect="scope.row.state === 3 ? 'light' : 'plain'">
  689. {{ getTagText(scope.row.state) }}
  690. </el-tag>
  691. </template>
  692. </el-table-column>
  693. <el-table-column prop="createTime" :label="$t('common_export.createTime')">
  694. <template #default="scope">
  695. {{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
  696. </template>
  697. </el-table-column>
  698. <el-table-column :label="$t('common_export.operation')">
  699. <template #default="scope">
  700. <el-button type="primary" size="small" @click="downloadExportFile(scope.row)"
  701. :disabled="scope.row.state !== 2">
  702. {{ $t('common_export.download') }}
  703. </el-button>
  704. </template>
  705. </el-table-column>
  706. </el-table>
  707. <template #footer>
  708. <div class="dialog-footer">
  709. <el-button text @click="exportListVisible = false">{{ $t('common_export.close') }}</el-button>
  710. </div>
  711. </template>
  712. </el-dialog>
  713. <el-dialog v-model="selectWalletVisible" width="30%" top="20%" :before-close="closeSelectWallet">
  714. <el-form :model="selectWalletForm" :rules="selectWalletRules" ref="selectWalletFormRef" label-width="120px">
  715. <el-form-item :label="$t('common_list.companyWallet')" prop="companyWalletId" style="margin-top: 30px;">
  716. <el-select v-model="selectWalletForm.companyWalletId" :placeholder="$t('common_list.companyWalletPlaceholder')"
  717. style="width: 80%;">
  718. <el-option v-for="item in companyWalletList" :key="item.id" :label="item.name" :value="item.id" />
  719. </el-select>
  720. </el-form-item>
  721. </el-form>
  722. <template #footer>
  723. <div style="display: flex; justify-content: flex-end;">
  724. <el-button type="primary" @click="exportExcelOnlyOne()">{{ $t('common.confirm') }}</el-button>
  725. </div>
  726. </template>
  727. </el-dialog>
  728. <el-dialog v-model="walletDetailVisible" width="70%" top="20vh">
  729. <template #header>
  730. <div class="wallet-detail-header"
  731. style="display: flex; gap: 40px; justify-content: space-between; align-items: center; font-size: 16px;">
  732. <span style="font-weight: bold; color: #F56C6C;">* {{ currentWalletInfo.walletName }}</span>
  733. <span><span style="color: #F56C6C;">*</span> {{ $t('clientCount.user') }}: {{ currentWalletInfo.userName }} (ID:
  734. {{ currentWalletInfo.jwcode }})</span>
  735. <span><span style="color: #F56C6C;">*</span> {{ $t('common.market') }}: {{ currentWalletInfo.marketName
  736. }}</span>
  737. </div>
  738. <div style="margin-top: 15px; font-size: 16px;">
  739. <span style="color: #F56C6C; font-weight: bold;">* {{ $t('clientCount.currentBalance') }}: {{
  740. format3(currentWalletInfo.currentBalance || 0) }} {{ $t('common.goldCoin') }}</span>
  741. </div>
  742. </template>
  743. <el-table :data="walletDetailList" v-loading="walletDetailLoading"
  744. style="width: 100%; height: 50vh; overflow-y: auto;" border stripe>
  745. <el-table-column prop="time" :label="$t('clientCount.time')" align="center" width="180">
  746. <template #default="scope">{{ scope.row.time }}</template>
  747. </el-table-column>
  748. <el-table-column prop="type" :label="$t('clientCount.transactionType')" align="center" width="120" />
  749. <el-table-column prop="amount" :label="$t('common_list.money')" align="center" width="120">
  750. <template #default="scope">
  751. <span :style="{ color: scope.row.amount >= 0 ? '#67C23A' : '#F56C6C', fontWeight: 'bold' }">
  752. {{ scope.row.amount > 0 ? '+' + format3(scope.row.amount) : format3(scope.row.amount) }}
  753. </span>
  754. </template>
  755. </el-table-column>
  756. <el-table-column prop="desc" :label="$t('clientCount.transactionDesc')" align="center" />
  757. <el-table-column prop="orderNo" :label="$t('clientCount.transactionOrderNo')" align="center" width="220" />
  758. <el-table-column prop="status" :label="$t('clientCount.transactionStatus')" align="center" width="220"
  759. fixed="right">
  760. <template #default="scope">
  761. <el-tag :type="scope.row.status === 1 ? 'success' : scope.row.status === 2 ? 'danger' : 'info'"
  762. :effect="scope.row.status === 1 ? 'light' : 'plain'">
  763. {{ scope.row.status === 1 ? t('common_list.normal') : scope.row.status === 2 ? t('common_list.refunded') :
  764. t('clientCount.exceptionData') }}
  765. </el-tag>
  766. </template>
  767. </el-table-column>
  768. </el-table>
  769. <template #footer>
  770. <div class="dialog-footer" style="display: flex; justify-content: space-between; align-items: center;">
  771. <div class="pagination-container">
  772. <el-pagination background :current-page="walletDetailQuery.pageNum" :page-size="walletDetailQuery.pageSize"
  773. :page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper" :total="walletDetailTotal"
  774. @size-change="handleWalletDetailSizeChange" @current-change="handleWalletDetailCurrentChange" />
  775. </div>
  776. <div>
  777. <el-button type="primary" @click="exportWalletDetail">{{ $t('common.exportExcel') }}</el-button>
  778. <el-button text @click="walletDetailVisible = false">{{ $t('common_export.close') }}</el-button>
  779. </div>
  780. </div>
  781. </template>
  782. </el-dialog>
  783. </template>
  784. <style scoped lang="scss">
  785. // 搜索的卡片样式
  786. .card1 {
  787. background: #F3FAFE;
  788. }
  789. // 表单的卡片样式
  790. .card2 {
  791. background: #E7F4FD;
  792. flex: 1;
  793. display: flex;
  794. flex-direction: column;
  795. :deep(.el-card__body) {
  796. padding: 20px;
  797. flex: 1;
  798. display: flex;
  799. flex-direction: column;
  800. overflow: hidden;
  801. }
  802. }
  803. // 表头背景等
  804. :deep(.el-table__header-wrapper),
  805. :deep(.el-table__body-wrapper),
  806. :deep(.el-table__cell),
  807. /* 表格 */
  808. :deep(.el-table__body td) {
  809. background-color: #F3FAFE !important;
  810. }
  811. /* 表头 */
  812. :deep(.el-table__header th) {
  813. background-color: #F3FAFE !important;
  814. }
  815. /* 鼠标悬停 */
  816. :deep(.el-table__row:hover > .el-table__cell) {
  817. background-color: #E5EBFE !important;
  818. }
  819. .pagination {
  820. display: flex;
  821. }
  822. .status {
  823. display: flex;
  824. }
  825. .head-card {
  826. display: flex;
  827. }
  828. .head-card-element {
  829. margin-right: 20px;
  830. }
  831. .head-card-btn {
  832. margin-left: auto;
  833. }
  834. .custom-box {
  835. display: flex;
  836. flex-wrap: wrap;
  837. row-gap: 5px;
  838. div:nth-child(1) {
  839. flex: 1 0 100%;
  840. }
  841. div {
  842. margin-right: 20px;
  843. }
  844. }
  845. </style>