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.
472 lines
14 KiB
472 lines
14 KiB
<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>
|