提现审核页增加待收款/成功失败等明细状态筛选。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="withdraw-audit">
|
||||
<!-- 顶部统计卡片 -->
|
||||
<el-row :gutter="20" class="stats-cards">
|
||||
<el-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
|
||||
<el-row :gutter="16" class="stats-cards">
|
||||
<el-col :xs="12" :sm="8" :md="4" :lg="4" :xl="4">
|
||||
<el-card class="stat-card" shadow="hover">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">总记录</div>
|
||||
@@ -10,18 +10,42 @@
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
|
||||
<el-card class="stat-card" shadow="hover" @click="changeStatus(1)">
|
||||
<el-col :xs="12" :sm="8" :md="4" :lg="4" :xl="4">
|
||||
<el-card class="stat-card" shadow="hover" @click="changeDetailStatus(1)">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">待审核</div>
|
||||
<div class="stat-value warning">{{ stats.awaiting || 0 }}</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
|
||||
<el-col :xs="12" :sm="8" :md="4" :lg="4" :xl="4" v-if="isAutoMode">
|
||||
<el-card class="stat-card" shadow="hover" @click="changeDetailStatus(6)">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">待收款</div>
|
||||
<div class="stat-value warning">{{ stats.pending_collect || 0 }}</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="8" :md="4" :lg="4" :xl="4">
|
||||
<el-card class="stat-card" shadow="hover" @click="changeDetailStatus(2)">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">提现成功</div>
|
||||
<div class="stat-value success">{{ stats.success || 0 }}</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="8" :md="4" :lg="4" :xl="4">
|
||||
<el-card class="stat-card" shadow="hover" @click="changeDetailStatus(3)">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">提现失败</div>
|
||||
<div class="stat-value danger">{{ stats.fail || 0 }}</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="8" :md="4" :lg="4" :xl="4">
|
||||
<el-card class="stat-card" shadow="hover" @click="changeStatus(2)">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">已处理</div>
|
||||
<div class="stat-label">已处理(全部)</div>
|
||||
<div class="stat-value success">{{ stats.processed || 0 }}</div>
|
||||
</div>
|
||||
</el-card>
|
||||
@@ -87,14 +111,52 @@
|
||||
<el-col :span="24">
|
||||
<div class="status-switch">
|
||||
<el-button
|
||||
:type="statusFilter === 1 ? 'primary' : 'default'"
|
||||
@click="changeStatus(1)"
|
||||
:type="isStatusActive(1) ? 'primary' : 'default'"
|
||||
@click="changeDetailStatus(1)"
|
||||
size="large"
|
||||
>
|
||||
待审核 <el-tag size="small" type="warning" v-if="stats.awaiting">{{ stats.awaiting }}</el-tag>
|
||||
</el-button>
|
||||
<el-button
|
||||
:type="statusFilter === 2 ? 'success' : 'default'"
|
||||
v-if="isAutoMode"
|
||||
:type="isStatusActive(6) ? 'warning' : 'default'"
|
||||
@click="changeDetailStatus(6)"
|
||||
size="large"
|
||||
>
|
||||
待收款 <el-tag size="small" type="warning" v-if="stats.pending_collect">{{ stats.pending_collect }}</el-tag>
|
||||
</el-button>
|
||||
<el-button
|
||||
:type="isStatusActive(2) ? 'success' : 'default'"
|
||||
@click="changeDetailStatus(2)"
|
||||
size="large"
|
||||
>
|
||||
提现成功 <el-tag size="small" type="success" v-if="stats.success">{{ stats.success }}</el-tag>
|
||||
</el-button>
|
||||
<el-button
|
||||
:type="isStatusActive(3) ? 'danger' : 'default'"
|
||||
@click="changeDetailStatus(3)"
|
||||
size="large"
|
||||
>
|
||||
提现失败
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="isAutoMode"
|
||||
:type="isStatusActive(4) ? 'success' : 'default'"
|
||||
@click="changeDetailStatus(4)"
|
||||
size="large"
|
||||
>
|
||||
审核成功
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="isAutoMode"
|
||||
:type="isStatusActive(5) ? 'danger' : 'default'"
|
||||
@click="changeDetailStatus(5)"
|
||||
size="large"
|
||||
>
|
||||
审核失败
|
||||
</el-button>
|
||||
<el-button
|
||||
:type="isProcessedActive ? 'success' : 'default'"
|
||||
@click="changeStatus(2)"
|
||||
size="large"
|
||||
>
|
||||
@@ -148,7 +210,7 @@
|
||||
</el-card>
|
||||
|
||||
<!-- 自动打款批量操作栏 -->
|
||||
<div v-if="isAutoMode && statusFilter === 1" class="batch-bar">
|
||||
<div v-if="isAutoMode && canBatchOperate" class="batch-bar">
|
||||
<span class="batch-tip">已选 {{ selectedRows.length }} 条</span>
|
||||
<el-button
|
||||
type="success"
|
||||
@@ -182,7 +244,7 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column
|
||||
v-if="isAutoMode && statusFilter === 1"
|
||||
v-if="isAutoMode && canBatchOperate"
|
||||
type="selection"
|
||||
width="48"
|
||||
fixed="left"
|
||||
@@ -200,13 +262,20 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jine" label="金额" width="120">
|
||||
<el-table-column prop="jine" label="申请金额" width="110">
|
||||
<template #default="{ row }">¥{{ row.jine }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isAutoMode" label="手续费" width="90">
|
||||
<template #default="{ row }">{{ row.shouxufei ? `¥${row.shouxufei}` : '--' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isAutoMode" label="实际到账" width="100">
|
||||
<template #default="{ row }">{{ row.shijidaozhang ? `¥${row.shijidaozhang}` : '--' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="提现类型" width="110">
|
||||
<template #default="{ row }">{{ getTypeText(row.leixing) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isAutoMode" prop="shenhe_danhao" label="审核单号" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column v-if="isAutoMode" prop="dakuan_mch_id" label="打款商户" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="打款方式" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.dakuan_mode === 2 ? 'success' : 'info'" size="small">
|
||||
@@ -220,15 +289,18 @@
|
||||
<el-table-column label="状态" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.zhuangtai)">
|
||||
{{ getStatusText(row.zhuangtai) }}
|
||||
{{ row.zhuangtai_text || getStatusText(row.zhuangtai) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="失败原因" min-width="140" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.fail_reason || row.bhliyou || '--' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" label="申请时间" width="160" :formatter="formatTime" />
|
||||
<el-table-column label="操作" :width="isAutoMode && statusFilter === 1 ? 200 : 80" fixed="right">
|
||||
<el-table-column label="操作" :width="isAutoMode && canBatchOperate ? 200 : 80" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click.stop="goToDetail(row)">详情</el-button>
|
||||
<template v-if="isAutoMode && statusFilter === 1 && row.zhuangtai === 1">
|
||||
<template v-if="isAutoMode && canBatchOperate && row.zhuangtai === 1">
|
||||
<el-button type="success" link @click.stop="handleInlineApprove(row)">同意</el-button>
|
||||
<el-button type="danger" link @click.stop="showInlineRejectDialog(row)">驳回</el-button>
|
||||
</template>
|
||||
@@ -294,6 +366,9 @@ const stats = ref({
|
||||
total: 0,
|
||||
awaiting: 0,
|
||||
processed: 0,
|
||||
pending_collect: 0,
|
||||
success: 0,
|
||||
fail: 0,
|
||||
total_amount: '0.00'
|
||||
})
|
||||
|
||||
@@ -307,7 +382,9 @@ const filters = reactive({
|
||||
dakuanMode: 1
|
||||
})
|
||||
|
||||
// statusFilter: 1=待审核粗粒度 2=已处理粗粒度;detailZhuangtai: 1~6 精确态(优先生效)
|
||||
const statusFilter = ref(1)
|
||||
const detailZhuangtai = ref(null)
|
||||
|
||||
const rejectDialogVisible = ref(false)
|
||||
const rejectReason = ref('')
|
||||
@@ -315,6 +392,14 @@ const rejectTargetRow = ref(null)
|
||||
const rejectMode = ref('single')
|
||||
|
||||
const isAutoMode = computed(() => filters.dakuanMode === 2)
|
||||
const canBatchOperate = computed(() => {
|
||||
if (detailZhuangtai.value != null) return Number(detailZhuangtai.value) === 1
|
||||
return Number(statusFilter.value) === 1
|
||||
})
|
||||
const isProcessedActive = computed(() => (
|
||||
detailZhuangtai.value == null && Number(statusFilter.value) === 2
|
||||
))
|
||||
const isStatusActive = (code) => Number(detailZhuangtai.value) === Number(code)
|
||||
|
||||
const getFullImageUrl = (url) => {
|
||||
if (!url) return ''
|
||||
@@ -425,6 +510,7 @@ const saveFiltersToStorage = () => {
|
||||
minAmount: filters.minAmount,
|
||||
maxAmount: filters.maxAmount,
|
||||
statusFilter: statusFilter.value,
|
||||
detailZhuangtai: detailZhuangtai.value,
|
||||
dakuanMode: filters.dakuanMode
|
||||
}
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(toStore))
|
||||
@@ -442,6 +528,10 @@ const loadFiltersFromStorage = () => {
|
||||
if (parsed.minAmount !== undefined) filters.minAmount = parsed.minAmount
|
||||
if (parsed.maxAmount !== undefined) filters.maxAmount = parsed.maxAmount
|
||||
if (parsed.statusFilter !== undefined && [1, 2].includes(parsed.statusFilter)) statusFilter.value = parsed.statusFilter
|
||||
if (parsed.detailZhuangtai !== undefined && parsed.detailZhuangtai !== null
|
||||
&& [1, 2, 3, 4, 5, 6].includes(Number(parsed.detailZhuangtai))) {
|
||||
detailZhuangtai.value = Number(parsed.detailZhuangtai)
|
||||
}
|
||||
if (parsed.dakuanMode !== undefined && [1, 2].includes(parsed.dakuanMode)) filters.dakuanMode = parsed.dakuanMode
|
||||
} catch (e) {
|
||||
console.error('恢复筛选条件失败', e)
|
||||
@@ -453,13 +543,18 @@ const buildListParams = () => {
|
||||
phone: localStorage.getItem('username'),
|
||||
page: page.value,
|
||||
page_size: pageSize.value,
|
||||
status: statusFilter.value,
|
||||
dakuan_mode: filters.dakuanMode,
|
||||
type: filters.type || undefined,
|
||||
payment: filters.payment === 0 ? undefined : filters.payment,
|
||||
search_uid: filters.searchUid || undefined,
|
||||
date: filters.date || undefined
|
||||
}
|
||||
// 明细状态优先;否则用粗粒度 status
|
||||
if (detailZhuangtai.value != null && [1, 2, 3, 4, 5, 6].includes(Number(detailZhuangtai.value))) {
|
||||
params.zhuangtai = Number(detailZhuangtai.value)
|
||||
} else {
|
||||
params.status = statusFilter.value
|
||||
}
|
||||
if (filters.minAmount !== null && filters.minAmount !== '') {
|
||||
params.min_amount = filters.minAmount
|
||||
}
|
||||
@@ -501,6 +596,9 @@ const fetchData = async () => {
|
||||
total: 0,
|
||||
awaiting: 0,
|
||||
processed: 0,
|
||||
pending_collect: 0,
|
||||
success: 0,
|
||||
fail: 0,
|
||||
total_amount: '0.00',
|
||||
...(data.stats || {})
|
||||
}
|
||||
@@ -524,13 +622,28 @@ const fetchData = async () => {
|
||||
const handleDakuanModeChange = () => {
|
||||
page.value = 1
|
||||
selectedRows.value = []
|
||||
// 手动打款无 4/5/6:若当前卡在这些态,回退待审核
|
||||
if (!isAutoMode.value && [4, 5, 6].includes(Number(detailZhuangtai.value))) {
|
||||
detailZhuangtai.value = 1
|
||||
statusFilter.value = 1
|
||||
}
|
||||
fetchData()
|
||||
saveFiltersToStorage()
|
||||
}
|
||||
|
||||
const changeStatus = (status) => {
|
||||
if (statusFilter.value === status) return
|
||||
// 粗粒度已处理 / 待审核(清掉明细态)
|
||||
statusFilter.value = status
|
||||
detailZhuangtai.value = null
|
||||
page.value = 1
|
||||
selectedRows.value = []
|
||||
fetchData()
|
||||
saveFiltersToStorage()
|
||||
}
|
||||
|
||||
const changeDetailStatus = (code) => {
|
||||
detailZhuangtai.value = Number(code)
|
||||
statusFilter.value = Number(code) === 1 ? 1 : 2
|
||||
page.value = 1
|
||||
selectedRows.value = []
|
||||
fetchData()
|
||||
@@ -552,6 +665,7 @@ const resetFilters = () => {
|
||||
filters.maxAmount = null
|
||||
filters.dakuanMode = 1
|
||||
statusFilter.value = 1
|
||||
detailZhuangtai.value = null
|
||||
page.value = 1
|
||||
localStorage.removeItem(STORAGE_KEY)
|
||||
fetchData()
|
||||
@@ -766,6 +880,9 @@ onMounted(() => {
|
||||
.stat-value.success {
|
||||
color: #67c23a;
|
||||
}
|
||||
.stat-value.danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
.total-amount {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
Reference in New Issue
Block a user