695593266@qq.com 2 месяцев назад
Родитель
Сommit
6a2e1e0453

+ 135 - 92
src/views/produceOrder/components/details/dotLineDetail.vue

@@ -6,25 +6,21 @@
         v-if="dotLineTaskList.length === 0"
         description="暂无工艺路线"
       ></el-empty>
-      <div v-else class="route-line">
-        <div
+      <el-steps
+        v-else
+        :active="dotLineRouteStepsActive"
+        space="20px"
+        align-center
+        finish-status="success"
+        class="route-steps"
+      >
+        <el-step
           v-for="(item, index) in dotLineTaskList"
-          :key="`route-seg-${item._taskKey}`"
-          class="route-segment"
-        >
-          <span
-            class="route-node"
-          >
-            {{ getDotLineTaskName(item, index) }}
-          </span>
-          <span
-            v-if="index < dotLineTaskList.length - 1"
-            class="route-arrow"
-            aria-hidden="true"
-            >→</span
-          >
-        </div>
-      </div>
+          :key="`route-step-${item._taskKey}`"
+          :title="dotLineRouteStepTitle(item, index)"
+          :class="{ active: dotLineRouteDesIndex === index }"
+        ></el-step>
+      </el-steps>
     </div>
     <div class="config-panel">
       <div class="panel-title">工艺配置</div>
@@ -44,14 +40,17 @@
           <el-table-column
             type="index"
             label="序号"
-            width="48"
+            width="60"
             align="center"
+            class-name="process-name-cell"
+            label-class-name="config-execution-team-header"
           />
           <el-table-column
             label="工序名称"
             min-width="100"
             show-overflow-tooltip
-            class-name="task-name-cell"
+            class-name="process-name-cell"
+            label-class-name="config-execution-team-header"
             align="center"
           >
             <template slot-scope="{ row, $index }">
@@ -60,7 +59,13 @@
               }}</span>
             </template>
           </el-table-column>
-          <el-table-column label="执行模式" min-width="100" align="center">
+          <el-table-column
+            label="执行模式"
+            min-width="100"
+            align="center"
+            label-class-name="config-execution-team-header"
+            class-name="config-meta-cell"
+          >
             <template slot-scope="{ row }">
               {{ executionTypeLabel(row.executionType) }}
             </template>
@@ -70,18 +75,24 @@
             min-width="130"
             align="center"
             prop="executionTeamName"
+            label-class-name="config-execution-team-header"
+            class-name="config-meta-cell"
           />
           <el-table-column
             label="执行开始时间"
             min-width="168"
             align="center"
             prop="executionStartTime"
+            label-class-name="config-execution-team-header"
+            class-name="config-meta-cell"
           />
           <el-table-column
             label="执行结束时间"
             min-width="168"
             align="center"
             prop="executionEndTime"
+            label-class-name="config-execution-team-header"
+            class-name="config-meta-cell"
           />
         </el-table>
       </div>
@@ -111,6 +122,21 @@
     computed: {
       executionTypeLabel() {
         return (val) => EXEC_TYPE_MAP[val] ?? '';
+      },
+      /** 与 details 计划布点详情一致:首个未配置执行模式的工序为当前步;全部已配置则全部 finish */
+      dotLineRouteStepsActive() {
+        const list = this.dotLineTaskList;
+        if (!list.length) return 0;
+        for (let i = 0; i < list.length; i++) {
+          if (!this.isDotLineTaskDone(list[i])) return i;
+        }
+        return list.length;
+      },
+      dotLineRouteDesIndex() {
+        const list = this.dotLineTaskList;
+        if (!list.length) return -1;
+        const a = this.dotLineRouteStepsActive;
+        return a >= list.length ? list.length - 1 : a;
       }
     },
 
@@ -137,20 +163,43 @@
             item.taskId ??
             item.produceTaskId ??
             item.taskSort ??
-            `${index}-${item.taskTypeName || item.taskName || ''}`
+            `detail-${item.taskId ?? index}`,
+          executionStartTime: this.formatDotLineTime(item.executionStartTime),
+          executionEndTime: this.formatDotLineTime(item.executionEndTime),
+          executionType:
+            item.executionType != null ? Number(item.executionType) : undefined
         };
       },
 
       getDotLineTaskName(item, index) {
+        return item.taskName || item.name || `工艺${index + 1}`;
+      },
+
+      dotLineRouteStepTitle(item, index) {
         return (
           item.taskTypeName ||
           item.taskName ||
-          item.produceTaskName ||
           item.name ||
-          `工${index + 1}`
+          `工${index + 1}`
         );
       },
 
+      isDotLineTaskDone(item) {
+        return item.executionType != null && item.executionType !== '';
+      },
+
+      formatDotLineTime(val) {
+        if (val == null || val === '') return '';
+        const str = String(val).trim();
+        if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(str)) return str;
+        const d = new Date(val);
+        if (Number.isNaN(d.getTime())) return '';
+        const p = (n) => String(n).padStart(2, '0');
+        return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(
+          d.getHours()
+        )}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
+      },
+
       triggerLoadDotLineData() {
         const workOrderId = this.workOrderInfo?.id ?? '';
         const productionPlanId = this.workOrderInfo?.productionPlanId ?? '';
@@ -180,7 +229,6 @@
             return;
           }
           this.hasDotLineDetail = true;
-          console.log(details, 'details');
           this.dotLineTaskList = details
             .slice()
             .sort((a, b) => (a.taskSort ?? 0) - (b.taskSort ?? 0))
@@ -199,34 +247,9 @@
 </script>
 
 <style lang="scss" scoped>
-  .top-box {
-    display: flex;
-    margin-bottom: 10px;
-    .item-box {
-      flex: 1;
-    }
-  }
-
-  .radio-box {
-    margin: 10px 0;
-  }
-
-  .table {
-    margin-top: 20px;
-  }
-
-  ::v-deep .el-radio-button__orig-radio:checked + .el-radio-button__inner {
-    box-shadow: none;
-  }
-
-  ::v-deep .el-input.is-disabled .el-input__inner {
-    color: #ab7777;
-  }
-
   .plan-dot-line,
   .top-route,
-  .config-panel,
-  .route-line {
+  .config-panel {
     width: 100%;
     max-width: 100%;
     min-width: 0;
@@ -234,7 +257,7 @@
   }
 
   .plan-dot-line {
-    min-height: 200px;
+    min-height: 360px;
   }
 
   .top-route,
@@ -245,6 +268,10 @@
     background: #fff;
   }
 
+  .top-route {
+    overflow: visible;
+  }
+
   .config-panel {
     margin-top: 12px;
   }
@@ -255,49 +282,58 @@
     margin-bottom: 10px;
   }
 
-  .route-line {
-    display: flex;
-    flex-wrap: nowrap;
-    align-items: stretch;
-    color: #303133;
-  }
-
-  .route-segment {
-    flex: 1 1 0;
-    min-width: 0;
-    display: flex;
-    align-items: center;
-    justify-content: center;
+  .route-steps {
+    width: 100%;
+    overflow-x: auto;
+    overflow-y: hidden;
+    padding-bottom: 8px;
+    box-sizing: content-box;
   }
 
-  .route-node {
-    flex: 0 1 auto;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    min-width: 0;
-    min-height: 22px;
-    border-radius: 4px;
-    padding: 2px 10px;
-    color: #fff;
-    background: #67c23a;
-    font-size: clamp(10px, 2.6vw, 12px);
-    font-weight: 600;
-    line-height: 1.2;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    white-space: nowrap;
-    text-align: center;
+  .route-steps ::v-deep {
+    .el-steps {
+      display: flex;
+      flex-wrap: nowrap;
+      align-items: flex-start;
+    }
+    .el-step {
+      flex-shrink: 0;
+    }
+    .el-step__title {
+      font-size: clamp(16px, 2.2vw, 16px);
+      line-height: 1.35;
+      max-width: 8em;
+      margin-left: auto;
+      margin-right: auto;
+      white-space: normal;
+      word-break: break-all;
+    }
+    .el-step.active .el-step__title {
+      color: #409eff;
+      font-weight: 600;
+    }
+    .el-step__line {
+      top: 14px;
+    }
+    .el-step__icon {
+      width: 30px;
+      height: 30px;
+    }
+    .el-step__main {
+      padding-top: 8px;
+      margin-top: 0;
+    }
+    .el-step__description {
+      margin-top: 0;
+      padding-right: 0;
+    }
   }
 
-  .route-arrow {
-    flex: 1 1 0;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    color: #909399;
-    font-size: clamp(14px, 2.5vw, 18px);
-    line-height: 1;
+  @media (max-width: 576px) {
+    .top-route,
+    .config-panel {
+      padding: 8px;
+    }
   }
 
   .task-config-table-wrap {
@@ -310,11 +346,18 @@
       font-size: 14px;
       text-align: center;
     }
+    th.config-execution-team-header > .cell,
+    td.config-meta-cell > .cell {
+      font-size: 14px;
+      font-weight: 500;
+      line-height: 1.4;
+    }
     .el-table__body .cell {
       padding-left: 6px;
       padding-right: 6px;
     }
-    td.task-name-cell .task-name-text {
+    th.process-name-header > .cell,
+    td.process-name-cell .task-name-text {
       font-size: 14px;
       font-weight: 500;
       line-height: 1.4;

+ 28 - 3
src/views/produceOrder/workReport.vue

@@ -56,7 +56,12 @@
           </div>
 
           <div class="drawer_content">
-            <el-steps :active="activeIndex" space="20px" align-center>
+            <el-steps
+              class="process-route-steps"
+              :active="activeIndex"
+              space="20px"
+              align-center
+            >
               <el-step
                 v-for="(item, index) in routeList"
                 :key="index"
@@ -1348,6 +1353,12 @@
     margin: 5px 10px;
     box-sizing: border-box;
 
+    .process-route-steps {
+      min-height: 120px;
+      padding: 18px 8px 22px;
+      box-sizing: border-box;
+    }
+
     .taskTitle {
       display: flex;
       width: 100%;
@@ -1378,8 +1389,22 @@
     color: #ffffff; /* 图标文字颜色 */
   }
 
-  ::v-deep .el-step__title {
-    line-height: 30px;
+  ::v-deep .process-route-steps {
+    .el-step__main {
+      padding-top: 10px;
+    }
+
+    .el-step__title {
+      font-size: 15px;
+      font-weight: 500;
+      line-height: 1.45;
+    }
+
+    .el-step__icon {
+      width: 32px;
+      height: 32px;
+      font-size: 18px;
+    }
   }
 
   ::v-deep .el-tabs__content {