feat(报表): 添加分条线统计组件并扩展合同字段

添加分条线专用的统计组件SplitSummary,用于展示分条处理的产出与消耗对比数据
在多个报表模板中集成该组件并添加钢卷高亮功能
扩展CrmOrder相关类的合同信息字段
This commit is contained in:
砂糖
2026-04-13 16:23:40 +08:00
parent 5ee730bffa
commit 37dc213605
11 changed files with 582 additions and 16 deletions

View File

@@ -85,6 +85,111 @@ public class CrmOrder extends BaseEntity {
*/
private String contractCode;
/**
* 合同名称
*/
private String contractName;
/**
* 供方
*/
private String supplier;
/**
* 需方
*/
private String customer;
/**
* 签订时间
*/
private Date signTime;
/**
* 签订地点
*/
private String signLocation;
/**
* 产品内容
*/
private String productContent;
/**
* 合同内容
*/
private String contractContent;
/**
* 供方地址
*/
private String supplierAddress;
/**
* 供方电话
*/
private String supplierPhone;
/**
* 供方开户行
*/
private String supplierBank;
/**
* 供方账号
*/
private String supplierAccount;
/**
* 供方税号
*/
private String supplierTaxNo;
/**
* 需方地址
*/
private String customerAddress;
/**
* 需方电话
*/
private String customerPhone;
/**
* 需方开户行
*/
private String customerBank;
/**
* 需方账号
*/
private String customerAccount;
/**
* 需方税号
*/
private String customerTaxNo;
/**
* 技术附件
*/
private String techAnnex;
/**
* 商务附件
*/
private String businessAnnex;
/**
* 排产函
*/
private String productionSchedule;
/**
* 合同状态 0=草稿 1=生效 2=作废 3=已完成
*/
private Long status;
/**
* 关联合同IDwms_contract.contract_id
*/

View File

@@ -95,6 +95,111 @@ public class CrmOrderBo extends BaseEntity {
*/
private String contractCode;
/**
* 合同名称
*/
private String contractName;
/**
* 供方
*/
private String supplier;
/**
* 需方
*/
private String customer;
/**
* 签订时间
*/
private Date signTime;
/**
* 签订地点
*/
private String signLocation;
/**
* 产品内容
*/
private String productContent;
/**
* 合同内容
*/
private String contractContent;
/**
* 供方地址
*/
private String supplierAddress;
/**
* 供方电话
*/
private String supplierPhone;
/**
* 供方开户行
*/
private String supplierBank;
/**
* 供方账号
*/
private String supplierAccount;
/**
* 供方税号
*/
private String supplierTaxNo;
/**
* 需方地址
*/
private String customerAddress;
/**
* 需方电话
*/
private String customerPhone;
/**
* 需方开户行
*/
private String customerBank;
/**
* 需方账号
*/
private String customerAccount;
/**
* 需方税号
*/
private String customerTaxNo;
/**
* 技术附件
*/
private String techAnnex;
/**
* 商务附件
*/
private String businessAnnex;
/**
* 排产函
*/
private String productionSchedule;
/**
* 合同状态 0=草稿 1=生效 2=作废 3=已完成
*/
private Long status;
/**
* 关联合同IDwms_contract.contract_id
*/

View File

@@ -114,6 +114,132 @@ public class CrmOrderVo extends BaseEntity {
@ExcelProperty(value = "合同号")
private String contractCode;
/**
* 合同名称
*/
@ExcelProperty(value = "合同名称")
private String contractName;
/**
* 供方
*/
@ExcelProperty(value = "供方")
private String supplier;
/**
* 需方
*/
@ExcelProperty(value = "需方")
private String customer;
/**
* 签订时间
*/
@ExcelProperty(value = "签订时间")
private Date signTime;
/**
* 签订地点
*/
@ExcelProperty(value = "签订地点")
private String signLocation;
/**
* 产品内容
*/
@ExcelProperty(value = "产品内容")
private String productContent;
/**
* 合同内容
*/
@ExcelProperty(value = "合同内容")
private String contractContent;
/**
* 供方地址
*/
@ExcelProperty(value = "供方地址")
private String supplierAddress;
/**
* 供方电话
*/
@ExcelProperty(value = "供方电话")
private String supplierPhone;
/**
* 供方开户行
*/
@ExcelProperty(value = "供方开户行")
private String supplierBank;
/**
* 供方账号
*/
@ExcelProperty(value = "供方账号")
private String supplierAccount;
/**
* 供方税号
*/
@ExcelProperty(value = "供方税号")
private String supplierTaxNo;
/**
* 需方地址
*/
@ExcelProperty(value = "需方地址")
private String customerAddress;
/**
* 需方电话
*/
@ExcelProperty(value = "需方电话")
private String customerPhone;
/**
* 需方开户行
*/
@ExcelProperty(value = "需方开户行")
private String customerBank;
/**
* 需方账号
*/
@ExcelProperty(value = "需方账号")
private String customerAccount;
/**
* 需方税号
*/
@ExcelProperty(value = "需方税号")
private String customerTaxNo;
/**
* 技术附件
*/
@ExcelProperty(value = "技术附件")
private String techAnnex;
/**
* 商务附件
*/
@ExcelProperty(value = "商务附件")
private String businessAnnex;
/**
* 排产函
*/
@ExcelProperty(value = "排产函")
private String productionSchedule;
/**
* 合同状态 0=草稿 1=生效 2=作废 3=已完成
*/
@ExcelProperty(value = "合同状态")
private Long status;
/**
* 关联合同IDwms_contract.contract_id
*/

View File

@@ -0,0 +1,5 @@
<template>
<div>
镀锌子系统
</div>
</template>

View File

@@ -0,0 +1,53 @@
<template>
<el-descriptions title="已处理重复分条统计信息" :column="3" border>
<el-descriptions-item label="产出数量">{{ splitSummary.outCount }}</el-descriptions-item>
<el-descriptions-item label="产出总重">{{ splitSummary.outTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="产出均重">{{ splitSummary.outAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗数量">{{ splitSummary.lossCount }}</el-descriptions-item>
<el-descriptions-item label="消耗总重">{{ splitSummary.lossTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗均重">{{ splitSummary.lossAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="数量差值">{{ splitSummary.countDiff }}</el-descriptions-item>
<el-descriptions-item label="总重差值">{{ splitSummary.weightDiff }}t</el-descriptions-item>
<el-descriptions-item label="均重差值">{{ splitSummary.avgWeightDiff }}t</el-descriptions-item>
<!-- 成品率 -->
<el-descriptions-item label="成品率">{{ splitSummary.passRate }}</el-descriptions-item>
<el-descriptions-item label="损耗率">{{ splitSummary.lossRate }}</el-descriptions-item>
<!-- 异常率 -->
<el-descriptions-item label="异常率">{{ splitSummary.abRate }}</el-descriptions-item>
<!-- 正品率 -->
<el-descriptions-item label="正品率">{{ splitSummary.passRate2 }}</el-descriptions-item>
</el-descriptions>
</template>
<script>
import { calcSplitSummary } from "@/views/wms/report/js/calc";
export default {
name: 'SplitSummary',
props: {
originOutputlist: {
type: Array,
default: () => []
},
originLossList: {
type: Array,
default: () => []
},
commonCoilIds: {
type: Array,
default: () => []
}
},
computed: {
splitSummary() {
return calcSplitSummary(this.originOutputlist, this.originLossList, this.commonCoilIds)
}
}
}
</script>
<style scoped>
</style>

View File

@@ -229,9 +229,76 @@ const calcMSummary = (list, lossList) => {
}
}
// 处理分条信息的统计信息
const calcSplitSummary = (originOutputlist, originLossList, commonCoilIds) => {
// 1. 将commonCoilIds中的coilId的卷从originOutputlist和originLossList中剔除
const list = originOutputlist.filter(item => !commonCoilIds.includes(item.coilId))
const lossList = originLossList.filter(item => !commonCoilIds.includes(item.coilId))
// 总钢卷数量、总重、均重
const outCount = list.length
const outTotalWeight = list.reduce((acc, cur) => acc + (parseFloat(cur.netWeight) || 0), 0) // 增加容错
const outAvgWeight = outCount > 0 ? (outTotalWeight / outCount)?.toFixed(2) : 0
// 损失钢卷数量、总重、均重
const lossCount = lossList.length
const lossTotalWeight = lossList.reduce((acc, cur) => acc + (parseFloat(cur.netWeight) || 0), 0) // 增加容错
const lossAvgWeight = lossCount > 0 ? (lossTotalWeight / lossCount)?.toFixed(2) : 0
// 合计数量、总重、均重
const totalCount = outCount + lossCount
const totalWeight = parseFloat((outTotalWeight + lossTotalWeight).toFixed(2))
const totalAvgWeight = totalCount > 0 ? (totalWeight / totalCount)?.toFixed(2) : 0
// 计算数量、总重、均重的插值
const countDiff = Math.abs(outCount - lossCount)
const weightDiff = Math.abs(parseFloat((outTotalWeight - lossTotalWeight).toFixed(2)))
const avgWeightDiff = Math.abs(parseFloat((outAvgWeight - lossAvgWeight).toFixed(2)))
// 成品比率
const passRate = outCount > 0 && lossTotalWeight > 0 ? (outTotalWeight / lossTotalWeight) : 0
// 损失比率
const lossRate = totalCount > 0 ? (1 - passRate) : 0
// 异常率,成品在warehouseId在'2019583656787259393',
// '2019583325311414274',
// '2019583429955104769',
// '2019583137616310273',这四个库中的占比
const abStatus = ['O', 'C-', 'C+', 'C', 'D-', 'D+', 'D']
const abRate = totalCount != 0 ? list.filter(item => {
// 质量状态为O, C- , C+, C, D-, D+, D的钢卷也属于异常
return (item.warehouseId == '2019583656787259393'
|| item.warehouseId == '2019583325311414274'
|| item.warehouseId == '2019583429955104769'
|| item.warehouseId == '2019583137616310273'
|| abStatus.includes(item.qualityStatus)
)
}).length / outCount : 0
// 正品率1-异常率)
const passRate2 = totalCount != 0 ? (1 - abRate) : 0
return {
outCount,
outTotalWeight: outTotalWeight.toFixed(2),
outAvgWeight,
lossCount,
lossTotalWeight: lossTotalWeight.toFixed(2),
lossAvgWeight,
totalCount,
totalWeight: totalWeight.toFixed(2),
totalAvgWeight,
countDiff,
weightDiff,
avgWeightDiff,
passRate: (passRate * 100)?.toFixed(2) + '%',
lossRate: (lossRate * 100)?.toFixed(2) + '%',
abRate: (abRate * 100)?.toFixed(2) + '%' || 0,
passRate2: (passRate2 * 100)?.toFixed(2) + '%' || 0,
}
}
export {
calcSummary,
calcAbSummary,
calcTeamSummary,
calcMSummary,
calcSplitSummary
}

View File

@@ -100,14 +100,17 @@
}}</el-descriptions-item>
</el-descriptions>
<!-- 分条信息统计 -->
<split-summary :origin-outputlist="list" :origin-loss-list="lossList" :common-coil-ids="commonCoilIds"></split-summary>
<el-descriptions title="明细信息" :column="3" border>
</el-descriptions>
<el-tabs v-model="activeTab">
<el-tab-pane label="产出钢卷" name="output">
<coil-table :columns="outputColumns" :data="list"></coil-table>
<coil-table :columns="outputColumns" :data="list" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
<el-tab-pane label="投入钢卷" name="loss">
<coil-table :columns="lossColumns" :data="lossList"></coil-table>
<coil-table :columns="lossColumns" :data="lossList" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
</el-tabs>
@@ -135,6 +138,7 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { calcSummary, calcAbSummary, calcMSummary } from "@/views/wms/report/js/calc";
import ColumnsSetting from "@/views/wms/report/components/setting/columns.vue";
import CoilTable from "@/views/wms/report/components/coilTable/index.vue";
import SplitSummary from "@/views/wms/report/components/summary/splitSummary.vue";
import { saveReportFile } from "@/views/wms/report/js/reportFile";
export default {
@@ -148,6 +152,7 @@ export default {
WarehouseSelect,
ColumnsSetting,
CoilTable,
SplitSummary,
},
props: {
actionTypes: {
@@ -279,7 +284,28 @@ export default {
},
mSummary() {
return calcMSummary(this.list, this.lossList)
}
},
// 找出list和lossList中id相同的卷
commonCoilIds() {
if (this.productionLine !== '分条线') {
return []
}
// 获取list中的coilId集合
const outputCoilIds = new Set(this.list.map(item => item.coilId))
// 获取lossList中的coilId集合
const lossCoilIds = new Set(this.lossList.map(item => item.coilId))
// 找出两个集合中相同的coilId
const commonIds = []
outputCoilIds.forEach(id => {
if (lossCoilIds.has(id)) {
commonIds.push(id)
}
})
return commonIds
},
},
methods: {
// 加载列设置

View File

@@ -97,6 +97,9 @@
}}</el-descriptions-item>
</el-descriptions>
<!-- 分条信息统计 -->
<split-summary :origin-outputlist="list" :origin-loss-list="lossList" :common-coil-ids="commonCoilIds"></split-summary>
<el-descriptions title="明细信息" :column="3" border>
</el-descriptions>
<el-tabs v-model="activeTab">
@@ -128,6 +131,7 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { calcSummary, calcAbSummary, calcMSummary } from "@/views/wms/report/js/calc";
import ColumnsSetting from "@/views/wms/report/components/setting/columns.vue";
import CoilTable from "@/views/wms/report/components/coilTable/index.vue";
import SplitSummary from "@/views/wms/report/components/summary/splitSummary.vue";
import { fetchLossList, fetchOutputList } from "@/views/wms/report/js/fetch";
import { saveReportFile } from "@/views/wms/report/js/reportFile";
@@ -143,6 +147,7 @@ export default {
WarehouseSelect,
ColumnsSetting,
CoilTable,
SplitSummary,
},
props: {
actionTypes: {

View File

@@ -97,14 +97,17 @@
}}</el-descriptions-item>
</el-descriptions>
<!-- 分条信息统计 -->
<split-summary :origin-outputlist="list" :origin-loss-list="lossList" :common-coil-ids="commonCoilIds"></split-summary>
<el-descriptions title="明细信息" :column="3" border>
</el-descriptions>
<el-tabs v-model="activeTab">
<el-tab-pane label="产出钢卷" name="output">
<coil-table :columns="outputColumns" :data="list"></coil-table>
<coil-table :columns="outputColumns" :data="list" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
<el-tab-pane label="投入钢卷" name="loss">
<coil-table :columns="lossColumns" :data="lossList"></coil-table>
<coil-table :columns="lossColumns" :data="lossList" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
</el-tabs>
@@ -132,6 +135,7 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { calcSummary, calcAbSummary, calcMSummary } from "@/views/wms/report/js/calc";
import ColumnsSetting from "@/views/wms/report/components/setting/columns.vue";
import CoilTable from "@/views/wms/report/components/coilTable/index.vue";
import SplitSummary from "@/views/wms/report/components/summary/splitSummary.vue";
import { fetchLossList, fetchOutputList } from "@/views/wms/report/js/fetch";
import { saveReportFile } from "@/views/wms/report/js/reportFile";
@@ -146,6 +150,7 @@ export default {
WarehouseSelect,
ColumnsSetting,
CoilTable,
SplitSummary,
},
props: {
actionTypes: {
@@ -276,7 +281,28 @@ export default {
},
mSummary() {
return calcMSummary(this.list, this.lossList)
}
},
// 找出list和lossList中id相同的卷
commonCoilIds() {
if (this.productionLine !== '分条线') {
return []
}
// 获取list中的coilId集合
const outputCoilIds = new Set(this.list.map(item => item.coilId))
// 获取lossList中的coilId集合
const lossCoilIds = new Set(this.lossList.map(item => item.coilId))
// 找出两个集合中相同的coilId
const commonIds = []
outputCoilIds.forEach(id => {
if (lossCoilIds.has(id)) {
commonIds.push(id)
}
})
return commonIds
},
},
methods: {
// 加载列设置

View File

@@ -106,6 +106,9 @@
}}</el-descriptions-item>
</el-descriptions>
<!-- 分条信息统计 -->
<split-summary :origin-outputlist="list" :origin-loss-list="lossList" :common-coil-ids="commonCoilIds"></split-summary>
<el-descriptions title="班组统计信息" :column="3" border>
</el-descriptions>
<el-table :data="teamSummary" border>
@@ -118,10 +121,10 @@
</el-descriptions>
<el-tabs v-model="activeTab">
<el-tab-pane label="产出钢卷" name="output">
<coil-table :columns="outputColumns" :data="list"></coil-table>
<coil-table :columns="outputColumns" :data="list" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
<el-tab-pane label="投入钢卷" name="loss">
<coil-table :columns="lossColumns" :data="lossList"></coil-table>
<coil-table :columns="lossColumns" :data="lossList" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
</el-tabs>
@@ -145,6 +148,7 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { calcSummary, calcAbSummary, calcTeamSummary, calcMSummary } from "@/views/wms/report/js/calc";
import ColumnsSetting from "@/views/wms/report/components/setting/columns.vue";
import CoilTable from "@/views/wms/report/components/coilTable/index.vue";
import SplitSummary from "@/views/wms/report/components/summary/splitSummary.vue";
import { fetchLossList, fetchOutputList } from "@/views/wms/report/js/fetch";
import { saveReportFile } from "@/views/wms/report/js/reportFile";
@@ -159,6 +163,7 @@ export default {
WarehouseSelect,
ColumnsSetting,
CoilTable,
SplitSummary,
},
props: {
actionTypes: {
@@ -273,7 +278,28 @@ export default {
outWeight: formatWeight(outData.weight)
};
});
}
},
// 找出list和lossList中id相同的卷
commonCoilIds() {
if (this.productionLine !== '分条线') {
return [];
}
// 获取list中的coilId集合
const outputCoilIds = new Set(this.list.map(item => item.coilId));
// 获取lossList中的coilId集合
const lossCoilIds = new Set(this.lossList.map(item => item.coilId));
// 找出两个集合中相同的coilId
const commonIds = [];
outputCoilIds.forEach(id => {
if (lossCoilIds.has(id)) {
commonIds.push(id);
}
});
return commonIds;
},
},
methods: {
// 加载列设置

View File

@@ -96,14 +96,17 @@
}}</el-descriptions-item>
</el-descriptions>
<!-- 分条信息统计 -->
<split-summary :origin-outputlist="list" :origin-loss-list="lossList" :common-coil-ids="commonCoilIds"></split-summary>
<el-descriptions title="明细信息" :column="3" border>
</el-descriptions>
<el-tabs v-model="activeTab">
<el-tab-pane label="产出钢卷" name="output">
<coil-table :columns="outputColumns" :data="list"></coil-table>
<coil-table :columns="outputColumns" :data="list" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
<el-tab-pane label="投入钢卷" name="loss">
<coil-table :columns="lossColumns" :data="lossList"></coil-table>
<coil-table :columns="lossColumns" :data="lossList" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
</el-tabs>
@@ -118,10 +121,6 @@
</template>
<script>
import { listCoilWithIds } from "@/api/wms/coil";
import {
listPendingAction,
} from '@/api/wms/pendingAction';
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
import CoilNo from "@/components/KLPService/Renderer/CoilNo.vue";
@@ -131,6 +130,7 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { calcSummary, calcAbSummary, calcMSummary } from "@/views/wms/report/js/calc";
import ColumnsSetting from "@/views/wms/report/components/setting/columns.vue";
import CoilTable from "@/views/wms/report/components/coilTable/index.vue";
import SplitSummary from "@/views/wms/report/components/summary/splitSummary.vue";
import { fetchLossList, fetchOutputList } from "@/views/wms/report/js/fetch";
import { saveReportFile } from "@/views/wms/report/js/reportFile";
@@ -145,6 +145,7 @@ export default {
WarehouseSelect,
ColumnsSetting,
CoilTable,
SplitSummary,
},
props: {
actionTypes: {
@@ -254,7 +255,28 @@ export default {
},
mSummary() {
return calcMSummary(this.list, this.lossList)
}
},
// 找出list和lossList中id相同的卷
commonCoilIds() {
if (this.productionLine !== '分条线') {
return []
}
// 获取list中的coilId集合
const outputCoilIds = new Set(this.list.map(item => item.coilId))
// 获取lossList中的coilId集合
const lossCoilIds = new Set(this.lossList.map(item => item.coilId))
// 找出两个集合中相同的coilId
const commonIds = []
outputCoilIds.forEach(id => {
if (lossCoilIds.has(id)) {
commonIds.push(id)
}
})
return commonIds
},
},
methods: {
// 加载列设置