From 32455daf42c0a274d14274f682417510c5003d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E6=98=8A?= <15984991+wwh2328692301@user.noreply.gitee.com> Date: Sat, 4 Jul 2026 10:54:41 +0800 Subject: [PATCH 01/15] =?UTF-8?q?refactor(wms):=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E9=92=A2=E5=8D=B7=E8=B4=A8=E9=87=8F=E7=8A=B6=E6=80=81=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E9=80=BB=E8=BE=91=EF=BC=8C=E9=9B=86=E4=B8=AD=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=94=B9=E5=88=A4=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增统一的updateQualityStatus方法,封装钢卷质量状态更新和改判日志记录逻辑 2. 替换mes模块中直接更新钢卷状态和插入改判日志的代码,改用统一服务方法 3. 移除冗余的改判日志Mapper注入和手动插入代码 --- .../impl/QcQualityReviewServiceImpl.java | 23 ++++--------- .../klp/service/IWmsMaterialCoilService.java | 10 ++++++ .../impl/WmsMaterialCoilServiceImpl.java | 34 +++++++++++++++++++ 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java b/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java index edcc61ea0..e0cb81783 100644 --- a/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java +++ b/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java @@ -9,10 +9,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.klp.common.core.domain.PageQuery; import com.klp.common.core.page.TableDataInfo; import com.klp.common.utils.StringUtils; -import com.klp.domain.WmsCoilQualityRejudge; import com.klp.domain.WmsMaterialCoil; -import com.klp.mapper.WmsCoilQualityRejudgeMapper; import com.klp.mapper.WmsMaterialCoilMapper; +import com.klp.service.IWmsMaterialCoilService; import com.klp.mes.qc.domain.QcQualityReview; import com.klp.mes.qc.domain.QcQualityReviewCoil; import com.klp.mes.qc.domain.QcQualityReviewLog; @@ -49,7 +48,7 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { private final QcQualityReviewCoilMapper coilMapper; private final QcQualityReviewLogMapper logMapper; private final WmsMaterialCoilMapper wmsMaterialCoilMapper; - private final WmsCoilQualityRejudgeMapper wmsCoilQualityRejudgeMapper; + private final IWmsMaterialCoilService wmsMaterialCoilService; /** * 查询评审单详情(含钢卷明细和审批日志) @@ -289,23 +288,15 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { } Date now = new Date(); + String reason = "异常产品评审改判,评审单号:" + review.getReviewNo(); for (QcQualityReviewCoil coil : coilList) { - // 1. 写入 wms_coil_quality_rejudge 改判记录 - WmsCoilQualityRejudge rejudge = new WmsCoilQualityRejudge(); - rejudge.setCoilId(coil.getCoilId()); - rejudge.setBeforeQuality(coil.getBeforeQuality()); - rejudge.setAfterQuality(coil.getRegradeQuality()); - rejudge.setRejudgeReason("异常产品评审改判,评审单号:" + review.getReviewNo()); - wmsCoilQualityRejudgeMapper.insert(rejudge); - - // 2. 更新钢卷的 qualityStatus 为改判后的值 + // 1. 通过统一方法更新钢卷质量状态 + 自动记录改判日志 if (coil.getCoilId() != null && StringUtils.isNotBlank(coil.getRegradeQuality())) { - wmsMaterialCoilMapper.update(null, Wrappers.lambdaUpdate() - .eq(WmsMaterialCoil::getCoilId, coil.getCoilId()) - .set(WmsMaterialCoil::getQualityStatus, coil.getRegradeQuality())); + wmsMaterialCoilService.updateQualityStatus( + coil.getCoilId(), coil.getRegradeQuality(), reason); } - // 3. 更新明细执行状态 + // 2. 更新明细执行状态 coilMapper.update(null, Wrappers.lambdaUpdate() .eq(QcQualityReviewCoil::getDetailId, coil.getDetailId()) .set(QcQualityReviewCoil::getExecuteStatus, 1L) diff --git a/klp-wms/src/main/java/com/klp/service/IWmsMaterialCoilService.java b/klp-wms/src/main/java/com/klp/service/IWmsMaterialCoilService.java index 0f3d8d9f7..d801dd314 100644 --- a/klp-wms/src/main/java/com/klp/service/IWmsMaterialCoilService.java +++ b/klp-wms/src/main/java/com/klp/service/IWmsMaterialCoilService.java @@ -194,6 +194,16 @@ public interface IWmsMaterialCoilService { */ String queryQualityStatusByWarehouseIdAndCurrentCoilNo(Long warehouseId, String currentCoilNo); + /** + * 统一更新钢卷质量状态(自动记录改判日志) + * 所有修改 quality_status 的地方都应当通过此方法,确保改判记录完整可追溯 + * + * @param coilId 钢卷ID + * @param newQuality 新质量状态 + * @param reason 变更原因 + */ + void updateQualityStatus(Long coilId, String newQuality, String reason); + int exportCoil(@NotEmpty(message = "主键不能为空") Long coilId); diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java index 20041efe5..3c80b55df 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java @@ -1823,6 +1823,40 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService { return qw; } + @Override + @Transactional(rollbackFor = Exception.class) + public void updateQualityStatus(Long coilId, String newQuality, String reason) { + if (coilId == null || StringUtils.isBlank(newQuality)) { + log.warn("updateQualityStatus 参数不足: coilId={}, newQuality={}", coilId, newQuality); + return; + } + // 查询当前钢卷 + WmsMaterialCoil coil = baseMapper.selectById(coilId); + if (coil == null) { + throw new RuntimeException("钢卷不存在:" + coilId); + } + String oldQuality = coil.getQualityStatus(); + // 状态没变,不处理 + if (StringUtils.equals(oldQuality, newQuality)) { + log.info("钢卷质量状态未变化,跳过: coilId={}, quality={}", coilId, oldQuality); + return; + } + // 1. 更新钢卷质量状态 + baseMapper.update(null, Wrappers.lambdaUpdate() + .eq(WmsMaterialCoil::getCoilId, coilId) + .set(WmsMaterialCoil::getQualityStatus, newQuality)); + + // 2. 记录改判记录 + WmsCoilQualityRejudge rejudge = new WmsCoilQualityRejudge(); + rejudge.setCoilId(coilId); + rejudge.setBeforeQuality(oldQuality); + rejudge.setAfterQuality(newQuality); + rejudge.setRejudgeReason(reason); + wmsCoilQualityRejudgeMapper.insert(rejudge); + + log.info("钢卷质量状态变更: coilId={}, {} -> {}, 原因: {}", coilId, oldQuality, newQuality, reason); + } + @Override public String queryQualityStatusByWarehouseIdAndCurrentCoilNo(Long warehouseId, String currentCoilNo) { if (warehouseId == null || StringUtils.isBlank(currentCoilNo)) { From d5d77c53b620bdba34cb2a636d7d8a006788d768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E6=98=8A?= <15984991+wwh2328692301@user.noreply.gitee.com> Date: Sat, 4 Jul 2026 11:23:13 +0800 Subject: [PATCH 02/15] =?UTF-8?q?refactor(qc):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E9=A1=B6=E9=83=A8=E5=AE=A1=E6=89=B9=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=8C=89=E9=92=AE=EF=BC=8C=E8=B0=83=E6=95=B4=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 移除待审批状态下页面顶部的审批通过和驳回按钮 2. 重构审批相关的前端方法,删除冗余的handleApprove和handleReject 3. 优化后端审批日志逻辑,自动获取当前登录用户作为操作人 4. 新增评审单修改状态校验,仅草稿和已驳回状态可修改 5. 新增钢卷改判状态完整性校验,确保所有钢卷都已指定改判质量 6. 完善保存前的数据校验,新增产品名称非空校验和默认传审部门 --- .../impl/QcQualityReviewServiceImpl.java | 44 +++++++++++++++---- .../src/views/mes/qc/qualityReview/index.vue | 24 +--------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java b/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java index e0cb81783..bdb9fa99e 100644 --- a/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java +++ b/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.klp.common.core.domain.PageQuery; import com.klp.common.core.page.TableDataInfo; import com.klp.common.utils.StringUtils; +import com.klp.common.helper.LoginHelper; import com.klp.domain.WmsMaterialCoil; import com.klp.mapper.WmsMaterialCoilMapper; import com.klp.service.IWmsMaterialCoilService; @@ -111,11 +112,19 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { } /** - * 修改评审单(仅草稿状态可修改) + * 修改评审单(仅草稿或已驳回状态可修改) */ @Override @Transactional(rollbackFor = Exception.class) public Boolean updateByBo(QcQualityReviewBo bo) { + // 校验:只有待提交或已驳回状态才能修改 + if (bo.getReviewId() != null) { + QcQualityReview exist = baseMapper.selectById(bo.getReviewId()); + if (exist != null && !Long.valueOf(1L).equals(exist.getFlowStatus()) + && !Long.valueOf(4L).equals(exist.getFlowStatus())) { + throw new RuntimeException("只有待提交或已驳回状态的评审单才能修改"); + } + } QcQualityReview update = BeanUtil.toBean(bo, QcQualityReview.class); validEntityBeforeSave(update); boolean flag = baseMapper.updateById(update) > 0; @@ -193,7 +202,7 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { .set(QcQualityReview::getRejectReason, null)); // 记录审批日志 - addLog(reviewId, "submit", "提交送审", null); + addLog(reviewId, "submit", "提交送审"); return true; } @@ -214,6 +223,20 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { throw new RuntimeException("请为每个钢卷指定改判后质量状态"); } + // 校验:coilRegradeList 是否覆盖了评审单中的所有有效钢卷 + List dbCoils = coilMapper.selectList( + Wrappers.lambdaQuery() + .eq(QcQualityReviewCoil::getReviewId, bo.getReviewId()) + .eq(QcQualityReviewCoil::getDelFlag, 0)); + Set regradedIds = bo.getCoilRegradeList().stream() + .map(QcQualityReviewApproveBo.CoilRegradeBo::getDetailId) + .collect(Collectors.toSet()); + for (QcQualityReviewCoil coil : dbCoils) { + if (!regradedIds.contains(coil.getDetailId())) { + throw new RuntimeException("钢卷【" + coil.getCurrentCoilNo() + "】未指定改判后质量状态"); + } + } + // 1. 更新主表流程状态 baseMapper.update(null, Wrappers.lambdaUpdate() .eq(QcQualityReview::getReviewId, bo.getReviewId()) @@ -230,7 +253,7 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { } // 3. 记录审批日志 - addLog(bo.getReviewId(), "approve", bo.getLeaderOpinion(), bo.getLeaderSign()); + addLog(bo.getReviewId(), "approve", bo.getLeaderOpinion()); return true; } @@ -258,7 +281,7 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { .set(QcQualityReview::getRejectReason, reason)); // 记录审批日志 - addLog(reviewId, "reject", reason, null); + addLog(reviewId, "reject", reason); return true; } @@ -355,14 +378,14 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { } /** - * 添加审批日志 + * 添加审批日志(自动记录当前登录用户为操作人) */ - private void addLog(Long reviewId, String action, String opinion, String operator) { + private void addLog(Long reviewId, String action, String opinion) { QcQualityReviewLog log = new QcQualityReviewLog(); log.setReviewId(reviewId); log.setAction(action); log.setOpinion(opinion); - log.setOperator(operator); + log.setOperator(LoginHelper.getUsername()); log.setOperateTime(new Date()); logMapper.insert(log); } @@ -378,6 +401,11 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { } private void validEntityBeforeSave(QcQualityReview entity) { - // TODO 数据校验 + if (StringUtils.isBlank(entity.getProductName())) { + throw new RuntimeException("产品名称不能为空"); + } + if (StringUtils.isBlank(entity.getTransmitDept())) { + entity.setTransmitDept("品质部"); + } } } diff --git a/klp-ui/src/views/mes/qc/qualityReview/index.vue b/klp-ui/src/views/mes/qc/qualityReview/index.vue index 3b84de969..6bae8bcd8 100644 --- a/klp-ui/src/views/mes/qc/qualityReview/index.vue +++ b/klp-ui/src/views/mes/qc/qualityReview/index.vue @@ -69,11 +69,7 @@ 提交送审 - - 审批通过 - 驳回 + 执行改判 @@ -541,20 +537,6 @@ export default { }, // ===== 审批 ===== - handleApprove() { - this.approveAction = 'approve' - this.approveForm = { - reviewId: this.currentRow.reviewId, - leaderOpinion: '', - leaderSign: '' - } - // 先构建完整对象再赋值 - const map = {} - this.coilList.forEach(c => { - map[c.detailId] = c.regradeQuality || '' - }) - this.approveCoilMap = map - }, doApprove() { if (!this.approveForm.leaderOpinion) { this.$modal.msgError('请输入审批意见') @@ -581,10 +563,6 @@ export default { }) }).catch(() => {}) }, - handleReject() { - this.approveAction = 'reject' - this.rejectReason = '' - }, doReject() { if (!this.rejectReason) { this.$modal.msgError('请输入驳回原因') From c922856a0814917b8e429d4f0ab461620ee54287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E6=98=8A?= <15984991+wwh2328692301@user.noreply.gitee.com> Date: Sat, 4 Jul 2026 11:49:04 +0800 Subject: [PATCH 03/15] feat(qc): add auto warehouse update logic for regraded coils MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根据改判后的钢卷质量等级自动将C/D级钢卷移动到技术部逻辑库区 --- .../impl/QcQualityReviewServiceImpl.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java b/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java index bdb9fa99e..1325fc981 100644 --- a/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java +++ b/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java @@ -45,6 +45,9 @@ import java.util.stream.Collectors; @Service public class QcQualityReviewServiceImpl implements IQcQualityReviewService { + /** 技术部逻辑库ID(C/D级改判后移入此库区) */ + private static final Long TECH_WAREHOUSE_ID = 2019583656787259393L; + private final QcQualityReviewMapper baseMapper; private final QcQualityReviewCoilMapper coilMapper; private final QcQualityReviewLogMapper logMapper; @@ -319,7 +322,15 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { coil.getCoilId(), coil.getRegradeQuality(), reason); } - // 2. 更新明细执行状态 + // 2. 根据改判后质量等级自动更新钢卷所在逻辑库区 + Long targetWarehouseId = determineTargetWarehouse(coil.getRegradeQuality()); + if (targetWarehouseId != null && coil.getCoilId() != null) { + wmsMaterialCoilMapper.update(null, Wrappers.lambdaUpdate() + .eq(WmsMaterialCoil::getCoilId, coil.getCoilId()) + .set(WmsMaterialCoil::getWarehouseId, targetWarehouseId)); + } + + // 3. 更新明细执行状态 coilMapper.update(null, Wrappers.lambdaUpdate() .eq(QcQualityReviewCoil::getDetailId, coil.getDetailId()) .set(QcQualityReviewCoil::getExecuteStatus, 1L) @@ -400,6 +411,23 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService { return "QR-" + dateStr + "-" + String.format("%04d", count + 1); } + /** + * 根据改判后质量等级确定目标逻辑库区 + * O/A/B → 不移动,C+/C/C- → 技术部逻辑库,D+/D/D- → 技术部逻辑库 + */ + private Long determineTargetWarehouse(String regradeQuality) { + if (regradeQuality == null) return null; + // O/A/B 级不移动 + if ("O".equals(regradeQuality) || "A".equals(regradeQuality) || "B".equals(regradeQuality)) { + return null; + } + // C/D 级 → 技术部逻辑库 + if (regradeQuality.startsWith("C") || regradeQuality.startsWith("D")) { + return TECH_WAREHOUSE_ID; + } + return null; + } + private void validEntityBeforeSave(QcQualityReview entity) { if (StringUtils.isBlank(entity.getProductName())) { throw new RuntimeException("产品名称不能为空"); From 85751acc46cea86cedc6264a6d119a61bf8f7870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= <2178503051@qq.com> Date: Sat, 4 Jul 2026 13:19:32 +0800 Subject: [PATCH 04/15] =?UTF-8?q?feat(cost/comprehensive):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=B1=87=E6=80=BB=E8=A1=8C=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=A1=A8=E6=A0=BC=E6=95=B0=E6=8D=AE=E6=B1=82?= =?UTF-8?q?=E5=92=8C=E4=B8=8E=E5=B9=B3=E5=9D=87=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增summaryRows计算属性,生成总和与平均两行汇总数据 2. 新增tableData计算属性,将汇总行合并到原表格数据中 3. 为汇总行添加专属样式,高亮显示并加粗文字 4. 优化表格列渲染逻辑,普通行保留编辑能力,汇总行仅展示静态数据 5. 调整删除按钮逻辑,仅对非汇总行生效并修复删除索引问题 6. 新增rowClassName方法为汇总行添加专属CSS类 --- klp-ui/src/views/cost/comprehensive.vue | 98 ++++++++++++++++++++----- 1 file changed, 79 insertions(+), 19 deletions(-) diff --git a/klp-ui/src/views/cost/comprehensive.vue b/klp-ui/src/views/cost/comprehensive.vue index 4afc366f3..845b899a0 100644 --- a/klp-ui/src/views/cost/comprehensive.vue +++ b/klp-ui/src/views/cost/comprehensive.vue @@ -30,9 +30,9 @@ - + - + - + @@ -82,7 +95,7 @@ - 删除 + 删除 @@ -494,6 +507,45 @@ export default { }) return col && col.color ? { background: col.color, color: '#fff' } : {} } + }, + summaryRows() { + const rows = this.gridRows.filter(r => r.detailDate) + if (!rows.length) return [] + const detailCols = this.allCols.filter(c => c.$type === 'detail') + const metricCols = this.allCols.filter(c => c.$type === 'metric') + const calc = (type) => { + const row = { detailDate: type === 'sum' ? '总和' : '平均', $isSummary: true, $summaryType: type } + const n = rows.length || 1 + detailCols.forEach(col => { + if (col.isShift) { + const s1 = rows.reduce((a, r) => a + (parseFloat(r['q' + col.itemId + '_1']) || 0), 0) + const s2 = rows.reduce((a, r) => a + (parseFloat(r['q' + col.itemId + '_2']) || 0), 0) + row['q' + col.itemId + '_1'] = type === 'sum' ? s1.toFixed(2) : (s1 / n).toFixed(2) + row['q' + col.itemId + '_2'] = type === 'sum' ? s2.toFixed(2) : (s2 / n).toFixed(2) + row['q' + col.itemId] = type === 'sum' ? (s1 + s2).toFixed(2) : ((s1 + s2) / n).toFixed(2) + } else { + const s = rows.reduce((a, r) => a + (parseFloat(r['q' + col.itemId]) || 0), 0) + row['q' + col.itemId] = type === 'sum' ? s.toFixed(2) : (s / n).toFixed(2) + } + }) + metricCols.forEach(col => { + if (col.isShift) { + const s1 = rows.reduce((a, r) => a + (parseFloat(r['mv' + col.mIdx + '_1']) || 0), 0) + const s2 = rows.reduce((a, r) => a + (parseFloat(r['mv' + col.mIdx + '_2']) || 0), 0) + row['mv' + col.mIdx + '_1'] = type === 'sum' ? s1.toFixed(2) : (s1 / n).toFixed(2) + row['mv' + col.mIdx + '_2'] = type === 'sum' ? s2.toFixed(2) : (s2 / n).toFixed(2) + row['mv' + col.mIdx] = type === 'sum' ? (s1 + s2).toFixed(2) : ((s1 + s2) / n).toFixed(2) + } else { + const s = rows.reduce((a, r) => a + (parseFloat(r['mv' + col.mIdx]) || 0), 0) + row['mv' + col.mIdx] = type === 'sum' ? s.toFixed(2) : (s / n).toFixed(2) + } + }) + return row + } + return [calc('sum'), calc('avg')] + }, + tableData() { + return [...this.summaryRows, ...this.gridRows] } }, watch: { configOpen(v) { if (!v) this.rpOpen = false } }, @@ -509,6 +561,10 @@ export default { } }, methods: { + rowClassName({ row }) { + if (row.$isSummary) return 'summary-row' + return '' + }, /* report */ getList() { this.loading = true @@ -1142,4 +1198,8 @@ export default { .ica-backfill { color: #67c23a; margin-right: 1px; } .ica:hover { opacity: 0.7; } /deep/ .anomaly-input .el-input__inner { background: #fef0f0 !important; border-color: #f56c6c !important; } +/deep/ .summary-row td { background: #f0f7ff !important; font-weight: bold; } +/deep/ .summary-row td .cell { color: #303133; } +.summary-label { font-weight: bold; color: #303133; padding: 0 5px; } +.summary-val { font-weight: bold; color: #303133; } From eecb7fcae665bd4c199d446715fd08925d732192 Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Sat, 4 Jul 2026 13:38:23 +0800 Subject: [PATCH 05/15] =?UTF-8?q?feat(erp):=20=E8=A1=A5=E5=85=85=E5=90=88?= =?UTF-8?q?=E5=90=8C=E4=BF=A1=E6=81=AF=E5=AD=97=E6=AE=B5=E5=B9=B6=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E9=87=87=E8=B4=AD=E8=AE=A1=E5=88=92=E5=85=B3=E8=81=94?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在ErpContractOptionVo中添加crm_order全量字段包括订单类型、交货日期、订单状态等 - 添加@JsonFormat注解支持日期格式化 - 新增selectContractsByOrderCodes方法支持按合同编号批量查询 - 更新SQL映射文件中的selectContractPage和新增selectContractsByOrderCodes查询 - 在采购计划服务实现中查询时刷新进度并关联合同详情 - 在前端界面中新增关联合同标签页显示合同详细信息表格 - 重构采购到货界面将采购要求和到货明细合并显示 - 添加合同状态文本转换方法和相关样式定义 --- .../erp/domain/vo/ErpContractOptionVo.java | 99 +++++++++++++++++ .../klp/erp/domain/vo/ErpPurchasePlanVo.java | 3 + .../klp/erp/mapper/ErpPurchasePlanMapper.java | 5 + .../impl/ErpPurchasePlanServiceImpl.java | 9 ++ .../mapper/erp/ErpPurchasePlanMapper.xml | 100 ++++++++++++++++-- .../src/views/erp/purchaseDelivery/index.vue | 49 +++++++-- klp-ui/src/views/erp/purchasePlan/index.vue | 28 +++++ 7 files changed, 276 insertions(+), 17 deletions(-) diff --git a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpContractOptionVo.java b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpContractOptionVo.java index 1e9f0eaad..3043ceb48 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpContractOptionVo.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpContractOptionVo.java @@ -1,9 +1,11 @@ package com.klp.erp.domain.vo; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; +import java.util.Date; /** * 采购计划左侧「合同列表」视图对象:crm_order + 该合同已有的采购计划数。 @@ -42,4 +44,101 @@ public class ErpContractOptionVo implements Serializable { /** 该合同已挂接的采购计划数 */ private Integer planCount; + + // ====== 以下为 crm_order 全量补充字段 ====== + + /** 订单类型:pre-预订单,formal-正式订单 */ + private Long orderType; + + /** 交货日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + private Date deliveryDate; + + /** 订单状态 */ + private Long orderStatus; + + /** 财务状态 */ + private Long financeStatus; + + /** 未结款数额 */ + private BigDecimal unpaidAmount; + + /** 签订时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + 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; + + /** 算单价备注 */ + private String unitPriceRemark; + + /** 应付定金(万元) */ + private BigDecimal depositPayable; + + /** 已付定金(万元) */ + private BigDecimal depositPaid; + + /** 定金比例(%) */ + private BigDecimal depositRatio; + + /** 合同状态 0=草稿 1=生效 2=作废 3=已完成 */ + private Long status; + + /** 关联合同ID */ + private Long contractId; + + /** 附件 */ + private String annexFiles; + + /** 备注 */ + private String remark; + + /** 是否置顶 */ + private Integer isTop; } diff --git a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanVo.java b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanVo.java index 3700fb25e..c3aecdd64 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanVo.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanVo.java @@ -86,6 +86,9 @@ public class ErpPurchasePlanVo implements Serializable { /** 关联销售合同编号(展示用) */ private List contractCodes; + /** 关联销售合同信息(来自 crm_order,含客户、金额、销售员等) */ + private List contractInfos; + /** 审核历史(每次审核/驳回留痕) */ private List auditLogs; } diff --git a/klp-erp/src/main/java/com/klp/erp/mapper/ErpPurchasePlanMapper.java b/klp-erp/src/main/java/com/klp/erp/mapper/ErpPurchasePlanMapper.java index 00c2cb581..c49b3a72b 100644 --- a/klp-erp/src/main/java/com/klp/erp/mapper/ErpPurchasePlanMapper.java +++ b/klp-erp/src/main/java/com/klp/erp/mapper/ErpPurchasePlanMapper.java @@ -61,4 +61,9 @@ public interface ErpPurchasePlanMapper extends BaseMapperPlus selectDistinctManufacturers(@Param("kw") String kw); + + /** + * 根据合同编号(order_code)批量查询 crm_order 合同信息。 + */ + List selectContractsByOrderCodes(@Param("codes") List codes); } diff --git a/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchasePlanServiceImpl.java b/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchasePlanServiceImpl.java index 6f7e5d341..b2967a137 100644 --- a/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchasePlanServiceImpl.java +++ b/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchasePlanServiceImpl.java @@ -73,6 +73,8 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { @Override public ErpPurchasePlanVo queryById(Long planId) { + // 刷新到货进度(含在途统计),确保每次查看都是最新数据 + refreshProgress(planId); ErpPurchasePlanVo vo = baseMapper.selectVoById(planId); if (vo == null) { return null; @@ -88,6 +90,10 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { if (!orderIds.isEmpty()) { vo.setContractCodes(baseMapper.selectOrderCodes(orderIds)); } + // 关联合同详情(从 crm_order 按 contractCodes 批量查) + if (vo.getContractCodes() != null && !vo.getContractCodes().isEmpty()) { + vo.setContractInfos(baseMapper.selectContractsByOrderCodes(vo.getContractCodes())); + } fillProgress(vo); // 审核历史(含每次驳回理由) vo.setAuditLogs(queryAuditLogs(planId)); @@ -484,6 +490,9 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { if (!orderIds.isEmpty()) { v.setContractCodes(baseMapper.selectOrderCodes(orderIds)); } + if (v.getContractCodes() != null && !v.getContractCodes().isEmpty()) { + v.setContractInfos(baseMapper.selectContractsByOrderCodes(v.getContractCodes())); + } } return TableDataInfo.build(result); } diff --git a/klp-erp/src/main/resources/mapper/erp/ErpPurchasePlanMapper.xml b/klp-erp/src/main/resources/mapper/erp/ErpPurchasePlanMapper.xml index 9bc505264..f4713426f 100644 --- a/klp-erp/src/main/resources/mapper/erp/ErpPurchasePlanMapper.xml +++ b/klp-erp/src/main/resources/mapper/erp/ErpPurchasePlanMapper.xml @@ -32,17 +32,48 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ORDER BY order_id, item_id - + + + +