|
|
<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="请输入精网号" clearable /> </div> <div class="head-card-element"> <el-text class="mx-1" size="large">{{ $t('common.market') }}:</el-text> <el-cascader v-model="selectedMarketPath" :options="marketLists" :placeholder="$t('common.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="height: 85vh; overflow-y: auto"> <el-table ref="tableRef" :data="tableData" v-loading="loading" style="width: 100%; height: 85vh" :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" width="220" /> <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: auto;}</style>
|