fix(@vben/web-antd): 修正工单详情步骤展示与状态分布配色
This commit is contained in:
@@ -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),
|
||||
},
|
||||
})),
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user