feat: 客服订单列表/详情展示自动结算倒计时,配置页文案改为结算率
平台单与商家单新增「待自动结算」筛选与自动结算列;详情状态旁展示预计时间。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -103,6 +103,10 @@
|
||||
{{ getStatusText(orderData.zhuangtai) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="orderData.auto_settle_eligible" label="自动结算">
|
||||
<span class="auto-settle-tip">{{ autoSettleText }}</span>
|
||||
<span v-if="orderData.auto_expire_at" class="auto-settle-at">({{ orderData.auto_expire_at }})</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="发单平台">
|
||||
{{ orderData.fadanpingtai === 1 ? '平台发单' : orderData.fadanpingtai === 2 ? '商家发单' : '未知' }}
|
||||
</el-descriptions-item>
|
||||
@@ -403,6 +407,26 @@ const getFullImageUrl = (url) => {
|
||||
|
||||
const formatPrice = (val) => parseFloat(val || 0).toFixed(2)
|
||||
|
||||
const formatRemainText = (sec) => {
|
||||
const s = Math.max(0, Number(sec) || 0)
|
||||
const h = Math.floor(s / 3600)
|
||||
const m = Math.floor((s % 3600) / 60)
|
||||
if (h >= 24) return `${Math.floor(h / 24)}天${h % 24}小时`
|
||||
if (h > 0) return `${h}小时${m}分`
|
||||
if (m > 0) return `${m}分钟`
|
||||
return s > 0 ? `${s}秒` : '即将结算'
|
||||
}
|
||||
|
||||
const autoSettleText = computed(() => {
|
||||
const d = orderData.value
|
||||
if (!d || !d.auto_settle_eligible) return ''
|
||||
const remain = d.auto_settle_remain_seconds
|
||||
if (remain == null || remain === '') {
|
||||
return d.auto_expire_at ? `预计 ${d.auto_expire_at} 自动结算` : ''
|
||||
}
|
||||
return Number(remain) <= 0 ? '即将自动结算' : `预计自动结算 ${formatRemainText(remain)}`
|
||||
})
|
||||
|
||||
const statusMap = {
|
||||
1: '下单中', 7: '指定中', 2: '进行中', 8: '结算中',
|
||||
3: '已完成', 4: '退款审核', 5: '已退款', 6: '退款失败'
|
||||
@@ -775,6 +799,15 @@ onMounted(() => {
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.auto-settle-tip {
|
||||
color: #c62828;
|
||||
font-weight: 600;
|
||||
}
|
||||
.auto-settle-at {
|
||||
color: #8d6e63;
|
||||
margin-left: 6px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.card-header {
|
||||
font-weight: 700;
|
||||
color: #1a2634;
|
||||
|
||||
@@ -114,6 +114,14 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="自动结算" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.auto_settle_eligible" class="auto-settle-cell">
|
||||
{{ formatAutoSettle(row) }}
|
||||
</span>
|
||||
<span v-else class="muted">--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click.stop="goToDetail(row.dingdan_id)">详情</el-button>
|
||||
@@ -179,6 +187,7 @@ const statusList = ref([
|
||||
{ label: '已下单', value: '1,7', count: 0 },
|
||||
{ label: '进行中', value: '2', count: 0 },
|
||||
{ label: '待结算', value: '8', count: 0 },
|
||||
{ label: '待自动结算', value: 'auto_settle', count: 0 },
|
||||
{ label: '已完成', value: '3', count: 0 },
|
||||
{ label: '退款审核', value: '4', count: 0 },
|
||||
{ label: '已退款', value: '5', count: 0 },
|
||||
@@ -225,7 +234,6 @@ const fetchOrders = async () => {
|
||||
username: phone,
|
||||
page: pageNum.value,
|
||||
pageSize: pageSize.value,
|
||||
zhuangtai: currentStatus.value === 'all' ? undefined : currentStatus.value,
|
||||
dingdan_id: search.ordId || undefined,
|
||||
shangjia_id: search.shangjiaId || undefined,
|
||||
dashou_id: search.dashouId || undefined,
|
||||
@@ -235,6 +243,12 @@ const fetchOrders = async () => {
|
||||
clkf: search.clkf || undefined,
|
||||
shangjia_nicheng: search.shangjiaNicheng || undefined
|
||||
}
|
||||
if (currentStatus.value === 'auto_settle') {
|
||||
params.zhuangtai = '8'
|
||||
params.auto_settle_pending = 1
|
||||
} else if (currentStatus.value !== 'all') {
|
||||
params.zhuangtai = currentStatus.value
|
||||
}
|
||||
if (currentType.value !== '' && currentType.value !== null && currentType.value !== undefined) {
|
||||
params.leixing = currentType.value
|
||||
}
|
||||
@@ -344,6 +358,24 @@ const handlePageChange = (val) => { pageNum.value = val; fetchOrders(); updateQu
|
||||
const goToDetail = (dingdanId) => router.push(`/order/detail/${dingdanId}`)
|
||||
|
||||
const formatPrice = (price) => parseFloat(price || 0).toFixed(2)
|
||||
const formatRemainText = (sec) => {
|
||||
const s = Math.max(0, Number(sec) || 0)
|
||||
const h = Math.floor(s / 3600)
|
||||
const m = Math.floor((s % 3600) / 60)
|
||||
if (h >= 24) return `${Math.floor(h / 24)}天${h % 24}小时`
|
||||
if (h > 0) return `${h}小时${m}分`
|
||||
if (m > 0) return `${m}分钟`
|
||||
return s > 0 ? `${s}秒` : '即将结算'
|
||||
}
|
||||
const formatAutoSettle = (row) => {
|
||||
if (!row || !row.auto_settle_eligible) return ''
|
||||
const remain = row.auto_settle_remain_seconds
|
||||
if (remain == null || remain === '') {
|
||||
return row.auto_expire_at ? `预计 ${row.auto_expire_at}` : ''
|
||||
}
|
||||
const text = formatRemainText(remain)
|
||||
return Number(remain) <= 0 ? '即将自动结算' : `预计自动结算 ${text}`
|
||||
}
|
||||
const getStatusText = (code) => {
|
||||
const map = { '1':'下单中','7':'指定中','2':'进行中','8':'待结算','3':'已完成','4':'退款审核','5':'已退款','6':'退款失败' }
|
||||
return map[code] || '未知'
|
||||
@@ -398,6 +430,8 @@ onMounted(async () => {
|
||||
.stat-label { font-size: 13px; color: #6b7a88; margin-bottom: 8px; }
|
||||
.stat-value { font-size: 24px; font-weight: 600; color: #1a2634; }
|
||||
.order-table { width: 100%; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.02); margin-bottom: 20px; }
|
||||
.auto-settle-cell { color: #c62828; font-size: 13px; }
|
||||
.muted { color: #9aa5b1; }
|
||||
.pagination { display: flex; justify-content: flex-end; }
|
||||
.no-permission { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 60vh; }
|
||||
.no-permission-icon { font-size: 80px; margin-bottom: 20px; opacity: 0.6; }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="page" v-loading="loading">
|
||||
<ClubScopeHint />
|
||||
<div class="header">
|
||||
<h2>成交指标与自动结算</h2>
|
||||
<h2>结算率指标与自动结算</h2>
|
||||
<el-button @click="load">刷新</el-button>
|
||||
</div>
|
||||
<el-alert
|
||||
@@ -33,7 +33,7 @@
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" class="card">
|
||||
<template #header>成交 / 罚款指标统计</template>
|
||||
<template #header>结算率 / 罚款指标统计</template>
|
||||
<el-form label-width="160px">
|
||||
<el-form-item label="启用指标统计">
|
||||
<el-switch v-model="form.stats_enabled" />
|
||||
@@ -52,7 +52,7 @@
|
||||
<el-table :data="merchantList" size="small" max-height="360">
|
||||
<el-table-column prop="merchant_uid" label="商家UID" width="120" />
|
||||
<el-table-column prop="order_count" label="订单量" width="90" />
|
||||
<el-table-column prop="deal_rate" label="成交率" width="100">
|
||||
<el-table-column prop="deal_rate" label="结算率" width="100">
|
||||
<template #default="{ row }">{{ pct(row.deal_rate) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fine_rate" label="罚款率" width="100">
|
||||
@@ -61,7 +61,7 @@
|
||||
<el-table-column prop="refund_rate" label="退款率" width="100">
|
||||
<template #default="{ row }">{{ pct(row.refund_rate) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="avg_deal_hours" label="平均成交时长(h)" min-width="120" />
|
||||
<el-table-column prop="avg_deal_hours" label="平均结算时长(h)" min-width="120" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<el-table :data="dashouList" size="small" max-height="360">
|
||||
<el-table-column prop="dashou_uid" label="打手UID" width="120" />
|
||||
<el-table-column prop="order_count" label="接单量" width="90" />
|
||||
<el-table-column prop="deal_rate" label="成交率" width="100">
|
||||
<el-table-column prop="deal_rate" label="结算率" width="100">
|
||||
<template #default="{ row }">{{ pct(row.deal_rate) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fined_rate" label="被罚款率" width="100">
|
||||
|
||||
@@ -118,6 +118,14 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="自动结算" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.auto_settle_eligible" class="auto-settle-cell">
|
||||
{{ formatAutoSettle(row) }}
|
||||
</span>
|
||||
<span v-else class="muted">--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click.stop="goToDetail(row.dingdan_id)">详情</el-button>
|
||||
@@ -183,6 +191,7 @@ const statusList = ref([
|
||||
{ label: '已下单', value: '1,7', count: 0 },
|
||||
{ label: '进行中', value: '2', count: 0 },
|
||||
{ label: '待结算', value: '8', count: 0 },
|
||||
{ label: '待自动结算', value: 'auto_settle', count: 0 },
|
||||
{ label: '已完成', value: '3', count: 0 },
|
||||
{ label: '退款审核', value: '4', count: 0 },
|
||||
{ label: '已退款', value: '5', count: 0 },
|
||||
@@ -228,7 +237,6 @@ const fetchOrders = async () => {
|
||||
phone: localStorage.getItem('username'),
|
||||
page: pageNum.value,
|
||||
pageSize: pageSize.value,
|
||||
zhuangtai: currentStatus.value === 'all' ? undefined : currentStatus.value,
|
||||
dingdan_id: search.ordId || undefined,
|
||||
laoban_id: search.laobanId || undefined,
|
||||
dashou_id: search.dashouId || undefined,
|
||||
@@ -237,6 +245,12 @@ const fetchOrders = async () => {
|
||||
jieshao: search.jieshao || undefined,
|
||||
clkf: search.clkf || undefined
|
||||
}
|
||||
if (currentStatus.value === 'auto_settle') {
|
||||
params.zhuangtai = '8'
|
||||
params.auto_settle_pending = 1
|
||||
} else if (currentStatus.value !== 'all') {
|
||||
params.zhuangtai = currentStatus.value
|
||||
}
|
||||
if (currentType.value !== '' && currentType.value !== null && currentType.value !== undefined) {
|
||||
params.leixing = currentType.value
|
||||
}
|
||||
@@ -344,6 +358,24 @@ const handlePageChange = (val) => { pageNum.value = val; fetchOrders(); updateQu
|
||||
const goToDetail = (dingdanId) => router.push(`/order/detail/${dingdanId}`)
|
||||
|
||||
const formatPrice = (price) => parseFloat(price || 0).toFixed(2)
|
||||
const formatRemainText = (sec) => {
|
||||
const s = Math.max(0, Number(sec) || 0)
|
||||
const h = Math.floor(s / 3600)
|
||||
const m = Math.floor((s % 3600) / 60)
|
||||
if (h >= 24) return `${Math.floor(h / 24)}天${h % 24}小时`
|
||||
if (h > 0) return `${h}小时${m}分`
|
||||
if (m > 0) return `${m}分钟`
|
||||
return s > 0 ? `${s}秒` : '即将结算'
|
||||
}
|
||||
const formatAutoSettle = (row) => {
|
||||
if (!row || !row.auto_settle_eligible) return ''
|
||||
const remain = row.auto_settle_remain_seconds
|
||||
if (remain == null || remain === '') {
|
||||
return row.auto_expire_at ? `预计 ${row.auto_expire_at}` : ''
|
||||
}
|
||||
const text = formatRemainText(remain)
|
||||
return Number(remain) <= 0 ? '即将自动结算' : `预计自动结算 ${text}`
|
||||
}
|
||||
const getStatusText = (code) => {
|
||||
const map = { '1':'下单中','7':'指定中','2':'进行中','8':'待结算','3':'已完成','4':'退款审核','5':'已退款','6':'退款失败' }
|
||||
return map[code] || '未知'
|
||||
@@ -394,6 +426,8 @@ onMounted(() => {
|
||||
.stat-label { font-size: 13px; color: #6b7a88; margin-bottom: 8px; }
|
||||
.stat-value { font-size: 24px; font-weight: 600; color: #1a2634; }
|
||||
.order-table { width: 100%; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.02); margin-bottom: 20px; }
|
||||
.auto-settle-cell { color: #c62828; font-size: 13px; }
|
||||
.muted { color: #9aa5b1; }
|
||||
.pagination { display: flex; justify-content: flex-end; }
|
||||
.no-permission { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 60vh; }
|
||||
.no-permission-icon { font-size: 80px; margin-bottom: 20px; opacity: 0.6; }
|
||||
|
||||
Reference in New Issue
Block a user