style(@vben/web-antd): 统一工单中心配色方案为柔和浅底双色风格
- 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) <noreply@anthropic.com>
This commit is contained in:
@@ -3,17 +3,18 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
|
||||
import { OpsOrderCenterApi } from '#/api/ops/order-center';
|
||||
|
||||
/** 状态颜色映射 */
|
||||
export const STATUS_COLOR_MAP: Record<string, string> = {
|
||||
PENDING: '#8c8c8c', // 灰色 - 待分配
|
||||
QUEUED: '#faad14', // 黄色 - 排队中
|
||||
DISPATCHED: '#1677ff', // 蓝色 - 已推送
|
||||
CONFIRMED: '#13c2c2', // 青色 - 已确认
|
||||
ARRIVED: '#52c41a', // 绿色 - 已到岗
|
||||
PAUSED: '#fa8c16', // 橙色 - 已暂停
|
||||
RESUMED: '#52c41a', // 绿色 - 已恢复
|
||||
COMPLETED: '#389e0d', // 深绿 - 已完成
|
||||
CANCELLED: '#ff4d4f', // 红色 - 已取消
|
||||
/** 状态颜色映射(背景色 + 文字色) */
|
||||
export const STATUS_COLOR_MAP: Record<string, { bg: string; text: string }> = {
|
||||
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<string, string> = {
|
||||
SECURITY: '安保',
|
||||
};
|
||||
|
||||
/** 工单类型颜色映射 */
|
||||
export const ORDER_TYPE_COLOR_MAP: Record<string, string> = {
|
||||
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' }, // 服务
|
||||
};
|
||||
|
||||
/** 工单状态选项 */
|
||||
|
||||
@@ -619,13 +619,20 @@ onUnmounted(stopPolling);
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-base font-semibold">{{ order.title }}</span>
|
||||
<Tag :color="STATUS_COLOR_MAP[order.status]" class="status-tag">
|
||||
<span
|
||||
v-if="STATUS_COLOR_MAP[order.status]"
|
||||
class="status-tag inline-flex items-center rounded px-2 py-0.5 text-xs font-medium"
|
||||
:style="{
|
||||
backgroundColor: STATUS_COLOR_MAP[order.status]?.bg,
|
||||
color: STATUS_COLOR_MAP[order.status]?.text,
|
||||
}"
|
||||
>
|
||||
<IconifyIcon
|
||||
:icon="STATUS_ICON_MAP[order.status] || 'solar:circle-bold'"
|
||||
class="mr-1"
|
||||
/>
|
||||
{{ STATUS_TEXT_MAP[order.status] }}
|
||||
</Tag>
|
||||
</span>
|
||||
<span
|
||||
v-if="order.priority != null"
|
||||
class="priority-badge inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium"
|
||||
@@ -1009,10 +1016,16 @@ onUnmounted(stopPolling);
|
||||
class="custom-descriptions"
|
||||
>
|
||||
<Descriptions.Item label="工单类型">
|
||||
<Tag :color="ORDER_TYPE_COLOR_MAP[order.orderType]">
|
||||
<span
|
||||
class="inline-flex items-center rounded px-2 py-0.5 text-xs font-medium"
|
||||
:style="{
|
||||
backgroundColor: ORDER_TYPE_COLOR_MAP[order.orderType]?.bg,
|
||||
color: ORDER_TYPE_COLOR_MAP[order.orderType]?.text,
|
||||
}"
|
||||
>
|
||||
<IconifyIcon icon="solar:broom-bold-duotone" class="mr-1" />
|
||||
{{ ORDER_TYPE_TEXT_MAP[order.orderType] }}
|
||||
</Tag>
|
||||
</span>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="作业区域">
|
||||
<span class="flex items-center gap-1">
|
||||
|
||||
@@ -463,16 +463,32 @@ onMounted(() => {
|
||||
<Grid>
|
||||
<!-- 工单类型列 -->
|
||||
<template #orderType="{ row }">
|
||||
<Tag :color="ORDER_TYPE_COLOR_MAP[row.orderType]" size="small">
|
||||
<span
|
||||
v-if="ORDER_TYPE_COLOR_MAP[row.orderType]"
|
||||
class="inline-block rounded px-1.5 py-0.5 text-xs font-medium"
|
||||
:style="{
|
||||
backgroundColor: ORDER_TYPE_COLOR_MAP[row.orderType]?.bg,
|
||||
color: ORDER_TYPE_COLOR_MAP[row.orderType]?.text,
|
||||
}"
|
||||
>
|
||||
{{ ORDER_TYPE_TEXT_MAP[row.orderType] }}
|
||||
</Tag>
|
||||
</span>
|
||||
<span v-else class="text-gray-400">-</span>
|
||||
</template>
|
||||
|
||||
<!-- 工单状态列 -->
|
||||
<template #status="{ row }">
|
||||
<Tag :color="STATUS_COLOR_MAP[row.status]" size="small">
|
||||
<span
|
||||
v-if="STATUS_COLOR_MAP[row.status]"
|
||||
class="inline-block rounded px-1.5 py-0.5 text-xs font-medium"
|
||||
:style="{
|
||||
backgroundColor: STATUS_COLOR_MAP[row.status]?.bg,
|
||||
color: STATUS_COLOR_MAP[row.status]?.text,
|
||||
}"
|
||||
>
|
||||
{{ STATUS_TEXT_MAP[row.status] }}
|
||||
</Tag>
|
||||
</span>
|
||||
<span v-else class="text-gray-400">-</span>
|
||||
</template>
|
||||
|
||||
<!-- 优先级列 -->
|
||||
|
||||
@@ -469,13 +469,13 @@ function getTimeTrendChartOptions(): ECOption {
|
||||
function getStatusDistributionChartOptions(): ECOption {
|
||||
const { statusDistribution } = statsData.value;
|
||||
const STATUS_COLORS: Record<string, string> = {
|
||||
待处理: '#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 {
|
||||
|
||||
@@ -8,17 +8,18 @@ import { useDictStore } from '@vben/stores';
|
||||
|
||||
import { OpsOrderCenterApi } from '#/api/ops/order-center';
|
||||
|
||||
/** 状态颜色映射 */
|
||||
export const STATUS_COLOR_MAP: Record<string, string> = {
|
||||
PENDING: '#8c8c8c', // 灰色 - 待分配
|
||||
QUEUED: '#faad14', // 黄色 - 排队中
|
||||
DISPATCHED: '#1677ff', // 蓝色 - 已推送
|
||||
CONFIRMED: '#13c2c2', // 青色 - 已确认
|
||||
ARRIVED: '#52c41a', // 绿色 - 已到岗
|
||||
PAUSED: '#fa8c16', // 橙色 - 已暂停
|
||||
RESUMED: '#52c41a', // 绿色 - 已恢复
|
||||
COMPLETED: '#389e0d', // 深绿 - 已完成
|
||||
CANCELLED: '#ff4d4f', // 红色 - 已取消
|
||||
/** 状态颜色映射(背景色 + 文字色) */
|
||||
export const STATUS_COLOR_MAP: Record<string, { bg: string; text: string }> = {
|
||||
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<string, string> = {
|
||||
SECURITY: '安保',
|
||||
};
|
||||
|
||||
/** 工单类型颜色映射 */
|
||||
export const ORDER_TYPE_COLOR_MAP: Record<string, string> = {
|
||||
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' }, // 服务
|
||||
};
|
||||
|
||||
/** 工单状态选项 */
|
||||
|
||||
@@ -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(() => {
|
||||
<Grid>
|
||||
<!-- 工单类型列 -->
|
||||
<template #orderType="{ row }">
|
||||
<Tag :color="ORDER_TYPE_COLOR_MAP[row.orderType]" size="small">
|
||||
<span
|
||||
v-if="ORDER_TYPE_COLOR_MAP[row.orderType]"
|
||||
class="inline-block rounded px-1.5 py-0.5 text-xs font-medium"
|
||||
:style="{
|
||||
backgroundColor: ORDER_TYPE_COLOR_MAP[row.orderType]?.bg,
|
||||
color: ORDER_TYPE_COLOR_MAP[row.orderType]?.text,
|
||||
}"
|
||||
>
|
||||
{{ ORDER_TYPE_TEXT_MAP[row.orderType] }}
|
||||
</Tag>
|
||||
</span>
|
||||
<span v-else class="text-gray-400">-</span>
|
||||
</template>
|
||||
|
||||
<!-- 工单状态列 -->
|
||||
<template #status="{ row }">
|
||||
<Tag :color="STATUS_COLOR_MAP[row.status]" size="small">
|
||||
<span
|
||||
v-if="STATUS_COLOR_MAP[row.status]"
|
||||
class="inline-block rounded px-1.5 py-0.5 text-xs font-medium"
|
||||
:style="{
|
||||
backgroundColor: STATUS_COLOR_MAP[row.status]?.bg,
|
||||
color: STATUS_COLOR_MAP[row.status]?.text,
|
||||
}"
|
||||
>
|
||||
{{ STATUS_TEXT_MAP[row.status] }}
|
||||
</Tag>
|
||||
</span>
|
||||
<span v-else class="text-gray-400">-</span>
|
||||
</template>
|
||||
|
||||
<!-- 优先级列 -->
|
||||
<template #priority="{ row }">
|
||||
<Tag v-if="row.priority === 0" color="error" size="small"> P0 </Tag>
|
||||
<Tag v-else-if="row.priority === 1" color="warning" size="small">
|
||||
P1
|
||||
</Tag>
|
||||
<span v-else class="text-gray-400">P2</span>
|
||||
<span
|
||||
class="inline-block rounded px-1.5 py-0.5 text-xs font-medium"
|
||||
:style="getPriorityInfo(row.priority).style"
|
||||
>
|
||||
{{ getPriorityInfo(row.priority).label }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<!-- 执行人列 -->
|
||||
|
||||
Reference in New Issue
Block a user