优化-订单列表和详情页
This commit is contained in:
@@ -12,6 +12,8 @@ const loading = ref(true)
|
||||
const errorMessage = ref('')
|
||||
const detail = ref<AdminOrderDetail | null>(null)
|
||||
|
||||
type TagType = 'success' | 'primary' | 'warning' | 'danger' | 'info'
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const response = await fetchAdminOrderDetail(String(route.params.orderId || ''))
|
||||
@@ -35,11 +37,76 @@ function formatSpecSummary(spec: Record<string, unknown>) {
|
||||
|
||||
return entries.length > 0 ? entries.join(' | ') : '-'
|
||||
}
|
||||
|
||||
function resolveResourceStageLabel(status: string) {
|
||||
const normalized = String(status || '').trim()
|
||||
const labelMap: Record<string, string> = {
|
||||
system_bound: '资源已准备',
|
||||
pending_binding: '待准备资源',
|
||||
pending_binding_prepare: '待准备资源',
|
||||
retry_pending: '待重试',
|
||||
manual_review: '人工处理',
|
||||
binding_exception: '资源异常',
|
||||
completed: '已完成',
|
||||
not_started: '未开始',
|
||||
}
|
||||
|
||||
return labelMap[normalized] || normalized || '-'
|
||||
}
|
||||
|
||||
function resolveCustomerStageLabel(status: string) {
|
||||
const normalized = String(status || '').trim()
|
||||
const labelMap: Record<string, string> = {
|
||||
not_started: '待打开链接',
|
||||
waiting_user_claim: '待打开链接',
|
||||
waiting_binding: '待客户绑定',
|
||||
link_opened: '已打开链接',
|
||||
user_binding: '客户绑定中',
|
||||
binding_confirmed: '已提交',
|
||||
binding_in_progress: '处理中',
|
||||
binding_completed: '客户已完成',
|
||||
binding_exception: '客户步骤异常',
|
||||
completed: '已完成',
|
||||
}
|
||||
|
||||
return labelMap[normalized] || normalized || '-'
|
||||
}
|
||||
|
||||
function resolveStageTone(status: string): TagType {
|
||||
const normalized = String(status || '').trim()
|
||||
if (['system_bound', 'binding_completed', 'completed'].includes(normalized)) return 'success'
|
||||
if (
|
||||
[
|
||||
'waiting_binding',
|
||||
'waiting_user_claim',
|
||||
'link_opened',
|
||||
'user_binding',
|
||||
'binding_confirmed',
|
||||
'binding_in_progress',
|
||||
].includes(normalized)
|
||||
) return 'primary'
|
||||
if (['binding_exception', 'manual_review', 'failed'].includes(normalized)) return 'danger'
|
||||
if (['pending_binding', 'pending_binding_prepare', 'retry_pending'].includes(normalized)) return 'warning'
|
||||
return 'info'
|
||||
}
|
||||
|
||||
function resolveOrderProgressText(summary: AdminOrderDetail['order']['bindingSummary']) {
|
||||
if (!summary.totalTaskCount) return '未生成履约任务'
|
||||
if (summary.completedBindingTaskCount >= summary.totalTaskCount) return '履约完成'
|
||||
if (summary.systemBoundTaskCount > 0) return '等待客户绑定'
|
||||
return '待准备领取链接'
|
||||
}
|
||||
|
||||
function resolveOrderProgressTone(summary: AdminOrderDetail['order']['bindingSummary']): TagType {
|
||||
if (!summary.totalTaskCount) return 'warning'
|
||||
if (summary.completedBindingTaskCount >= summary.totalTaskCount) return 'success'
|
||||
return 'warning'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="admin-panel">
|
||||
<AdminPageHeader title="订单详情" description="查看订单原始信息、商品子项和关联任务。" />
|
||||
<AdminPageHeader title="订单详情" description="查看 91 订单、核销店铺、商品和自动履约任务。" />
|
||||
|
||||
<el-alert v-if="errorMessage" :title="errorMessage" type="error" show-icon :closable="false" />
|
||||
|
||||
@@ -47,100 +114,65 @@ function formatSpecSummary(spec: Record<string, unknown>) {
|
||||
|
||||
<template v-else-if="detail">
|
||||
<el-card shadow="never" class="section-card">
|
||||
<div class="detail-card-header">
|
||||
<div>
|
||||
<section class="order-hero">
|
||||
<div class="order-hero-main">
|
||||
<h2>{{ detail.order.platformOrderId }}</h2>
|
||||
<p class="subtitle">
|
||||
{{ detail.order.platform }} /
|
||||
{{ detail.order.shopName || detail.order.shopId || '未识别店铺' }}
|
||||
{{ detail.order.provider }} / {{ detail.order.platform }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="status-stack">
|
||||
<AdminStatusTag :status="detail.order.payStatus" />
|
||||
<AdminStatusTag :status="detail.order.orderStatus" />
|
||||
<AdminStatusTag :status="detail.order.bindingSummary.systemBindingStatus" />
|
||||
<AdminStatusTag :status="detail.order.bindingSummary.userBindingStatus" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="summary-grid">
|
||||
<div class="summary-block summary-block--wide">
|
||||
<span>91 商品</span>
|
||||
<strong>{{ detail.order.itemSummary || '-' }}</strong>
|
||||
<small>用于匹配 cloudtentacles 商品或覆盖规则</small>
|
||||
</div>
|
||||
<div class="summary-block">
|
||||
<span>核销店铺</span>
|
||||
<strong>{{ detail.order.shopName || detail.order.shopId || '-' }}</strong>
|
||||
<small>shopId:{{ detail.order.shopId || '-' }}</small>
|
||||
</div>
|
||||
<div class="summary-block">
|
||||
<span>订单金额</span>
|
||||
<strong>{{ detail.order.totalAmount }} {{ detail.order.currency }}</strong>
|
||||
<small>支付:{{ formatAdminDateTime(detail.order.paidAt) }}</small>
|
||||
</div>
|
||||
<div class="summary-block">
|
||||
<span>履约进度</span>
|
||||
<el-tag :type="resolveOrderProgressTone(detail.order.bindingSummary)" effect="light">
|
||||
{{ resolveOrderProgressText(detail.order.bindingSummary) }}
|
||||
</el-tag>
|
||||
<small>
|
||||
完成 {{ detail.order.bindingSummary.completedBindingTaskCount }}/{{ detail.order.bindingSummary.totalTaskCount }}
|
||||
· 资源 {{ detail.order.bindingSummary.systemBoundTaskCount }}/{{ detail.order.bindingSummary.totalTaskCount }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-grid">
|
||||
<el-card shadow="never" class="info-tile">
|
||||
<span>商品标题</span>
|
||||
<strong>{{ detail.order.itemSummary || '-' }}</strong>
|
||||
<small>来自订单详情 title / 商品标题字段</small>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="info-tile">
|
||||
<span>订单金额</span>
|
||||
<strong>{{ detail.order.totalAmount }} {{ detail.order.currency }}</strong>
|
||||
<small>支付时间:{{ formatAdminDateTime(detail.order.paidAt) }}</small>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="info-tile">
|
||||
<span>买家信息</span>
|
||||
<strong>{{ detail.order.buyerName || '-' }}</strong>
|
||||
<small>ID:{{ detail.order.buyerId || '-' }}</small>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="info-tile">
|
||||
<span>联系方式</span>
|
||||
<strong>{{ detail.order.receiverContact || '-' }}</strong>
|
||||
<small>店铺:{{ detail.order.shopName || detail.order.shopId || '-' }}</small>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="info-tile">
|
||||
<span>任务进度</span>
|
||||
<strong
|
||||
>{{ detail.order.bindingSummary.completedBindingTaskCount }}/{{
|
||||
detail.order.bindingSummary.totalTaskCount
|
||||
}}
|
||||
完整绑定</strong
|
||||
>
|
||||
<small
|
||||
>{{ detail.order.bindingSummary.systemBoundTaskCount }}/{{
|
||||
detail.order.bindingSummary.totalTaskCount
|
||||
}}
|
||||
系统绑定</small
|
||||
>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-table :data="[detail.order]" size="small" :show-header="false">
|
||||
<el-table-column label="内部订单 ID" width="120">
|
||||
<template #default="{ row }">{{ row.orderId }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="提供方" width="120">
|
||||
<template #default="{ row }">{{ row.provider }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="平台" width="100">
|
||||
<template #default="{ row }">{{ row.platform }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="店铺 ID">
|
||||
<template #default="{ row }">{{ row.shopId || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" width="180">
|
||||
<template #default="{ row }">{{ formatAdminDateTime(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="更新时间" width="180">
|
||||
<template #default="{ row }">{{ formatAdminDateTime(row.updatedAt) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<dl class="order-facts">
|
||||
<div>
|
||||
<dt>内部订单</dt>
|
||||
<dd>{{ detail.order.orderId }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>创建时间</dt>
|
||||
<dd>{{ formatAdminDateTime(detail.order.createdAt) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>更新时间</dt>
|
||||
<dd>{{ formatAdminDateTime(detail.order.updatedAt) }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" class="section-card">
|
||||
<h3>商品子项</h3>
|
||||
<el-table :data="detail.items" size="small">
|
||||
<el-table-column prop="skuCode" label="SKU" />
|
||||
<el-table-column prop="itemTitle" label="标题">
|
||||
<template #default="{ row }">{{ row.itemTitle || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="skuName" label="商品" />
|
||||
<el-table-column prop="deliveryMode" label="发放方式" />
|
||||
<el-table-column prop="quantity" label="数量" width="80" />
|
||||
<el-table-column label="规格摘要">
|
||||
<template #default="{ row }">{{ formatSpecSummary(row.spec) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" class="section-card">
|
||||
<h3>关联任务</h3>
|
||||
<h3>履约任务</h3>
|
||||
<el-table :data="detail.tasks" size="small">
|
||||
<el-table-column label="任务号">
|
||||
<template #default="{ row }">
|
||||
@@ -152,25 +184,38 @@ function formatSpecSummary(spec: Record<string, unknown>) {
|
||||
<AdminStatusTag :status="row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="系统绑定">
|
||||
<el-table-column label="资源准备">
|
||||
<template #default="{ row }">
|
||||
<AdminStatusTag :status="row.systemBindingStatus" />
|
||||
<el-tag :type="resolveStageTone(row.systemBindingStatus)" effect="light" size="small">
|
||||
{{ resolveResourceStageLabel(row.systemBindingStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="完整绑定">
|
||||
<el-table-column label="客户步骤">
|
||||
<template #default="{ row }">
|
||||
<AdminStatusTag :status="row.userBindingStatus" />
|
||||
<el-tag :type="resolveStageTone(row.userBindingStatus)" effect="light" size="small">
|
||||
{{ resolveCustomerStageLabel(row.userBindingStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="登录方式">
|
||||
<template #default="{ row }">{{ row.loginType || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="错误">
|
||||
<template #default="{ row }">{{ row.lastError || '-' }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" class="section-card">
|
||||
<h3>商品子项</h3>
|
||||
<el-table :data="detail.items" size="small">
|
||||
<el-table-column prop="skuName" label="91 商品" min-width="220" />
|
||||
<el-table-column prop="skuCode" label="匹配标识" min-width="180" />
|
||||
<el-table-column prop="quantity" label="数量" width="80" />
|
||||
<el-table-column label="规格摘要">
|
||||
<template #default="{ row }">{{ formatSpecSummary(row.spec) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" class="section-card">
|
||||
<h3>原始载荷</h3>
|
||||
<details class="payload-box">
|
||||
@@ -195,17 +240,19 @@ function formatSpecSummary(spec: Record<string, unknown>) {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.detail-card-header {
|
||||
.order-hero {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-4);
|
||||
align-items: flex-start;
|
||||
margin-bottom: var(--space-4);
|
||||
margin-bottom: var(--space-5);
|
||||
}
|
||||
|
||||
.detail-card-header h2 {
|
||||
.order-hero h2 {
|
||||
margin: 0;
|
||||
color: var(--text-primary);
|
||||
font-size: 30px;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
@@ -220,40 +267,95 @@ function formatSpecSummary(spec: Record<string, unknown>) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.info-grid {
|
||||
.summary-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
grid-template-columns: minmax(260px, 1.4fr) repeat(3, minmax(180px, 1fr));
|
||||
gap: var(--space-3);
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.info-tile {
|
||||
padding: 14px var(--space-4);
|
||||
border-radius: var(--radius-md);
|
||||
background: linear-gradient(180deg, rgba(247, 250, 255, 0.98), rgba(241, 245, 249, 0.92));
|
||||
border: 1px solid var(--border-default);
|
||||
.summary-block {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
align-content: start;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
min-height: 112px;
|
||||
padding: var(--space-4);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--bg-subtle);
|
||||
}
|
||||
|
||||
.info-tile span,
|
||||
.info-tile small {
|
||||
.summary-block--wide {
|
||||
background: var(--bg-surface);
|
||||
}
|
||||
|
||||
.summary-block span,
|
||||
.summary-block small {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.info-tile strong {
|
||||
.summary-block span {
|
||||
font-size: var(--text-sm);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.summary-block strong {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: var(--text-primary);
|
||||
font-size: var(--text-lg);
|
||||
line-height: 1.35;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tile-tag-line {
|
||||
display: flex;
|
||||
.summary-block small {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.summary-block :deep(.el-tag) {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.order-facts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 1px;
|
||||
margin: 0;
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-full);
|
||||
background: var(--border-default);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.order-facts div {
|
||||
display: grid;
|
||||
grid-template-columns: max-content minmax(0, 1fr);
|
||||
gap: var(--space-2);
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
padding: 10px var(--space-4);
|
||||
background: var(--bg-subtle);
|
||||
}
|
||||
|
||||
.binding-copy {
|
||||
margin-top: 6px;
|
||||
.order-facts dt,
|
||||
.order-facts dd {
|
||||
margin: 0;
|
||||
min-width: 0;
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.order-facts dt {
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.order-facts dd {
|
||||
overflow: hidden;
|
||||
color: var(--text-primary);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.payload-box summary {
|
||||
@@ -276,13 +378,17 @@ function formatSpecSummary(spec: Record<string, unknown>) {
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.info-grid {
|
||||
.summary-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.summary-block--wide {
|
||||
grid-column: span 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.detail-card-header {
|
||||
.order-hero {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@@ -290,8 +396,17 @@ function formatSpecSummary(spec: Record<string, unknown>) {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.info-grid {
|
||||
.summary-grid,
|
||||
.order-facts {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.summary-block--wide {
|
||||
grid-column: auto;
|
||||
}
|
||||
|
||||
.order-facts {
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -47,8 +47,11 @@ const summary = computed(() => ({
|
||||
paidCount: items.value.filter((item) => item.payStatus === "paid").length,
|
||||
refundedCount: items.value.filter((item) => item.payStatus === "refunded")
|
||||
.length,
|
||||
bindingReadyCount: items.value.filter(
|
||||
(item) => item.completedBindingTaskCount > 0
|
||||
completedCount: items.value.filter(
|
||||
(item) =>
|
||||
item.taskCount > 0 &&
|
||||
item.completedBindingTaskCount >= item.taskCount &&
|
||||
item.payStatus === "paid"
|
||||
).length,
|
||||
issueCount: items.value.filter((item) => hasOrderIssue(item)).length,
|
||||
}));
|
||||
@@ -72,10 +75,6 @@ async function applyFilters(page = 1) {
|
||||
await loadOrders(page);
|
||||
}
|
||||
|
||||
function resolveBuyerLabel(item: AdminOrderListItem) {
|
||||
return item.buyerName || item.buyerId || "未识别";
|
||||
}
|
||||
|
||||
function resolveShopLabel(item: AdminOrderListItem) {
|
||||
return item.shopName || item.shopId || "未识别店铺";
|
||||
}
|
||||
@@ -84,10 +83,6 @@ function resolveItemSummary(item: AdminOrderListItem) {
|
||||
return item.itemSummary || "未识别商品";
|
||||
}
|
||||
|
||||
function resolveBindingSummary(item: AdminOrderListItem) {
|
||||
return `共 ${item.totalBindingCount} 条 · 预占 ${item.reservedBindingCount} · 已消耗 ${item.consumedBindingCount} · 已释放 ${item.releasedBindingCount}`;
|
||||
}
|
||||
|
||||
function hasOrderIssue(item: AdminOrderListItem) {
|
||||
return (
|
||||
["refunded", "failed", "unpaid"].includes(item.payStatus) ||
|
||||
@@ -97,26 +92,62 @@ function hasOrderIssue(item: AdminOrderListItem) {
|
||||
}
|
||||
|
||||
function resolveFollowUpText(item: AdminOrderListItem) {
|
||||
if (item.payStatus === "unpaid") return "待支付";
|
||||
if (item.payStatus === "refunded") return "已退款";
|
||||
if (item.payStatus === "failed") return "支付失败";
|
||||
if (
|
||||
item.userBindingStatus === "binding_exception" ||
|
||||
item.systemBindingStatus === "binding_exception"
|
||||
)
|
||||
return "绑定异常";
|
||||
if (item.completedBindingTaskCount <= 0) return "待完整绑定";
|
||||
if (item.systemBoundTaskCount < item.taskCount) return "系统绑定未完成";
|
||||
return "链路正常";
|
||||
) {
|
||||
return "履约异常";
|
||||
}
|
||||
if (item.taskCount <= 0) return "未生成履约任务";
|
||||
if (item.completedBindingTaskCount >= item.taskCount) return "履约完成";
|
||||
if (item.systemBoundTaskCount > 0) return "等待客户绑定";
|
||||
return "待准备领取链接";
|
||||
}
|
||||
|
||||
function resolveFollowUpTone(item: AdminOrderListItem) {
|
||||
if (hasOrderIssue(item)) return "danger";
|
||||
if (
|
||||
item.completedBindingTaskCount <= 0 ||
|
||||
item.systemBoundTaskCount < item.taskCount
|
||||
)
|
||||
if (item.taskCount <= 0 || item.completedBindingTaskCount < item.taskCount)
|
||||
return "warning";
|
||||
return "success";
|
||||
}
|
||||
|
||||
function resolveResourceStageLabel(status: string) {
|
||||
const normalized = String(status || "").trim();
|
||||
const labelMap: Record<string, string> = {
|
||||
system_bound: "资源已准备",
|
||||
pending_binding: "待准备资源",
|
||||
pending_binding_prepare: "待准备资源",
|
||||
retry_pending: "待重试",
|
||||
manual_review: "人工处理",
|
||||
binding_exception: "资源异常",
|
||||
completed: "已完成",
|
||||
not_started: "未开始",
|
||||
};
|
||||
|
||||
return labelMap[normalized] || normalized || "-";
|
||||
}
|
||||
|
||||
function resolveCustomerStageLabel(status: string) {
|
||||
const normalized = String(status || "").trim();
|
||||
const labelMap: Record<string, string> = {
|
||||
not_started: "待打开链接",
|
||||
waiting_user_claim: "待打开链接",
|
||||
waiting_binding: "待客户绑定",
|
||||
link_opened: "已打开链接",
|
||||
user_binding: "客户绑定中",
|
||||
binding_confirmed: "已提交",
|
||||
binding_in_progress: "处理中",
|
||||
binding_completed: "客户已完成",
|
||||
binding_exception: "客户步骤异常",
|
||||
completed: "已完成",
|
||||
};
|
||||
|
||||
return labelMap[normalized] || normalized || "-";
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void applyFilters(readQueryPage());
|
||||
});
|
||||
@@ -126,7 +157,7 @@ onMounted(() => {
|
||||
<div class="orders-page list-page">
|
||||
<AdminPageHeader
|
||||
title="订单列表"
|
||||
description="查看平台订单、支付状态、商品摘要和对应任务推进情况。"
|
||||
description="查看 91 订单、核销店铺、商品和自动履约进度。"
|
||||
>
|
||||
<template #extra>
|
||||
<span class="total-badge">共 {{ pagination.total }} 条订单</span>
|
||||
@@ -138,7 +169,7 @@ onMounted(() => {
|
||||
<div class="card-header">
|
||||
<span class="card-title">查询订单</span>
|
||||
<span class="card-desc"
|
||||
>按平台订单号、支付状态、SKU 和日期范围筛选。</span
|
||||
>按订单号、支付状态、商品名和日期范围筛选。</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
@@ -166,7 +197,7 @@ onMounted(() => {
|
||||
<el-input
|
||||
v-model="skuCode"
|
||||
class="filter-control"
|
||||
placeholder="SKU,如 dnf-cdk-a"
|
||||
placeholder="商品名 / SKU"
|
||||
clearable
|
||||
@keyup.enter="applyFilters(1)"
|
||||
/>
|
||||
@@ -197,7 +228,7 @@ onMounted(() => {
|
||||
>已退款 <strong>{{ summary.refundedCount }}</strong></span
|
||||
>
|
||||
<span class="summary-metric" data-tone="primary"
|
||||
>完整绑定 <strong>{{ summary.bindingReadyCount }}</strong></span
|
||||
>已完成 <strong>{{ summary.completedCount }}</strong></span
|
||||
>
|
||||
<span
|
||||
class="summary-metric"
|
||||
@@ -252,72 +283,42 @@ onMounted(() => {
|
||||
<div class="order-meta-block">
|
||||
<span class="source-badge">{{ row.platform || "-" }}</span>
|
||||
<span class="order-meta-text" :title="resolveShopLabel(row)">
|
||||
店铺 {{ resolveShopLabel(row) }}
|
||||
</span>
|
||||
<span class="order-meta-text" :title="resolveBuyerLabel(row)">
|
||||
买家 {{ resolveBuyerLabel(row) }}
|
||||
核销店铺 {{ resolveShopLabel(row) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商品摘要" min-width="180">
|
||||
<el-table-column label="商品 / 任务" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<div class="cell-stack">
|
||||
<span class="cell-title" :title="resolveItemSummary(row)">{{
|
||||
resolveItemSummary(row)
|
||||
}}</span>
|
||||
<span class="cell-subline"
|
||||
>{{ row.itemCount }} 项,合计 {{ row.totalQuantity }} 件</span
|
||||
>
|
||||
<span
|
||||
class="cell-subline"
|
||||
:title="resolveBindingSummary(row)"
|
||||
>{{ resolveBindingSummary(row) }}</span
|
||||
>{{ row.itemCount }} 项 · 合计 {{ row.totalQuantity }} 件</span
|
||||
>
|
||||
<span class="cell-subline">履约任务 {{ row.taskCount }} 个</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付/状态" min-width="140">
|
||||
<el-table-column label="状态" min-width="230">
|
||||
<template #default="{ row }">
|
||||
<div class="status-line-stack">
|
||||
<div class="status-line">
|
||||
<span class="status-label">支付</span>
|
||||
<AdminStatusTag :status="row.payStatus" :show-raw="false" />
|
||||
</div>
|
||||
<div class="status-line">
|
||||
<span class="status-label">订单</span>
|
||||
<AdminStatusTag :status="row.orderStatus" :show-raw="false" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="交付状态" min-width="260">
|
||||
<template #default="{ row }">
|
||||
<div class="delivery-status-panel">
|
||||
<div class="order-status-summary">
|
||||
<span
|
||||
class="follow-up-chip"
|
||||
:data-tone="resolveFollowUpTone(row)"
|
||||
>{{ resolveFollowUpText(row) }}</span
|
||||
>
|
||||
<div class="delivery-track-list">
|
||||
<div class="delivery-track">
|
||||
<span class="delivery-track-label">完整绑定</span>
|
||||
<strong>{{ row.completedBindingTaskCount }}/{{ row.taskCount }}</strong>
|
||||
<AdminStatusTag
|
||||
:status="row.userBindingStatus"
|
||||
:show-raw="false"
|
||||
/>
|
||||
</div>
|
||||
<div class="delivery-track">
|
||||
<span class="delivery-track-label">系统绑定</span>
|
||||
<strong>{{ row.systemBoundTaskCount }}/{{ row.taskCount }}</strong>
|
||||
<AdminStatusTag
|
||||
:status="row.systemBindingStatus"
|
||||
:show-raw="false"
|
||||
/>
|
||||
</div>
|
||||
<div class="status-note-line">
|
||||
<span>支付</span>
|
||||
<AdminStatusTag :status="row.payStatus" :show-raw="false" />
|
||||
</div>
|
||||
<p class="status-note">
|
||||
客户 {{ resolveCustomerStageLabel(row.userBindingStatus) }}
|
||||
· 资源 {{ resolveResourceStageLabel(row.systemBindingStatus) }}
|
||||
· {{ row.completedBindingTaskCount }}/{{ row.taskCount }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -404,111 +405,41 @@ onMounted(() => {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.status-line-stack,
|
||||
.delivery-status-panel {
|
||||
display: grid;
|
||||
gap: var(--space-2);
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.status-line {
|
||||
display: grid;
|
||||
grid-template-columns: 34px minmax(0, 1fr);
|
||||
gap: var(--space-2);
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 22px;
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-full);
|
||||
background: #f7f9fc;
|
||||
color: var(--text-secondary);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.status-line :deep(.el-tag),
|
||||
.status-line :deep(.el-tag__content) {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.status-line :deep(.el-tag) {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.status-line :deep(.el-tag__content) {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.delivery-track-list {
|
||||
.order-status-summary {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.delivery-track {
|
||||
display: grid;
|
||||
grid-template-columns: 64px 42px minmax(0, 1fr);
|
||||
gap: var(--space-2);
|
||||
align-items: center;
|
||||
min-height: 28px;
|
||||
align-content: start;
|
||||
min-width: 0;
|
||||
padding: 3px 6px;
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-subtle);
|
||||
}
|
||||
|
||||
.delivery-track-label {
|
||||
.status-note-line {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.delivery-track strong {
|
||||
color: var(--text-primary);
|
||||
.status-note-line :deep(.el-tag) {
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.status-note {
|
||||
margin: 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.delivery-track :deep(.el-tag),
|
||||
.delivery-track :deep(.el-tag__content) {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.delivery-track :deep(.el-tag) {
|
||||
justify-content: center;
|
||||
background: var(--bg-card);
|
||||
}
|
||||
|
||||
.delivery-track :deep(.el-tag__content) {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.follow-up-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
min-height: 30px;
|
||||
width: fit-content;
|
||||
min-height: 26px;
|
||||
padding: 0 9px;
|
||||
border-radius: var(--radius-sm);
|
||||
border-radius: var(--radius-full);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 800;
|
||||
border: 1px solid transparent;
|
||||
|
||||
Reference in New Issue
Block a user