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

+ 47 - 20
src/views/produce/components/workOrderHandover/index.vue

@@ -269,9 +269,10 @@
         </div>
         <ele-pro-table
           ref="table"
+          :key="'handover-material-' + materialTableKey"
           :needPage="false"
           :columns="columns"
-          :datasource="list"
+          :datasource="getSafeDetailList()"
           class="time-form"
           max-height="600"
           @columns-change="handleColumnChange"
@@ -371,7 +372,7 @@
         personList: [],
         selection: [],
         cacheKeyUrl: 'mes_produce_workOrderHandover_materialTable',
-        materialList: [],
+        materialTableKey: 0,
         submitHandoverLoading: false,
         submitHandoverAction: null
       };
@@ -391,9 +392,6 @@
       taskObj() {
         return this.$store.state.user.taskObj;
       },
-      list() {
-        return this.materialList;
-      },
       columns() {
         return [
           {
@@ -482,13 +480,26 @@
     },
 
     methods: {
+      getSafeDetailList() {
+        return Array.isArray(this.workOrderInfo.detailList)
+          ? this.workOrderInfo.detailList
+          : [];
+      },
+      refreshMaterialTable() {
+        this.materialTableKey += 1;
+      },
       loadWorkOrderInfo(ids) {
         let param = {
           ids: ids,
           taskId: this.taskObj.id
         };
         workorderList(param).then((res) => {
-          this.workOrderInfo = res[0];
+          const workOrderInfo = res[0] || {};
+          if (!Array.isArray(workOrderInfo.detailList)) {
+            workOrderInfo.detailList = [];
+          }
+          this.workOrderInfo = workOrderInfo;
+          this.refreshMaterialTable();
         });
       },
 
@@ -576,7 +587,7 @@
         const param = {
           ...this.handoverForm,
           ...this.workOrderInfo,
-          detailList: this.materialList,
+          detailList: this.getSafeDetailList(),
           isRelease,
           categoryCode: this.workOrderInfo.productCode,
           categoryName: this.workOrderInfo.productName,
@@ -609,7 +620,7 @@
         this.$refs.pickingListRef.open(
           '',
           {
-            pickList: this.list
+            pickList: this.getSafeDetailList()
           },
           '选择列表'
         );
@@ -634,40 +645,53 @@
                 .filter(Boolean)
             );
             if (selectedIds.size) {
-              this.materialList = this.materialList.filter(
-                (item) => !selectedIds.has(String(item.id))
+              this.$set(
+                this.workOrderInfo,
+                'detailList',
+                this.getSafeDetailList().filter(
+                  (item) => !selectedIds.has(String(item.id))
+                )
               );
             } else {
-              this.materialList = this.materialList.filter(
-                (item) => !selected.includes(item)
+              this.$set(
+                this.workOrderInfo,
+                'detailList',
+                this.getSafeDetailList().filter((item) => !selected.includes(item))
               );
             }
             this.selection = [];
             this.$nextTick(() => {
               this.$refs.table && this.$refs.table.clearSelection();
             });
+            this.refreshMaterialTable();
             this.$message.success('删除成功');
           })
           .catch(() => {});
       },
       allSelection(id, list) {
-        // console.log(list, 'list');
-        this.materialList = list.map((item) => {
+        const next = (list || []).map((item) => {
           return {
             ...item,
             modelType: item.categoryModel
           };
         });
+        this.$set(this.workOrderInfo, 'detailList', next);
+        this.selection = [];
+        this.refreshMaterialTable();
       },
       /* 删除 */
       remove(row) {
         if (!row) return;
-        this.materialList = this.materialList.filter((item) => {
-          if (row.id != null && item.id != null) {
-            return String(item.id) !== String(row.id);
-          }
-          return item !== row;
-        });
+        this.$set(
+          this.workOrderInfo,
+          'detailList',
+          this.getSafeDetailList().filter((item) => {
+            if (row.id != null && item.id != null) {
+              return String(item.id) !== String(row.id);
+            }
+            return item !== row;
+          })
+        );
         this.selection = this.selection.filter((item) => {
           if (row.id != null && item.id != null) {
             return String(item.id) !== String(row.id);
@@ -680,6 +704,7 @@
             this.$refs.table && this.$refs.table.toggleRowSelection(item, true);
           });
         });
+        this.refreshMaterialTable();
         this.$message.success('删除成功');
       }
     }
@@ -690,6 +715,8 @@
   .work-order-handover {
     background: #fff;
     padding: 12px;
+    max-height: calc(100vh - 220px);
+    overflow-y: auto;
     min-height: 100%;
   }
 

+ 4 - 1
src/views/produceOrder/components/chooseStation.vue

@@ -206,10 +206,13 @@
       },
 
       datasource({ page, limit }) {
+        const notInIdsStr = this.allSelection.map((item) => item.id).join(',');
+
         return getFactoryworkstation({
           pageNum: page,
           size: limit,
-          workCenterId: this.workCenterId
+          workCenterId: this.workCenterId,
+          notInIdsStr
         });
       },
 

+ 125 - 23
src/views/produceOrder/components/releaseDialog/index.vue

@@ -242,6 +242,7 @@
                 <el-date-picker
                   v-model="row.endTime"
                   :disabled="row.disposalStatus == 1"
+                  @change="handleEndTimeChange(row, item)"
                   class="w100"
                   placeholder="完成时间"
                   type="datetime"
@@ -250,6 +251,15 @@
               </template>
 
               <template v-slot:action="{ row }">
+                <el-link
+                  v-if="canDeleteAddedStation(row)"
+                  type="danger"
+                  :underline="false"
+                  style="margin-right: 8px"
+                  @click="deleteRow(row, item)"
+                >
+                  删除
+                </el-link>
                 <!--  :disabled="resetBtnDis(row)" -->
                 <el-popconfirm
                   v-if="resetBtnDis(row)"
@@ -769,6 +779,7 @@
           .map((item) => ({
             ...item,
             isNew: 1,
+            addedByChooseStation: true,
             __tempKey: item.id || `temp_${Date.now()}_${Math.random()}`,
             disposalStatus: 0,
             assetCode: item.extInfo?.assetCode,
@@ -785,7 +796,71 @@
 
         this.$nextTick(() => {
           const tab = `tableRef${process.index}`;
-          this.$refs[tab]?.[0]?.setSelectedRowKeys(process.selection);
+          this.$refs[tab]?.[0]?.setSelectedRowKeys?.(
+            this.getSelectionKeys(process.selection)
+          );
+        });
+      },
+
+      getRowUniqueKey(row) {
+        if (!row) return '';
+        return row.id || row.__tempKey || '';
+      },
+
+      getSelectionKeys(selection = []) {
+        return selection
+          .map((item) =>
+            item && typeof item === 'object' ? this.getRowUniqueKey(item) : item
+          )
+          .filter((item) => item !== undefined && item !== null && item !== '');
+      },
+
+      isAddedStationRow(row) {
+        return !!row && (row.addedByChooseStation === true || row.isNew === 1);
+      },
+
+      isSavedOrDispatched(row) {
+        const statusDesc = row?.status?.desc || '';
+        return statusDesc.includes('保存') || statusDesc.includes('派单');
+      },
+
+      canDeleteAddedStation(row) {
+        return this.isAddedStationRow(row) && !this.isSavedOrDispatched(row);
+      },
+
+      deleteRow(row, process) {
+        if (!this.canDeleteAddedStation(row)) {
+          this.$message.warning(
+            '只有通过添加工位新增且未保存、未派单的数据才可以删除'
+          );
+          return;
+        }
+
+        const rowKey = this.getRowUniqueKey(row);
+        if (!rowKey) return;
+
+        const nextList = (process.list || []).filter(
+          (item) => this.getRowUniqueKey(item) !== rowKey
+        );
+        this.$set(process, 'list', nextList);
+
+        const nextSelection = (process.selection || []).filter((item) => {
+          const currentKey =
+            item && typeof item === 'object' ? this.getRowUniqueKey(item) : item;
+          return currentKey !== rowKey;
+        });
+        this.$set(process, 'selection', nextSelection);
+
+        this.$nextTick(() => {
+          const tabIndex =
+            process.index ?? this.processList.findIndex((item) => item === process);
+          const tab = `tableRef${tabIndex}`;
+          const selectedKeys = nextSelection
+            .map((item) =>
+              item && typeof item === 'object' ? this.getRowUniqueKey(item) : item
+            )
+            .filter(Boolean);
+          this.$refs[tab]?.[0]?.setSelectedRowKeys?.(selectedKeys);
         });
       },
 
@@ -1106,25 +1181,23 @@
           type === 1 ? taskAssignment : type === 2 ? taskRevoked : taskSave;
 
         api(data)
-          .then((res) => {
-            this.toolbarLoading = false;
+          .then(async (res) => {
             if (res) {
-              this.$message.success('操作成功');
-
-              // 更新表格数据,包括新增工位状态
-              this.setCurrentTab(row);
+              // 等待当前页数据刷新完成,确保新增工位能回填 changeId
+              await this.setCurrentTab(row);
 
               row.list.forEach((item) => {
                 if (item.isNew === 1) {
-                  // item.disposalStatus =
-                  //   type === 1 ? 1 : item.disposalStatus || 0;
                   item.status = {
                     code: type === 1 ? 1 : 0,
                     desc: type === 1 ? '已派单' : '已保存'
                   };
                 }
               });
+
+              this.$message.success('操作成功');
             }
+            this.toolbarLoading = false;
           })
           .catch((err) => {
             this.toolbarLoading = false;
@@ -1145,7 +1218,7 @@
         } else {
           arr = this.productionList;
         }
-        this.getAssignData(row.index, arr);
+        return this.getAssignData(row.index, arr);
       },
       // 工序选择
       async handleClick(tab) {
@@ -1154,10 +1227,7 @@
         this.isTask = false;
         await this.FirstTaskIdFn(id);
         let data = this.processList.find((item) => item.id == this.processId);
-        if (
-          data &&
-          (data.type == 2 || data.type == 3 || data.type == 6)
-        ) {
+        if (data && (data.type == 2 || data.type == 3 || data.type == 6)) {
           this.$message.warning('请前往质检系统派单');
         }
         await this.changeRadio(data.assignType, data.index);
@@ -1247,13 +1317,19 @@
           // 已操作过数据处理
           this.operationalData(index, res, list);
 
+          const syncedLocalNewList = this.syncAddedStationAssignments(
+            localNewList,
+            res?.[0]?.assignees || [],
+            dataRow.assignType
+          );
+
           // 合并新增工位并去重
           const existingIds = new Set(
             (dataRow.list || []).map((i) => i.id || i.__tempKey)
           );
           const mergedList = [
             ...dataRow.list,
-            ...localNewList.filter((i) => !existingIds.has(i.id || i.__tempKey))
+            ...syncedLocalNewList.filter((i) => !existingIds.has(i.id || i.__tempKey))
           ];
 
           // 更新新增工位状态
@@ -1274,6 +1350,32 @@
         }
       },
 
+      syncAddedStationAssignments(localNewList, assignees, assignType) {
+        const assignmentMap = new Map();
+
+        (assignees || []).forEach((item) => {
+          if (String(item?.assigneeType?.code) !== String(assignType)) return;
+          assignmentMap.set(String(item.assigneeId), item);
+        });
+
+        return (localNewList || []).map((item) => {
+          const matched = assignmentMap.get(String(item.id));
+          if (!matched) return item;
+
+          return {
+            ...item,
+            disposalStatus: matched.disposalStatus,
+            status: matched.status,
+            startTime: matched.startTime,
+            endTime: matched.endTime,
+            quantity: matched.quantity,
+            weight: matched.weight,
+            changeId: matched.id,
+            teamTimeIds: matched.teamTimeIds
+          };
+        });
+      },
+
       // 操作过的数据 赋值
       operationalData(index, res, list) {
         const dataRow = this.processList[index];
@@ -1494,13 +1596,13 @@
       // 默认选中当前更改数据
       selectedListData(row, item) {
         this.$nextTick(() => {
-          let data = item.selection.find((el) => el.id == row.id);
-          if (!data) {
-            let ids = item.selection.map((el) => el.id);
-            ids.push(row.id);
-            let tab = `tableRef${[item.index]}`;
-            this.$refs[tab][0].setSelectedRowKeys(ids);
+          const rowKey = this.getRowUniqueKey(row);
+          const selectedKeys = this.getSelectionKeys(item.selection || []);
+          if (!selectedKeys.includes(rowKey)) {
+            selectedKeys.push(rowKey);
           }
+          let tab = `tableRef${[item.index]}`;
+          this.$refs[tab]?.[0]?.setSelectedRowKeys?.(selectedKeys);
         });
       },
       // 多选班次时间数据
@@ -1690,11 +1792,11 @@
       // 时间校验
       checkEndTimeValid(row) {
         const { startTime: start, endTime: end } = row;
-        // if (!start || !end) return; // 开始/结束时间未填,跳过
+        if (!start || !end) return;
         const startTime = new Date(start); // 开始时间
         const endTime = new Date(end); // 结束时间
         if (endTime < startTime) {
-          row.endTime = new Date(startTime); // 修正为开始时间
+          row.endTime = start; // 修正为开始时间
           this.$message.info('结束时间不能早于开始时间,已自动设为开始时间');
         }
       }

+ 124 - 19
src/views/produceOrder/components/releaseDialog/planDotLineReleaseDialog.vue

@@ -250,6 +250,7 @@
                 <el-date-picker
                   v-model="row.endTime"
                   :disabled="row.disposalStatus == 1"
+                  @change="handleEndTimeChange(row, item)"
                   class="w100"
                   placeholder="完成时间"
                   type="datetime"
@@ -258,6 +259,15 @@
               </template>
 
               <template v-slot:action="{ row }">
+                <el-link
+                  v-if="canDeleteAddedStation(row)"
+                  type="danger"
+                  :underline="false"
+                  style="margin-right: 8px"
+                  @click="deleteRow(row, item)"
+                >
+                  删除
+                </el-link>
                 <!--  :disabled="resetBtnDis(row)" -->
                 <el-popconfirm
                   v-if="resetBtnDis(row)"
@@ -756,6 +766,7 @@
           .map((item) => ({
             ...item,
             isNew: 1,
+            addedByChooseStation: true,
             __tempKey: item.id || `temp_${Date.now()}_${Math.random()}`,
             disposalStatus: 0,
             assetCode: item.extInfo?.assetCode,
@@ -772,7 +783,71 @@
 
         this.$nextTick(() => {
           const tab = `tableRef${process.index}`;
-          this.$refs[tab]?.[0]?.setSelectedRowKeys(process.selection);
+          this.$refs[tab]?.[0]?.setSelectedRowKeys?.(
+            this.getSelectionKeys(process.selection)
+          );
+        });
+      },
+
+      getRowUniqueKey(row) {
+        if (!row) return '';
+        return row.id || row.__tempKey || '';
+      },
+
+      getSelectionKeys(selection = []) {
+        return selection
+          .map((item) =>
+            item && typeof item === 'object' ? this.getRowUniqueKey(item) : item
+          )
+          .filter((item) => item !== undefined && item !== null && item !== '');
+      },
+
+      isAddedStationRow(row) {
+        return !!row && (row.addedByChooseStation === true || row.isNew === 1);
+      },
+
+      isSavedOrDispatched(row) {
+        const statusDesc = row?.status?.desc || '';
+        return statusDesc.includes('保存') || statusDesc.includes('派单');
+      },
+
+      canDeleteAddedStation(row) {
+        return this.isAddedStationRow(row) && !this.isSavedOrDispatched(row);
+      },
+
+      deleteRow(row, process) {
+        if (!this.canDeleteAddedStation(row)) {
+          this.$message.warning(
+            '只有通过添加工位新增且未保存、未派单的数据才可以删除'
+          );
+          return;
+        }
+
+        const rowKey = this.getRowUniqueKey(row);
+        if (!rowKey) return;
+
+        const nextList = (process.list || []).filter(
+          (item) => this.getRowUniqueKey(item) !== rowKey
+        );
+        this.$set(process, 'list', nextList);
+
+        const nextSelection = (process.selection || []).filter((item) => {
+          const currentKey =
+            item && typeof item === 'object' ? this.getRowUniqueKey(item) : item;
+          return currentKey !== rowKey;
+        });
+        this.$set(process, 'selection', nextSelection);
+
+        this.$nextTick(() => {
+          const tabIndex =
+            process.index ?? this.processList.findIndex((item) => item === process);
+          const tab = `tableRef${tabIndex}`;
+          const selectedKeys = nextSelection
+            .map((item) =>
+              item && typeof item === 'object' ? this.getRowUniqueKey(item) : item
+            )
+            .filter(Boolean);
+          this.$refs[tab]?.[0]?.setSelectedRowKeys?.(selectedKeys);
         });
       },
 
@@ -975,25 +1050,23 @@
           type === 1 ? taskAssignment : type === 2 ? taskRevoked : taskSave;
 
         api(data)
-          .then((res) => {
-            this.toolbarLoading = false;
+          .then(async (res) => {
             if (res) {
-              this.$message.success('操作成功');
-
-              // 更新表格数据,包括新增工位状态
-              this.setCurrentTab(row);
+              // 等待当前页数据刷新完成,确保新增工位能回填 changeId
+              await this.setCurrentTab(row);
 
               row.list.forEach((item) => {
                 if (item.isNew === 1) {
-                  // item.disposalStatus =
-                  //   type === 1 ? 1 : item.disposalStatus || 0;
                   item.status = {
                     code: type === 1 ? 1 : 0,
                     desc: type === 1 ? '已派单' : '已保存'
                   };
                 }
               });
+
+              this.$message.success('操作成功');
             }
+            this.toolbarLoading = false;
           })
           .catch((err) => {
             this.toolbarLoading = false;
@@ -1014,7 +1087,7 @@
         } else {
           arr = this.productionList;
         }
-        this.getAssignData(row.index, arr);
+        return this.getAssignData(row.index, arr);
       },
       async handleClick(tab) {
         console.log(tab, 'tabtabtabtab');
@@ -1092,13 +1165,19 @@
           // 已操作过数据处理
           this.operationalData(index, res, list);
 
+          const syncedLocalNewList = this.syncAddedStationAssignments(
+            localNewList,
+            res?.[0]?.assignees || [],
+            dataRow.assignType
+          );
+
           // 合并新增工位并去重
           const existingIds = new Set(
             (dataRow.list || []).map((i) => i.id || i.__tempKey)
           );
           const mergedList = [
             ...dataRow.list,
-            ...localNewList.filter((i) => !existingIds.has(i.id || i.__tempKey))
+            ...syncedLocalNewList.filter((i) => !existingIds.has(i.id || i.__tempKey))
           ];
 
           // 更新新增工位状态
@@ -1119,6 +1198,32 @@
         }
       },
 
+      syncAddedStationAssignments(localNewList, assignees, assignType) {
+        const assignmentMap = new Map();
+
+        (assignees || []).forEach((item) => {
+          if (String(item?.assigneeType?.code) !== String(assignType)) return;
+          assignmentMap.set(String(item.assigneeId), item);
+        });
+
+        return (localNewList || []).map((item) => {
+          const matched = assignmentMap.get(String(item.id));
+          if (!matched) return item;
+
+          return {
+            ...item,
+            disposalStatus: matched.disposalStatus,
+            status: matched.status,
+            startTime: matched.startTime,
+            endTime: matched.endTime,
+            quantity: matched.quantity,
+            weight: matched.weight,
+            changeId: matched.id,
+            teamTimeIds: matched.teamTimeIds
+          };
+        });
+      },
+
       // 操作过的数据 赋值
       operationalData(index, res, list) {
         const dataRow = this.processList[index];
@@ -1350,13 +1455,13 @@
       // 默认选中当前更改数据
       selectedListData(row, item) {
         this.$nextTick(() => {
-          let data = item.selection.find((el) => el.id == row.id);
-          if (!data) {
-            let ids = item.selection.map((el) => el.id);
-            ids.push(row.id);
-            let tab = `tableRef${[item.index]}`;
-            this.$refs[tab][0].setSelectedRowKeys(ids);
+          const rowKey = this.getRowUniqueKey(row);
+          const selectedKeys = this.getSelectionKeys(item.selection || []);
+          if (!selectedKeys.includes(rowKey)) {
+            selectedKeys.push(rowKey);
           }
+          let tab = `tableRef${[item.index]}`;
+          this.$refs[tab]?.[0]?.setSelectedRowKeys?.(selectedKeys);
         });
       },
       // 多选班次时间数据
@@ -1546,11 +1651,11 @@
       // 时间校验
       checkEndTimeValid(row) {
         const { startTime: start, endTime: end } = row;
-        // if (!start || !end) return; // 开始/结束时间未填,跳过
+        if (!start || !end) return;
         const startTime = new Date(start); // 开始时间
         const endTime = new Date(end); // 结束时间
         if (endTime < startTime) {
-          row.endTime = new Date(startTime); // 修正为开始时间
+          row.endTime = start; // 修正为开始时间
           this.$message.info('结束时间不能早于开始时间,已自动设为开始时间');
         }
       },

+ 27 - 2
src/views/produceOrder/workReport.vue

@@ -141,6 +141,15 @@
                       ></jobBooking>
                     </div>
 
+                    <div v-if="operationType == 'workOrder'">
+                      <workOrderHandover
+                        :workListIds="workListIds"
+                        :workData="workOrderInfo"
+                        ref="workOrderHandoverRef"
+                        @cancel="closeWorkOrderHandover"
+                      ></workOrderHandover>
+                    </div>
+
                     <!-- 工步 -->
                     <div v-if="operationType == 'workStep'"> </div>
                     <!-- 质检工序 -->
@@ -309,6 +318,7 @@
   import jobDetails from '@/views/produce/components/jobBooking/details.vue';
   import addPlease from '@/views/produce/components/outsourcing/addPlease.vue';
   import qualityInspection from '@/views/produce/components/qualityInspection/index.vue';
+  import workOrderHandover from '@/views/produce/components/workOrderHandover/index.vue';
   import { checkProductionResult } from '@/api/producetaskrulerecord/index.js';
   import { getPlanDotLine } from '@/api/produceOrder/index.js';
 
@@ -340,7 +350,8 @@
       pleaseEntrust,
       addPlease,
       qualityInspection,
-      prenatalExamination
+      prenatalExamination,
+      workOrderHandover
     },
     data() {
       return {
@@ -842,8 +853,18 @@
         this.workPlanType = '';
         // this.operationType = t;
         // 新增判断 *** 出现弹窗的时候不然右边数据消失
-        if ((t == 'work' || t == 'workStep', t === 'task')) {
+        if (['work', 'workStep', 'task'].includes(t)) {
           this.popupType = t;
+        } else if (t === 'workOrder') {
+          if (this.workListIds.length == 0) {
+            this.$message.warning('请选择工单');
+            return false;
+          }
+          if (this.workListIds.length > 1) {
+            this.$message.warning('工单交接只能选择一个工单');
+            return false;
+          }
+          this.operationType = t;
         } else {
           this.operationType = t;
         }
@@ -1155,6 +1176,10 @@
         this.workPlanType = type;
       },
 
+      closeWorkOrderHandover() {
+        this.operationType = null;
+      },
+
       refreshPlease() {
         this.$nextTick(() => {
           this.$refs.outsourcingListRef.getPleaseData(