Kaynağa Gözat

生产统计功能修改

lucw 10 ay önce
ebeveyn
işleme
f434ca060e

+ 158 - 123
src/views/batchRecord/components/editModal.vue

@@ -54,6 +54,7 @@
                 dictName="记录规则事项类型"
                 v-model="form.itemType"
                 @change="itemTypeChange"
+                :disabled="reportWorkType == 4"
               >
               </DictSelection>
             </el-form-item>
@@ -146,11 +147,11 @@
 
         <header-title
           title="基本信息"
-          v-if="form.itemType == 2"
+          v-if="form.itemType == 2 && reportWorkType != 4"
           style="margin-top: 20px"
         ></header-title>
 
-        <template v-if="form.itemType == 2">
+        <template v-if="form.itemType == 2 && reportWorkType != 4">
           <el-row style="margin-bottom: 20px">
             <el-col :span="8">
               <el-form-item
@@ -218,42 +219,44 @@
           <el-row style="margin-bottom: 20px">
             <el-col :span="8">
               <el-form-item label="执行人" required prop="teamId">
-                <el-select
-                  v-model="form.teamId"
-                  placeholder="请选择班组"
-                  filterable
-                  style="width: 120px"
-                  @change="checkTeamList(form.teamId)"
-                >
-                  <el-option
-                    v-for="item in teamList"
-                    :label="item.name"
-                    :value="item.id"
-                    :key="item.id"
+                <div style="display: flex">
+                  <el-select
+                    v-model="form.teamId"
+                    placeholder="请选择班组"
+                    filterable
+                    style="width: 120px"
+                    @change="checkTeamList(form.teamId)"
                   >
-                  </el-option>
-                </el-select>
-                <el-select
-                  v-model="form.executeUsersIds"
-                  placeholder="请选择执行人"
-                  filterable
-                  multiple
-                  @change="changeId"
-                  style="max-width: 100%"
-                >
-                  <div class="checkboxWrapper">
-                    <el-checkbox v-model="checked" @change="checkChange">
-                      全选
-                    </el-checkbox>
-                  </div>
-                  <el-option
-                    v-for="item in teamUserList"
-                    :label="item.name"
-                    :value="item.id"
-                    :key="item.id"
+                    <el-option
+                      v-for="item in teamList"
+                      :label="item.name"
+                      :value="item.id"
+                      :key="item.id"
+                    >
+                    </el-option>
+                  </el-select>
+                  <el-select
+                    v-model="form.executeUsersIds"
+                    placeholder="请选择执行人"
+                    filterable
+                    multiple
+                    @change="changeId"
+                    style="max-width: 100%"
                   >
-                  </el-option>
-                </el-select>
+                    <div class="checkboxWrapper">
+                      <el-checkbox v-model="checked" @change="checkChange">
+                        全选
+                      </el-checkbox>
+                    </div>
+                    <el-option
+                      v-for="item in teamUserList"
+                      :label="item.name"
+                      :value="item.id"
+                      :key="item.id"
+                    >
+                    </el-option>
+                  </el-select>
+                </div>
               </el-form-item>
             </el-col>
             <el-col :span="8">
@@ -343,7 +346,7 @@
         <el-row style="margin-bottom: 20px">
           <el-col :span="8">
             <el-form-item label="生产工单号" prop="workOrderCode">
-              <el-select
+              <!-- <el-select
                 v-model="form.workOrderCode"
                 placeholder="请选择生产工单"
                 style="width: 100%"
@@ -360,11 +363,21 @@
                   :value="item.code"
                 >
                 </el-option>
-              </el-select>
+              </el-select> -->
+              <el-input
+                v-model="form.workOrderCode"
+                placeholder="请选择生产工单"
+                @click.native="openWorkOrderDialog"
+                readonly
+              />
             </el-form-item>
           </el-col>
           <el-col :span="8">
-            <el-form-item label="工序名称" prop="produceTaskId">
+            <el-form-item
+              v-if="reportWorkType != 4"
+              label="工序名称"
+              prop="produceTaskId"
+            >
               <el-select
                 v-model="form.produceTaskId"
                 placeholder="请选择工序"
@@ -394,8 +407,12 @@
           <el-col :span="8">
             <el-form-item
               label="产品编码"
-              :required="form.recordRulesClassify != '4'"
-              :prop="form.recordRulesClassify != '4' ? 'productCode' : ''"
+              :required="form.recordRulesClassify != '4' && reportWorkType != 4"
+              :prop="
+                form.recordRulesClassify != '4' && reportWorkType != 4
+                  ? 'productCode'
+                  : ''
+              "
             >
               <el-input
                 v-model="form.productCode"
@@ -412,8 +429,12 @@
           <el-col :span="8">
             <el-form-item
               label="产品名称"
-              :required="form.recordRulesClassify != '4'"
-              :prop="form.recordRulesClassify != '4' ? 'productName' : ''"
+              :required="form.recordRulesClassify != '4' && reportWorkType != 4"
+              :prop="
+                form.recordRulesClassify != '4' && reportWorkType != 4
+                  ? 'productName'
+                  : ''
+              "
             >
               <el-input
                 v-model="form.productName"
@@ -459,7 +480,11 @@
           <el-col :span="8">
             <el-form-item
               label="要求生产数量"
-              :prop="form.recordRulesClassify != '4' ? 'formingNum' : ''"
+              :prop="
+                form.recordRulesClassify != '4' && reportWorkType != 4
+                  ? 'formingNum'
+                  : ''
+              "
             >
               <el-input
                 v-model.number="form.formingNum"
@@ -499,16 +524,7 @@
           style="margin-top: 20px"
         ></header-title>
 
-        <template
-          v-if="
-            form.itemType == 2 &&
-            form.recordRulesClassify == 10 &&
-            form.workOrderId &&
-            form.produceTaskId &&
-            form.ruleId &&
-            form.produceRoutingId
-          "
-        >
+        <template v-if="form.itemType == 2 && form.reportWorkType == 4">
           <el-tabs v-model="statisticsType" type="card">
             <el-tab-pane
               v-for="i in statisticsTypeList"
@@ -522,15 +538,16 @@
             ref="statisticsRef"
             :details.sync="form.details"
             :statisticsType="statisticsType"
-            :produceTaskId="form.produceTaskId"
-            :workOrderId="form.workOrderId"
-            :routingId="form.produceRoutingId"
+            :workOrderId="workOrderInfo ? workOrderInfo.id : ''"
+            :routingId="workOrderInfo ? workOrderInfo.produceRoutingId : ''"
+            :bomCategoryId="workOrderInfo ? workOrderInfo.bomCategoryId : ''"
             :ruleId="form.ruleId"
+            :rulesDetailList="rulesDetailList"
           ></statistics>
         </template>
 
         <ele-pro-table
-          v-if="form.itemType == 2 && form.recordRulesClassify != 10"
+          v-if="form.itemType == 2 && reportWorkType != 4"
           v-loading="loading"
           ref="table"
           row-key="id"
@@ -715,6 +732,13 @@
     ></SelectUser>
 
     <toolModal ref="toolModalRef" @chooseModal="chooseModal" />
+
+    <!-- 选择生产工单 -->
+    <selectWorkOrder
+      ref="selectWorkOrderRef"
+      @confirm="selectWorkOrderConfirm"
+      :multiple="false"
+    ></selectWorkOrder>
   </ele-modal>
 </template>
 
@@ -749,7 +773,8 @@
   import { getFactoryarea } from '@/api/aps/index';
   import { getTeam } from '@/api/produce/job.js';
   import material from '@/views/produce/components/prenatalExamination/material.vue';
-  import statistics from '@/views/produce/components/prenatalExamination/statistics.vue';
+  import statistics from './statistics.vue';
+  import selectWorkOrder from '@/views/checklistManagement/components/selectWorkOrder.vue';
 
   export default {
     name: 'editModal',
@@ -768,10 +793,11 @@
       bpmDetail,
       bpmTask,
       material,
-      statistics
+      statistics,
+      selectWorkOrder
     },
     props: {
-      // 1-产前准备,2-过程监测,3-产后检查
+      // 1-产前准备,2-过程监测,3-产后检查 4-生产统计
       reportWorkType: {
         type: Number,
         default: 1
@@ -1032,7 +1058,8 @@
           { label: '成品统计', value: '1' },
           { label: '物料统计', value: '2' },
           { label: '工序统计', value: '3' }
-        ]
+        ],
+        rulesDetailList: []
       };
     },
     computed: {
@@ -1146,6 +1173,9 @@
             this.getWorkOrderById(this.form.workOrderId);
             this.getDetias();
           }
+          if (data.ruleId) {
+            this.getRulesDetiasList(data.ruleId);
+          }
         } else if (type == 'detail') {
           this.title = `${this.reportWorkTypeName}事项`;
           this.form.workOrderId = data.workOrderId;
@@ -1156,6 +1186,9 @@
             this.getWorkOrderById(this.form.workOrderId);
             this.getDetias();
           }
+          if (data.ruleId) {
+            this.getRulesDetiasList(data.ruleId);
+          }
         } else {
         }
         this.visible = true;
@@ -1214,9 +1247,34 @@
               toolNames: i.tools.map((i) => i.toolName).join(',')
             };
           });
+          this.rulesDetailList = JSON.parse(JSON.stringify(this.form.details));
           console.log('this.form.details', this.form.details);
         }
       },
+      // 查询规则详情
+      async getRulesDetiasList(ruleId) {
+        if (ruleId) {
+          const { list } = await recordRulesDetailPage({
+            pageNum: 1,
+            size: 999,
+            rulesId: ruleId
+          });
+          this.rulesDetailList = list.map((i) => {
+            return {
+              ...i,
+              id: null,
+              checkResult: null,
+              checkStatus: null,
+              checkStatusDesc: i.defaultValue || '',
+              errorMsg: '',
+              checkUsers: [],
+              paramValue: i.paramValue,
+              toolNames: i.tools.map((i) => i.toolName).join(',')
+            };
+          });
+          console.log('this.rulesDetailList', this.rulesDetailList);
+        }
+      },
       // 关闭时清理表单
       handleClose() {
         this.form = JSON.parse(JSON.stringify(this.formBaseData));
@@ -1298,45 +1356,10 @@
         console.log('生产工单', list);
         this.workOrderList = list;
       },
-      // 选择生产工单
-      workOrderCodeChange(code) {
-        console.log('code', code);
-        if (code) {
-          const workOrder = this.workOrderList.find((i) => i.code == code);
-          console.log('workOrder', workOrder);
-          this.workOrderInfo = workOrder;
-          this.form.workOrderId = workOrder.id;
-          // 赋值产品信息
-          this.form.productCode = workOrder.productCode;
-          this.form.productModel = workOrder.productModel;
-          this.form.productName = workOrder.productName;
-          this.form.batchNo = workOrder.batchNo;
-          this.form.specification = workOrder.specification;
-          this.form.formingNum = workOrder.formingNum;
-          this.form.brandNo = workOrder.brandNo;
-          this.form.produceRoutingId = workOrder.produceRoutingId;
-          this.getProductTaskList(workOrder.id);
-        } else {
-          this.workOrderInfo = null;
-          this.form.workOrderId = null;
-          // 赋值产品信息
-          this.form.productCode = null;
-          this.form.productModel = null;
-          this.form.productName = '';
-          this.form.batchNo = '';
-          this.form.specification = null;
-          this.form.formingNum = null;
-          this.form.brandNo = '';
-          this.form.produceRoutingId = '';
-
-          this.produceTaskList = [];
-        }
-        this.form.produceTaskId = null;
-        this.form.produceTaskName = '';
-        this.form.produceTaskInstanceId = '';
-      },
       // 获取工序列表
       async getProductTaskList(id) {
+        // 生产统计不关联工序
+        if (this.reportWorkType == 4) return;
         const data = await getTaskInstanceList(id);
         console.log('data 工序列表', data);
         this.produceTaskList = data.filter(
@@ -1357,18 +1380,6 @@
           this.form.produceTaskInstanceId = prodceTask.taskId;
         }
 
-        if (this.form.ruleId) {
-          // 清空记录规则
-          this.form.ruleId = null;
-          this.form.ruleName = null;
-          this.form.recordRulesClassify = null;
-          this.form.recordRulesExecuteMethodId = null;
-          this.form.recordRulesExecuteMethodName = null;
-          this.$message.warning(
-            '工序变更,已清空已选择的记录规则,请选择工序下的记录规则'
-          );
-        }
-
         // 查询物料信息
         this.getListByWorkOrderId();
       },
@@ -1409,12 +1420,6 @@
 
           try {
             if (this.form.itemType == 2) {
-              // 验证产出物数量;
-              const valid = this.$refs.materialRef.validateOutputQuantities();
-              if (!valid) {
-                return;
-              }
-
               // 记录规则保存
               return this.releaseRulesSaveOrSubmit('save');
             }
@@ -1437,12 +1442,12 @@
       },
       // 记录规则保存或者 一键报工
       async releaseRulesSaveOrSubmit(type) {
-        if (this.form.executeUsersIds.length == 0) {
+        if (this.form.executeUsersIds.length == 0 && this.reportWorkType != 4) {
           this.$message.warning('请选择执行人!');
           return;
         }
 
-        if (this.form.duration <= 0) {
+        if (this.form.duration <= 0 && this.reportWorkType != 4) {
           this.$message.warning('工时必须大于0!');
           return;
         }
@@ -1451,7 +1456,7 @@
         if (
           type.includes('submit') &&
           this.form.recordRulesClassify != '4' &&
-          this.form.recordRulesClassify != '10'
+          this.reportWorkType != 4
         ) {
           // 验证检查项目
           const detailRequired = this.form.details.some((i) => {
@@ -1487,9 +1492,11 @@
 
         const body = JSON.parse(JSON.stringify(this.form));
 
-        // 工时小时转毫秒
-        body.duration = Number(body.duration);
-        body.duration = body.duration * 60 * 60 * 1000;
+        if (body.duration) {
+          // 工时小时转毫秒
+          body.duration = Number(body.duration);
+          body.duration = body.duration * 60 * 60 * 1000;
+        }
 
         this.butLoading = true;
         console.log('body', body);
@@ -1785,6 +1792,34 @@
         });
 
         console.log('row', row);
+      },
+      // 打开选择工单弹窗
+      openWorkOrderDialog() {
+        this.$refs.selectWorkOrderRef.open();
+      },
+      selectWorkOrderConfirm(workOrder) {
+        console.log('workOrder', workOrder);
+        this.workOrderInfo = workOrder;
+        this.form.workOrderId = workOrder.id;
+        this.form.workOrderCode = workOrder.code;
+        // 赋值产品信息
+        this.form.productCode = workOrder.productCode;
+        this.form.productModel = workOrder.productModel;
+        this.form.productName = workOrder.productName;
+        this.form.batchNo = workOrder.batchNo;
+        this.form.specification = workOrder.specification;
+        this.form.formingNum = workOrder.formingNum;
+        this.form.brandNo = workOrder.brandNo;
+        this.form.produceRoutingId = workOrder.produceRoutingId;
+        this.getProductTaskList(workOrder.id);
+        this.form.produceTaskId = null;
+        this.form.produceTaskName = '';
+        this.form.produceTaskInstanceId = '';
+
+        this.$nextTick(() => {
+          // 工单变化构建物料和工序数据
+          this.$refs.statisticsRef.rebuildMaterialAndProcessData();
+        });
       }
     }
   };

+ 720 - 0
src/views/batchRecord/components/statistics.vue

@@ -0,0 +1,720 @@
+<template>
+  <div>
+    <ele-pro-table
+      v-if="
+        statisticsType == 1 &&
+        localDetails[0] &&
+        localDetails[0].statisticsValue
+      "
+      ref="table"
+      :columns="typeOneColumns"
+      :datasource="localDetails[0].statisticsValue"
+      cacheKey="mes-statistics-type-1-2511041946"
+      :needPage="false"
+      show-summary
+      :summary-method="getSummaries"
+    >
+      <template v-slot:toolkit>
+        <el-button
+          v-if="localDetails[0].statisticsValue[0]"
+          type="primary"
+          @click="addRow"
+        >
+          添加
+        </el-button>
+      </template>
+
+      <template
+        v-for="(item, index) in localDetails[0].statisticsValue[0]"
+        v-slot:[`column_${index}`]="{ row }"
+      >
+        <div :key="`column_${index}`" class="column_content">
+          <div v-if="row[index].isOnlyShow">
+            {{ row[index].value }}
+          </div>
+          <el-input
+            v-else
+            v-model.number="row[index].value"
+            :placeholder="
+              row[index].formula
+                ? row[index].formula.replace(/[\[\]]/g, '')
+                : `请输入${row[index].title}`
+            "
+            :disabled="Boolean(row[index].formula)"
+            @input="handleDataChange(row[index], row)"
+          >
+            <template v-if="!row[index].isOnlyShow" slot="append">
+              <div style="width: 80px; height: 100%">
+                <DictSelection
+                  v-model="row[index].unit"
+                  dictName="工艺参数单位"
+                  placeholder="单位"
+                >
+                </DictSelection>
+              </div>
+            </template>
+          </el-input>
+        </div>
+      </template>
+    </ele-pro-table>
+    <div
+      v-if="
+        statisticsType == 1 &&
+        localDetails[0] &&
+        localDetails[0].statisticsValue
+      "
+      class=""
+    >
+    </div>
+    <ele-pro-table
+      v-if="
+        statisticsType == 2 &&
+        localDetails[1] &&
+        localDetails[1].statisticsValue
+      "
+      ref="table"
+      :columns="typeTwoColumns"
+      :datasource="typeTwoDataSource"
+      cacheKey="mes-statistics-type-2-2511041946"
+      :needPage="false"
+    >
+      <template v-slot:toolkit>
+        <el-select
+          v-model="activeProductTaskName"
+          placeholder="请选择"
+          style="margin-right: 20px"
+        >
+          <el-option
+            v-for="item in productTaskNameList"
+            :key="item"
+            :label="item"
+            :value="item"
+          >
+          </el-option>
+        </el-select>
+      </template>
+      <template
+        v-for="(item, index) in localDetails[1].statisticsValue[0]"
+        v-slot:[`column_${index}`]="{ row }"
+      >
+        <div :key="`column_${index}`" class="column_content">
+          <div v-if="row[index].isOnlyShow">
+            {{ row[index].value }}
+          </div>
+          <el-input
+            v-else
+            v-model.number="row[index].value"
+            :placeholder="
+              row[index].formula
+                ? row[index].formula.replace(/[\[\]]/g, '')
+                : `请输入${row[index].title}`
+            "
+            :disabled="Boolean(row[index].formula)"
+            @input="handleDataChange(row[index], row)"
+          >
+            <template v-if="!row[index].isOnlyShow" slot="append">
+              <div style="width: 80px; height: 100%">
+                <DictSelection
+                  v-model="row[index].unit"
+                  dictName="工艺参数单位"
+                  placeholder="单位"
+                >
+                </DictSelection>
+              </div>
+            </template>
+          </el-input>
+        </div>
+      </template>
+    </ele-pro-table>
+
+    <ele-pro-table
+      v-if="
+        statisticsType == 3 &&
+        localDetails[2] &&
+        localDetails[2].statisticsValue
+      "
+      ref="table"
+      :columns="typeThreeColumns"
+      :datasource="localDetails[2].statisticsValue"
+      cacheKey="mes-statistics-type-3-2511051037"
+      :needPage="false"
+    >
+      <template
+        v-for="(item, index) in localDetails[2].statisticsValue[0]"
+        v-slot:[`column_${index}`]="{ row }"
+      >
+        <div :key="`column_${index}`" class="column_content">
+          <div v-if="row[index].isOnlyShow">
+            {{ row[index].value }}
+          </div>
+          <el-input
+            v-else
+            v-model.number="row[index].value"
+            :placeholder="
+              row[index].formula
+                ? row[index].formula.replace(/[\[\]]/g, '')
+                : `请输入${row[index].title}`
+            "
+            :disabled="Boolean(row[index].formula)"
+            @input="handleDataChange(row[index], row)"
+          >
+            <template v-if="!row[index].isOnlyShow" slot="append">
+              <div style="width: 80px; height: 100%">
+                <DictSelection
+                  v-model="row[index].unit"
+                  dictName="工艺参数单位"
+                  placeholder="单位"
+                >
+                </DictSelection>
+              </div>
+            </template>
+          </el-input>
+        </div>
+      </template>
+    </ele-pro-table>
+  </div>
+</template>
+
+<script>
+  import {
+    getAllRoutingTaskList,
+    getPickAndFeed
+  } from '@/api/producetaskrecordrulesrecord/index';
+
+  export default {
+    props: {
+      details: {
+        type: Array,
+        default: () => []
+      },
+      // 规则详情列表
+      rulesDetailList: {
+        type: Array,
+        default: () => []
+      },
+      statisticsType: {
+        type: String,
+        default: '1' // 1-成品统计,2-物料统计,3-工序统计
+      },
+      // 工艺路线id
+      routingId: {
+        type: [String, Number],
+        default: ''
+      },
+      // workOrderId 工单id
+      workOrderId: {
+        type: [String, Number],
+        default: ''
+      },
+      // bomCategoryId
+      bomCategoryId: {
+        type: [String, Number],
+        default: ''
+      },
+      //ruleId
+      ruleId: {
+        type: [String, Number],
+        default: ''
+      }
+    },
+    watch: {
+      details: {
+        deep: true,
+        immediate: true,
+        handler(val) {
+          // 已构建过统计数据
+          if (
+            val[0] &&
+            val[0].statisticsValue &&
+            val[0].statisticsValue.length > 0
+          ) {
+            console.log('直接赋值');
+            this.localDetails = JSON.parse(JSON.stringify(val));
+          } else {
+            this.buildDetials(val);
+          }
+        }
+      }
+    },
+    computed: {
+      // 成品统计表头
+      typeOneColumns() {
+        if (
+          this.localDetails.length > 0 &&
+          this.localDetails[0].statisticsValue &&
+          this.localDetails[0].statisticsType == 1 &&
+          this.localDetails[0].statisticsValue[0]
+        ) {
+          const cList = this.localDetails[0].statisticsValue[0].map(
+            (item, index) => {
+              return {
+                label: item.title,
+                slot: `column_${index}`,
+                align: 'center',
+                minWidth: 200
+              };
+            }
+          );
+          cList.unshift({
+            width: 50,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center'
+          });
+          return cList;
+        } else {
+          return [];
+        }
+      },
+      // 物料统计表头
+      typeTwoColumns() {
+        if (
+          this.localDetails.length > 1 &&
+          this.localDetails[1].statisticsValue &&
+          this.localDetails[1].statisticsType == 2 &&
+          this.localDetails[1].statisticsValue[0]
+        ) {
+          const cList = this.localDetails[1].statisticsValue[0].map(
+            (item, index) => {
+              return {
+                label: item.title,
+                slot: `column_${index}`,
+                align: 'center',
+                minWidth: 200
+              };
+            }
+          );
+          cList.unshift({
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center'
+          });
+          return cList;
+        } else {
+          return [];
+        }
+      },
+      // 工序统计表头
+      typeThreeColumns() {
+        if (
+          this.localDetails.length > 2 &&
+          this.localDetails[2].statisticsValue &&
+          this.localDetails[2].statisticsType == 3 &&
+          this.localDetails[2].statisticsValue[0]
+        ) {
+          const cList = this.localDetails[2].statisticsValue[0].map(
+            (item, index) => {
+              return {
+                label: item.title,
+                slot: `column_${index}`,
+                align: 'center',
+                minWidth: 200
+              };
+            }
+          );
+          cList.unshift({
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center'
+          });
+          return cList;
+        } else {
+          return [];
+        }
+      },
+      // 工序名称列表
+      productTaskNameList() {
+        if (this.localDetails[2]?.statisticsValue) {
+          const list = this.localDetails[2].statisticsValue.map((rows) => {
+            return rows.find((i) => i.title === '工序名称')?.value || '';
+          });
+
+          list.unshift('全部'); // 全部选项
+          return list;
+        } else {
+          return [];
+        }
+      },
+      typeTwoDataSource() {
+        if (this.activeProductTaskName === '全部') {
+          return this.localDetails[1].statisticsValue;
+        } else {
+          return this.localDetails[1].statisticsValue.filter((rows) => {
+            const nameItem = rows.find((i) => i.title === '物料名称');
+            return (
+              nameItem &&
+              nameItem.produceTaskName === this.activeProductTaskName
+            );
+          });
+        }
+      }
+    },
+    data() {
+      return {
+        localDetails: [
+          {
+            ruleId: this.ruleId,
+            statisticsType: 1,
+            statisticsValue: []
+          },
+          {
+            ruleId: this.ruleId,
+            statisticsType: 2,
+            statisticsValue: []
+          },
+          {
+            ruleId: this.ruleId,
+            statisticsType: 3,
+            statisticsValue: []
+          }
+        ],
+        activeProductTaskName: '全部'
+      };
+    },
+
+    methods: {
+      // 通知父组件数据变更
+      emitChange() {
+        console.log('this.localDetails', this.localDetails);
+        this.$emit('update:details', this.localDetails);
+      },
+      // 构建统计数据
+      async buildDetials(detials) {
+        if (detials.length === 0) {
+          return;
+        }
+        console.log('this.localDetails', this.localDetails);
+
+        if (
+          (this.localDetails[0].statisticsValue &&
+            this.localDetails[0].statisticsValue.length == 0) ||
+          this.localDetails[0].ruleId != this.ruleId
+        ) {
+          // 已构建过统计数据
+          this.localDetails[0] = {
+            ...this.localDetails[0],
+            ruleId: this.ruleId,
+            statisticsType: 1,
+            statisticsValue: [
+              this.rulesDetailList
+                .filter((i) => i.statisticsType == 1)
+                .map((i) => {
+                  return {
+                    title: i.paramValue,
+                    value: i.defaultValue,
+                    formula: i.formula,
+                    unit: i.unitName
+                  };
+                })
+            ]
+          };
+        }
+        // 构建物料和工序数据
+        this.rebuildMaterialAndProcessData();
+      },
+      // 构建物料和工序数据
+      async rebuildMaterialAndProcessData() {
+        let routingTaskList = [];
+        let pickAndFeed = [];
+
+        if (this.workOrderId) {
+          // 并发获取工序任务列表和物料数据
+          let [routingTaskObj, pickAndFeedList] = await Promise.all([
+            getAllRoutingTaskList({ routingId: this.routingId }),
+            getPickAndFeed({
+              workOrderId: this.workOrderId,
+              bomCategoryId: this.bomCategoryId
+            })
+          ]);
+          pickAndFeed = pickAndFeedList || [];
+          routingTaskList = routingTaskObj?.list || [];
+        }
+
+        console.log('routingTaskList 工序数据', routingTaskList);
+        console.log('物料数据 pickAndFeed', pickAndFeed);
+
+        this.localDetails[1] = {
+          ...this.localDetails[1],
+          ruleId: this.ruleId,
+          statisticsType: 2,
+          statisticsValue: pickAndFeed.map((pick) => {
+            const data = this.rulesDetailList
+              .filter((i) => i.statisticsType == 2)
+              .map((i) => {
+                return {
+                  title: i.paramValue,
+                  value: i.defaultValue,
+                  formula: i.formula,
+                  unit: i.unitName
+                };
+              });
+
+            data.unshift({
+              title: '领用量',
+              value: pick.pickQuantity,
+              formula: '',
+              unit: pick.pickUnit
+            });
+
+            data.unshift({
+              title: '使用量',
+              value: pick.feedQuantity,
+              formula: '',
+              unit: pick.feedUnit
+            });
+
+            data.unshift({
+              title: '物料编码',
+              value: pick.categoryCode,
+              formula: '',
+              unit: '',
+              // 仅展示不计算和输入
+              isOnlyShow: true
+            });
+
+            data.unshift({
+              title: '物料名称',
+              value: pick.categoryName,
+              formula: '',
+              unit: '',
+              // 仅展示不计算和输入
+              isOnlyShow: true,
+              // produceTaskName 工序名称
+              produceTaskName: pick.produceTaskName
+            });
+
+            return data;
+          })
+        };
+
+        this.localDetails[2] = {
+          ...this.localDetails[2],
+          ruleId: this.ruleId,
+          statisticsType: 3,
+          statisticsValue: routingTaskList.map((task) => {
+            const data = this.rulesDetailList
+              .filter((i) => i.statisticsType == 3)
+              .map((i) => {
+                return {
+                  title: i.paramValue,
+                  value: i.defaultValue,
+                  formula: i.formula,
+                  unit: i.unitName
+                };
+              });
+
+            data.unshift({
+              title: '工序名称',
+              value: task.taskInstanceName,
+              formula: '',
+              unit: '',
+              // 仅展示不计算和输入
+              isOnlyShow: true
+            });
+
+            return data;
+          })
+        };
+
+        console.log('this.localDetails', this.localDetails);
+
+        // 通知父组件数据变更
+        this.emitChange();
+      },
+      // 当数据变化时计算公式
+      handleDataChange(item, row) {
+        // todo 计算公式
+        console.log('item', item);
+        console.log('row', row);
+        // 寻找当前行的所有可计算项,进行计算更新
+        const formulaItmes = row.filter((i) => i.formula);
+
+        formulaItmes.forEach((formulaItem) => {
+          // 简单示例 公式为 [(][合格品量][+][取样量][)][/][接收量] 其中合格品量、取样量、接收量为标题在row中寻找对应value进行计算
+          const tokens = formulaItem.formula
+            ? formulaItem.formula.match(/\[([^\]]+)\]/g) || []
+            : [];
+          let expr = '';
+          let invalid = false;
+          for (const token of tokens) {
+            if (invalid) break;
+            const content = token.slice(1, -1).trim();
+            if (['+', '-', '*', '/', '(', ')', '%'].includes(content)) {
+              expr += content;
+            } else {
+              const target = row.find((r) => r.title === content);
+              // 若对应的项不存在 或 value为空 则取消计算
+              if (
+                !target ||
+                target.value === '' ||
+                target.value === null ||
+                target.value === undefined
+              ) {
+                invalid = true;
+                expr = ''; // 置空表达式,后续将不计算
+                break;
+              }
+              const num = Number(target.value);
+              if (!Number.isFinite(num)) {
+                invalid = true;
+                expr = '';
+                break;
+              }
+              expr += num;
+            }
+          }
+          // 若无效则直接跳过后续计算 (expr 已被置空)
+          if (/^[0-9+\-*/().\s]+$/.test(expr)) {
+            try {
+              console.log('expr', expr);
+              const result = Function(`"use strict";return (${expr})`)();
+              let value =
+                Number.isFinite(result) && !Number.isNaN(result) ? result : '';
+
+              if (value) {
+                // 如果超出4位小数 则保留4位小数
+                if (typeof value === 'number') {
+                  const dec = value.toString().split('.')[1];
+                  if (dec && dec.length > 4) {
+                    const parts = value.toString().split('.');
+                    if (parts[1] && parts[1].length > 4) {
+                      value = Number(parts[0] + '.' + parts[1].slice(0, 4));
+                    }
+                  }
+                }
+              }
+
+              formulaItem.value = value;
+            } catch (e) {
+              formulaItem.value = '';
+            }
+          } else {
+            formulaItem.value = '';
+          }
+        });
+
+        // 通知父组件数据变更
+        this.emitChange();
+      },
+      // 验证所有行/列(排除仅展示项),收集缺失项并提示;返回布尔值
+      validateStatisticsFilled() {
+        return true; // 暂时不验证
+
+        if (
+          !Array.isArray(this.localDetails) ||
+          this.localDetails.length === 0
+        ) {
+          this.$message.error('统计数据为空');
+          return false;
+        }
+
+        const typeNameMap = {
+          1: '成品统计',
+          2: '物料统计',
+          3: '工序统计'
+        };
+
+        const missing = [];
+
+        this.localDetails.forEach((detail, detailIndex) => {
+          if (!detail || !detail.statisticsValue) return;
+
+          // 统一转成多行结构
+          const rows =
+            detail.statisticsType === 1
+              ? [detail.statisticsValue[0] || []]
+              : detail.statisticsValue || [];
+
+          rows.forEach((row, rowIndex) => {
+            // 记录行的标识(物料名称 / 工序名称)
+            let rowLabel = '';
+            if (detail.statisticsType === 2) {
+              const nameItem = row.find((i) => i && i.title === '物料名称');
+              if (nameItem)
+                rowLabel = `(${nameItem.value || '物料行' + (rowIndex + 1)})`;
+            } else if (detail.statisticsType === 3) {
+              const procItem = row.find((i) => i && i.title === '工序名称');
+              if (procItem)
+                rowLabel = `(${procItem.value || '工序行' + (rowIndex + 1)})`;
+            }
+
+            row.forEach((item, colIndex) => {
+              if (!item || item.isOnlyShow) return;
+              const val = item.value;
+              if (val === '' || val === null || val === undefined) {
+                missing.push(
+                  `${typeNameMap[detail.statisticsType]}${rowLabel} - 第${
+                    colIndex + 1
+                  }列【${item.title}】未填写`
+                );
+              }
+            });
+          });
+        });
+
+        if (missing.length > 0) {
+          // 过多时截断
+          const displayList =
+            missing.length > 1
+              ? missing.slice(0, 1).concat(`, 共有 ${missing.length} 项未填写`)
+              : missing;
+          this.$message.warning(`请完善统计数据:\n${displayList.join('\n')}`);
+          return false;
+        }
+        return true;
+      },
+      getSummaries() {
+        const sums = [];
+        if (this.localDetails[0].statisticsValue.length == 0) {
+          return sums;
+        }
+        sums.push('合计');
+        this.localDetails[0].statisticsValue.forEach((itemList, index) => {
+          itemList.forEach((item, colIndex) => {
+            if (item.isOnlyShow) {
+              sums[colIndex + 1] = '';
+            } else {
+              if (sums[colIndex + 1]) {
+                if (isNaN(Number(item.value))) {
+                  sums[colIndex + 1] += 0;
+                } else {
+                  sums[colIndex + 1] += Number(item.value) || 0;
+                }
+              } else {
+                if (isNaN(Number(item.value))) {
+                  sums[colIndex + 1] = 0;
+                } else {
+                  sums[colIndex + 1] = Number(item.value) || 0;
+                }
+              }
+            }
+          });
+        });
+        console.log('sums', sums);
+        return sums;
+      },
+      // 添加行
+      addRow() {
+        const row = JSON.parse(
+          JSON.stringify(this.localDetails[0].statisticsValue[0])
+        );
+
+        row.forEach((item) => {
+          if (!item.isOnlyShow) {
+            item.value = '';
+          }
+        });
+
+        this.localDetails[0].statisticsValue.push(row);
+      }
+    }
+  };
+</script>
+
+<style scoped lang="scss">
+  .column_content ::v-deep .el-input-group__append {
+    padding: 0;
+  }
+</style>

+ 16 - 0
src/views/batchRecord/statistics.vue

@@ -0,0 +1,16 @@
+<template>
+  <div class="ele-body"> <list :reportWorkType="4"></list> </div>
+</template>
+
+<script>
+  import list from './components/list.vue';
+
+  export default {
+    components: { list },
+    data() {
+      return {};
+    }
+  };
+</script>
+
+<style lang="scss" scoped></style>

+ 2 - 1
src/views/checklistManagement/components/checkDetails.vue

@@ -320,7 +320,8 @@
         type: '',
         // 生产工单查询条件
         workOrderWhere: {
-          statusList: ['6']
+          statusList: ['6'],
+          queryTermination: 0
         },
         loading: false,
         butLoading: false,

+ 64 - 15
src/views/checklistManagement/components/selectWorkOrder.vue

@@ -25,6 +25,21 @@
         autoAmendPage
         :cache-key="cacheKeyUrl"
       >
+        <template v-slot:radio="{ row }">
+          <el-radio
+            class="radio"
+            :label="row.id"
+            v-model="currentId"
+            @change="
+              () => {
+                currentObj = row;
+              }
+            "
+          >
+            <i></i
+          ></el-radio>
+        </template>
+
         <template v-slot:code="{ row }">
           <el-link type="primary" :underline="false" @click="goDetail(row)">
             {{ row.code }}
@@ -80,7 +95,6 @@
 <script>
   import dictMixins from '@/mixins/dictMixins';
   import tableColumnsMixin from '@/mixins/tableColumnsMixin';
-  import { getPage } from '@/api/produceOrder/index.js';
   import { pageOrderByProduct } from '@/api/produce/workOrder.js';
 
   export default {
@@ -95,6 +109,11 @@
       autoClose: {
         type: Boolean,
         default: true
+      },
+      // 是否多选
+      multiple: {
+        type: Boolean,
+        default: true
       }
     },
     data() {
@@ -117,7 +136,9 @@
           { label: '预制计划', value: '3' }
         ],
         cacheKeyUrl: 'public-2025926-select-work-order',
-        selection: []
+        selection: [],
+        currentId: '',
+        currentObj: null
       };
     },
     computed: {
@@ -167,13 +188,13 @@
             value: 'code',
             type: 'input',
             placeholder: '',
-            labelWidth: 100
+            labelWidth: '100'
           },
           {
             label: '生产订单号:',
             value: 'apsWorkOrderCode',
             type: 'input',
-            labelWidth: 100
+            labelWidth: '100'
           },
           {
             label: '计划编号:',
@@ -231,15 +252,7 @@
         ];
       },
       basicColumns() {
-        return [
-          {
-            width: 45,
-            type: 'selection',
-            columnKey: 'selection',
-            align: 'center',
-            fixed: 'left'
-          },
-
+        const list = [
           {
             slot: 'code',
             label: '生产工单号',
@@ -493,6 +506,26 @@
             showOverflowTooltip: true
           }
         ];
+
+        if (this.multiple) {
+          list.unshift({
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center',
+            fixed: 'left'
+          });
+        } else {
+          list.unshift({
+            width: 50,
+            slot: 'radio',
+            columnKey: 'selection',
+            align: 'center',
+            fixed: 'left'
+          });
+        }
+
+        return list;
       }
     },
     methods: {
@@ -502,12 +535,29 @@
       },
       // 关闭时清理表单
       handleClose() {
+        this.currentId = '';
+        this.currentObj = null;
         this.visible = false;
       },
       // 提交 选择
       submit() {
         console.log('this.selection', this.selection);
-        this.$emit('confirm', this.selection);
+
+        if (this.multiple) {
+          if (this.selection.length == 0) {
+            this.$message.warning('请至少选择一条工单');
+            return;
+          }
+
+          this.$emit('confirm', this.selection);
+        } else {
+          if (!this.currentObj) {
+            this.$message.warning('请选择工单');
+            return;
+          }
+          this.$emit('confirm', this.currentObj);
+        }
+
         if (this.autoClose) {
           this.handleClose();
         }
@@ -519,7 +569,6 @@
           ...order,
           pageNum: page,
           size: limit,
-          queryTermination: 0,
           ...this.where
         });
       },

+ 323 - 152
src/views/produce/components/prenatalExamination/statistics.vue

@@ -11,30 +11,42 @@
       :datasource="localDetails[0].statisticsValue"
       cacheKey="mes-statistics-type-1-2511041946"
       :needPage="false"
+      show-summary
+      :summary-method="getSummaries"
     >
+      <template v-slot:toolkit>
+        <el-button
+          v-if="localDetails[0].statisticsValue[0]"
+          type="primary"
+          @click="addRow"
+        >
+          添加
+        </el-button>
+      </template>
+
       <template
         v-for="(item, index) in localDetails[0].statisticsValue[0]"
         v-slot:[`column_${index}`]="{ row }"
       >
         <div :key="`column_${index}`" class="column_content">
-          <div v-if="item.isOnlyShow">
-            {{ item.value }}
+          <div v-if="row[index].isOnlyShow">
+            {{ row[index].value }}
           </div>
           <el-input
             v-else
-            v-model.number="item.value"
+            v-model.number="row[index].value"
             :placeholder="
-              item.formula
-                ? item.formula.replace(/[\[\]]/g, '')
-                : `请输入${item.title}`
+              row[index].formula
+                ? row[index].formula.replace(/[\[\]]/g, '')
+                : `请输入${row[index].title}`
             "
-            :disabled="Boolean(item.formula)"
-            @input="handleDataChange(item, row)"
+            :disabled="Boolean(row[index].formula)"
+            @input="handleDataChange(row[index], row)"
           >
-            <template slot="append">
+            <template v-if="!row[index].isOnlyShow" slot="append">
               <div style="width: 80px; height: 100%">
                 <DictSelection
-                  v-model="item.unit"
+                  v-model="row[index].unit"
                   dictName="工艺参数单位"
                   placeholder="单位"
                 >
@@ -45,6 +57,15 @@
         </div>
       </template>
     </ele-pro-table>
+    <div
+      v-if="
+        statisticsType == 1 &&
+        localDetails[0] &&
+        localDetails[0].statisticsValue
+      "
+      class=""
+    >
+    </div>
     <ele-pro-table
       v-if="
         statisticsType == 2 &&
@@ -53,10 +74,25 @@
       "
       ref="table"
       :columns="typeTwoColumns"
-      :datasource="localDetails[1].statisticsValue"
+      :datasource="typeTwoDataSource"
       cacheKey="mes-statistics-type-2-2511041946"
       :needPage="false"
     >
+      <template v-slot:toolkit>
+        <el-select
+          v-model="activeProductTaskName"
+          placeholder="请选择"
+          style="margin-right: 20px"
+        >
+          <el-option
+            v-for="item in productTaskNameList"
+            :key="item"
+            :label="item"
+            :value="item"
+          >
+          </el-option>
+        </el-select>
+      </template>
       <template
         v-for="(item, index) in localDetails[1].statisticsValue[0]"
         v-slot:[`column_${index}`]="{ row }"
@@ -151,29 +187,34 @@
         type: Array,
         default: () => []
       },
+      // 规则详情列表
+      rulesDetailList: {
+        type: Array,
+        default: () => []
+      },
       statisticsType: {
         type: String,
         default: '1' // 1-成品统计,2-物料统计,3-工序统计
       },
-      // 工艺路线id 必填
+      // 工艺路线id
       routingId: {
         type: [String, Number],
-        required: true
+        default: ''
       },
-      // workOrderId 工单id 必填
+      // workOrderId 工单id
       workOrderId: {
         type: [String, Number],
-        required: true
+        default: ''
       },
-      // produceTaskId 工序id
-      produceTaskId: {
+      // bomCategoryId
+      bomCategoryId: {
         type: [String, Number],
-        required: true
+        default: ''
       },
       //ruleId
       ruleId: {
         type: [String, Number],
-        required: true
+        default: ''
       }
     },
     watch: {
@@ -181,19 +222,18 @@
         deep: true,
         immediate: true,
         handler(val) {
-          // const details = JSON.parse(JSON.stringify(val));
-          this.buildDetials(val);
+          // 已构建过统计数据
+          if (
+            val[0] &&
+            val[0].statisticsValue &&
+            val[0].statisticsValue.length > 0
+          ) {
+            console.log('直接赋值');
+            this.localDetails = JSON.parse(JSON.stringify(val));
+          } else {
+            this.buildDetials(val);
+          }
         }
-      },
-      // ruleId变化时修改
-      ruleId: {
-        handler(val) {
-          this.localDetails.forEach((item) => {
-            item.ruleId = val;
-          });
-          this.emitChange();
-        },
-        immediate: true
       }
     },
     computed: {
@@ -205,14 +245,23 @@
           this.localDetails[0].statisticsType == 1 &&
           this.localDetails[0].statisticsValue[0]
         ) {
-          return this.localDetails[0].statisticsValue[0].map((item, index) => {
-            return {
-              label: item.title,
-              slot: `column_${index}`,
-              align: 'center',
-              minWidth: 200
-            };
+          const cList = this.localDetails[0].statisticsValue[0].map(
+            (item, index) => {
+              return {
+                label: item.title,
+                slot: `column_${index}`,
+                align: 'center',
+                minWidth: 200
+              };
+            }
+          );
+          cList.unshift({
+            width: 50,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center'
           });
+          return cList;
         } else {
           return [];
         }
@@ -222,16 +271,26 @@
         if (
           this.localDetails.length > 1 &&
           this.localDetails[1].statisticsValue &&
-          this.localDetails[1].statisticsType == 2
+          this.localDetails[1].statisticsType == 2 &&
+          this.localDetails[1].statisticsValue[0]
         ) {
-          return this.localDetails[1].statisticsValue[0].map((item, index) => {
-            return {
-              label: item.title,
-              slot: `column_${index}`,
-              align: 'center',
-              minWidth: 200
-            };
+          const cList = this.localDetails[1].statisticsValue[0].map(
+            (item, index) => {
+              return {
+                label: item.title,
+                slot: `column_${index}`,
+                align: 'center',
+                minWidth: 200
+              };
+            }
+          );
+          cList.unshift({
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center'
           });
+          return cList;
         } else {
           return [];
         }
@@ -241,24 +300,77 @@
         if (
           this.localDetails.length > 2 &&
           this.localDetails[2].statisticsValue &&
-          this.localDetails[2].statisticsType == 3
+          this.localDetails[2].statisticsType == 3 &&
+          this.localDetails[2].statisticsValue[0]
         ) {
-          return this.localDetails[2].statisticsValue[0].map((item, index) => {
-            return {
-              label: item.title,
-              slot: `column_${index}`,
-              align: 'center',
-              minWidth: 200
-            };
+          const cList = this.localDetails[2].statisticsValue[0].map(
+            (item, index) => {
+              return {
+                label: item.title,
+                slot: `column_${index}`,
+                align: 'center',
+                minWidth: 200
+              };
+            }
+          );
+          cList.unshift({
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center'
           });
+          return cList;
         } else {
           return [];
         }
+      },
+      // 工序名称列表
+      productTaskNameList() {
+        if (this.localDetails[2]?.statisticsValue) {
+          const list = this.localDetails[2].statisticsValue.map((rows) => {
+            return rows.find((i) => i.title === '工序名称')?.value || '';
+          });
+
+          list.unshift('全部'); // 全部选项
+          return list;
+        } else {
+          return [];
+        }
+      },
+      typeTwoDataSource() {
+        if (this.activeProductTaskName === '全部') {
+          return this.localDetails[1].statisticsValue;
+        } else {
+          return this.localDetails[1].statisticsValue.filter((rows) => {
+            const nameItem = rows.find((i) => i.title === '物料名称');
+            return (
+              nameItem &&
+              nameItem.produceTaskName === this.activeProductTaskName
+            );
+          });
+        }
       }
     },
     data() {
       return {
-        localDetails: []
+        localDetails: [
+          {
+            ruleId: this.ruleId,
+            statisticsType: 1,
+            statisticsValue: []
+          },
+          {
+            ruleId: this.ruleId,
+            statisticsType: 2,
+            statisticsValue: []
+          },
+          {
+            ruleId: this.ruleId,
+            statisticsType: 3,
+            statisticsValue: []
+          }
+        ],
+        activeProductTaskName: '全部'
       };
     },
 
@@ -271,37 +383,22 @@
       // 构建统计数据
       async buildDetials(detials) {
         if (detials.length === 0) {
-          this.localDetails = [];
           return;
         }
-        // 已构建过统计数据
+        console.log('this.localDetails', this.localDetails);
+
         if (
-          detials[0].statisticsValue &&
-          detials[0].statisticsValue.length > 0
+          (this.localDetails[0].statisticsValue &&
+            this.localDetails[0].statisticsValue.length == 0) ||
+          this.localDetails[0].ruleId != this.ruleId
         ) {
-          return (this.localDetails = JSON.parse(JSON.stringify(detials)));
-        }
-        // 构建统计数据
-        const list = JSON.parse(JSON.stringify(detials));
-
-        // 并发请求工序任务列表与物料数据
-        const [routingTaskList, pickAndFeed] = await Promise.all([
-          getAllRoutingTaskList({ routingId: this.routingId }),
-          getPickAndFeed({
-            workOrderId: this.workOrderId,
-            produceTaskId: this.produceTaskId
-          })
-        ]);
-
-        console.log('routingTaskList 工序数据', routingTaskList);
-        console.log('物料数据 pickAndFeed', pickAndFeed);
-
-        this.localDetails = [
-          {
+          // 已构建过统计数据
+          this.localDetails[0] = {
+            ...this.localDetails[0],
             ruleId: this.ruleId,
             statisticsType: 1,
             statisticsValue: [
-              list
+              this.rulesDetailList
                 .filter((i) => i.statisticsType == 1)
                 .map((i) => {
                   return {
@@ -312,87 +409,115 @@
                   };
                 })
             ]
-          },
-          // 物料统计
-          {
-            ruleId: this.ruleId,
-            statisticsType: 2,
-            statisticsValue: pickAndFeed.map((pick) => {
-              const data = list
-                .filter((i) => i.statisticsType == 2)
-                .map((i) => {
-                  return {
-                    title: i.paramValue,
-                    value: i.defaultValue,
-                    formula: i.formula,
-                    unit: i.unitName
-                  };
-                });
+          };
+        }
+        // 构建物料和工序数据
+        this.rebuildMaterialAndProcessData();
+      },
+      // 构建物料和工序数据
+      async rebuildMaterialAndProcessData() {
+        let routingTaskList = [];
+        let pickAndFeed = [];
 
-              data.unshift({
-                title: '领用量',
-                value: pick.pickQuantity,
-                formula: '',
-                unit: pick.pickUnit
-              });
+        if (this.workOrderId) {
+          // 并发获取工序任务列表和物料数据
+          let [routingTaskObj, pickAndFeedList] = await Promise.all([
+            getAllRoutingTaskList({ routingId: this.routingId }),
+            getPickAndFeed({
+              workOrderId: this.workOrderId,
+              bomCategoryId: this.bomCategoryId
+            })
+          ]);
+          pickAndFeed = pickAndFeedList || [];
+          routingTaskList = routingTaskObj?.list || [];
+        }
 
-              data.unshift({
-                title: '使用量',
-                value: pick.feedQuantity,
-                formula: '',
-                unit: pick.feedUnit
-              });
+        console.log('routingTaskList 工序数据', routingTaskList);
+        console.log('物料数据 pickAndFeed', pickAndFeed);
 
-              data.unshift({
-                title: '物料编码',
-                value: pick.categoryCode,
-                formula: '',
-                unit: '',
-                // 仅展示不计算和输入
-                isOnlyShow: true
+        this.localDetails[1] = {
+          ...this.localDetails[1],
+          ruleId: this.ruleId,
+          statisticsType: 2,
+          statisticsValue: pickAndFeed.map((pick) => {
+            const data = this.rulesDetailList
+              .filter((i) => i.statisticsType == 2)
+              .map((i) => {
+                return {
+                  title: i.paramValue,
+                  value: i.defaultValue,
+                  formula: i.formula,
+                  unit: i.unitName
+                };
               });
 
-              data.unshift({
-                title: '物料名称',
-                value: pick.categoryName,
-                formula: '',
-                unit: '',
-                // 仅展示不计算和输入
-                isOnlyShow: true
-              });
+            data.unshift({
+              title: '领用量',
+              value: pick.pickQuantity,
+              formula: '',
+              unit: pick.pickUnit
+            });
 
-              return data;
-            })
-          },
-          // 工序统计
-          {
-            ruleId: this.ruleId,
-            statisticsType: 3,
-            statisticsValue: routingTaskList.list.map((task) => {
-              const data = list
-                .filter((i) => i.statisticsType == 3)
-                .map((i) => {
-                  return {
-                    title: i.paramValue,
-                    value: i.defaultValue,
-                    formula: i.formula,
-                    unit: i.unitName
-                  };
-                });
-
-              data.unshift({
-                title: '工序名称',
-                value: task.taskInstanceName,
-                formula: '',
-                unit: '',
-                // 仅展示不计算和输入
-                isOnlyShow: true
+            data.unshift({
+              title: '使用量',
+              value: pick.feedQuantity,
+              formula: '',
+              unit: pick.feedUnit
+            });
+
+            data.unshift({
+              title: '物料编码',
+              value: pick.categoryCode,
+              formula: '',
+              unit: '',
+              // 仅展示不计算和输入
+              isOnlyShow: true
+            });
+
+            data.unshift({
+              title: '物料名称',
+              value: pick.categoryName,
+              formula: '',
+              unit: '',
+              // 仅展示不计算和输入
+              isOnlyShow: true,
+              // produceTaskName 工序名称
+              produceTaskName: pick.produceTaskName
+            });
+
+            return data;
+          })
+        };
+
+        this.localDetails[2] = {
+          ...this.localDetails[2],
+          ruleId: this.ruleId,
+          statisticsType: 3,
+          statisticsValue: routingTaskList.map((task) => {
+            const data = this.rulesDetailList
+              .filter((i) => i.statisticsType == 3)
+              .map((i) => {
+                return {
+                  title: i.paramValue,
+                  value: i.defaultValue,
+                  formula: i.formula,
+                  unit: i.unitName
+                };
               });
 
-              return data;
-            })
-          }
-        ];
+            data.unshift({
+              title: '工序名称',
+              value: task.taskInstanceName,
+              formula: '',
+              unit: '',
+              // 仅展示不计算和输入
+              isOnlyShow: true
+            });
+
+            return data;
+          })
+        };
+
         console.log('this.localDetails', this.localDetails);
 
         // 通知父组件数据变更
@@ -475,6 +600,8 @@
       },
       // 验证所有行/列(排除仅展示项),收集缺失项并提示;返回布尔值
       validateStatisticsFilled() {
+        return true; // 暂时不验证
+
         if (
           !Array.isArray(this.localDetails) ||
           this.localDetails.length === 0
@@ -537,6 +664,50 @@
           return false;
         }
         return true;
+      },
+      getSummaries() {
+        const sums = [];
+        if (this.localDetails[0].statisticsValue.length == 0) {
+          return sums;
+        }
+        sums.push('合计');
+        this.localDetails[0].statisticsValue.forEach((itemList, index) => {
+          itemList.forEach((item, colIndex) => {
+            if (item.isOnlyShow) {
+              sums[colIndex + 1] = '';
+            } else {
+              if (sums[colIndex + 1]) {
+                if (isNaN(Number(item.value))) {
+                  sums[colIndex + 1] += 0;
+                } else {
+                  sums[colIndex + 1] += Number(item.value) || 0;
+                }
+              } else {
+                if (isNaN(Number(item.value))) {
+                  sums[colIndex + 1] = 0;
+                } else {
+                  sums[colIndex + 1] = Number(item.value) || 0;
+                }
+              }
+            }
+          });
+        });
+        console.log('sums', sums);
+        return sums;
+      },
+      // 添加行
+      addRow() {
+        const row = JSON.parse(
+          JSON.stringify(this.localDetails[0].statisticsValue[0])
+        );
+
+        row.forEach((item) => {
+          if (!item.isOnlyShow) {
+            item.value = '';
+          }
+        });
+
+        this.localDetails[0].statisticsValue.push(row);
       }
     }
   };