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 ad179a2cb..c5ca2d958 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
@@ -51,45 +51,10 @@ export const STATUS_TAB_OPTIONS = [
label: '进行中',
statuses: ['DISPATCHED', 'CONFIRMED', 'ARRIVED', 'QUEUED'],
},
- { key: 'PAUSED', label: '已暂停', statuses: ['PAUSED'] },
{ key: 'COMPLETED', label: '已完成', statuses: ['COMPLETED'] },
{ key: 'CANCELLED', label: '已取消', statuses: ['CANCELLED'] },
];
-/** 优先级样式映射 */
-export const PRIORITY_STYLE_MAP: Record<
- number,
- {
- animation: boolean;
- bgColor: string;
- color: string;
- icon: string;
- label: string;
- }
-> = {
- 0: {
- label: 'P0',
- color: '#F44336',
- bgColor: '#FFEBEE',
- icon: 'lucide:zap',
- animation: true,
- },
- 1: {
- label: 'P1',
- color: '#FF9800',
- bgColor: '#FFF3E0',
- icon: 'lucide:alert-triangle',
- animation: false,
- },
- 2: {
- label: 'P2',
- color: '#9E9E9E',
- bgColor: '#FAFAFA',
- icon: 'lucide:info', // Added icon
- animation: false,
- },
-};
-
/** 工单类型选项 */
export const ORDER_TYPE_OPTIONS = [
{ label: '保洁', value: OpsOrderCenterApi.OrderType.CLEAN },
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 a6ba37e72..0fc3225dc 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
@@ -18,7 +18,6 @@ import { IconifyIcon } from '@vben/icons';
import { formatDateTime } from '@vben/utils';
import {
- Alert,
Avatar,
Button,
Card,
@@ -43,11 +42,12 @@ import {
} from '#/api/ops/cleaning';
import { getOrderDetail } from '#/api/ops/order-center';
+import { usePriorityInfo } from '../../../work-order/data';
+import CleaningDetailExt from '../components/cleaning-detail-ext.vue';
import {
CLEANING_TYPE_TEXT_MAP,
ORDER_TYPE_COLOR_MAP,
ORDER_TYPE_TEXT_MAP,
- PRIORITY_STYLE_MAP,
STATUS_COLOR_MAP,
STATUS_ICON_MAP,
STATUS_TEXT_MAP,
@@ -295,10 +295,7 @@ const [CancelFormModal, cancelFormModalApi] = useVbenModal({
destroyOnClose: true,
});
-/** 获取优先级样式 */
-function getPriorityStyle(priority: number) {
- return PRIORITY_STYLE_MAP[priority] || PRIORITY_STYLE_MAP[2];
-}
+const { getPriorityInfo } = usePriorityInfo();
/** 计算作业时长 */
const workDuration = computed(() => {
@@ -334,15 +331,6 @@ const isOvertime = computed(() => {
);
});
-/** 是否显示离岗警告 */
-const showLeaveWarning = computed(() => {
- return (
- order.value.status === 'ARRIVED' &&
- badgeStatus.value &&
- !badgeStatus.value.isInArea
- );
-});
-
/** 动态生成应该显示的状态步骤(根据 timeline 过滤) */
const visibleSteps = computed(() => {
// 必须显示的节点(主流程)
@@ -639,22 +627,18 @@ onUnmounted(stopPolling);
{{ STATUS_TEXT_MAP[order.status] }}
- {{ getPriorityStyle(order.priority)?.label }}
+ {{ getPriorityInfo(order.priority).label }}
@@ -852,26 +836,6 @@ onUnmounted(stopPolling);
-
-
-
- 保洁员已离开作业区域
-
-
-
- 检测到保洁员不在指定区域,请及时确认情况
-
-
-
-
-
@@ -891,7 +855,7 @@ onUnmounted(stopPolling);
作业进度
-
+
@@ -791,18 +883,12 @@ onUnmounted(stopPolling);
-
-
-
+
+
-
+
-
+
@@ -815,35 +901,11 @@ onUnmounted(stopPolling);
-
-
-
- {{ ORDER_TYPE_TEXT_MAP[order.orderType] }}
-
-
-
-
-
- {{ order.location || '-' }}
-
-
+
+ {{ order.triggerDeviceKey }}
+
+
+
+
+
+ {{ order.assigneeName?.charAt(0) || '?' }}
+
+
{{ order.assigneeName || '未知' }}
+
+ {{ getBadgeStatusText(badgeStatus.status) }}
+
+
+
+ 暂未分配
+
+
+
-
- {{ order.triggerDeviceKey }}
+
+
+ {{ order.description }}
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
- {{ order.assigneeName?.charAt(0) || '?' }}
-
-
-
- {{ order.assigneeName || '未知' }}
+
+
+
+
+
电量
+
+
-
工号: {{ order.assigneeId }}
+
+ {{ badgeStatus.batteryLevel }}%
+
-
未知
+
+
+
+
- {{ getBadgeStatusText(badgeStatus.status) }}
-
-
-
-
-
-
-
-
-
-
-
-
-
位置状态
-
-
- {{ badgeStatus.isInArea ? '在区域内' : '已离开' }}
-
-
- {{ badgeStatus.areaName }}
-
-
-
-
-
-
-
-
-
-
电池电量
-
-
-
- {{ badgeStatus.batteryLevel }}%
-
-
-
未知
-
-
-
-
-
-
-
-
信号强度
-
-
-
- {{ badgeStatus.rssi }} dBm
-
-
-
未知
-
-
-
-
-
-
-
-
最后心跳
-
- {{ formatRelativeTime(badgeStatus.lastHeartbeatTime) }}
-
-
-
+ />
+
位置
+
+
+ {{ badgeStatus.isInArea ? '在区域内' : '已离开' }}
+
+
+ {{ badgeStatus.areaName }}
+
-
-
-
-
-
-
暂未分配执行人
-
-
-
-
-
-
-
-
+
+
- 快捷操作
-
-
-
-
-
-
+
+
- 取消工单
-
-
-
-
-
- 升级为 P0 紧急
-
+ 心跳
+
+ {{ formatRelativeTime(badgeStatus.lastHeartbeatTime) }}
+
+
@@ -1457,82 +1456,22 @@ onUnmounted(stopPolling);
border-radius: 6px;
}
-/* ========== 离岗警告 ========== */
-.leave-warning {
- border-left: 3px solid #faad14;
- border-radius: 8px;
-}
-
-.leave-warning :deep(.ant-alert-message) {
- font-size: 14px;
-}
-
-.leave-warning :deep(.ant-alert-description) {
- font-size: 13px;
-}
-
-/* ========== 作业进度卡片 ========== */
-.work-progress-card {
- background: linear-gradient(135deg, #fff 0%, #f0f7ff 100%);
-}
-
-.progress-circle-wrapper {
+/* ========== 基础信息行:左右等高 ========== */
+.info-row :deep(> .ant-col) {
display: flex;
- align-items: center;
- justify-content: center;
}
-.progress-inner {
- text-align: center;
+.info-row .info-card {
+ flex: 1;
}
-.progress-value {
- font-size: 22px;
- font-weight: 700;
- line-height: 1.2;
- color: #1677ff;
+.info-row :deep(.work-progress-card) {
+ flex: 1;
}
-.progress-label {
- font-size: 12px;
- color: #8c8c8c;
-}
-
-.work-stats-grid {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 12px;
-}
-
-.stat-item {
- display: flex;
- gap: 10px;
- align-items: center;
- padding: 10px 12px;
- background: #fff;
- border-radius: 8px;
- box-shadow: 0 1px 2px rgb(0 0 0 / 4%);
-}
-
-.stat-icon {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 32px;
- height: 32px;
- font-size: 16px;
- border-radius: 8px;
-}
-
-.stat-label {
- font-size: 12px;
- color: #8c8c8c;
-}
-
-.stat-value {
- font-size: 14px;
- font-weight: 600;
- color: #262626;
+.info-row :deep(.work-progress-card .wp-card) {
+ height: 100%;
+ margin-bottom: 0;
}
/* ========== 信息卡片 ========== */
@@ -1667,59 +1606,54 @@ onUnmounted(stopPolling);
padding: 12px 0;
}
-/* ========== 执行人卡片 ========== */
-.assignee-info {
- display: flex;
- gap: 10px;
- align-items: center;
- padding-bottom: 12px;
- margin-bottom: 12px;
- border-bottom: 1px solid #f0f0f0;
-}
-
+/* ========== 执行人(内联在基础信息中) ========== */
.assignee-avatar {
background: linear-gradient(135deg, #1677ff 0%, #4096ff 100%);
- box-shadow: 0 2px 8px rgb(22 119 255 / 20%);
+ box-shadow: 0 1px 4px rgb(22 119 255 / 20%);
}
-.assignee-detail {
- flex: 1;
-}
-
-.assignee-name {
- font-size: 14px;
- font-weight: 600;
- color: #262626;
-}
-
-.assignee-id {
- font-size: 12px;
- color: #8c8c8c;
-}
-
-.status-badge {
- padding: 2px 10px;
- font-size: 12px;
- border-radius: 10px;
-}
-
-/* ========== 工牌状态面板 ========== */
-.badge-status-panel {
- padding: 12px;
- background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
- border-radius: 8px;
-}
-
-.panel-header {
- display: flex;
- gap: 6px;
- align-items: center;
- margin-bottom: 12px;
+/* ========== 工单描述 ========== */
+.desc-text {
font-size: 13px;
- font-weight: 500;
- color: #595959;
+ line-height: 1.8;
+ color: rgb(0 0 0 / 75%);
+ overflow-wrap: break-word;
+ white-space: pre-wrap;
}
+/* ========== 工单图片 ========== */
+.order-images {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.order-image-thumb {
+ overflow: hidden;
+ cursor: pointer;
+ border: 1px solid #f0f0f0;
+ border-radius: 6px;
+ transition: transform 0.2s;
+}
+
+.order-image-thumb:hover {
+ transform: scale(1.03);
+}
+
+/* ========== 头部操作区 ========== */
+.header-actions {
+ display: flex;
+ flex-shrink: 0;
+ gap: 8px;
+ align-items: center;
+}
+
+.header-divider {
+ height: 20px;
+ margin: 0;
+}
+
+/* ========== 工牌信息卡片 ========== */
.pulse-dot {
width: 6px;
height: 6px;
@@ -1729,41 +1663,36 @@ onUnmounted(stopPolling);
animation: pulse 1.5s infinite;
}
-.badge-stats {
+.badge-stats-compact {
display: flex;
flex-direction: column;
- gap: 8px;
+ gap: 10px;
}
-.badge-stat-item {
+.badge-row {
display: flex;
gap: 8px;
align-items: center;
+ font-size: 13px;
}
-.badge-stat-icon {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 28px;
- height: 28px;
- font-size: 14px;
-}
-
-.badge-stat-content {
- flex: 1;
-}
-
-.badge-stat-label {
- margin-bottom: 2px;
+.badge-row-label {
+ flex-shrink: 0;
+ width: 32px;
font-size: 12px;
color: #8c8c8c;
}
-.battery-bar {
- width: 100%;
+.badge-row-value {
+ display: flex;
+ flex: 1;
+ gap: 6px;
+ align-items: center;
+}
+
+.battery-bar-sm {
+ width: 60px;
height: 5px;
- margin-bottom: 2px;
overflow: hidden;
background: #e8e8e8;
border-radius: 2px;
@@ -1775,11 +1704,6 @@ onUnmounted(stopPolling);
transition: width 0.3s;
}
-.battery-text {
- font-size: 12px;
- font-weight: 500;
-}
-
.signal-strength {
display: flex;
gap: 3px;
@@ -1816,80 +1740,10 @@ onUnmounted(stopPolling);
color: #8c8c8c;
}
-.heartbeat-time {
- font-size: 13px;
- font-weight: 500;
- color: #262626;
-}
-
-/* ========== 无执行人 ========== */
-.no-assignee {
- display: flex;
- flex-direction: column;
- gap: 12px;
- align-items: center;
- padding: 24px 0;
-}
-
-.no-assignee-icon {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 48px;
- height: 48px;
- font-size: 20px;
- color: #bfbfbf;
- background: #f5f5f5;
- border-radius: 50%;
-}
-
-.no-assignee-text {
- font-size: 14px;
- color: #8c8c8c;
-}
-
-/* ========== 操作卡片 ========== */
-.actions-list {
- display: flex;
- flex-direction: column;
- gap: 10px;
-}
-
-.action-btn {
- display: flex;
- gap: 6px;
- align-items: center;
- justify-content: center;
- height: 36px;
- font-size: 14px;
- font-weight: 500;
- border-radius: 6px;
- transition: all 0.2s;
-}
-
-.action-btn:hover {
- box-shadow: 0 2px 8px rgb(0 0 0 / 10%);
- transform: translateY(-1px);
-}
-
-.action-btn-success {
- background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
- border: none;
-}
-
-.action-btn-success:hover {
- background: linear-gradient(135deg, #389e0d 0%, #52c41a 100%);
-}
-
-.action-btn-upgrade {
- border-style: dashed;
-}
-
/* ========== 暗色模式适配 ========== */
:deep(.dark) {
.detail-header,
- .progress-overview-card,
- .work-progress-card {
+ .progress-overview-card {
background: var(--component-background);
}
@@ -1906,10 +1760,6 @@ onUnmounted(stopPolling);
background: rgb(255 255 255 / 5%);
}
- .stat-item {
- background: rgb(255 255 255 / 5%);
- }
-
.logs-toggle-btn {
color: #a6a6a6;
background: rgb(255 255 255 / 5%);
@@ -1937,12 +1787,8 @@ onUnmounted(stopPolling);
color: #a6a6a6;
}
- .badge-status-panel {
- background: rgb(255 255 255 / 5%);
- }
-
- .no-assignee-icon {
- background: rgb(255 255 255 / 5%);
+ .desc-text {
+ color: rgb(255 255 255 / 75%);
}
.cancelled-banner {
diff --git a/apps/web-antd/src/views/ops/work-order/modules/card-view.vue b/apps/web-antd/src/views/ops/work-order/modules/card-view.vue
index 190b5f44e..ed075c153 100644
--- a/apps/web-antd/src/views/ops/work-order/modules/card-view.vue
+++ b/apps/web-antd/src/views/ops/work-order/modules/card-view.vue
@@ -1,5 +1,5 @@
@@ -673,18 +624,19 @@ onMounted(() => {
}
.info-text {
+ flex: 1;
+ min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
- word-break: break-all;
- white-space: normal;
+ white-space: nowrap;
&--muted {
- font-style: italic;
color: #bfbfbf;
}
}
.order-code-styled {
+ flex: none;
padding: 1px 6px;
font-family: 'SF Mono', Monaco, monospace;
font-size: 12px;