|
|
@@ -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>
|