Forráskód Böngészése

Merge branch 'dev' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-mes into test

wuzh 1 hónapja
szülő
commit
de835f9581

+ 1 - 1
src/views/batchRecord/components/tables/qualityInspection.vue

@@ -232,7 +232,7 @@
       },
 
       reportClick(row, type, mode) {
-        this.$refs.selfReportingRef.open(row, type, mode);
+        this.$refs.selfReportingRef.open(row, type, mode, 'dialog');
       }
     }
   };

+ 15 - 1
src/views/entrust/components/goodsDetail.vue

@@ -236,6 +236,13 @@
         ];
       }
     },
+    watch:{
+      visible(newVal, oldVal) {
+        if(!newVal) {
+          this.goodsList = [];
+        }
+      }
+    },
 
     methods: {
       // 根据后端 status 返回对应的展示文案和 el-tag 类型,未匹配时回落为驳回
@@ -276,6 +283,8 @@
           // isReceiptDetail 在 open() 里已经重置,此处只处理 params
         }
 
+        if(this.type === "add") return;
+
         await pleaseEntrustGoodsDetail(params).then(async (res) => {
           this.goodsList = [];
           res.data.forEach((item) => {
@@ -337,7 +346,12 @@
             .then((res) => {
               this.loading.close();
               this.$message.success('收货成功');
-              this.$emit('done');
+              // 将收货上下文继续传给生产工单页,用于切换到下一工序并打开报工。
+              this.$emit('done', {
+                action: 'pleaseEntrustReceive',
+                item: this.itemData,
+                details: this.goodsList
+              });
               this.visible = false;
             })
             .catch(() => {

+ 9 - 2
src/views/produce/components/footBtn.vue

@@ -51,6 +51,10 @@
       activeName: {
         type: String,
         default: '0'
+      },
+      workOrderInfo: {
+        type: Object,
+        default: () => {}
       }
     },
     data() {
@@ -397,10 +401,10 @@
                 '请先完成领料、投料后再进行首件两检'
             };
           }
-          // 当前工序已分配给他人时,禁用领料/投料/报工/委外请托
+          // 当前工序已分配给他人时,禁用投料/报工
           if (
             this.isSomeoneDisabled &&
-            ['pick', 'feed', 'job', 'Outsourcing'].includes(i.type)
+            ['feed', 'job'].includes(i.type)
           ) {
             return {
               ...i,
@@ -507,6 +511,9 @@
           if (v == '2' || v == '3' || v == '6') {
             this.$set(this, 'btnList', this.btnList2);
           } else if (v == '5') {
+            if(this.workOrderInfo.workOrderType === 3){
+              this.btnList3[0].name = '发货';
+            }
             this.$set(this, 'btnList', this.btnList3);
           } else {
             this.$set(this, 'btnList', this.btnList1);

+ 0 - 1
src/views/produce/components/jobBooking/components/jobBom.vue

@@ -281,7 +281,6 @@
             const result = finalList.reduce(
               (acc, item) => {
                 const qty = getQty(item);
-
                 if (item.extInfo.isLoss == 1) {
                   // 损耗计入损耗数量
                   acc.lossNum = this.add(acc.lossNum, qty);

+ 1 - 1
src/views/produce/components/jobBooking/index.vue

@@ -215,6 +215,7 @@
           </div>
 
           <div v-else>
+            <!-- :picker-options="pickerOptions" -->
             报工时间:
             <el-date-picker
               v-model="item.workReportInfo.executorTime"
@@ -223,7 +224,6 @@
               value-format="yyyy-MM-dd HH:mm:ss"
               placeholder="选择日期"
               style="margin-right: 25px; width: 190px"
-              :picker-options="pickerOptions"
               @change="onSingleExecutorTimeChange(index)"
             >
             </el-date-picker>

+ 1 - 1
src/views/produce/components/outsourcing/addPlease.vue

@@ -367,7 +367,7 @@
           let URL;
 
           const clearOrderIds = () => {
-            this.orderList.forEach((it) => (it.id = ''));
+            this.form.id = '';
           };
 
           if (type === 1 && this.form.id) {

+ 11 - 4
src/views/produce/components/outsourcing/details.vue

@@ -284,7 +284,7 @@
         <el-link
           type="primary"
           :underline="false"
-          @click="sendGoods(row, 'receipt')"
+          @click="sendGoods(row, 'receipt', 3)"
           v-if="row.approvalStatus == 2 && row.sendStatus == 3"
         >
           收货
@@ -327,7 +327,7 @@
     <detail ref="detailsRef"></detail>
 
     <timeDialog ref="timeDialogRef"></timeDialog>
-    <goodsDetail ref="goodsDetailRef" @done="reloads"></goodsDetail>
+    <goodsDetail ref="goodsDetailRef" @done="handleGoodsDone"></goodsDetail>
 
     <Create ref="create" @refresh="reloads" />
   </div>
@@ -896,8 +896,8 @@
         return data.length != 0 ? data[0].label : '';
       },
 
-      sendGoods(item, type) {
-        this.$refs.goodsDetailRef.open(item, type);
+      sendGoods(item, type, detailType) {
+        this.$refs.goodsDetailRef.open(item, type, detailType);
       },
 
       open(type, row) {
@@ -953,6 +953,13 @@
         });
       },
 
+      handleGoodsDone(payload) {
+        this.reloads();
+        if (payload && payload.action === 'pleaseEntrustReceive') {
+          this.$emit('pleaseEntrustReceived', payload);
+        }
+      },
+
       handleRelease(row) {
         this.$refs.releaseRef.open(row);
       },

+ 64 - 12
src/views/produce/components/outsourcing/index.vue

@@ -239,10 +239,13 @@
             <template slot="append">{{ form.measuringUnit }}</template>
           </el-input>
         </el-form-item>
-        <el-form-item label="请托工序:" prop="taskId">
+        <el-form-item label="请托工序:" prop="taskIdList">
           <el-select
-            v-model="form.taskId"
-            placeholder="请选择"
+            v-model="form.taskIdList"
+            multiple
+            filterable
+            collapse-tags
+            placeholder="请从当前工序开始连续选择"
             style="width: 260px"
             @change="taskListChange"
           >
@@ -467,7 +470,14 @@
           totalCount: [
             { required: true, message: '请输入', trigger: 'change' }
           ],
-          taskId: [{ required: true, message: '请选择', trigger: 'change' }]
+          taskIdList: [
+            {
+              type: 'array',
+              required: true,
+              message: '请选择请托工序',
+              trigger: 'change'
+            }
+          ]
         },
 
         form: {
@@ -482,6 +492,7 @@
           isLast: 0,
           describes: '',
           taskId: '',
+          taskIdList: [],
           planDeliveryTime: '',
           beEntrustedDeptName: '',
           beEntrustedFactoriesName: '',
@@ -697,15 +708,25 @@
           let { data } = res;
           if (data.length) {
             data = data.filter((item) => item.taskId != -2);
-            let arr = data.findIndex((item) =>
-              item.name ? item.sourceTaskId : item.taskId == this.form.taskId
-            );
+            const currentTaskId = this.form.taskId;
+            const arr = data.findIndex((item) => item.taskId == currentTaskId);
 
             if (arr != -1) {
               data.splice(0, arr);
             }
 
             this.pleaseNewStepsList = data;
+            const selectedTaskIds = Array.isArray(this.form.taskIdList)
+              ? this.form.taskIdList
+              : [];
+            const initialTaskIds = selectedTaskIds.length
+              ? selectedTaskIds
+              : currentTaskId
+              ? [currentTaskId]
+              : data.length
+              ? [data[0].taskId]
+              : [];
+            this.taskListChange(initialTaskIds, false);
           }
         });
       },
@@ -813,12 +834,43 @@
         this.$refs.timeDialogRef.open(this.attributeData, null, false);
       },
 
-      taskListChange() {
-        const data = this.pleaseNewStepsList.filter(
-          (it) => it.taskId == this.form.taskId
-        );
+      taskListChange(taskIdList, showWarning = true) {
+        const selected = Array.isArray(taskIdList) ? taskIdList : [];
+        if (selected.length === 0) {
+          this.form.taskIdList = [];
+          this.form.taskId = '';
+          this.form.taskIds = '';
+          this.form.taskName = '';
+          return;
+        }
+
+        const selectedIndexes = selected
+          .map((id) =>
+            this.pleaseNewStepsList.findIndex((item) => item.taskId == id)
+          )
+          .filter((index) => index >= 0);
+        if (selectedIndexes.length === 0) {
+          this.form.taskIdList = [];
+          return;
+        }
 
-        this.form.taskName = data[0].taskTypeName;
+        const endIndex = Math.max(...selectedIndexes);
+        const normalizedTasks = this.pleaseNewStepsList.slice(0, endIndex + 1);
+        const normalizedTaskIds = normalizedTasks.map((item) => item.taskId);
+        const isContinuous =
+          selectedIndexes.length === normalizedTaskIds.length &&
+          selectedIndexes.every((index) => index <= endIndex);
+
+        this.form.taskIdList = normalizedTaskIds;
+        this.form.taskId = normalizedTaskIds[0] || '';
+        this.form.taskIds = normalizedTaskIds.join(',');
+        this.form.taskName = normalizedTasks.length
+          ? normalizedTasks[0].taskTypeName
+          : '';
+
+        if (!isContinuous && showWarning) {
+          this.$message.info('请托工序必须连续,已自动补齐中间工序');
+        }
       },
 
       changeTaskId(e) {

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 848 - 421
src/views/produce/components/qualityInspection/components/selfInspectionReporting.vue


+ 136 - 21
src/views/produce/components/workPlan/components/inspectionProjectReport.vue

@@ -63,9 +63,10 @@
         <el-input
           v-model="row.sampleNoQualifiedNumber"
           @input="formSampleNoQualifiedNumberChange"
-          placeholder="请输入"
+          @blur="formSampleNoQualifiedNumberChange"
+          placeholder="自动取值(质检项中最大不合格数)"
           type="number"
-          :disabled="type == 'detail'"
+          :disabled="type == 'detail' || qms_defaultDisposalType"
         >
           <template slot="append">{{ form.measureUnit }}</template>
         </el-input>
@@ -164,7 +165,7 @@
         <el-input
           v-model="row.lossNumber"
           placeholder="请输入"
-          :disabled="type == 'detail'"
+          :disabled="type == 'detail' || qms_defaultDisposalType"
           type="number"
           @input="inputValue('lossNumber', row, $index)"
           @click.native="curretNum = row.lossNumber"
@@ -176,7 +177,7 @@
         <el-input
           v-model="row.lossNumberUnqualified"
           placeholder="请输入"
-          :disabled="type == 'detail'"
+          :disabled="type == 'detail' || qms_defaultDisposalType"
           type="number"
           @input="inputValue('lossNumberUnqualified', row, $index)"
           @click.native="curretNum = row.lossNumberUnqualified"
@@ -214,6 +215,7 @@
           placeholder="请选择"
           style="width: 100%"
           :disabled="type == 'detail'"
+          @change="handleQualityResultChange(row, $index)"
         >
           <el-option
             v-for="item in qualityResultsList"
@@ -421,14 +423,6 @@
             label: '样品数',
             showOverflowTooltip: true
           },
-          {
-            minWidth: 180,
-            prop: 'sampleNoQualifiedNumber',
-            slot: 'sampleNoQualifiedNumber',
-            align: 'center',
-            label: '样品不合格数',
-            showOverflowTooltip: true
-          },
           {
             minWidth: 140,
             prop: 'sampleQualifiedNumber',
@@ -445,6 +439,15 @@
             label: '样品合格数',
             showOverflowTooltip: true
           },
+          {
+            minWidth: 180,
+            prop: 'sampleNoQualifiedNumber',
+            headerSlot: 'isRequired',
+            slot: 'sampleNoQualifiedNumber',
+            align: 'center',
+            label: '样品不合格数',
+            showOverflowTooltip: true
+          },
           {
             minWidth: 140,
             prop: 'lossNumber',
@@ -748,7 +751,8 @@
             label: '让步接收'
           }
         ],
-        qms_qualityResultContent: 1
+        qms_qualityResultContent: 1,
+        qms_defaultDisposalType: false
       };
     },
     computed: {
@@ -756,8 +760,60 @@
         return this.form.sampleQuantity;
       }
     },
+    watch: {
+      // 任意质检项的不合格数变更时,自动同步最大不合格数到样品不合格数
+      tableData: {
+        deep: true,
+        handler(newVal) {
+          if (!newVal || !newVal.length) {
+            this.form.sampleNoQualifiedNumber = 0;
+            this.form.sampleQualifiedNumber = this.form.sampleQuantity || 0;
+            return;
+          }
+          const maxNoQualified = newVal.reduce((max, item) => {
+            const val = Number(item.noQualifiedQuantity) || 0;
+            return val > max ? val : max;
+          }, 0);
+          this.$set(this.form, 'sampleNoQualifiedNumber', maxNoQualified);
+          const qualifiedNumber =
+            (Number(this.form.sampleQuantity) || 0) - maxNoQualified;
+          if (qualifiedNumber < 0) {
+            this.$message.warning('样品合格数不能小于0');
+            this.$set(this.form, 'sampleQualifiedNumber', 0);
+          } else {
+            this.$set(this.form, 'sampleQualifiedNumber', qualifiedNumber);
+          }
+
+          // 损耗数逻辑:从下方 lossNumberUnqualified 取最大值,lossNumberUnqualified = 总数量 - lossNumber
+          if(this.qms_defaultDisposalType) {
+            const maxLossNumberUnqualified = newVal.reduce((max, item) => {
+              const val = Number(item.lossNumberUnqualified) || 0;
+              return val > max ? val : max;
+            }, 0);
+            this.$set(this.form, 'lossNumberUnqualified', maxLossNumberUnqualified);
+            const lossNumber = Number(this.form.lossNumber) || 0;
+            const sampleQuantity = Number(this.form.sampleQuantity) || 0;
+            const maxLossNumber = sampleQuantity - maxLossNumberUnqualified;
+            if(lossNumber > maxLossNumber) {
+              this.$set(this.form, 'lossNumber', maxLossNumber);
+            }
+          } else {
+             const lossNumberUnqualified = Number(this.form.lossNumberUnqualified) || 0;
+             const sampleNoQualifiedNumber = Number(this.form.sampleNoQualifiedNumber) || 0;
+             if(lossNumberUnqualified > sampleNoQualifiedNumber) {
+               this.$set(this.form, 'sampleNoQualifiedNumber', lossNumberUnqualified);
+             }
+          }
+        }
+      }
+    },
 
     created() {
+      parameterGetByCode({
+        code: 'default_disposal_type'
+      }).then((res) => {
+        this.qms_defaultDisposalType = res?.value == 1 ? true : false;
+      });
       this.requestDict('质检计划类型');
       this.requestDict('取样类型');
       this.requestDict('质检标准类型');
@@ -814,6 +870,22 @@
         this.$set(this.tableData, index, data);
       },
 
+      //当 qms_defaultDisposalType 为 true 时,损耗数自动同步合格/不合格数
+      syncLossNumber(row, index) {
+        if (!this.qms_defaultDisposalType) return;
+        this.$set(
+          this.tableData[index],
+          'lossNumber',
+          Number(row.qualifiedQuantity) || 0
+        );
+        this.$set(
+          this.tableData[index],
+          'lossNumberUnqualified',
+          Number(row.noQualifiedQuantity) || 0
+        );
+        this.initData();
+      },
+
       async open({ workData, row, list }, type, pageName) {
         this.tableData = [];
         console.log(workData, row, list, 'workDataworkData');
@@ -864,6 +936,13 @@
           this.tableData = JSON.parse(JSON.stringify(list));
         }
 
+        //当 qms_defaultDisposalType 为 true 时,初始化时同步损耗数
+        if (this.qms_defaultDisposalType) {
+          this.tableData.forEach((item, index) => {
+            this.syncLossNumber(item, index);
+          });
+        }
+
         this.visible = true;
       },
       formSampleQuantityChange() {
@@ -887,13 +966,52 @@
             ]);
           });
         }
-        this.form.sampleQualifiedNumber = this.form.sampleQuantity;
-        this.form.sampleNoQualifiedNumber = 0;
+        // 样品数变化后,重新计算合格数/不合格数
+        this.form.sampleNoQualifiedNumber = this.tableData.length
+          ? this.tableData.reduce(
+              (max, item) =>
+                Math.max(max, Number(item.noQualifiedQuantity) || 0),
+              0
+            )
+          : 0;
+        this.form.sampleQualifiedNumber =
+          this.form.sampleQuantity - this.form.sampleNoQualifiedNumber;
+      },
+
+      handleOneKeyQualified() {
+        this.tableData.forEach((item, index) => {
+          this.$set(this.tableData[index], 'qualityResults', 1);
+        });
+      },
+      // 切换质检结果(合格/不合格)时,若合格数与不合格数其一为 0,则互换两个数值
+      handleQualityResultChange(row, index) {
+        const qualified = Number(row.qualifiedQuantity) || 0;
+        const noQualified = Number(row.noQualifiedQuantity) || 0;
+        // 切换为合格:noQualifiedQuantity -> qualifiedQuantity
+        if (row.qualityResults == 1 && qualified === 0 && noQualified > 0) {
+          this.$set(this.tableData[index], 'qualifiedQuantity', noQualified);
+          this.$set(this.tableData[index], 'noQualifiedQuantity', 0);
+        }
+        // 切换为不合格:qualifiedQuantity -> noQualifiedQuantity
+        if (row.qualityResults == 2 && noQualified === 0 && qualified > 0) {
+          this.$set(this.tableData[index], 'qualifiedQuantity', 0);
+          this.$set(this.tableData[index], 'noQualifiedQuantity', qualified);
+        }
+        //当 qms_defaultDisposalType 为 true 时,损耗数自动同步合格/不合格数
+        this.syncLossNumber(row, index);
       },
       formSampleNoQualifiedNumberChange() {
         if (+this.form.sampleNoQualifiedNumber < 0) {
           this.form.sampleNoQualifiedNumber = 0;
         }
+
+        const sampleNoQualifiedNumber = Number(this.form.sampleNoQualifiedNumber) || 0;
+        const lossNumberUnqualified = Number(this.form.lossNumberUnqualified) || 0;
+        if(lossNumberUnqualified && sampleNoQualifiedNumber && sampleNoQualifiedNumber < lossNumberUnqualified) {
+          this.$message.error("样品不合格数不能小于损耗数(不合格数)")
+          this.$set(this.form, 'sampleNoQualifiedNumber', lossNumberUnqualified);
+        }
+
         if (+this.form.sampleNoQualifiedNumber > this.form.sampleQuantity) {
           this.form.sampleNoQualifiedNumber = this.form.sampleQuantity;
         }
@@ -901,12 +1019,6 @@
           this.form.sampleQuantity - this.form.sampleNoQualifiedNumber;
       },
 
-      handleOneKeyQualified() {
-        this.tableData.forEach((item, index) => {
-          this.$set(this.tableData[index], 'qualityResults', 1);
-        });
-      },
-
       handleClose() {
         this.visible = false;
 
@@ -961,6 +1073,9 @@
           if (type == 'noQualifiedQuantity' && item[type] > 0) {
             this.$set(this.tableData[index], 'qualityResults', 2);
           }
+
+          //当 qms_defaultDisposalType 为 true 时,损耗数自动同步合格/不合格数
+          this.syncLossNumber(item, index);
         }
         //损耗数
         if (type == 'lossNumber' || type == 'lossNumberUnqualified') {

+ 48 - 1
src/views/produceOrder/workReport.vue

@@ -220,6 +220,7 @@
                       <outsourcingDetails
                         ref="outsourcingListRef"
                         @outsourcingAdd="outsourcingAdd"
+                        @pleaseEntrustReceived="handlePleaseEntrustReceived"
                         v-if="!isStep && !isOutsource && !isPleaseEntrust"
                         :chooseType="chooseType"
                       ></outsourcingDetails>
@@ -265,6 +266,7 @@
                 :isSomeoneDisabled="isSomeoneDisabled"
                 :isSomeoneDisabledMsg="'无法操作'"
                 :activeName="activeName"
+                :workOrderInfo="workOrderInfo"
                 style="background: rgba(223, 250, 222, 0.6); padding: 10px"
               ></footBtn>
             </el-tab-pane>
@@ -716,6 +718,20 @@
           null
         );
       },
+      // 当前所选工序对应的“工序实例id”,随顶部步骤条切换而变化
+      getCurrentTaskInstanceId() {
+        const routeItem = this.getCurrentRouteItem();
+        const candidates = [
+          routeItem && routeItem.taskId,
+          this.newId,
+          this.workOrderInfo && this.workOrderInfo.taskId
+        ];
+        // 过滤空值与完结态(-2),避免把无效工序实例id传给首件两检接口
+        return candidates.find(
+          (id) =>
+            id !== undefined && id !== null && id !== '' && String(id) !== '-2'
+        );
+      },
       checkCurrentTaskTeamPermission(actionName) {
         const deny = (message) => {
           this.operationType = null;
@@ -981,6 +997,29 @@
         this.getOrderData();
         this.getTaskFn();
       },
+      /**
+       * 请托最终收货后刷新工单当前工序,并打开下一工序的报工区域。
+       * 收货生成的在制品由 jobBooking 重新查询,报工数量直接使用实际收货数量。
+       */
+      async handlePleaseEntrustReceived() {
+        try {
+          await this.getOrderData();
+          await this.getTaskFn();
+          this.isStep = false;
+          this.isOutsource = false;
+          this.isPleaseEntrust = false;
+          this.isFinalCheckProduction = true;
+          this.operationType = 'job';
+          console.info('[请托收货] 已刷新工单并打开下一工序报工', {
+            workOrderId: this.workOrderInfo.id,
+            taskId: this.workOrderInfo.taskId,
+            sourceTaskId: this.taskObj.id
+          });
+        } catch (error) {
+          console.error('[请托收货] 打开下一工序报工失败', error);
+          this.$message.error('收货成功,但打开下一工序报工失败,请重新进入工单报工');
+        }
+      },
       reloadData() {
         this.getOrderData();
         this.getTaskFn();
@@ -1454,8 +1493,16 @@
             this.workOrderInfo.id
           );
 
+          // 首件两检按“顶部步骤条当前所选工序”取数:
+          // workOrderInfo.taskId 是进入抽屉时的定位工序,切换工序后不会变,
+          // 这里用当前工序的实例id覆盖,保证 produceTaskInstanceId 跟随步骤条
+          const curWorkOrder = {
+            ...this.workOrderInfo,
+            taskId: this.getCurrentTaskInstanceId()
+          };
+
           this.$refs.qualityInspectionRef.open(
-            this.workOrderInfo,
+            curWorkOrder,
             this.taskObj,
             '',
             req

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott