fix(@vben/web-antd): 修正工单详情步骤展示与状态分布配色

This commit is contained in:
lzh
2026-03-31 22:55:34 +08:00
parent 16434a0d88
commit f5f488080c
2 changed files with 62 additions and 51 deletions

View File

@@ -17,6 +17,8 @@ import { Card, Col, Row, Spin, Statistic, Tooltip } from 'ant-design-vue';
import { getDashboardStats } from '#/api/ops/order-center';
import { STATUS_COLOR_MAP, STATUS_TEXT_MAP } from '../data';
defineOptions({ name: 'CleaningWorkOrderDashboard' });
// ========== 保洁类型映射 ==========
@@ -468,14 +470,22 @@ function getTimeTrendChartOptions(): ECOption {
*/
function getStatusDistributionChartOptions(): ECOption {
const { statusDistribution } = statsData.value;
const STATUS_COLORS: Record<string, string> = {
待处理: '#C2540A', // PENDING
排队中: '#6D28D9', // QUEUED
已派单: '#0284C7', // DISPATCHED
已到岗: '#0D9488', // ARRIVED
已完成: '#0A7A55', // COMPLETED
已取消: '#6B5E52', // CANCELLED
已暂停: '#92400E', // PAUSED
// 中文名 → 状态码映射(兼容后端返回的中文名与前端 TEXT_MAP 的差异)
const NAME_TO_CODE: Record<string, string> = {
// 从 STATUS_TEXT_MAP 自动生成
...Object.fromEntries(
Object.entries(STATUS_TEXT_MAP).map(([code, label]) => [label, code]),
),
// 后端可能返回的别名补充
待处理: 'PENDING',
已派单: 'DISPATCHED',
已到岗: 'ARRIVED',
进行中: 'IN_PROGRESS',
已恢复: 'RESUMED',
};
const getStatusColor = (name: string) => {
const code = NAME_TO_CODE[name];
return code ? STATUS_COLOR_MAP[code]?.text : '#d9d9d9';
};
const total = statusDistribution.reduce((sum, item) => sum + item.value, 0);
return {
@@ -547,7 +557,7 @@ function getStatusDistributionChartOptions(): ECOption {
data: statusDistribution.map((item) => ({
...item,
itemStyle: {
color: STATUS_COLORS[item.name] || '#d9d9d9',
color: getStatusColor(item.name),
},
})),
},

View File

@@ -363,10 +363,26 @@ function getStepTime(key: string): string {
return '';
}
/** 将 timeline 节点转为步骤展示项 */
function toStepItem(t: OpsCleaningApi.TimelineItem) {
const step = STATUS_STEPS.find((s) => s.key === t.status);
return {
key: t.status,
title:
t.status === 'CANCELLED'
? '已取消'
: step?.title || t.statusName || t.status,
icon: step?.icon || 'solar:circle-bold-duotone',
desc: t.description || step?.desc || '',
};
}
/** 动态生成应该显示的状态步骤(根据 timeline 过滤) */
const visibleSteps = computed(() => {
// 取消状态:只展示 timeline 中已发生的节点(按时间顺序,去重)
if (isCancelled.value) {
const currentStatus = order.value.status;
// 终态(已完成/已取消):直接按 timeline 返回顺序展示,去重
if (['CANCELLED', 'COMPLETED'].includes(currentStatus)) {
const seen = new Set<string>();
return timeline.value
.filter((t) => {
@@ -374,59 +390,44 @@ const visibleSteps = computed(() => {
seen.add(t.status);
return true;
})
.map((t) => {
const step = STATUS_STEPS.find((s) => s.key === t.status);
return {
key: t.status,
title:
t.status === 'CANCELLED'
? '已取消'
: step?.title || t.statusName || t.status,
icon: step?.icon || 'solar:close-circle-bold-duotone',
desc: t.description || step?.desc || '',
};
});
.map((t) => toStepItem(t));
}
// 必须显示的节点(主流程)
const requiredSteps = new Set([
'ARRIVED',
'COMPLETED',
'CONFIRMED',
'DISPATCHED',
'PENDING',
]);
// 进行中状态timeline 中已有的节点 + 当前状态后续的预期节点
// 从 timeline 中已发生的节点(去重、保序)
const seen = new Set<string>();
const steps = timeline.value
.filter((t) => {
if (seen.has(t.status)) return false;
seen.add(t.status);
return true;
})
.map((t) => toStepItem(t));
// timeline 中存在的状态
const timelineStatuses = new Set(timeline.value.map((t) => t.status));
// 当前状态
const currentStatus = order.value.status;
// 过滤出要显示的节点
return STATUS_STEPS.filter((step) => {
// 必须显示的节点
if (requiredSteps.has(step.key)) return true;
// QUEUED 节点:只有在 timeline 中明确存在时才显示
if (step.key === 'QUEUED') {
return timelineStatuses.has('QUEUED');
// 追加尚未到达的后续预期节点(从 STATUS_STEPS 中取当前状态之后的)
const currentIdx = STATUS_STEPS.findIndex((s) => s.key === currentStatus);
for (const step of STATUS_STEPS.slice(currentIdx + 1)) {
if (!seen.has(step.key)) {
// QUEUED 只在 timeline 中明确出现时才展示
if (step.key === 'QUEUED') continue;
steps.push({ ...step });
seen.add(step.key);
}
}
// 其他节点timeline 中存在,或者是当前状态
return timelineStatuses.has(step.key) || currentStatus === step.key;
});
return steps;
});
/** 计算当前状态步骤索引 */
const currentStepIndex = computed(() => {
// 取消状态:所有节点都视为"已走过"索引指向最后一个
if (isCancelled.value) {
// 终态(取消/完成):索引指向最后一个节点
if (isCancelled.value || order.value.status === 'COMPLETED') {
return visibleSteps.value.length - 1;
}
if (order.value.status === 'PAUSED') {
// 暂停状态显示在到岗后
return visibleSteps.value.findIndex((s) => s.key === 'ARRIVED');
const arrivedIdx = visibleSteps.value.findIndex((s) => s.key === 'ARRIVED');
return arrivedIdx === -1 ? visibleSteps.value.length - 1 : arrivedIdx;
}
const index = visibleSteps.value.findIndex(
(s) => s.key === order.value.status,