-
-
-
-
-
-
- {{ step.executor || (step.getOrderPersonVo && step.getOrderPersonVo.userName) || '待分配' }}
-
-
- 预期时间:{{ formatDateTime(step.intendedTime) }}
-
-
预期目的:{{ step.intendedPurpose || '-' }}
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ step.code || index + 1 }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ step.executor || (step.getOrderPersonVo && step.getOrderPersonVo.userName) || '待分配' }}
+
+
+
+
+ 预期时间:{{ formatDateTime(step.intendedTime) }}
+
+
+
+
+ 预期目的:{{ step.intendedPurpose || '-' }}
+
+
+
@@ -612,7 +640,8 @@ const updateCurrentTrackedOrder = () => {
intendedTime: node.intendedTime,
finishTime: node.finishTime,
intendedPurpose: node.intendedPurpose || '-',
- remark: node.remark || ''
+ remark: node.remark || '',
+ status: node.status || '' // 添加status字段
}));
} else {
// 如果nodes数组为空,创建一些默认的步骤数据
@@ -620,13 +649,12 @@ const updateCurrentTrackedOrder = () => {
}
// 设置当前激活步骤索引
- // 如果有实际的完成时间,我们可以基于此设置激活步骤
- // 否则默认设置为第一个步骤
+ // 根据status字段判断,status='1'表示完成,status='2'表示未完成,status='3'表示失败
activeStepIndex.value = 0;
// 检查是否有已完成的步骤,如果有,将激活步骤设置为最后一个已完成步骤的下一个
for (let i = trackingSteps.value.length - 1; i >= 0; i--) {
- if (trackingSteps.value[i].finishTime) {
+ if (trackingSteps.value[i].status === '1') {
activeStepIndex.value = Math.min(i + 1, trackingSteps.value.length - 1);
break;
}
@@ -796,8 +824,10 @@ const refreshTrackingSteps = async () => {
// 根据索引获取步骤状态
const getStatusByIndex = (index) => {
+ if (!currentTrackedWorkOrder.value) return 'wait';
+
if (index < activeStepIndex.value) {
- return 'success';
+ return 'finish';
} else if (index === activeStepIndex.value) {
return 'process';
} else {
@@ -805,6 +835,101 @@ const getStatusByIndex = (index) => {
}
};
+// 试验记录页面步骤条状态判断 - 重点跟踪区域专用
+const getStepStatusClass = (index) => {
+ if (!currentTrackedWorkOrder.value) return 'pending';
+
+ const step = trackingSteps.value[index];
+ if (step) {
+ // 优先根据status字段判断状态
+ const status = step.status?.toString() || '';
+
+ if (status === '1') {
+ return 'completed'; // 完成状态 - 绿色
+ } else if (status === '3') {
+ return 'delayed'; // 失败状态 - 红色
+ } else if (status === '2') {
+ return 'pending'; // 未完成状态 - 灰色
+ }
+ }
+
+ // fallback到基于索引的判断逻辑
+ if (index < activeStepIndex.value) {
+ return 'completed';
+ } else if (index === activeStepIndex.value) {
+ return 'active';
+ } else {
+ return 'pending';
+ }
+};
+
+// 获取进度线状态 - 重点跟踪区域专用
+const getLineStatusClass = (index) => {
+ if (!currentTrackedWorkOrder.value) return 'pending';
+
+ // 进度线状态与前一个步骤状态保持一致
+ const prevStepIndex = index;
+ const prevStep = trackingSteps.value[prevStepIndex];
+
+ if (prevStep) {
+ const status = prevStep.status?.toString() || '';
+
+ if (status === '1') {
+ return 'completed'; // 前一步骤已完成 - 绿色
+ } else if (status === '3') {
+ return 'delayed'; // 前一步骤失败 - 红色
+ }
+ }
+
+ // fallback到基于索引的判断逻辑
+ if (index < activeStepIndex.value) {
+ return 'completed';
+ } else {
+ return 'pending';
+ }
+};
+
+// 计算进度百分比
+const getProgressPercentage = () => {
+ if (!currentTrackedWorkOrder.value || trackingSteps.value.length === 0) return 0;
+
+ // 优先使用API返回的progress字段值
+ if (currentTrackedWorkOrder.value.progress) {
+ try {
+ // 将字符串类型的progress转换为数字
+ const progressValue = parseFloat(currentTrackedWorkOrder.value.progress);
+ // 确保进度值在0-100之间
+ return Math.min(Math.max(progressValue, 0), 100);
+ } catch (error) {
+ console.warn('解析progress字段失败,使用默认计算逻辑:', error);
+ // 解析失败时使用原有逻辑
+ }
+ }
+
+ // 计算已完成步骤数
+ const completedSteps = trackingSteps.value.filter((step) => step.status === '1').length;
+
+ // 如果没有已完成步骤,但有活跃步骤,则使用活跃步骤的位置
+ if (completedSteps === 0 && activeStepIndex.value >= 0) {
+ return (activeStepIndex.value / trackingSteps.value.length) * 100;
+ }
+
+ // 计算进度百分比
+ const percentage = (completedSteps / trackingSteps.value.length) * 100;
+
+ // 确保最大为100%
+ return Math.min(percentage, 100);
+};
+
+// 计算节点位置百分比
+const getNodePosition = (index) => {
+ if (!currentTrackedWorkOrder.value || trackingSteps.value.length <= 1) return 0;
+
+ // 等距分布节点
+ const position = (index / (trackingSteps.value.length - 1)) * 100;
+ return position;
+};
+
// 将状态码转换为可读的状态文本
const getStatusText = (statusCode) => {
const statusMap = {
@@ -1762,10 +1887,6 @@ const handleCloseDetailDialog = () => {
transition: all 0.3s ease;
}
-.step-connector.connector-completed {
- background: linear-gradient(to bottom, #52c41a, #73d13d);
-}
-
/* 动画效果 */
@keyframes fadeInUp {
from {
@@ -3320,13 +3441,299 @@ const handleCloseDetailDialog = () => {
position: relative;
}
+/* 重点跟踪区域进度条样式 */
+.tracking-progress-container {
+ padding: 20px;
+ background-color: #fff;
+}
+
+/* 进度条包装器 */
+.progress-bar-wrapper {
+ position: relative;
+ height: 40px;
+ margin-bottom: 30px;
+ display: flex;
+ align-items: center;
+}
+
+/* 进度条背景 */
+.progress-bar-background {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ height: 6px;
+ background-color: #e5e7eb;
+ border-radius: 3px;
+ transform: translateY(-50%);
+}
+
+/* 进度条填充 */
+.progress-bar-fill {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ height: 6px;
+ background: linear-gradient(90deg, #00b42a, #95de64);
+ border-radius: 3px;
+ transition: width 0.6s ease;
+ transform: translateY(-50%);
+}
+
+/* 进度条节点容器 */
+.progress-bar-nodes {
+ position: relative;
+ width: 100%;
+ height: 100%;
+}
+
+/* 进度条节点 */
+.progress-node {
+ position: absolute;
+ top: 50%;
+ transform: translate(-50%, -50%);
+}
+
+/* 节点圆圈 */
+.node-circle {
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ background-color: #fff;
+ border: 2px solid #e5e7eb;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ transition: all 0.3s ease;
+ z-index: 2;
+}
+
+/* 节点图标/数字 */
+.node-icon {
+ font-size: 14px;
+ font-weight: 600;
+ color: #6b7280;
+}
+
+/* 步骤信息卡片容器 */
+.progress-steps-info {
+ display: flex;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+/* 单个步骤信息卡片 */
+.step-info-card {
+ flex: 1;
+ min-width: 160px;
+ max-width: 250px;
+ padding: 12px;
+ border-radius: 6px;
+ border: 1px solid #f0f0f0;
+ background-color: #fff;
+ transition: all 0.3s ease;
+}
+
+/* 步骤卡片头部 */
+.step-header {
+ display: flex;
+ align-items: center;
+ margin-bottom: 8px;
+}
+
+/* 步骤数字 */
+.step-info-card .step-number {
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ background-color: #e5e7eb;
+ color: #6b7280;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 11px;
+ font-weight: 600;
+ margin-right: 6px;
+}
+
+/* 步骤名称 */
+.step-name {
+ font-size: 16px;
+ font-weight: 600;
+ color: #1f2937;
+}
+
+/* 步骤详情 */
+.step-details {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ font-size: 14px;
+}
+
+.step-details > div {
+ display: flex;
+ align-items: center;
+ color: #6b7280;
+}
+
+.step-details i {
+ margin-right: 6px;
+ font-size: 14px;
+}
+
+/* 已完成状态样式 - 绿色 */
+.step-info-card.completed {
+ border-color: #00b42a;
+ background-color: #f6ffed;
+}
+
+.step-info-card.completed .step-number {
+ background-color: #00b42a;
+ color: white;
+}
+
+.progress-node.completed .node-circle {
+ border-color: #00b42a;
+ background-color: #fff;
+}
+
+.progress-node.completed .node-icon {
+ background-color: #00b42a;
+ color: white;
+ border-radius: 50%;
+ width: 28px;
+ height: 28px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* 进行中状态样式 */
+.step-info-card.active {
+ border-color: #165dff;
+ background-color: #f0f7ff;
+ box-shadow: 0 4px 12px rgba(22, 93, 255, 0.1);
+}
+
+.step-info-card.active .step-number {
+ background-color: #165dff;
+ color: white;
+}
+
+.progress-node.active .node-circle {
+ border-color: #165dff;
+ background-color: #fff;
+ animation: pulse 2s infinite;
+}
+
+.progress-node.active .node-icon {
+ background-color: #165dff;
+ color: white;
+ border-radius: 50%;
+ width: 28px;
+ height: 28px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* 待处理状态样式 */
+.step-info-card.pending {
+ border-color: #e5e7eb;
+ background-color: #fff;
+}
+
+/* 失败/逾期状态样式 */
+.step-info-card.delayed {
+ border-color: #ff4d4f;
+ background-color: #fff2f0;
+}
+
+.step-info-card.delayed .step-number {
+ background-color: #ff4d4f;
+ color: white;
+}
+
+.progress-node.delayed .node-circle {
+ border-color: #ff4d4f;
+ background-color: #fff;
+}
+
+.progress-node.delayed .node-icon {
+ background-color: #ff4d4f;
+ color: white;
+ border-radius: 50%;
+ width: 28px;
+ height: 28px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* 脉冲动画 */
+@keyframes pulse {
+ 0% {
+ box-shadow: 0 0 0 0 rgba(22, 93, 255, 0.4);
+ }
+ 70% {
+ box-shadow: 0 0 0 10px rgba(22, 93, 255, 0);
+ }
+ 100% {
+ box-shadow: 0 0 0 0 rgba(22, 93, 255, 0);
+ }
+}
+
+.tracking-progress-timeline .progress-step.completed .step-number {
+ background-color: #00b42a;
+ color: white;
+}
+
+.tracking-progress-timeline .progress-line.completed {
+ background-color: #00b42a;
+}
+
+.tracking-progress-timeline .progress-step.delayed .step-number {
+ background-color: #dc2626;
+ color: white;
+}
+
+.tracking-progress-timeline .progress-line.delayed {
+ background-color: #dc2626;
+}
+
+.tracking-progress-timeline .step-name {
+ font-size: 14px;
+ font-weight: 500;
+ color: #1f2329;
+ margin-bottom: 8px;
+ text-align: center;
+}
+
+.tracking-progress-timeline .step-info {
+ font-size: 12px;
+ color: #6b7280;
+ text-align: center;
+}
+
+.tracking-progress-timeline .step-person-time {
+ margin-bottom: 4px;
+}
+
+.tracking-progress-timeline .step-purpose {
+ margin-top: 4px;
+ line-height: 1.4;
+}
+
.custom-step:hover {
transform: translateY(-8px);
filter: brightness(1.03);
}
-/* 步骤连接线 */
-.custom-step:not(:last-child)::after {
+/* 步骤连接线 - 默认(进行中) */
+.custom-step:not(:last-child):not(.is-wait)::after {
content: '';
position: absolute;
top: 32px;
@@ -3338,6 +3745,12 @@ const handleCloseDetailDialog = () => {
box-shadow: 0 2px 8px rgba(22, 93, 255, 0.3);
}
+/* 已完成步骤连接线 */
+.custom-step.completed:not(:last-child)::after {
+ background: linear-gradient(90deg, #00b42a 0%, #95de64 100%);
+ box-shadow: 0 2px 8px rgba(0, 180, 42, 0.3);
+}
+
/* 待处理步骤连接线 */
.custom-step.is-wait:not(:last-child)::after {
background: linear-gradient(90deg, #dcdfe6 0%, #e4e7ed 100%);