Browse Source

Merge remote-tracking branch 'origin/dev' into dev

lucw 4 days ago
parent
commit
d46d0cbaa6

+ 53 - 40
src/views/inspectionPlan/components/new-baseInfo.vue

@@ -42,9 +42,22 @@
           ></DictSelection>
         </el-form-item>
       </el-col>
-      <el-col :span="6">
+      <el-col :span="6" style="height: 58px">
+        <el-form-item label="班组/个人" prop="assignType">
+          <el-select
+            v-model="form.assignType"
+            size="small"
+            @change="typeChange"
+            style="width: 100%"
+            :disabled="btnType == 'detail' || btnType == 'issued'"
+          >
+            <el-option :value="1" label="班组"></el-option>
+            <el-option :value="0" label="个人"></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <!-- <el-col :span="6">
         <el-form-item label="计量类型" prop="inspectionStandards">
-          <!-- 计量 计重 -->
           <el-select
             style="width: 100%"
             v-model="form.inspectionStandards"
@@ -65,7 +78,7 @@
             ></el-option>
           </el-select>
         </el-form-item>
-      </el-col>
+      </el-col> -->
     </el-row>
     <el-row>
       <el-col :span="6">
@@ -88,20 +101,36 @@
           />
         </el-form-item>
       </el-col>
-      <el-col :span="6" style="height: 58px">
-        <el-form-item label="班组/个人" prop="assignType">
+      <el-col :span="6" v-if="!form.assignType">
+        <el-form-item label="接收部门:" prop="groupId">
+          <deptSelect
+            :disabled="btnType == 'detail'"
+            v-model="form.groupId"
+            filterable
+            company-scope
+            @changeGroup="searchDeptNodeClick"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="6" v-if="!form.assignType">
+        <el-form-item label="接收人:" prop="executeId">
           <el-select
-            v-model="form.assignType"
-            size="small"
-            @change="typeChange"
+            :disabled="btnType == 'detail'"
+            v-model="form.executeId"
+            @change="changeExecutor"
+            filterable
             style="width: 100%"
-            :disabled="btnType == 'detail' || btnType == 'issued'"
           >
-            <el-option :value="1" label="班组"></el-option>
-            <el-option :value="0" label="个人"></el-option>
+            <el-option
+              v-for="item in executorList"
+              :key="item.id"
+              :value="item.id"
+              :label="item.name"
+            ></el-option>
           </el-select>
         </el-form-item>
       </el-col>
+
       <el-col :span="6" v-if="form.assignType == 1">
         <el-form-item label="班组" prop="teamId">
           <el-select
@@ -138,35 +167,7 @@
           </el-select>
         </el-form-item>
       </el-col>
-      <el-col :span="6" v-if="!form.assignType">
-        <el-form-item label="接收部门:" prop="groupId">
-          <deptSelect
-            :disabled="btnType == 'detail'"
-            v-model="form.groupId"
-            filterable
-            company-scope
-            @changeGroup="searchDeptNodeClick"
-          />
-        </el-form-item>
-      </el-col>
-      <el-col :span="6" v-if="!form.assignType">
-        <el-form-item label="接收人:" prop="executeId">
-          <el-select
-            :disabled="btnType == 'detail'"
-            v-model="form.executeId"
-            @change="changeExecutor"
-            filterable
-            style="width: 100%"
-          >
-            <el-option
-              v-for="item in executorList"
-              :key="item.id"
-              :value="item.id"
-              :label="item.name"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
+
       <el-col :span="18">
         <el-form-item label="周期:" prop="frequencyValue">
           <rule-cycle
@@ -565,6 +566,15 @@
           }
         },
         immediate: false
+      },
+      /* 编辑/详情回显: 按已保存的接收部门加载人员列表, 否则接收人下拉回显不出姓名 */
+      'form.groupId': {
+        immediate: true,
+        handler(val) {
+          if (val && !this.executorList.length) {
+            this.getUserList({ groupId: val });
+          }
+        }
       }
     },
     data() {
@@ -712,6 +722,9 @@
           const params = { groupId: info };
           this.getUserList(params);
           this.form.groupName = row.name;
+          /* 接收部门与接收人联动: 换部门后原接收人不属于新部门, 清空待重选 */
+          this.form.executeId = null;
+          this.form.executeName = '';
         } else {
           this.form.executeGroupId = null;
         }

+ 26 - 1
src/views/inspectionPlan/components/new-edit.vue

@@ -125,6 +125,18 @@
             @columns-change="handleColumnChange"
             :cache-key="cacheKeyUrl"
           >
+            <!-- 主数据来源: 计量数量可手动修改, 改动后同步数量/总重量 -->
+            <template v-slot:measureQuantity="{ row }">
+              <el-input-number
+                v-model="row.measureQuantity"
+                :min="1"
+                :precision="0"
+                :controls="false"
+                size="mini"
+                style="width: 100%"
+                @change="measureQuantityChange(row)"
+              />
+            </template>
             <!-- <template
               v-slot:toolbar
               v-if="this.baseForm.qualityMode == 2 && btnType != 'detail'"
@@ -727,7 +739,16 @@
             }
           },
           { label: '包装单位', prop: 'packingUnit', align: 'center' },
-          { label: '计量数量', prop: 'measureQuantity', align: 'center' },
+          /* 计划来源=主数据(7)时计量数量允许手动修改, 其余来源保持只读 */
+          this.baseForm.planSource == '7' && this.btnType != 'detail'
+            ? {
+                label: '计量数量',
+                prop: 'measureQuantity',
+                align: 'center',
+                slot: 'measureQuantity',
+                width: 140
+              }
+            : { label: '计量数量', prop: 'measureQuantity', align: 'center' },
           { label: '计量单位', prop: 'measureUnit', align: 'center' },
           { label: '物料代号', prop: 'materielDesignation', align: 'center' },
           { label: '客户代号', prop: 'clientCode', align: 'center' },
@@ -1806,6 +1827,10 @@
           return pre.measureQuantity ? acc + Number(pre.measureQuantity) : acc;
         }, 0);
       },
+      /* 主数据来源: 来源清单计量数量手动修改后, 同步基本信息里的数量/总重量 */
+      measureQuantityChange() {
+        this.calculateWeightAndQuantity(this.sourceList);
+      },
       //从来源数组取样到目标数组
       async getNewFullSampleList(
         sampleCount,

+ 57 - 39
src/views/inspectionPlan/components/stokledger.vue

@@ -27,6 +27,44 @@
             </template>
           </el-form-item>
         </el-col>
+        <el-col :span="6">
+          <el-form-item label="所属工厂" prop="factoryId">
+            <el-select
+              filterable
+              placeholder="请选择"
+              v-model="searchForm.factoryId"
+              clearable
+              class="w100"
+              @change="handleFactoryChange"
+            >
+              <el-option
+                v-for="item in factoryList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="仓库">
+            <el-select
+              clearable
+              filterable
+              style="width: 100%"
+              v-model="searchForm.warehouseId"
+              placeholder="请选择"
+            >
+              <el-option
+                v-for="item in warehouseOptions"
+                :label="item.name"
+                :value="item.id"
+                :key="item.id"
+              >
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
         <el-col :span="6">
           <el-form-item label="物品编码:">
             <el-input
@@ -90,42 +128,7 @@
             ></el-input>
           </el-form-item>
         </el-col>
-        <el-col :span="6">
-          <el-form-item label="仓库">
-            <el-select
-              clearable
-              style="width: 100%"
-              v-model="searchForm.warehouseId"
-              placeholder="请选择"
-            >
-              <el-option
-                v-for="item in warehouseList"
-                :label="item.name"
-                :value="item.id"
-                :key="item.id"
-              >
-              </el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="6">
-          <el-form-item label="所属工厂" prop="factoryId">
-            <el-select
-              filterable
-              placeholder="请选择"
-              v-model="searchForm.factoryId"
-              clearable
-              class="w100"
-            >
-              <el-option
-                v-for="item in factoryList"
-                :key="item.id"
-                :label="item.name"
-                :value="item.id"
-              ></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
+
 
         <el-col>
           <div style="float: right">
@@ -353,7 +356,6 @@
 import warehouseDefinition from '@/api/warehouseManagement/warehouseDefinition';
 import storageApi from '@/api/warehouseManagement';
 import AssetTree from './assetTree.vue';
-import { getWarehouseList } from '@/api/classifyManage/itemInformation';
 export default {
   components: { AssetTree },
   props: {
@@ -413,6 +415,17 @@ export default {
     this.getWarehouse();
     this.getFactoryList();
   },
+  computed: {
+    // 仓库级联:仓库归属工厂,选择了工厂后只显示该工厂下的仓库
+    warehouseOptions() {
+      if (this.searchForm.factoryId) {
+        return this.warehouseList.filter(
+          (item) => item.factoryId == this.searchForm.factoryId
+        );
+      }
+      return this.warehouseList;
+    }
+  },
   watch: {
     tableData(val) {
       this.doLayout();
@@ -429,8 +442,13 @@ export default {
       this.factoryList = res.list;
     },
     async getWarehouse() {
-      const { data } = await getWarehouseList();
-      this.warehouseList = data;
+      // 用带工厂信息(factoryId/factoryName)的仓库列表接口,供工厂-仓库级联
+      const res = await warehouseDefinition.list({});
+      this.warehouseList = res || [];
+    },
+    // 切换工厂时清空已选仓库,保持级联关系
+    handleFactoryChange() {
+      this.searchForm.warehouseId = '';
     },
     doLayout() {
       let that = this;

+ 42 - 8
src/views/inspectionWork/components/baseInfo.vue

@@ -594,6 +594,17 @@
       changeExecuteJob(item) {
         this.$set(this.form, 'executeJobName', item.name);
         this.$set(this.form, 'executeUserId', '');
+        // 换班组后执行人清空, 重新默认报工人(当前登录用户, 须在新班组成员内)
+        this.$set(this.form, 'executeUserIdList', []);
+        const userInfo = this.$store?.state?.user?.info;
+        const reporter = (item.userVOList || []).find(
+          (u) => u.id == userInfo?.userId
+        );
+        if (reporter) {
+          this.$set(this.form, 'executeUserIdList', [userInfo.userId]);
+          this.$set(this.form, 'executeUserName', userInfo.name);
+          this.$set(this.form, 'executeUserId', String(userInfo.userId));
+        }
       },
       getCode() {
         parameterGetByCode({
@@ -786,14 +797,14 @@
           this.executorList = (res && res.list) || [];
         } catch (error) {}
       },
-      /* 默认执行部门=当前登录用户所属公司, 默认执行人=当前登录用户 */
+      /* 默认执行部门=当前登录用户所属公司, 默认执行人=当前登录用户(报工人) */
       async setDefaultExecuteInfo() {
         const userInfo = this.$store?.state?.user?.info;
         if (!userInfo || !userInfo.userId) {
           return;
         }
-        // 班组模式下执行人由班组决定, 检验方案模式下没有执行部门, 均不处理
-        if (this.form.assignType == 1 || this.form.qualityType == 2) {
+        // 指定班组模式(assignType==1)执行人是禁用回显字段, 不做默认
+        if (this.form.assignType == 1) {
           return;
         }
         // 执行人: 未指定时默认当前登录用户
@@ -802,12 +813,35 @@
           !this.form.executeUserIdList ||
           !this.form.executeUserIdList.length
         ) {
-          this.$set(this.form, 'executeUserIdList', [userInfo.userId]);
-          this.$set(this.form, 'executeUserName', userInfo.name);
-          this.$set(this.form, 'executeUserId', String(userInfo.userId));
+          if (this.form.qualityType == 2) {
+            /* 检验方案模式: 执行人候选项 = 所选执行班组的成员,
+               默认人必须在班组成员列表里, 否则多选框回显不出来 */
+            const job = (this.form.jobList || []).find(
+              (item) => item.id == this.form.executeJobId
+            );
+            const teamUsers = (job && job.userVOList) || [];
+            const reporter = teamUsers.find(
+              (item) => item.id == userInfo.userId
+            );
+            if (reporter) {
+              this.$set(this.form, 'executeUserIdList', [userInfo.userId]);
+              this.$set(this.form, 'executeUserName', userInfo.name);
+              this.$set(this.form, 'executeUserId', String(userInfo.userId));
+            } else {
+              console.warn(
+                '[报工] 当前登录人不在执行班组成员中, 执行人无法默认为报工人',
+                '执行班组:', job && job.name,
+                '班组成员:', teamUsers.map((i) => ({ id: i.id, name: i.name }))
+              );
+            }
+          } else {
+            this.$set(this.form, 'executeUserIdList', [userInfo.userId]);
+            this.$set(this.form, 'executeUserName', userInfo.name);
+            this.$set(this.form, 'executeUserId', String(userInfo.userId));
+          }
         }
-        // 执行部门: 未指定时默认当前登录用户所属公司
-        if (!this.form.executeDeptId) {
+        // 执行部门: 未指定时默认当前登录用户所属公司(检验方案模式没有执行部门, 不处理)
+        if (this.form.qualityType != 2 && !this.form.executeDeptId) {
           let company = null;
           try {
             company = await getCurrentUserCompany(userInfo);

+ 27 - 11
src/views/inspectionWork/components/inspectionProjectReport.vue

@@ -955,12 +955,16 @@
             this.form.sampleQuantity
           );
         } else {
+          /* 与 watch tableData 同规则:明细不合格数总和 > 样品数取样品数(封顶),否则取总和 */
+          const sumNoQualified = this.tableData.reduce(
+            (sum, item) => sum + (Number(item.noQualifiedQuantity) || 0),
+            0
+          );
+          const sampleQuantity = Number(this.form.sampleQuantity) || 0;
           this.form.sampleNoQualifiedNumber = this.tableData.length
-            ? this.tableData.reduce(
-                (max, item) =>
-                  Math.max(max, Number(item.noQualifiedQuantity) || 0),
-                0
-              )
+            ? sumNoQualified > sampleQuantity
+              ? sampleQuantity
+              : sumNoQualified
             : 0;
         }
         this.form.sampleQualifiedNumber =
@@ -1111,13 +1115,25 @@
               this.$set(this.form, 'sampleQualifiedNumber', qualifiedNumber);
             }
           } else {
-            const maxNoQualified = newVal.reduce((max, item) => {
-              const val = Number(item.noQualifiedQuantity) || 0;
-              return val > max ? val : max;
-            }, 0);
-            this.$set(this.form, 'sampleNoQualifiedNumber', maxNoQualified);
+            /* 样品不合格数规则(2026-11-10 二次确认):
+               下方明细不合格数总和 > 样品数 → 取样品数(封顶);
+               总和 <= 样品数 → 取明细不合格数总和 */
+            const sumNoQualified = newVal.reduce(
+              (sum, item) => sum + (Number(item.noQualifiedQuantity) || 0),
+              0
+            );
+            const sampleQuantity = Number(this.form.sampleQuantity) || 0;
+            const sampleNoQualifiedNumber =
+              sumNoQualified > sampleQuantity
+                ? sampleQuantity
+                : sumNoQualified;
+            this.$set(
+              this.form,
+              'sampleNoQualifiedNumber',
+              sampleNoQualifiedNumber
+            );
             const qualifiedNumber =
-              (Number(this.form.sampleQuantity) || 0) - maxNoQualified;
+              sampleQuantity - sampleNoQualifiedNumber;
             if (qualifiedNumber < 0) {
               this.$message.warning('样品合格数不能小于0');
               this.$set(this.form, 'sampleQualifiedNumber', 0);

+ 55 - 19
src/views/recordComponents/workOrderReport.vue

@@ -577,7 +577,10 @@
               i.checkUsersIds = i.checkUsers.map((j) => j.userId);
             }
 
-            if (i.checkUsersIds?.length == 0 && data.executeUsers.length > 0) {
+            if (
+              i.checkUsersIds?.length == 0 &&
+              (data.executeUsers || []).length > 0
+            ) {
               // 默认执行人作为检查人
               i.checkUsersIds = data.executeUsers
                 .filter((i) => i.userId)
@@ -599,8 +602,8 @@
           Object.assign(this.addForm, data);
           console.log('this.addForm', this.addForm);
 
-          // 处理数据
-          this.addForm.executeUsersIds = this.addForm.executeUsers
+          // 处理数据(executeUsers 可能为 null,需判空,否则后续默认执行人逻辑不会执行)
+          this.addForm.executeUsersIds = (this.addForm.executeUsers || [])
             .map((i) => i.userId)
             .filter((i) => i); // 过滤掉 undefined
 
@@ -609,7 +612,10 @@
           //     ? this.addForm.executeUsers[0].teamId
           //     : '';
 
-          if (this.addForm.executeUsers.length > 0 && !this.addForm.type) {
+          if (
+            (this.addForm.executeUsers || []).length > 0 &&
+            !this.addForm.type
+          ) {
             let groupIds = this.addForm.executeUsers
               .map((i) => i.groupId)
               .filter(
@@ -634,24 +640,54 @@
 
           this.addForm.recordRulesClassify += '';
 
-          // 加载班组人员列表
+          // 加载班组人员列表(工单班组可能不在班组分页里,判空防止抛异常中断后续逻辑)
           if (this.addForm.teamId) {
-            const index = this.allTeamList.findIndex(
+            const team = this.allTeamList.find(
               (item) => item.id == this.addForm.teamId
             );
-            console.log(this.allTeamList[index], 'dsadas');
-            this.teamUserList = this.allTeamList[index].userVOList;
-
-            this.productLineList = this.allTeamList[
-              index
-            ].factoryWorkstationVOList.map((item) => {
-              return {
-                name: item.productionLineName,
-                id: item.productionLineId
-              };
-            });
+            if (team && team.userVOList) {
+              this.teamUserList = team.userVOList;
 
-            console.log('this.teamUserList', this.teamUserList);
+              this.productLineList = (team.factoryWorkstationVOList || []).map(
+                (item) => {
+                  return {
+                    name: item.productionLineName,
+                    id: item.productionLineId
+                  };
+                }
+              );
+            }
+          }
+
+          /* 报工模式下执行人未指定时, 默认报工人(当前登录用户)。
+             后端 executeUsers 有值时保持后端默认, 不覆盖 */
+          if (
+            this.addForm.type &&
+            !(this.addForm.executeUsersIds || []).length
+          ) {
+            const userInfo = this.$store?.state?.user?.info;
+            const reporter = this.teamUserList.find(
+              (item) => item.id == userInfo?.userId
+            );
+            if (reporter) {
+              this.addForm.executeUsersIds = [reporter.id];
+              this.addForm.executeUsers = [
+                {
+                  teamId: this.addForm.teamId,
+                  teamName: this.teamList.find(
+                    (team) => team.id == this.addForm.teamId
+                  )?.name,
+                  userId: reporter.id,
+                  userName: reporter.name
+                }
+              ];
+            } else {
+              console.warn(
+                '[报工] 当前登录人不在工单班组人员列表中, 执行人无法默认为报工人',
+                '登录人 userId:', userInfo?.userId,
+                '班组人员:', this.teamUserList.map((i) => ({ id: i.id, name: i.name }))
+              );
+            }
           }
 
           this.$nextTick(() => {
@@ -660,7 +696,7 @@
             this.loading = false;
           });
         } catch (error) {
-          console.log('error', error);
+          console.error('[报工] 工单详情处理异常(会导致默认执行人等后续逻辑中断):', error);
           this.loading = false;
         }
       },