From d0395ba40a5ee2e06a2e23af5de76ae8f1130e43 Mon Sep 17 00:00:00 2001 From: lzh Date: Wed, 25 Mar 2026 11:35:37 +0800 Subject: [PATCH] =?UTF-8?q?style(@vben/web-antd):=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E5=B7=A5=E5=8D=95=E4=B8=AD=E5=BF=83=E9=85=8D=E8=89=B2=E6=96=B9?= =?UTF-8?q?=E6=A1=88=E4=B8=BA=E6=9F=94=E5=92=8C=E6=B5=85=E5=BA=95=E5=8F=8C?= =?UTF-8?q?=E8=89=B2=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - STATUS_COLOR_MAP / ORDER_TYPE_COLOR_MAP 由单色改为 { bg, text } 双色结构 - 新增 FACILITIES / SERVICE 工单类型配色 - 优先级配色改为按数值直接映射(P0~P3),不再依赖字典 colorType - Tag 组件替换为 span + inline style,精确控制背景色与文字色 - 仪表板饼图 STATUS_COLORS 同步更新 - 同步更新 cleaning/work-order 模块保持一致 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/views/ops/cleaning/work-order/data.ts | 37 ++++--- .../ops/cleaning/work-order/detail/index.vue | 21 +++- .../views/ops/cleaning/work-order/index.vue | 24 +++- .../views/ops/work-order/dashboard/index.vue | 14 +-- .../web-antd/src/views/ops/work-order/data.ts | 103 ++++++++++-------- .../src/views/ops/work-order/index.vue | 47 +++++--- 6 files changed, 149 insertions(+), 97 deletions(-) diff --git a/apps/web-antd/src/views/ops/cleaning/work-order/data.ts b/apps/web-antd/src/views/ops/cleaning/work-order/data.ts index c5ca2d958..d44930461 100644 --- a/apps/web-antd/src/views/ops/cleaning/work-order/data.ts +++ b/apps/web-antd/src/views/ops/cleaning/work-order/data.ts @@ -3,17 +3,18 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import { OpsOrderCenterApi } from '#/api/ops/order-center'; -/** 状态颜色映射 */ -export const STATUS_COLOR_MAP: Record = { - PENDING: '#8c8c8c', // 灰色 - 待分配 - QUEUED: '#faad14', // 黄色 - 排队中 - DISPATCHED: '#1677ff', // 蓝色 - 已推送 - CONFIRMED: '#13c2c2', // 青色 - 已确认 - ARRIVED: '#52c41a', // 绿色 - 已到岗 - PAUSED: '#fa8c16', // 橙色 - 已暂停 - RESUMED: '#52c41a', // 绿色 - 已恢复 - COMPLETED: '#389e0d', // 深绿 - 已完成 - CANCELLED: '#ff4d4f', // 红色 - 已取消 +/** 状态颜色映射(背景色 + 文字色) */ +export const STATUS_COLOR_MAP: Record = { + PENDING: { bg: '#FFF3E8', text: '#C2540A' }, // 待分配 + QUEUED: { bg: '#F0EDFF', text: '#6D28D9' }, // 排队中 + DISPATCHED: { bg: '#E0F2FE', text: '#0284C7' }, // 已派发 + CONFIRMED: { bg: '#EEF0FF', text: '#3730A3' }, // 已确认 + ARRIVED: { bg: '#E5F5EF', text: '#0D9488' }, // 已到岗 + IN_PROGRESS: { bg: '#E8F0FE', text: '#1558C0' }, // 进行中 + PAUSED: { bg: '#FFF7E0', text: '#92400E' }, // 已暂停 + RESUMED: { bg: '#E5F6FB', text: '#0891B2' }, // 已恢复 + COMPLETED: { bg: '#E8FAF2', text: '#0A7A55' }, // 已完成 + CANCELLED: { bg: '#F0EDE8', text: '#6B5E52' }, // 已取消 }; /** 状态文本映射 */ @@ -69,11 +70,15 @@ export const ORDER_TYPE_TEXT_MAP: Record = { SECURITY: '安保', }; -/** 工单类型颜色映射 */ -export const ORDER_TYPE_COLOR_MAP: Record = { - CLEAN: '#52c41a', // 绿色 - REPAIR: '#fa8c16', // 橙色 - SECURITY: '#1890ff', // 蓝色 +/** 工单类型颜色映射(背景色 + 文字色) */ +export const ORDER_TYPE_COLOR_MAP: Record< + string, + { bg: string; text: string } +> = { + CLEAN: { bg: '#E5FAF2', text: '#047857' }, // 保洁 + SECURITY: { bg: '#EEF0FF', text: '#3730A3' }, // 安保 + FACILITIES: { bg: '#FFF5E0', text: '#92400E' }, // 设施 + SERVICE: { bg: '#E0F2FE', text: '#0369A1' }, // 服务 }; /** 工单状态选项 */ diff --git a/apps/web-antd/src/views/ops/cleaning/work-order/detail/index.vue b/apps/web-antd/src/views/ops/cleaning/work-order/detail/index.vue index 0fc3225dc..3a22d8be6 100644 --- a/apps/web-antd/src/views/ops/cleaning/work-order/detail/index.vue +++ b/apps/web-antd/src/views/ops/cleaning/work-order/detail/index.vue @@ -619,13 +619,20 @@ onUnmounted(stopPolling);
{{ order.title }} - + {{ STATUS_TEXT_MAP[order.status] }} - + - + {{ ORDER_TYPE_TEXT_MAP[order.orderType] }} - + diff --git a/apps/web-antd/src/views/ops/cleaning/work-order/index.vue b/apps/web-antd/src/views/ops/cleaning/work-order/index.vue index c146ce0db..f0dce9010 100644 --- a/apps/web-antd/src/views/ops/cleaning/work-order/index.vue +++ b/apps/web-antd/src/views/ops/cleaning/work-order/index.vue @@ -463,16 +463,32 @@ onMounted(() => { diff --git a/apps/web-antd/src/views/ops/work-order/dashboard/index.vue b/apps/web-antd/src/views/ops/work-order/dashboard/index.vue index 5273c205b..ad5ad9614 100644 --- a/apps/web-antd/src/views/ops/work-order/dashboard/index.vue +++ b/apps/web-antd/src/views/ops/work-order/dashboard/index.vue @@ -469,13 +469,13 @@ function getTimeTrendChartOptions(): ECOption { function getStatusDistributionChartOptions(): ECOption { const { statusDistribution } = statsData.value; const STATUS_COLORS: Record = { - 待处理: '#faad14', - 排队中: '#722ed1', - 已派单: '#1677ff', - 已到岗: '#13c2c2', - 已完成: '#52c41a', - 已取消: '#ff4d4f', - 已暂停: '#8c8c8c', + 待处理: '#C2540A', // PENDING + 排队中: '#6D28D9', // QUEUED + 已派单: '#0284C7', // DISPATCHED + 已到岗: '#0D9488', // ARRIVED + 已完成: '#0A7A55', // COMPLETED + 已取消: '#6B5E52', // CANCELLED + 已暂停: '#92400E', // PAUSED }; const total = statusDistribution.reduce((sum, item) => sum + item.value, 0); return { diff --git a/apps/web-antd/src/views/ops/work-order/data.ts b/apps/web-antd/src/views/ops/work-order/data.ts index 0d1718fcf..a881f9b34 100644 --- a/apps/web-antd/src/views/ops/work-order/data.ts +++ b/apps/web-antd/src/views/ops/work-order/data.ts @@ -8,17 +8,18 @@ import { useDictStore } from '@vben/stores'; import { OpsOrderCenterApi } from '#/api/ops/order-center'; -/** 状态颜色映射 */ -export const STATUS_COLOR_MAP: Record = { - PENDING: '#8c8c8c', // 灰色 - 待分配 - QUEUED: '#faad14', // 黄色 - 排队中 - DISPATCHED: '#1677ff', // 蓝色 - 已推送 - CONFIRMED: '#13c2c2', // 青色 - 已确认 - ARRIVED: '#52c41a', // 绿色 - 已到岗 - PAUSED: '#fa8c16', // 橙色 - 已暂停 - RESUMED: '#52c41a', // 绿色 - 已恢复 - COMPLETED: '#389e0d', // 深绿 - 已完成 - CANCELLED: '#ff4d4f', // 红色 - 已取消 +/** 状态颜色映射(背景色 + 文字色) */ +export const STATUS_COLOR_MAP: Record = { + PENDING: { bg: '#FFF3E8', text: '#C2540A' }, // 待分配 + QUEUED: { bg: '#F0EDFF', text: '#6D28D9' }, // 排队中 + DISPATCHED: { bg: '#E0F2FE', text: '#0284C7' }, // 已派发 + CONFIRMED: { bg: '#EEF0FF', text: '#3730A3' }, // 已确认 + ARRIVED: { bg: '#E5F5EF', text: '#0D9488' }, // 已到岗 + IN_PROGRESS: { bg: '#E8F0FE', text: '#1558C0' }, // 进行中 + PAUSED: { bg: '#FFF7E0', text: '#92400E' }, // 已暂停 + RESUMED: { bg: '#E5F6FB', text: '#0891B2' }, // 已恢复 + COMPLETED: { bg: '#E8FAF2', text: '#0A7A55' }, // 已完成 + CANCELLED: { bg: '#F0EDE8', text: '#6B5E52' }, // 已取消 }; /** 状态文本映射 */ @@ -60,7 +61,36 @@ export const STATUS_TAB_OPTIONS = [ { key: 'CANCELLED', label: '已取消', statuses: ['CANCELLED'] }, ]; -/** 获取优先级信息(基于字典),返回 getPriorityInfo 函数 */ +/** 优先级颜色映射(按数值直接映射,不依赖字典 colorType) */ +const PRIORITY_STYLE_MAP: Record< + number, + { style: { backgroundColor: string; color: string }; icon: string } +> = { + 0: { + style: { backgroundColor: '#FFF0F0', color: '#C01D1D' }, + icon: 'solar:bolt-bold', + }, // P0 紧急 + 1: { + style: { backgroundColor: '#FFF4E6', color: '#C2410C' }, + icon: 'lucide:alert-triangle', + }, // P1 重要 + 2: { + style: { backgroundColor: '#F0EDE8', color: '#6B5E52' }, + icon: 'lucide:info', + }, // P2 一般 + 3: { + style: { backgroundColor: '#E8FAF2', color: '#0A7A55' }, + icon: 'lucide:info', + }, // P3 低优 +}; + +/** 默认优先级样式(未匹配时回退) */ +const DEFAULT_PRIORITY = { + style: { backgroundColor: '#F0EDE8', color: '#6B5E52' }, + icon: 'lucide:info', +}; + +/** 获取优先级信息(基于字典标签 + 数值精确配色) */ export function usePriorityInfo() { const dictStore = useDictStore(); const priorityOptions = computed(() => @@ -68,40 +98,13 @@ export function usePriorityInfo() { ); function getPriorityInfo(priority: number | string | undefined) { + const p = Number(priority); const dictItem = priorityOptions.value.find( (item) => item.value === String(priority), ); - if (!dictItem) { - return { - label: `P${priority}`, - style: { color: '#8c8c8c', backgroundColor: '#f5f5f5' }, - icon: 'lucide:info', - }; - } - let style = { color: '#8c8c8c', backgroundColor: '#f5f5f5' }; - switch (dictItem.colorType) { - case 'danger': { - style = { color: '#ff4d4f', backgroundColor: '#fff1f0' }; - break; - } - case 'info': { - style = { color: '#1677ff', backgroundColor: '#e6f4ff' }; - break; - } - case 'success': { - style = { color: '#52c41a', backgroundColor: '#f6ffed' }; - break; - } - case 'warning': { - style = { color: '#fa8c16', backgroundColor: '#fff7e6' }; - break; - } - // No default - } - let icon = 'lucide:info'; - if (Number(priority) === 0) icon = 'solar:bolt-bold'; - else if (Number(priority) === 1) icon = 'lucide:alert-triangle'; - return { label: dictItem.label, style, icon }; + const label = dictItem?.label ?? `P${priority}`; + const mapped = PRIORITY_STYLE_MAP[p] ?? DEFAULT_PRIORITY; + return { label, ...mapped }; } return { getPriorityInfo }; @@ -121,11 +124,15 @@ export const ORDER_TYPE_TEXT_MAP: Record = { SECURITY: '安保', }; -/** 工单类型颜色映射 */ -export const ORDER_TYPE_COLOR_MAP: Record = { - CLEAN: '#52c41a', // 绿色 - REPAIR: '#fa8c16', // 橙色 - SECURITY: '#1890ff', // 蓝色 +/** 工单类型颜色映射(背景色 + 文字色) */ +export const ORDER_TYPE_COLOR_MAP: Record< + string, + { bg: string; text: string } +> = { + CLEAN: { bg: '#E5FAF2', text: '#047857' }, // 保洁 + SECURITY: { bg: '#EEF0FF', text: '#3730A3' }, // 安保 + FACILITIES: { bg: '#FFF5E0', text: '#92400E' }, // 设施 + SERVICE: { bg: '#E0F2FE', text: '#0369A1' }, // 服务 }; /** 工单状态选项 */ diff --git a/apps/web-antd/src/views/ops/work-order/index.vue b/apps/web-antd/src/views/ops/work-order/index.vue index aeac2030b..2ec68c7a8 100644 --- a/apps/web-antd/src/views/ops/work-order/index.vue +++ b/apps/web-antd/src/views/ops/work-order/index.vue @@ -8,15 +8,7 @@ import { useRouter } from 'vue-router'; import { Page, useVbenModal } from '@vben/common-ui'; import { IconifyIcon } from '@vben/icons'; -import { - Button, - Card, - Input, - message, - Select, - Tabs, - Tag, -} from 'ant-design-vue'; +import { Button, Card, Input, message, Select, Tabs } from 'ant-design-vue'; import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { OpsCleaningApi, sendDeviceNotify } from '#/api/ops/cleaning'; @@ -32,6 +24,7 @@ import { STATUS_TAB_OPTIONS, STATUS_TEXT_MAP, useGridColumns, + usePriorityInfo, } from './data'; import AssignForm from './modules/assign-form.vue'; import CancelForm from './modules/cancel-form.vue'; @@ -42,6 +35,7 @@ import UpgradePriorityForm from './modules/upgrade-priority-form.vue'; defineOptions({ name: 'WorkOrderCenter' }); +const { getPriorityInfo } = usePriorityInfo(); const router = useRouter(); const viewMode = ref<'card' | 'list'>('card'); const activeTab = ref('ALL'); @@ -490,25 +484,42 @@ onActivated(() => {