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