From f617bb884da05140b503088db668e3df3618c02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= Date: Tue, 7 Jul 2026 11:22:17 +0800 Subject: [PATCH 01/23] =?UTF-8?q?refactor(crm/contract):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E5=90=88=E5=90=8C=E9=A1=B5=E9=9D=A2=E5=B8=83=E5=B1=80?= =?UTF-8?q?=E4=B8=8ETab=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 移除合同页面的拖拽拆分面板功能,合并预览区到Tab页签 2. 将原生el-tabs替换为自定义Tab头部,新增合同信息页签 3. 调整产品类型列表列宽,优化页面展示效果 4. 精简冗余代码与样式,提升页面性能与可维护性 --- klp-ui/src/views/crm/components/CoilTable.vue | 2 +- .../crm/contract/components/ContractTabs.vue | 193 +++++++++++++----- klp-ui/src/views/crm/contract/index.vue | 55 +---- 3 files changed, 149 insertions(+), 101 deletions(-) diff --git a/klp-ui/src/views/crm/components/CoilTable.vue b/klp-ui/src/views/crm/components/CoilTable.vue index 26d7b08d1..2b7eb6ffc 100644 --- a/klp-ui/src/views/crm/components/CoilTable.vue +++ b/klp-ui/src/views/crm/components/CoilTable.vue @@ -42,7 +42,7 @@ - + + + + + diff --git a/klp-ui/src/views/micro/pages/acid/index.vue b/klp-ui/src/views/micro/pages/acid/index.vue index e8e39034b..bb6e6b7ac 100644 --- a/klp-ui/src/views/micro/pages/acid/index.vue +++ b/klp-ui/src/views/micro/pages/acid/index.vue @@ -54,6 +54,10 @@ app + + + 模型 +
@@ -76,6 +80,7 @@ import Stoppage from '@/views/timing/stoppage/index.vue'; import AcidTiming from '@/views/lines/acid/index.vue'; import TrackingView from './components/TrackingView.vue'; import ProcessSpec from './components/ProcessSpec.vue'; +import Model from './components/Model.vue'; export default { name: 'AcidSystem', @@ -92,7 +97,8 @@ export default { Stoppage, AcidTiming, TrackingView, - ProcessSpec + ProcessSpec, + Model, }, data() { return { @@ -115,6 +121,7 @@ export default { acidTiming: 'AcidTiming', tracking: 'TrackingView', processSpec: 'ProcessSpec', + model: 'Model', }; return componentMap[this.activeMenu]; }, From af7b73d29c760c96d14367008646d6c384cc3455 Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Wed, 8 Jul 2026 10:22:58 +0800 Subject: [PATCH 12/23] =?UTF-8?q?feat(wms):=20=E6=B7=BB=E5=8A=A0=E6=A3=80?= =?UTF-8?q?=E9=AA=8C=E4=B8=BB=E6=95=B0=E6=8D=AE=E5=85=B3=E8=81=94=E6=98=8E?= =?UTF-8?q?=E7=BB=86=E6=9F=A5=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 WmsInspectionDetail 相关依赖和映射器 - 在 WmsInspectionMainVo 中添加 detailList 字段存储明细列表 - 实现 fillDetailList 方法批量填充检验明细数据 - 优化查询方法在分页和列表查询时自动关联明细信息 - 使用流式处理和分组操作提升数据关联性能 --- .../klp/domain/vo/WmsInspectionMainVo.java | 5 ++++ .../impl/WmsInspectionMainServiceImpl.java | 27 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/klp-wms/src/main/java/com/klp/domain/vo/WmsInspectionMainVo.java b/klp-wms/src/main/java/com/klp/domain/vo/WmsInspectionMainVo.java index aaa8d781c..bb030dc29 100644 --- a/klp-wms/src/main/java/com/klp/domain/vo/WmsInspectionMainVo.java +++ b/klp-wms/src/main/java/com/klp/domain/vo/WmsInspectionMainVo.java @@ -1,6 +1,7 @@ package com.klp.domain.vo; import java.util.Date; +import java.util.List; import com.fasterxml.jackson.annotation.JsonFormat; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; @@ -73,5 +74,9 @@ public class WmsInspectionMainVo { @ExcelProperty(value = "备注") private String remark; + /** + * 检验项目明细列表 + */ + private List detailList; } diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsInspectionMainServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsInspectionMainServiceImpl.java index a6b9c9850..9acf2a9cb 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsInspectionMainServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsInspectionMainServiceImpl.java @@ -1,6 +1,7 @@ package com.klp.service.impl; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; import com.klp.common.core.page.TableDataInfo; import com.klp.common.core.domain.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -11,13 +12,18 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import com.klp.domain.bo.WmsInspectionMainBo; import com.klp.domain.vo.WmsInspectionMainVo; +import com.klp.domain.vo.WmsInspectionDetailVo; import com.klp.domain.WmsInspectionMain; +import com.klp.domain.WmsInspectionDetail; import com.klp.mapper.WmsInspectionMainMapper; +import com.klp.mapper.WmsInspectionDetailMapper; import com.klp.service.IWmsInspectionMainService; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Collection; +import java.util.stream.Collectors; /** * 检验主Service业务层处理 @@ -30,6 +36,7 @@ import java.util.Collection; public class WmsInspectionMainServiceImpl implements IWmsInspectionMainService { private final WmsInspectionMainMapper baseMapper; + private final WmsInspectionDetailMapper detailMapper; /** * 查询检验主 @@ -46,6 +53,7 @@ public class WmsInspectionMainServiceImpl implements IWmsInspectionMainService { public TableDataInfo queryPageList(WmsInspectionMainBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + fillDetailList(result.getRecords()); return TableDataInfo.build(result); } @@ -55,7 +63,9 @@ public class WmsInspectionMainServiceImpl implements IWmsInspectionMainService { @Override public List queryList(WmsInspectionMainBo bo) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); - return baseMapper.selectVoList(lqw); + List list = baseMapper.selectVoList(lqw); + fillDetailList(list); + return list; } private LambdaQueryWrapper buildQueryWrapper(WmsInspectionMainBo bo) { @@ -72,6 +82,21 @@ public class WmsInspectionMainServiceImpl implements IWmsInspectionMainService { return lqw; } + private void fillDetailList(List voList) { + if (CollUtil.isEmpty(voList)) { + return; + } + List mainIds = voList.stream().map(WmsInspectionMainVo::getMainId).collect(Collectors.toList()); + List allDetails = detailMapper.selectVoList( + new LambdaQueryWrapper().in(WmsInspectionDetail::getMainId, mainIds) + ); + Map> detailMap = allDetails.stream() + .collect(Collectors.groupingBy(WmsInspectionDetailVo::getMainId)); + for (WmsInspectionMainVo vo : voList) { + vo.setDetailList(detailMap.getOrDefault(vo.getMainId(), Collections.emptyList())); + } + } + /** * 新增检验主 */ From f0a74c1e1cbc9c01217413c5ae8c683df76f3a77 Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Wed, 8 Jul 2026 10:25:41 +0800 Subject: [PATCH 13/23] =?UTF-8?q?feat(wms):=20=E6=B7=BB=E5=8A=A0=E6=A3=80?= =?UTF-8?q?=E5=8C=96=E9=AA=8C=E7=94=B3=E8=AF=B7=E5=8D=95=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建检化验申请单实体类 WmsInspectionApplication - 定义检化验申请单服务接口 IWmsInspectionApplicationService - 实现检化验申请单服务业务逻辑 WmsInspectionApplicationServiceImpl - 添加检化验申请单控制器 WmsInspectionApplicationController - 创建检化验申请单数据访问层 WmsInspectionApplicationMapper - 设计检化验申请单业务对象 WmsInspectionApplicationBo 和视图对象 WmsInspectionApplicationVo - 配置检化验申请单 MyBatis 映射文件 - 实现检化验申请单的增删改查功能 - 添加检化验申请单列表查询和导出功能 --- .../WmsInspectionApplicationController.java | 99 ++++++++++ .../klp/domain/WmsInspectionApplication.java | 135 +++++++++++++ .../domain/bo/WmsInspectionApplicationBo.java | 153 ++++++++++++++ .../domain/vo/WmsInspectionApplicationVo.java | 187 ++++++++++++++++++ .../WmsInspectionApplicationMapper.java | 15 ++ .../IWmsInspectionApplicationService.java | 49 +++++ .../WmsInspectionApplicationServiceImpl.java | 132 +++++++++++++ .../klp/WmsInspectionApplicationMapper.xml | 42 ++++ 8 files changed, 812 insertions(+) create mode 100644 klp-wms/src/main/java/com/klp/controller/WmsInspectionApplicationController.java create mode 100644 klp-wms/src/main/java/com/klp/domain/WmsInspectionApplication.java create mode 100644 klp-wms/src/main/java/com/klp/domain/bo/WmsInspectionApplicationBo.java create mode 100644 klp-wms/src/main/java/com/klp/domain/vo/WmsInspectionApplicationVo.java create mode 100644 klp-wms/src/main/java/com/klp/mapper/WmsInspectionApplicationMapper.java create mode 100644 klp-wms/src/main/java/com/klp/service/IWmsInspectionApplicationService.java create mode 100644 klp-wms/src/main/java/com/klp/service/impl/WmsInspectionApplicationServiceImpl.java create mode 100644 klp-wms/src/main/resources/mapper/klp/WmsInspectionApplicationMapper.xml diff --git a/klp-wms/src/main/java/com/klp/controller/WmsInspectionApplicationController.java b/klp-wms/src/main/java/com/klp/controller/WmsInspectionApplicationController.java new file mode 100644 index 000000000..77a009a6f --- /dev/null +++ b/klp-wms/src/main/java/com/klp/controller/WmsInspectionApplicationController.java @@ -0,0 +1,99 @@ +package com.klp.controller; + +import java.util.List; +import java.util.Arrays; + +import lombok.RequiredArgsConstructor; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.*; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import com.klp.common.annotation.RepeatSubmit; +import com.klp.common.annotation.Log; +import com.klp.common.core.controller.BaseController; +import com.klp.common.core.domain.PageQuery; +import com.klp.common.core.domain.R; +import com.klp.common.core.validate.AddGroup; +import com.klp.common.core.validate.EditGroup; +import com.klp.common.enums.BusinessType; +import com.klp.common.utils.poi.ExcelUtil; +import com.klp.domain.vo.WmsInspectionApplicationVo; +import com.klp.domain.bo.WmsInspectionApplicationBo; +import com.klp.service.IWmsInspectionApplicationService; +import com.klp.common.core.page.TableDataInfo; + +/** + * 检化验申请单 + * + * @author klp + * @date 2026-07-08 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/wms/inspectionApplication") +public class WmsInspectionApplicationController extends BaseController { + + private final IWmsInspectionApplicationService iWmsInspectionApplicationService; + + /** + * 查询检化验申请单列表 + */ + @GetMapping("/list") + public TableDataInfo list(WmsInspectionApplicationBo bo, PageQuery pageQuery) { + return iWmsInspectionApplicationService.queryPageList(bo, pageQuery); + } + + /** + * 导出检化验申请单列表 + */ + @Log(title = "检化验申请单", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(WmsInspectionApplicationBo bo, HttpServletResponse response) { + List list = iWmsInspectionApplicationService.queryList(bo); + ExcelUtil.exportExcel(list, "检化验申请单", WmsInspectionApplicationVo.class, response); + } + + /** + * 获取检化验申请单详细信息 + * + * @param applicationId 主键 + */ + @GetMapping("/{applicationId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long applicationId) { + return R.ok(iWmsInspectionApplicationService.queryById(applicationId)); + } + + /** + * 新增检化验申请单 + */ + @Log(title = "检化验申请单", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody WmsInspectionApplicationBo bo) { + return toAjax(iWmsInspectionApplicationService.insertByBo(bo)); + } + + /** + * 修改检化验申请单 + */ + @Log(title = "检化验申请单", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody WmsInspectionApplicationBo bo) { + return toAjax(iWmsInspectionApplicationService.updateByBo(bo)); + } + + /** + * 删除检化验申请单 + * + * @param applicationIds 主键串 + */ + @Log(title = "检化验申请单", businessType = BusinessType.DELETE) + @DeleteMapping("/{applicationIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] applicationIds) { + return toAjax(iWmsInspectionApplicationService.deleteWithValidByIds(Arrays.asList(applicationIds), true)); + } +} diff --git a/klp-wms/src/main/java/com/klp/domain/WmsInspectionApplication.java b/klp-wms/src/main/java/com/klp/domain/WmsInspectionApplication.java new file mode 100644 index 000000000..bb83b90e4 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/WmsInspectionApplication.java @@ -0,0 +1,135 @@ +package com.klp.domain; + +import com.baomidou.mybatisplus.annotation.*; +import com.klp.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * 检化验申请单对象 wms_inspection_application + * + * @author klp + * @date 2026-07-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("wms_inspection_application") +public class WmsInspectionApplication extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * 申请单主键 + */ + @TableId(value = "application_id") + private Long applicationId; + /** + * 申请单编号(如 LAB-20260708-0001) + */ + private String applicationNo; + /** + * 申请标题 + */ + private String applicationTitle; + /** + * 产线(如:1#产线、2#产线) + */ + private String productionLine; + /** + * 实验类型(字典:lab_experiment_type:physical=物理检验 chemical=化学检验) + */ + private String experimentType; + /** + * 样品名称 + */ + private String sampleName; + /** + * 样品批号 + */ + private String sampleBatchNo; + /** + * 样品来源(如:来料、过程样、成品样) + */ + private String sampleSource; + /** + * 样品数量 + */ + private Long sampleQuantity; + /** + * 检验目的/用途说明 + */ + private String testPurpose; + /** + * 要求完成日期 + */ + private Date requiredDate; + /** + * 流程状态(字典:lab_application_status):1=草稿 2=待审批 3=已通过 4=已驳回 5=实验中 6=已完成 + */ + private Integer flowStatus; + /** + * 提交送审时间 + */ + private Date submitTime; + /** + * 审批人 + */ + private String approveBy; + /** + * 审批时间 + */ + private Date approveTime; + /** + * 审批意见 + */ + private String approveOpinion; + /** + * 驳回原因 + */ + private String rejectReason; + /** + * 主表id + */ + private Long mainId; + /** + * 记录此次操作结果ids + */ + private String detailIds; + /** + * 实验操作人 + */ + private String experimentOperator; + /** + * 实验开始时间 + */ + private Date experimentStartTime; + /** + * 实验结束时间 + */ + private Date experimentEndTime; + /** + * 实验结果汇总/结论 + */ + private String resultSummary; + /** + * 结果填报人(录入台账的人) + */ + private String resultFiller; + /** + * 结果填报时间 + */ + private Date resultFillTime; + /** + * 删除标志(0=正常 2=删除) + */ + @TableLogic + private Integer delFlag; + /** + * 备注 + */ + private String remark; + +} diff --git a/klp-wms/src/main/java/com/klp/domain/bo/WmsInspectionApplicationBo.java b/klp-wms/src/main/java/com/klp/domain/bo/WmsInspectionApplicationBo.java new file mode 100644 index 000000000..4c77b0734 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/bo/WmsInspectionApplicationBo.java @@ -0,0 +1,153 @@ +package com.klp.domain.bo; + +import com.klp.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; +import javax.validation.constraints.*; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * 检化验申请单业务对象 wms_inspection_application + * + * @author klp + * @date 2026-07-08 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class WmsInspectionApplicationBo extends BaseEntity { + + /** + * 申请单主键 + */ + private Long applicationId; + + /** + * 申请单编号(如 LAB-20260708-0001) + */ + private String applicationNo; + + /** + * 申请标题 + */ + private String applicationTitle; + + /** + * 产线(如:1#产线、2#产线) + */ + private String productionLine; + + /** + * 实验类型(字典:lab_experiment_type:physical=物理检验 chemical=化学检验) + */ + private String experimentType; + + /** + * 样品名称 + */ + private String sampleName; + + /** + * 样品批号 + */ + private String sampleBatchNo; + + /** + * 样品来源(如:来料、过程样、成品样) + */ + private String sampleSource; + + /** + * 样品数量 + */ + private Long sampleQuantity; + + /** + * 检验目的/用途说明 + */ + private String testPurpose; + + /** + * 要求完成日期 + */ + private Date requiredDate; + + /** + * 流程状态(字典:lab_application_status):1=草稿 2=待审批 3=已通过 4=已驳回 5=实验中 6=已完成 + */ + private Integer flowStatus; + + /** + * 提交送审时间 + */ + private Date submitTime; + + /** + * 审批人 + */ + private String approveBy; + + /** + * 审批时间 + */ + private Date approveTime; + + /** + * 审批意见 + */ + private String approveOpinion; + + /** + * 驳回原因 + */ + private String rejectReason; + + /** + * 主表id + */ + private Long mainId; + + /** + * 记录此次操作结果ids + */ + private String detailIds; + + /** + * 实验操作人 + */ + private String experimentOperator; + + /** + * 实验开始时间 + */ + private Date experimentStartTime; + + /** + * 实验结束时间 + */ + private Date experimentEndTime; + + /** + * 实验结果汇总/结论 + */ + private String resultSummary; + + /** + * 结果填报人(录入台账的人) + */ + private String resultFiller; + + /** + * 结果填报时间 + */ + private Date resultFillTime; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/klp-wms/src/main/java/com/klp/domain/vo/WmsInspectionApplicationVo.java b/klp-wms/src/main/java/com/klp/domain/vo/WmsInspectionApplicationVo.java new file mode 100644 index 000000000..1eeb59200 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/vo/WmsInspectionApplicationVo.java @@ -0,0 +1,187 @@ +package com.klp.domain.vo; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.klp.common.annotation.ExcelDictFormat; +import com.klp.common.convert.ExcelDictConvert; +import lombok.Data; + + +/** + * 检化验申请单视图对象 wms_inspection_application + * + * @author klp + * @date 2026-07-08 + */ +@Data +@ExcelIgnoreUnannotated +public class WmsInspectionApplicationVo { + + private static final long serialVersionUID = 1L; + + /** + * 申请单主键 + */ + @ExcelProperty(value = "申请单主键") + private Long applicationId; + + /** + * 申请单编号(如 LAB-20260708-0001) + */ + @ExcelProperty(value = "申请单编号", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "如=,L=AB-20260708-0001") + private String applicationNo; + + /** + * 申请标题 + */ + @ExcelProperty(value = "申请标题") + private String applicationTitle; + + /** + * 产线(如:1#产线、2#产线) + */ + @ExcelProperty(value = "产线", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "如=:1#产线、2#产线") + private String productionLine; + + /** + * 实验类型(字典:lab_experiment_type:physical=物理检验 chemical=化学检验) + */ + @ExcelProperty(value = "实验类型", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "字=典:lab_experiment_type:physical=物理检验,c=hemical=化学检验") + private String experimentType; + + /** + * 样品名称 + */ + @ExcelProperty(value = "样品名称") + private String sampleName; + + /** + * 样品批号 + */ + @ExcelProperty(value = "样品批号") + private String sampleBatchNo; + + /** + * 样品来源(如:来料、过程样、成品样) + */ + @ExcelProperty(value = "样品来源", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "如=:来料、过程样、成品样") + private String sampleSource; + + /** + * 样品数量 + */ + @ExcelProperty(value = "样品数量") + private Long sampleQuantity; + + /** + * 检验目的/用途说明 + */ + @ExcelProperty(value = "检验目的/用途说明") + private String testPurpose; + + /** + * 要求完成日期 + */ + @ExcelProperty(value = "要求完成日期") + private Date requiredDate; + + /** + * 流程状态(字典:lab_application_status):1=草稿 2=待审批 3=已通过 4=已驳回 5=实验中 6=已完成 + */ + @ExcelProperty(value = "流程状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "字=典:lab_application_status") + private Integer flowStatus; + + /** + * 提交送审时间 + */ + @ExcelProperty(value = "提交送审时间") + private Date submitTime; + + /** + * 审批人 + */ + @ExcelProperty(value = "审批人") + private String approveBy; + + /** + * 审批时间 + */ + @ExcelProperty(value = "审批时间") + private Date approveTime; + + /** + * 审批意见 + */ + @ExcelProperty(value = "审批意见") + private String approveOpinion; + + /** + * 驳回原因 + */ + @ExcelProperty(value = "驳回原因") + private String rejectReason; + + /** + * 主表id + */ + @ExcelProperty(value = "主表id") + private Long mainId; + + /** + * 记录此次操作结果ids + */ + @ExcelProperty(value = "记录此次操作结果ids") + private String detailIds; + + /** + * 实验操作人 + */ + @ExcelProperty(value = "实验操作人") + private String experimentOperator; + + /** + * 实验开始时间 + */ + @ExcelProperty(value = "实验开始时间") + private Date experimentStartTime; + + /** + * 实验结束时间 + */ + @ExcelProperty(value = "实验结束时间") + private Date experimentEndTime; + + /** + * 实验结果汇总/结论 + */ + @ExcelProperty(value = "实验结果汇总/结论") + private String resultSummary; + + /** + * 结果填报人(录入台账的人) + */ + @ExcelProperty(value = "结果填报人", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "录=入台账的人") + private String resultFiller; + + /** + * 结果填报时间 + */ + @ExcelProperty(value = "结果填报时间") + private Date resultFillTime; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + +} diff --git a/klp-wms/src/main/java/com/klp/mapper/WmsInspectionApplicationMapper.java b/klp-wms/src/main/java/com/klp/mapper/WmsInspectionApplicationMapper.java new file mode 100644 index 000000000..110ddd1c9 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/mapper/WmsInspectionApplicationMapper.java @@ -0,0 +1,15 @@ +package com.klp.mapper; + +import com.klp.domain.WmsInspectionApplication; +import com.klp.domain.vo.WmsInspectionApplicationVo; +import com.klp.common.core.mapper.BaseMapperPlus; + +/** + * 检化验申请单Mapper接口 + * + * @author klp + * @date 2026-07-08 + */ +public interface WmsInspectionApplicationMapper extends BaseMapperPlus { + +} diff --git a/klp-wms/src/main/java/com/klp/service/IWmsInspectionApplicationService.java b/klp-wms/src/main/java/com/klp/service/IWmsInspectionApplicationService.java new file mode 100644 index 000000000..ae7593b79 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/IWmsInspectionApplicationService.java @@ -0,0 +1,49 @@ +package com.klp.service; + +import com.klp.domain.WmsInspectionApplication; +import com.klp.domain.vo.WmsInspectionApplicationVo; +import com.klp.domain.bo.WmsInspectionApplicationBo; +import com.klp.common.core.page.TableDataInfo; +import com.klp.common.core.domain.PageQuery; + +import java.util.Collection; +import java.util.List; + +/** + * 检化验申请单Service接口 + * + * @author klp + * @date 2026-07-08 + */ +public interface IWmsInspectionApplicationService { + + /** + * 查询检化验申请单 + */ + WmsInspectionApplicationVo queryById(Long applicationId); + + /** + * 查询检化验申请单列表 + */ + TableDataInfo queryPageList(WmsInspectionApplicationBo bo, PageQuery pageQuery); + + /** + * 查询检化验申请单列表 + */ + List queryList(WmsInspectionApplicationBo bo); + + /** + * 新增检化验申请单 + */ + Boolean insertByBo(WmsInspectionApplicationBo bo); + + /** + * 修改检化验申请单 + */ + Boolean updateByBo(WmsInspectionApplicationBo bo); + + /** + * 校验并批量删除检化验申请单信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsInspectionApplicationServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsInspectionApplicationServiceImpl.java new file mode 100644 index 000000000..1969c89da --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsInspectionApplicationServiceImpl.java @@ -0,0 +1,132 @@ +package com.klp.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.klp.common.core.page.TableDataInfo; +import com.klp.common.core.domain.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.klp.common.utils.StringUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import com.klp.domain.bo.WmsInspectionApplicationBo; +import com.klp.domain.vo.WmsInspectionApplicationVo; +import com.klp.domain.WmsInspectionApplication; +import com.klp.mapper.WmsInspectionApplicationMapper; +import com.klp.service.IWmsInspectionApplicationService; + +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 检化验申请单Service业务层处理 + * + * @author klp + * @date 2026-07-08 + */ +@RequiredArgsConstructor +@Service +public class WmsInspectionApplicationServiceImpl implements IWmsInspectionApplicationService { + + private final WmsInspectionApplicationMapper baseMapper; + + /** + * 查询检化验申请单 + */ + @Override + public WmsInspectionApplicationVo queryById(Long applicationId){ + return baseMapper.selectVoById(applicationId); + } + + /** + * 查询检化验申请单列表 + */ + @Override + public TableDataInfo queryPageList(WmsInspectionApplicationBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询检化验申请单列表 + */ + @Override + public List queryList(WmsInspectionApplicationBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(WmsInspectionApplicationBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(StringUtils.isNotBlank(bo.getApplicationNo()), WmsInspectionApplication::getApplicationNo, bo.getApplicationNo()); + lqw.eq(StringUtils.isNotBlank(bo.getApplicationTitle()), WmsInspectionApplication::getApplicationTitle, bo.getApplicationTitle()); + lqw.eq(StringUtils.isNotBlank(bo.getProductionLine()), WmsInspectionApplication::getProductionLine, bo.getProductionLine()); + lqw.eq(StringUtils.isNotBlank(bo.getExperimentType()), WmsInspectionApplication::getExperimentType, bo.getExperimentType()); + lqw.like(StringUtils.isNotBlank(bo.getSampleName()), WmsInspectionApplication::getSampleName, bo.getSampleName()); + lqw.eq(StringUtils.isNotBlank(bo.getSampleBatchNo()), WmsInspectionApplication::getSampleBatchNo, bo.getSampleBatchNo()); + lqw.eq(StringUtils.isNotBlank(bo.getSampleSource()), WmsInspectionApplication::getSampleSource, bo.getSampleSource()); + lqw.eq(bo.getSampleQuantity() != null, WmsInspectionApplication::getSampleQuantity, bo.getSampleQuantity()); + lqw.eq(StringUtils.isNotBlank(bo.getTestPurpose()), WmsInspectionApplication::getTestPurpose, bo.getTestPurpose()); + lqw.eq(bo.getRequiredDate() != null, WmsInspectionApplication::getRequiredDate, bo.getRequiredDate()); + lqw.eq(bo.getFlowStatus() != null, WmsInspectionApplication::getFlowStatus, bo.getFlowStatus()); + lqw.eq(bo.getSubmitTime() != null, WmsInspectionApplication::getSubmitTime, bo.getSubmitTime()); + lqw.eq(StringUtils.isNotBlank(bo.getApproveBy()), WmsInspectionApplication::getApproveBy, bo.getApproveBy()); + lqw.eq(bo.getApproveTime() != null, WmsInspectionApplication::getApproveTime, bo.getApproveTime()); + lqw.eq(StringUtils.isNotBlank(bo.getApproveOpinion()), WmsInspectionApplication::getApproveOpinion, bo.getApproveOpinion()); + lqw.eq(StringUtils.isNotBlank(bo.getRejectReason()), WmsInspectionApplication::getRejectReason, bo.getRejectReason()); + lqw.eq(bo.getMainId() != null, WmsInspectionApplication::getMainId, bo.getMainId()); + lqw.eq(StringUtils.isNotBlank(bo.getDetailIds()), WmsInspectionApplication::getDetailIds, bo.getDetailIds()); + lqw.eq(StringUtils.isNotBlank(bo.getExperimentOperator()), WmsInspectionApplication::getExperimentOperator, bo.getExperimentOperator()); + lqw.eq(bo.getExperimentStartTime() != null, WmsInspectionApplication::getExperimentStartTime, bo.getExperimentStartTime()); + lqw.eq(bo.getExperimentEndTime() != null, WmsInspectionApplication::getExperimentEndTime, bo.getExperimentEndTime()); + lqw.eq(StringUtils.isNotBlank(bo.getResultSummary()), WmsInspectionApplication::getResultSummary, bo.getResultSummary()); + lqw.eq(StringUtils.isNotBlank(bo.getResultFiller()), WmsInspectionApplication::getResultFiller, bo.getResultFiller()); + lqw.eq(bo.getResultFillTime() != null, WmsInspectionApplication::getResultFillTime, bo.getResultFillTime()); + return lqw; + } + + /** + * 新增检化验申请单 + */ + @Override + public Boolean insertByBo(WmsInspectionApplicationBo bo) { + WmsInspectionApplication add = BeanUtil.toBean(bo, WmsInspectionApplication.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setApplicationId(add.getApplicationId()); + } + return flag; + } + + /** + * 修改检化验申请单 + */ + @Override + public Boolean updateByBo(WmsInspectionApplicationBo bo) { + WmsInspectionApplication update = BeanUtil.toBean(bo, WmsInspectionApplication.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(WmsInspectionApplication entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除检化验申请单 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } +} diff --git a/klp-wms/src/main/resources/mapper/klp/WmsInspectionApplicationMapper.xml b/klp-wms/src/main/resources/mapper/klp/WmsInspectionApplicationMapper.xml new file mode 100644 index 000000000..0a0bfade8 --- /dev/null +++ b/klp-wms/src/main/resources/mapper/klp/WmsInspectionApplicationMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From eef375cc2adbf765f060cb8756765948541e9acd 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: Wed, 8 Jul 2026 10:34:10 +0800 Subject: [PATCH 14/23] =?UTF-8?q?feat(wms/move):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=B0=83=E6=8B=A8=E5=8D=95=E8=AE=B0=E5=BF=86=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90=E4=B8=8E=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增MemoInput组件的maxSuggestions配置,限制下拉提示条数 2. 为调拨单相关页面替换输入框为带记忆功能的MemoInput 3. 移除冗余的regrade_quality_type字典依赖 4. 给删除按钮增加glc角色权限控制 5. 简化删除操作的Promise链式调用逻辑 6. 新增调拨单号、名称的枚举存储key --- klp-ui/src/components/MemoInput/index.vue | 8 ++++- klp-ui/src/utils/enum.js | 2 ++ .../src/views/mes/qc/qualityReview/index.vue | 2 +- .../src/views/mes/qc/qualityReview/todo.vue | 2 +- klp-ui/src/views/wms/move/batch.vue | 29 ++++++------------- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/klp-ui/src/components/MemoInput/index.vue b/klp-ui/src/components/MemoInput/index.vue index 89b24fbe9..790555ac3 100644 --- a/klp-ui/src/components/MemoInput/index.vue +++ b/klp-ui/src/components/MemoInput/index.vue @@ -58,6 +58,12 @@ export default { disabled: { type: Boolean, default: false + }, + // 下拉最多展示条数,默认6条 + maxSuggestions: { + type: Number, + default: 6, + validator: (value) => value > 0 } }, data() { @@ -118,7 +124,7 @@ export default { }); } - cb(results); // 回调返回匹配结果 + cb(results.slice(0, this.maxSuggestions)); // 回调返回匹配结果(限制条数) }, /** diff --git a/klp-ui/src/utils/enum.js b/klp-ui/src/utils/enum.js index ea440f4fc..64ffaf902 100644 --- a/klp-ui/src/utils/enum.js +++ b/klp-ui/src/utils/enum.js @@ -12,4 +12,6 @@ export const MemoInputStorageKey = { packagingRequirement: 'packagingRequirement', // 打包要求 coilSpec: 'coilSpec', // 钢卷规格 coatingType: 'coatingType', // 钢卷镀层种类 + transferNo: 'transferNo', // 调拨单号 + transferName: 'transferName', // 调拨单名称 } \ No newline at end of file diff --git a/klp-ui/src/views/mes/qc/qualityReview/index.vue b/klp-ui/src/views/mes/qc/qualityReview/index.vue index 3d16e6490..09305fefc 100644 --- a/klp-ui/src/views/mes/qc/qualityReview/index.vue +++ b/klp-ui/src/views/mes/qc/qualityReview/index.vue @@ -411,7 +411,7 @@ import { listWarehouse } from '@/api/wms/warehouse' export default { name: 'QualityReview', components: { CoilSelector }, - dicts: ['quality_review_status', 'regrade_quality_type', 'coil_quality_status'], + dicts: ['quality_review_status', 'coil_quality_status'], data() { return { // 列表 diff --git a/klp-ui/src/views/mes/qc/qualityReview/todo.vue b/klp-ui/src/views/mes/qc/qualityReview/todo.vue index fe0b5eb07..98b92aa24 100644 --- a/klp-ui/src/views/mes/qc/qualityReview/todo.vue +++ b/klp-ui/src/views/mes/qc/qualityReview/todo.vue @@ -93,7 +93,7 @@ import { listQualityReview, approveQualityReview, rejectQualityReview, getQualit export default { name: 'QualityReviewTodo', - dicts: ['quality_review_status', 'regrade_quality_type', 'coil_quality_status'], + dicts: ['quality_review_status', 'coil_quality_status'], data() { return { loading: false, diff --git a/klp-ui/src/views/wms/move/batch.vue b/klp-ui/src/views/wms/move/batch.vue index 3d7034c3a..2f90f578b 100644 --- a/klp-ui/src/views/wms/move/batch.vue +++ b/klp-ui/src/views/wms/move/batch.vue @@ -2,11 +2,10 @@
- + - + 删除 + v-hasRole="['glc']" @click="handleDelete">删除 导出 @@ -80,8 +79,8 @@ 查看 修改 - 删除 + 删除 提交 - + - + { - this.loading = true; - return delTransferOrder(orderIds); - }).then(() => { - this.loading = false; + this.loading = true; + delTransferOrder(orderIds).then(() => { this.getList(); this.$modal.msgSuccess("删除成功"); - }).catch(() => { }).finally(() => { this.loading = false; }); From d1af1c28a65950670602501923c0e514a0dc6346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=98=8A=E5=A4=A9?= <15984976+n2319_0@user.noreply.gitee.com> Date: Wed, 8 Jul 2026 10:43:27 +0800 Subject: [PATCH 15/23] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=BB=B4=E4=BF=9D?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=AD=97=E6=AE=B5=E5=92=8C=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flow/domain/EqpMaintenancePlanDetail.java | 24 ++ .../domain/bo/EqpMaintenancePlanDetailBo.java | 24 ++ .../domain/vo/EqpMaintenancePlanDetailVo.java | 77 ++-- .../flow/EqpMaintenancePlanDetailMapper.xml | 6 + klp-ui/src/utils/enum.js | 10 +- klp-ui/src/views/wms/post/eqp/approval.vue | 27 +- klp-ui/src/views/wms/post/eqp/execute.vue | 24 +- klp-ui/src/views/wms/post/eqp/index.vue | 344 ++++++++++++++---- ...707_eqp_maintenance_plan_detail_fields.sql | 7 + 9 files changed, 399 insertions(+), 144 deletions(-) create mode 100644 script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql diff --git a/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java b/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java index 1be5a9ede..94a5f5cbf 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java @@ -55,6 +55,30 @@ public class EqpMaintenancePlanDetail extends BaseEntity { * 维修内容描述 */ private String repairContent; + /** + * 产线执行人员 + */ + private String lineExecutor; + /** + * 设备执行人员 + */ + private String equipmentExecutor; + /** + * 预计完成时间 + */ + private String plannedCompleteTime; + /** + * 实际完成时间 + */ + private String actualCompleteTime; + /** + * 总耗时(h) + */ + private String totalHours; + /** + * 验收人 + */ + private String acceptanceUser; /** * 维修负责人 */ diff --git a/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java b/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java index f02ccc350..254c030a9 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java @@ -62,6 +62,30 @@ public class EqpMaintenancePlanDetailBo extends BaseEntity { * 维修内容描述 */ private String repairContent; + /** + * 产线执行人员 + */ + private String lineExecutor; + /** + * 设备执行人员 + */ + private String equipmentExecutor; + /** + * 预计完成时间 + */ + private String plannedCompleteTime; + /** + * 实际完成时间 + */ + private String actualCompleteTime; + /** + * 总耗时(h) + */ + private String totalHours; + /** + * 验收人 + */ + private String acceptanceUser; /** * 维修负责人 diff --git a/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java b/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java index 61569a24a..1cbd5a1a3 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java @@ -1,8 +1,6 @@ package com.klp.flow.domain.vo; -import java.math.BigDecimal; import java.util.Date; -import com.fasterxml.jackson.annotation.JsonFormat; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import com.klp.common.annotation.ExcelDictFormat; @@ -25,7 +23,7 @@ public class EqpMaintenancePlanDetailVo { /** * 明细ID */ - @ExcelProperty(value = "明细ID") + @ExcelProperty(value = "编号") private Long detailId; /** @@ -35,71 +33,66 @@ public class EqpMaintenancePlanDetailVo { private Long planId; /** - * 产线名称 + * 时间 */ - @ExcelProperty(value = "产线名称") - private String productionLine; - - /** - * 设备部件名称 - */ - @ExcelProperty(value = "设备部件名称") - private String componentName; - - /** - * 单条维修项计划执行日期 - */ - @ExcelProperty(value = "单条维修项计划执行日期") + @ExcelProperty(value = "时间") private Date itemPlanDate; /** * 明细类型:0=保养 1=维修 */ - @ExcelProperty(value = "明细类型:0=保养 1=维修") + @ExcelProperty(value = "明细类型", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=保养,1=维修") private Long maintenanceCategory; /** - * 明细完成状态:0=未开始 1=进行中 2=已完成 + * 具体工作内容 */ - @ExcelProperty(value = "明细完成状态:0=未开始 1=进行中 2=已完成") - private Long detailStatus; - - /** - * 维修内容描述 - */ - @ExcelProperty(value = "维修内容描述") + @ExcelProperty(value = "具体工作内容") private String repairContent; /** - * 维修负责人 + * 产线执行人员 */ - @ExcelProperty(value = "维修负责人") - private String repairUser; + @ExcelProperty(value = "产线执行人员") + private String lineExecutor; /** - * 完成时间(打勾时记录) + * 设备执行人员 */ - @ExcelProperty(value = "完成时间", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "打=勾时记录") - private Date completeTime; + @ExcelProperty(value = "设备执行人员") + private String equipmentExecutor; /** - * 实际支出金额(元) + * 预计完成时间 */ - @ExcelProperty(value = "实际支出金额(元)") - private BigDecimal actualCost; + @ExcelProperty(value = "预计完成时间") + private String plannedCompleteTime; /** - * 完成进度百分比(0-100) + * 实际完成时间 */ - @ExcelProperty(value = "完成进度百分比(0-100)") - private Long progressRate; + @ExcelProperty(value = "实际完成时间") + private String actualCompleteTime; /** - * 目标厂家 + * 总耗时(h) */ - @ExcelProperty(value = "目标厂家") - private String targetManufacturer; + @ExcelProperty(value = "总耗时(h)") + private String totalHours; + + /** + * 验收人 + */ + @ExcelProperty(value = "验收人") + private String acceptanceUser; + + /** + * 是否完成 + */ + @ExcelProperty(value = "是否完成", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=否,1=否,2=是") + private Long detailStatus; /** * 备注 diff --git a/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml b/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml index a51a88805..6732e384d 100644 --- a/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml +++ b/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml @@ -13,6 +13,12 @@ + + + + + + diff --git a/klp-ui/src/utils/enum.js b/klp-ui/src/utils/enum.js index ea440f4fc..fe5fe8652 100644 --- a/klp-ui/src/utils/enum.js +++ b/klp-ui/src/utils/enum.js @@ -12,4 +12,12 @@ export const MemoInputStorageKey = { packagingRequirement: 'packagingRequirement', // 打包要求 coilSpec: 'coilSpec', // 钢卷规格 coatingType: 'coatingType', // 钢卷镀层种类 -} \ No newline at end of file + maintenanceRepairContent: 'maintenanceRepairContent', // 维修明细-具体工作内容 + maintenanceLineExecutor: 'maintenanceLineExecutor', // 维修明细-产线执行人员 + maintenanceEquipmentExecutor: 'maintenanceEquipmentExecutor', // 维修明细-设备执行人员 + maintenancePlannedCompleteTime: 'maintenancePlannedCompleteTime', // 维修明细-预计完成时间 + maintenanceActualCompleteTime: 'maintenanceActualCompleteTime', // 维修明细-实际完成时间 + maintenanceTotalHours: 'maintenanceTotalHours', // 维修明细-总耗时 + maintenanceAcceptanceUser: 'maintenanceAcceptanceUser', // 维修明细-验收人 + maintenanceRemark: 'maintenanceRemark', // 维修明细-备注 +} diff --git a/klp-ui/src/views/wms/post/eqp/approval.vue b/klp-ui/src/views/wms/post/eqp/approval.vue index 5cdfa9ab2..8ec3ac0a6 100644 --- a/klp-ui/src/views/wms/post/eqp/approval.vue +++ b/klp-ui/src/views/wms/post/eqp/approval.vue @@ -103,20 +103,23 @@ 维修明细 · Maintenance Details
- - - - + + - - - - + + - + + + + + + + + + + +
暂无维修明细
diff --git a/klp-ui/src/views/wms/post/eqp/execute.vue b/klp-ui/src/views/wms/post/eqp/execute.vue index ddb6af688..9d7467632 100644 --- a/klp-ui/src/views/wms/post/eqp/execute.vue +++ b/klp-ui/src/views/wms/post/eqp/execute.vue @@ -92,16 +92,22 @@ 维修明细进度 · Detail Progress
- - - - + + + + + + + + + + + + + + + - - @@ -273,11 +354,7 @@ export default { inspectionQueried: false, selectedInspectionRows: [], // 维修明细 - detailList: [], - detailDialogVisible: false, - detailDialogTitle: "", - detailForm: {}, - editingDetailId: null + detailList: [] }; }, created() { @@ -324,7 +401,9 @@ export default { loadDetailList(planId) { var self = this; listMaintenancePlanDetail({ planId: planId, pageNum: 1, pageSize: 999 }).then(function(r) { - self.detailList = r.rows || []; + self.detailList = (r.rows || []).map(function(item) { + return self.decorateDetailRow(item); + }); }); }, // ---- 检修记录查询 ---- @@ -373,9 +452,17 @@ export default { componentName: rec.partName || '', productionLine: self.currentRow.productionLine || rec.productionLine || '', maintenanceCategory: 1, + itemPlanDate: rec.inspectTime ? parseTime(rec.inspectTime, '{y}-{m}-{d}') : parseTime(new Date(), '{y}-{m}-{d}'), repairContent: rec.abnormalDesc || '', + lineExecutor: rec.inspector || '', + equipmentExecutor: '', + plannedCompleteTime: '', + actualCompleteTime: '', + totalHours: '', + acceptanceUser: '', repairUser: rec.inspector || '', - detailStatus: 0 + detailStatus: 0, + remark: rec.remark || '' }); }); Promise.all(promises).then(function() { @@ -463,45 +550,122 @@ export default { }).catch(function() { }).finally(function() { self.loading = false; }); }, // ---- 明细管理 ---- - handleAddDetail() { - this.detailForm = { - planId: this.currentRow.planId, + getDefaultDetailRow() { + return { + detailId: undefined, + planId: this.currentRow ? this.currentRow.planId : undefined, componentName: '', - productionLine: this.currentRow.productionLine || '', + productionLine: this.currentRow ? (this.currentRow.productionLine || '') : '', maintenanceCategory: 1, + itemPlanDate: parseTime(new Date(), '{y}-{m}-{d}'), repairContent: '', + lineExecutor: '', + equipmentExecutor: '', + plannedCompleteTime: '', + actualCompleteTime: '', + totalHours: '', + acceptanceUser: '', repairUser: '', - itemPlanDate: undefined, targetManufacturer: '', - detailStatus: 0 + detailStatus: 0, + remark: '' }; - this.editingDetailId = null; - this.detailDialogTitle = "添加维修明细"; - this.detailDialogVisible = true; + }, + decorateDetailRow(row) { + const decorated = Object.assign({}, this.getDefaultDetailRow(), row); + decorated._editing = false; + decorated._isNew = false; + decorated._origin = null; + decorated._rowKey = row.detailId || `detail-${Date.now()}-${Math.random()}`; + return decorated; + }, + getEditingDetailRow() { + return this.detailList.find(function(item) { return item._editing; }); + }, + beginDetailEdit(row, isNew = false) { + if (isNew) { + row._isNew = true; + } + row._origin = JSON.parse(JSON.stringify(row)); + row._editing = true; + }, + handleAddDetail() { + if (!this.currentRow) { + this.$modal.msgWarning("请先选择检修单"); + return; + } + if (this.getEditingDetailRow()) { + this.$modal.msgWarning("请先保存或取消当前正在编辑的维修明细"); + return; + } + const row = this.decorateDetailRow(this.getDefaultDetailRow()); + this.beginDetailEdit(row, true); + this.detailList.unshift(row); }, handleEditDetail(row) { - this.detailForm = Object.assign({}, row); - this.editingDetailId = row.detailId; - this.detailDialogTitle = "编辑维修明细"; - this.detailDialogVisible = true; + const editingRow = this.getEditingDetailRow(); + if (editingRow && editingRow._rowKey !== row._rowKey) { + this.$modal.msgWarning("请先保存或取消当前正在编辑的维修明细"); + return; + } + if (row._editing) return; + this.beginDetailEdit(row); }, - submitDetailForm() { - if (!this.detailForm.componentName) { - this.$modal.msgWarning("请输入设备部件名称"); + cancelEditDetail(row) { + if (row._isNew) { + this.detailList = this.detailList.filter(function(item) { return item._rowKey !== row._rowKey; }); + return; + } + const restored = Object.assign({}, row._origin || {}); + Object.keys(row).forEach((key) => { + if (key.indexOf('_') === 0) return; + this.$set(row, key, restored[key]); + }); + row._editing = false; + row._isNew = false; + row._origin = null; + }, + buildDetailPayload(row) { + return { + detailId: row.detailId, + planId: this.currentRow.planId, + componentName: row.componentName || '', + productionLine: row.productionLine || this.currentRow.productionLine || '', + maintenanceCategory: row.maintenanceCategory == null ? 1 : row.maintenanceCategory, + itemPlanDate: row.itemPlanDate, + repairContent: row.repairContent, + lineExecutor: row.lineExecutor, + equipmentExecutor: row.equipmentExecutor, + plannedCompleteTime: row.plannedCompleteTime, + actualCompleteTime: row.actualCompleteTime, + totalHours: row.totalHours, + acceptanceUser: row.acceptanceUser, + repairUser: row.lineExecutor || row.repairUser || '', + targetManufacturer: row.targetManufacturer || '', + detailStatus: row.detailStatus === 2 ? 2 : 0, + remark: row.remark + }; + }, + saveDetailRow(row) { + if (!row.repairContent) { + this.$modal.msgWarning("请输入具体工作内容"); + return; + } + if (!row.itemPlanDate) { + this.$modal.msgWarning("请选择时间"); return; } var self = this; + var payload = this.buildDetailPayload(row); this.detailButtonLoading = true; - if (this.editingDetailId) { - updateMaintenancePlanDetail(this.detailForm).then(function() { + if (row.detailId) { + updateMaintenancePlanDetail(payload).then(function() { self.$modal.msgSuccess("修改成功"); - self.detailDialogVisible = false; self.loadDetailList(self.currentRow.planId); }).finally(function() { self.detailButtonLoading = false; }); } else { - addMaintenancePlanDetail(this.detailForm).then(function() { + addMaintenancePlanDetail(payload).then(function() { self.$modal.msgSuccess("添加成功"); - self.detailDialogVisible = false; self.loadDetailList(self.currentRow.planId); }).finally(function() { self.detailButtonLoading = false; }); } @@ -530,6 +694,11 @@ export default { .search-row { display: flex; align-items: center; gap: 6px; padding: 0 14px 10px; background: #f5f7fa; } .search-row .el-input { flex: 1; } .list-body { flex: 1; overflow-y: auto; padding: 0 6px; } +.list-body { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } +.list-body::-webkit-scrollbar { width: 8px; height: 8px; } +.list-body::-webkit-scrollbar-track { background: transparent; } +.list-body::-webkit-scrollbar-thumb { background: rgba(144, 147, 153, 0.35); border-radius: 6px; } +.list-body::-webkit-scrollbar-thumb:hover { background: rgba(144, 147, 153, 0.55); } .list-item { display: flex; align-items: center; padding: 10px 12px; margin-bottom: 2px; cursor: pointer; border-radius: 6px; transition: all 0.15s; } .list-item:hover { background: #ebeef5; } .list-item.active { background: #d9ecff; } @@ -546,7 +715,7 @@ export default { /* ========== 右侧面板 ========== */ .right-panel { height: 100%; overflow: hidden; display: flex; flex-direction: column; background: #faf8f5; } .empty-tip { display: flex; align-items: center; justify-content: center; height: 100%; color: #909399; font-size: 14px; gap: 8px; } -.right-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; padding: 12px 16px; } +.right-content { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; padding: 12px 16px; } /* 基本信息栏 */ .info-bar { display: flex; align-items: center; justify-content: space-between; padding: 8px 16px; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; margin-bottom: 10px; flex-shrink: 0; } @@ -563,10 +732,25 @@ export default { .section-count { font-size: 12px; color: #909399; } .section-actions { display: flex; align-items: center; gap: 6px; } .inspection-section .el-table { flex: 1; overflow-y: auto; } +.inspection-section ::v-deep .el-table, +.detail-section ::v-deep .el-table { display: flex; flex-direction: column; height: 100%; } +.inspection-section ::v-deep .el-table__body-wrapper, +.detail-section ::v-deep .el-table__body-wrapper { flex: 1; min-height: 0; } +.inspection-section .el-table { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } +.detail-section .el-table { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar { width: 8px; height: 8px; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track { background: transparent; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb { background: rgba(144, 147, 153, 0.35); border-radius: 6px; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover { background: rgba(144, 147, 153, 0.55); } /* 下半部分:维修明细 */ .detail-section { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; } .detail-section .el-table { flex: 1; overflow-y: auto; } +.cell-pre-wrap { white-space: pre-wrap; word-break: break-all; line-height: 18px; } .empty-data { padding: 24px 0; text-align: center; color: #c0c4cc; font-size: 13px; } diff --git a/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql b/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql new file mode 100644 index 000000000..ae8c0009f --- /dev/null +++ b/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql @@ -0,0 +1,7 @@ +ALTER TABLE `eqp_maintenance_plan_detail` + ADD COLUMN `line_executor` varchar(255) DEFAULT NULL COMMENT '产线执行人员' AFTER `repair_content`, + ADD COLUMN `equipment_executor` varchar(255) DEFAULT NULL COMMENT '设备执行人员' AFTER `line_executor`, + ADD COLUMN `planned_complete_time` varchar(255) DEFAULT NULL COMMENT '预计完成时间' AFTER `equipment_executor`, + ADD COLUMN `actual_complete_time` varchar(255) DEFAULT NULL COMMENT '实际完成时间' AFTER `planned_complete_time`, + ADD COLUMN `total_hours` varchar(100) DEFAULT NULL COMMENT '总耗时(h)' AFTER `actual_complete_time`, + ADD COLUMN `acceptance_user` varchar(255) DEFAULT NULL COMMENT '验收人' AFTER `total_hours`; From 1a3de775c85f5444fca2b11733dead6d56e3be61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=98=8A=E5=A4=A9?= <15984976+n2319_0@user.noreply.gitee.com> Date: Wed, 8 Jul 2026 10:49:00 +0800 Subject: [PATCH 16/23] =?UTF-8?q?Revert=20"=E8=AE=BE=E5=A4=87=E7=BB=B4?= =?UTF-8?q?=E4=BF=9D=E8=B0=83=E6=95=B4=E5=AD=97=E6=AE=B5=E5=92=8C=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E9=80=BB=E8=BE=91"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit d1af1c28a65950670602501923c0e514a0dc6346. --- .../flow/domain/EqpMaintenancePlanDetail.java | 24 -- .../domain/bo/EqpMaintenancePlanDetailBo.java | 24 -- .../domain/vo/EqpMaintenancePlanDetailVo.java | 77 ++-- .../flow/EqpMaintenancePlanDetailMapper.xml | 6 - klp-ui/src/utils/enum.js | 10 +- klp-ui/src/views/wms/post/eqp/approval.vue | 27 +- klp-ui/src/views/wms/post/eqp/execute.vue | 24 +- klp-ui/src/views/wms/post/eqp/index.vue | 352 +++++------------- ...707_eqp_maintenance_plan_detail_fields.sql | 7 - 9 files changed, 148 insertions(+), 403 deletions(-) delete mode 100644 script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql diff --git a/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java b/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java index 94a5f5cbf..1be5a9ede 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java @@ -55,30 +55,6 @@ public class EqpMaintenancePlanDetail extends BaseEntity { * 维修内容描述 */ private String repairContent; - /** - * 产线执行人员 - */ - private String lineExecutor; - /** - * 设备执行人员 - */ - private String equipmentExecutor; - /** - * 预计完成时间 - */ - private String plannedCompleteTime; - /** - * 实际完成时间 - */ - private String actualCompleteTime; - /** - * 总耗时(h) - */ - private String totalHours; - /** - * 验收人 - */ - private String acceptanceUser; /** * 维修负责人 */ diff --git a/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java b/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java index 254c030a9..f02ccc350 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java @@ -62,30 +62,6 @@ public class EqpMaintenancePlanDetailBo extends BaseEntity { * 维修内容描述 */ private String repairContent; - /** - * 产线执行人员 - */ - private String lineExecutor; - /** - * 设备执行人员 - */ - private String equipmentExecutor; - /** - * 预计完成时间 - */ - private String plannedCompleteTime; - /** - * 实际完成时间 - */ - private String actualCompleteTime; - /** - * 总耗时(h) - */ - private String totalHours; - /** - * 验收人 - */ - private String acceptanceUser; /** * 维修负责人 diff --git a/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java b/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java index 1cbd5a1a3..61569a24a 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java @@ -1,6 +1,8 @@ package com.klp.flow.domain.vo; +import java.math.BigDecimal; import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import com.klp.common.annotation.ExcelDictFormat; @@ -23,7 +25,7 @@ public class EqpMaintenancePlanDetailVo { /** * 明细ID */ - @ExcelProperty(value = "编号") + @ExcelProperty(value = "明细ID") private Long detailId; /** @@ -33,66 +35,71 @@ public class EqpMaintenancePlanDetailVo { private Long planId; /** - * 时间 + * 产线名称 */ - @ExcelProperty(value = "时间") + @ExcelProperty(value = "产线名称") + private String productionLine; + + /** + * 设备部件名称 + */ + @ExcelProperty(value = "设备部件名称") + private String componentName; + + /** + * 单条维修项计划执行日期 + */ + @ExcelProperty(value = "单条维修项计划执行日期") private Date itemPlanDate; /** * 明细类型:0=保养 1=维修 */ - @ExcelProperty(value = "明细类型", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "0=保养,1=维修") + @ExcelProperty(value = "明细类型:0=保养 1=维修") private Long maintenanceCategory; /** - * 具体工作内容 + * 明细完成状态:0=未开始 1=进行中 2=已完成 */ - @ExcelProperty(value = "具体工作内容") + @ExcelProperty(value = "明细完成状态:0=未开始 1=进行中 2=已完成") + private Long detailStatus; + + /** + * 维修内容描述 + */ + @ExcelProperty(value = "维修内容描述") private String repairContent; /** - * 产线执行人员 + * 维修负责人 */ - @ExcelProperty(value = "产线执行人员") - private String lineExecutor; + @ExcelProperty(value = "维修负责人") + private String repairUser; /** - * 设备执行人员 + * 完成时间(打勾时记录) */ - @ExcelProperty(value = "设备执行人员") - private String equipmentExecutor; + @ExcelProperty(value = "完成时间", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "打=勾时记录") + private Date completeTime; /** - * 预计完成时间 + * 实际支出金额(元) */ - @ExcelProperty(value = "预计完成时间") - private String plannedCompleteTime; + @ExcelProperty(value = "实际支出金额(元)") + private BigDecimal actualCost; /** - * 实际完成时间 + * 完成进度百分比(0-100) */ - @ExcelProperty(value = "实际完成时间") - private String actualCompleteTime; + @ExcelProperty(value = "完成进度百分比(0-100)") + private Long progressRate; /** - * 总耗时(h) + * 目标厂家 */ - @ExcelProperty(value = "总耗时(h)") - private String totalHours; - - /** - * 验收人 - */ - @ExcelProperty(value = "验收人") - private String acceptanceUser; - - /** - * 是否完成 - */ - @ExcelProperty(value = "是否完成", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "0=否,1=否,2=是") - private Long detailStatus; + @ExcelProperty(value = "目标厂家") + private String targetManufacturer; /** * 备注 diff --git a/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml b/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml index 6732e384d..a51a88805 100644 --- a/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml +++ b/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml @@ -13,12 +13,6 @@ - - - - - - diff --git a/klp-ui/src/utils/enum.js b/klp-ui/src/utils/enum.js index fe5fe8652..ea440f4fc 100644 --- a/klp-ui/src/utils/enum.js +++ b/klp-ui/src/utils/enum.js @@ -12,12 +12,4 @@ export const MemoInputStorageKey = { packagingRequirement: 'packagingRequirement', // 打包要求 coilSpec: 'coilSpec', // 钢卷规格 coatingType: 'coatingType', // 钢卷镀层种类 - maintenanceRepairContent: 'maintenanceRepairContent', // 维修明细-具体工作内容 - maintenanceLineExecutor: 'maintenanceLineExecutor', // 维修明细-产线执行人员 - maintenanceEquipmentExecutor: 'maintenanceEquipmentExecutor', // 维修明细-设备执行人员 - maintenancePlannedCompleteTime: 'maintenancePlannedCompleteTime', // 维修明细-预计完成时间 - maintenanceActualCompleteTime: 'maintenanceActualCompleteTime', // 维修明细-实际完成时间 - maintenanceTotalHours: 'maintenanceTotalHours', // 维修明细-总耗时 - maintenanceAcceptanceUser: 'maintenanceAcceptanceUser', // 维修明细-验收人 - maintenanceRemark: 'maintenanceRemark', // 维修明细-备注 -} +} \ No newline at end of file diff --git a/klp-ui/src/views/wms/post/eqp/approval.vue b/klp-ui/src/views/wms/post/eqp/approval.vue index 8ec3ac0a6..5cdfa9ab2 100644 --- a/klp-ui/src/views/wms/post/eqp/approval.vue +++ b/klp-ui/src/views/wms/post/eqp/approval.vue @@ -103,23 +103,20 @@ 维修明细 · Maintenance Details - - + + + + - - + + + + - - - - - - - - - - - +
暂无维修明细
diff --git a/klp-ui/src/views/wms/post/eqp/execute.vue b/klp-ui/src/views/wms/post/eqp/execute.vue index 9d7467632..ddb6af688 100644 --- a/klp-ui/src/views/wms/post/eqp/execute.vue +++ b/klp-ui/src/views/wms/post/eqp/execute.vue @@ -92,22 +92,16 @@ 维修明细进度 · Detail Progress - - - - - - - - - - - - - - - + + + + + + @@ -354,7 +273,11 @@ export default { inspectionQueried: false, selectedInspectionRows: [], // 维修明细 - detailList: [] + detailList: [], + detailDialogVisible: false, + detailDialogTitle: "", + detailForm: {}, + editingDetailId: null }; }, created() { @@ -401,9 +324,7 @@ export default { loadDetailList(planId) { var self = this; listMaintenancePlanDetail({ planId: planId, pageNum: 1, pageSize: 999 }).then(function(r) { - self.detailList = (r.rows || []).map(function(item) { - return self.decorateDetailRow(item); - }); + self.detailList = r.rows || []; }); }, // ---- 检修记录查询 ---- @@ -452,17 +373,9 @@ export default { componentName: rec.partName || '', productionLine: self.currentRow.productionLine || rec.productionLine || '', maintenanceCategory: 1, - itemPlanDate: rec.inspectTime ? parseTime(rec.inspectTime, '{y}-{m}-{d}') : parseTime(new Date(), '{y}-{m}-{d}'), repairContent: rec.abnormalDesc || '', - lineExecutor: rec.inspector || '', - equipmentExecutor: '', - plannedCompleteTime: '', - actualCompleteTime: '', - totalHours: '', - acceptanceUser: '', repairUser: rec.inspector || '', - detailStatus: 0, - remark: rec.remark || '' + detailStatus: 0 }); }); Promise.all(promises).then(function() { @@ -550,122 +463,45 @@ export default { }).catch(function() { }).finally(function() { self.loading = false; }); }, // ---- 明细管理 ---- - getDefaultDetailRow() { - return { - detailId: undefined, - planId: this.currentRow ? this.currentRow.planId : undefined, - componentName: '', - productionLine: this.currentRow ? (this.currentRow.productionLine || '') : '', - maintenanceCategory: 1, - itemPlanDate: parseTime(new Date(), '{y}-{m}-{d}'), - repairContent: '', - lineExecutor: '', - equipmentExecutor: '', - plannedCompleteTime: '', - actualCompleteTime: '', - totalHours: '', - acceptanceUser: '', - repairUser: '', - targetManufacturer: '', - detailStatus: 0, - remark: '' - }; - }, - decorateDetailRow(row) { - const decorated = Object.assign({}, this.getDefaultDetailRow(), row); - decorated._editing = false; - decorated._isNew = false; - decorated._origin = null; - decorated._rowKey = row.detailId || `detail-${Date.now()}-${Math.random()}`; - return decorated; - }, - getEditingDetailRow() { - return this.detailList.find(function(item) { return item._editing; }); - }, - beginDetailEdit(row, isNew = false) { - if (isNew) { - row._isNew = true; - } - row._origin = JSON.parse(JSON.stringify(row)); - row._editing = true; - }, handleAddDetail() { - if (!this.currentRow) { - this.$modal.msgWarning("请先选择检修单"); - return; - } - if (this.getEditingDetailRow()) { - this.$modal.msgWarning("请先保存或取消当前正在编辑的维修明细"); - return; - } - const row = this.decorateDetailRow(this.getDefaultDetailRow()); - this.beginDetailEdit(row, true); - this.detailList.unshift(row); + this.detailForm = { + planId: this.currentRow.planId, + componentName: '', + productionLine: this.currentRow.productionLine || '', + maintenanceCategory: 1, + repairContent: '', + repairUser: '', + itemPlanDate: undefined, + targetManufacturer: '', + detailStatus: 0 + }; + this.editingDetailId = null; + this.detailDialogTitle = "添加维修明细"; + this.detailDialogVisible = true; }, handleEditDetail(row) { - const editingRow = this.getEditingDetailRow(); - if (editingRow && editingRow._rowKey !== row._rowKey) { - this.$modal.msgWarning("请先保存或取消当前正在编辑的维修明细"); - return; - } - if (row._editing) return; - this.beginDetailEdit(row); + this.detailForm = Object.assign({}, row); + this.editingDetailId = row.detailId; + this.detailDialogTitle = "编辑维修明细"; + this.detailDialogVisible = true; }, - cancelEditDetail(row) { - if (row._isNew) { - this.detailList = this.detailList.filter(function(item) { return item._rowKey !== row._rowKey; }); - return; - } - const restored = Object.assign({}, row._origin || {}); - Object.keys(row).forEach((key) => { - if (key.indexOf('_') === 0) return; - this.$set(row, key, restored[key]); - }); - row._editing = false; - row._isNew = false; - row._origin = null; - }, - buildDetailPayload(row) { - return { - detailId: row.detailId, - planId: this.currentRow.planId, - componentName: row.componentName || '', - productionLine: row.productionLine || this.currentRow.productionLine || '', - maintenanceCategory: row.maintenanceCategory == null ? 1 : row.maintenanceCategory, - itemPlanDate: row.itemPlanDate, - repairContent: row.repairContent, - lineExecutor: row.lineExecutor, - equipmentExecutor: row.equipmentExecutor, - plannedCompleteTime: row.plannedCompleteTime, - actualCompleteTime: row.actualCompleteTime, - totalHours: row.totalHours, - acceptanceUser: row.acceptanceUser, - repairUser: row.lineExecutor || row.repairUser || '', - targetManufacturer: row.targetManufacturer || '', - detailStatus: row.detailStatus === 2 ? 2 : 0, - remark: row.remark - }; - }, - saveDetailRow(row) { - if (!row.repairContent) { - this.$modal.msgWarning("请输入具体工作内容"); - return; - } - if (!row.itemPlanDate) { - this.$modal.msgWarning("请选择时间"); + submitDetailForm() { + if (!this.detailForm.componentName) { + this.$modal.msgWarning("请输入设备部件名称"); return; } var self = this; - var payload = this.buildDetailPayload(row); this.detailButtonLoading = true; - if (row.detailId) { - updateMaintenancePlanDetail(payload).then(function() { + if (this.editingDetailId) { + updateMaintenancePlanDetail(this.detailForm).then(function() { self.$modal.msgSuccess("修改成功"); + self.detailDialogVisible = false; self.loadDetailList(self.currentRow.planId); }).finally(function() { self.detailButtonLoading = false; }); } else { - addMaintenancePlanDetail(payload).then(function() { + addMaintenancePlanDetail(this.detailForm).then(function() { self.$modal.msgSuccess("添加成功"); + self.detailDialogVisible = false; self.loadDetailList(self.currentRow.planId); }).finally(function() { self.detailButtonLoading = false; }); } @@ -694,11 +530,6 @@ export default { .search-row { display: flex; align-items: center; gap: 6px; padding: 0 14px 10px; background: #f5f7fa; } .search-row .el-input { flex: 1; } .list-body { flex: 1; overflow-y: auto; padding: 0 6px; } -.list-body { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } -.list-body::-webkit-scrollbar { width: 8px; height: 8px; } -.list-body::-webkit-scrollbar-track { background: transparent; } -.list-body::-webkit-scrollbar-thumb { background: rgba(144, 147, 153, 0.35); border-radius: 6px; } -.list-body::-webkit-scrollbar-thumb:hover { background: rgba(144, 147, 153, 0.55); } .list-item { display: flex; align-items: center; padding: 10px 12px; margin-bottom: 2px; cursor: pointer; border-radius: 6px; transition: all 0.15s; } .list-item:hover { background: #ebeef5; } .list-item.active { background: #d9ecff; } @@ -715,7 +546,7 @@ export default { /* ========== 右侧面板 ========== */ .right-panel { height: 100%; overflow: hidden; display: flex; flex-direction: column; background: #faf8f5; } .empty-tip { display: flex; align-items: center; justify-content: center; height: 100%; color: #909399; font-size: 14px; gap: 8px; } -.right-content { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; padding: 12px 16px; } +.right-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; padding: 12px 16px; } /* 基本信息栏 */ .info-bar { display: flex; align-items: center; justify-content: space-between; padding: 8px 16px; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; margin-bottom: 10px; flex-shrink: 0; } @@ -732,25 +563,10 @@ export default { .section-count { font-size: 12px; color: #909399; } .section-actions { display: flex; align-items: center; gap: 6px; } .inspection-section .el-table { flex: 1; overflow-y: auto; } -.inspection-section ::v-deep .el-table, -.detail-section ::v-deep .el-table { display: flex; flex-direction: column; height: 100%; } -.inspection-section ::v-deep .el-table__body-wrapper, -.detail-section ::v-deep .el-table__body-wrapper { flex: 1; min-height: 0; } -.inspection-section .el-table { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } -.detail-section .el-table { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } -.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar, -.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar { width: 8px; height: 8px; } -.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track, -.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track { background: transparent; } -.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb, -.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb { background: rgba(144, 147, 153, 0.35); border-radius: 6px; } -.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover, -.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover { background: rgba(144, 147, 153, 0.55); } /* 下半部分:维修明细 */ .detail-section { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; } .detail-section .el-table { flex: 1; overflow-y: auto; } -.cell-pre-wrap { white-space: pre-wrap; word-break: break-all; line-height: 18px; } .empty-data { padding: 24px 0; text-align: center; color: #c0c4cc; font-size: 13px; } diff --git a/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql b/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql deleted file mode 100644 index ae8c0009f..000000000 --- a/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql +++ /dev/null @@ -1,7 +0,0 @@ -ALTER TABLE `eqp_maintenance_plan_detail` - ADD COLUMN `line_executor` varchar(255) DEFAULT NULL COMMENT '产线执行人员' AFTER `repair_content`, - ADD COLUMN `equipment_executor` varchar(255) DEFAULT NULL COMMENT '设备执行人员' AFTER `line_executor`, - ADD COLUMN `planned_complete_time` varchar(255) DEFAULT NULL COMMENT '预计完成时间' AFTER `equipment_executor`, - ADD COLUMN `actual_complete_time` varchar(255) DEFAULT NULL COMMENT '实际完成时间' AFTER `planned_complete_time`, - ADD COLUMN `total_hours` varchar(100) DEFAULT NULL COMMENT '总耗时(h)' AFTER `actual_complete_time`, - ADD COLUMN `acceptance_user` varchar(255) DEFAULT NULL COMMENT '验收人' AFTER `total_hours`; From 3e36d411768a92c4f83be5c8b6dbaeed31ecd10b Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Wed, 8 Jul 2026 10:56:50 +0800 Subject: [PATCH 17/23] =?UTF-8?q?feat(wms):=20=E6=B7=BB=E5=8A=A0=E9=92=A2?= =?UTF-8?q?=E5=8D=B7=E6=8A=A5=E8=A1=A8=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=9A=84=E5=A4=9A=E8=A1=8C=E5=90=88=E5=B9=B6=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在异常报表页面添加导出产出钢卷(多行合并)和导出消耗钢卷(多行合并)菜单项 - 新增 mergeCoilCells 工具函数实现 Excel 单元格合并功能 - 实现 exportWithMerge 通用方法处理带合并的 Excel 导出 - 添加导出时的加载提示和错误处理机制 - 优化 MES 质检样本详情加载逻辑,移除不必要的异步请求 --- .../views/mes/qc/inspectionSample/index.vue | 35 ++++----- klp-ui/src/views/wms/report/abnormal.vue | 59 +++++++++++++++ .../views/wms/report/js/mergeExcelCells.js | 74 +++++++++++++++++++ 3 files changed, 149 insertions(+), 19 deletions(-) create mode 100644 klp-ui/src/views/wms/report/js/mergeExcelCells.js diff --git a/klp-ui/src/views/mes/qc/inspectionSample/index.vue b/klp-ui/src/views/mes/qc/inspectionSample/index.vue index 84b709aed..d422f538e 100644 --- a/klp-ui/src/views/mes/qc/inspectionSample/index.vue +++ b/klp-ui/src/views/mes/qc/inspectionSample/index.vue @@ -344,27 +344,24 @@ export default { loadMainDetails() { if (this.mainList.length === 0) return - const promises = this.mainList.map(main => { - return listInspectionDetail({ mainId: main.mainId, pageNum: 1, pageSize: 9999 }).then(response => { - const details = response.rows || [] - details.forEach(detail => { - if (main._items[detail.itemName]) { - main._items[detail.itemName] = { - detailId: detail.detailId, - mainId: detail.mainId, - itemName: detail.itemName, - itemValue: detail.itemValue || '', - itemUnit: detail.itemUnit || main._items[detail.itemName].itemUnit, - upperLimit: detail.upperLimit, - lowerLimit: detail.lowerLimit, - rangeDesc: detail.rangeDesc - } + this.mainList.forEach(main => { + const details = main.detailList || [] + details.forEach(detail => { + if (main._items[detail.itemName]) { + main._items[detail.itemName] = { + detailId: detail.detailId, + mainId: detail.mainId, + itemName: detail.itemName, + itemValue: detail.itemValue || '', + itemUnit: detail.itemUnit || main._items[detail.itemName].itemUnit, + upperLimit: detail.upperLimit, + lowerLimit: detail.lowerLimit, + rangeDesc: detail.rangeDesc } - }) - main._originalItems = JSON.parse(JSON.stringify(main._items)) - }).catch(() => {}) + } + }) + main._originalItems = JSON.parse(JSON.stringify(main._items)) }) - return Promise.all(promises) }, handleAddMain() { diff --git a/klp-ui/src/views/wms/report/abnormal.vue b/klp-ui/src/views/wms/report/abnormal.vue index 9e62b3b1b..66cdf9d96 100644 --- a/klp-ui/src/views/wms/report/abnormal.vue +++ b/klp-ui/src/views/wms/report/abnormal.vue @@ -58,6 +58,8 @@ 导出产出钢卷(多行) 导出消耗钢卷(多行) + 导出产出钢卷(多行合并) + 导出消耗钢卷(多行合并) @@ -144,6 +146,11 @@ import CoilTable from "@/views/wms/report/components/coilTable"; import ColumnsSetting from "@/views/wms/report/components/setting/columns"; import TimeRangePicker from "@/views/wms/report/components/timeRangePicker.vue"; import { saveReportFile } from "@/views/wms/report/js/reportFile"; +import { mergeCoilCells } from "@/views/wms/report/js/mergeExcelCells"; +import { saveAs } from 'file-saver' +import request from '@/utils/request' +import { tansParams } from "@/utils/klp"; +import { Loading } from 'element-ui' export default { name: 'MergeTemplate', @@ -362,6 +369,54 @@ export default { abnormalExportCount: 0 }, `materialCoil_${new Date().getTime()}.xlsx`) }, + // 导出产出钢卷(多行合并) — 二次合并钢卷列单元格 + async exportDataMerged() { + if (this.outList.length === 0) { + this.$message.warning('暂无数据可导出') + return + } + await this.exportWithMerge('wms/materialCoil/exportAbnormal', { + coilIds: this.outList.map(item => item.coilId).join(','), + abnormalExportCount: 0 + }, `abnormalCoil_${new Date().getTime()}.xlsx`) + }, + + // 导出消耗钢卷(多行合并) — 二次合并钢卷列单元格 + async exportLossDataMerged() { + if (this.lossList.length === 0) { + this.$message.warning('暂无数据可导出') + return + } + await this.exportWithMerge('wms/materialCoil/export', { + coilIds: this.lossList.map(item => item.coilId).join(','), + abnormalExportCount: 0 + }, `materialCoil_${new Date().getTime()}.xlsx`) + }, + + // 通用:导出多行 → ExcelJS 二次合并钢卷列 → 保存 + async exportWithMerge(url, params, filename) { + const loading = Loading.service({ + text: '正在导出并合并单元格,请稍候', + spinner: 'el-icon-loading', + background: 'rgba(0, 0, 0, 0.7)' + }) + try { + const data = await request.post(url, params, { + transformRequest: [(params) => { return tansParams(params) }], + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + responseType: 'blob' + }) + // data 是拦截器返回的 res.data(Blob),与 download 函数一致 + const blob = new Blob([data]) + const mergedBlob = await mergeCoilCells(blob, 26) + saveAs(mergedBlob, filename) + } catch (e) { + console.error('导出合并失败', e) + this.$message.error('导出失败,请联系管理员') + } finally { + loading.close() + } + }, // 处理命令 handleCommand(command) { if (command === 'exportData') { @@ -376,6 +431,10 @@ export default { this.exportDataMore() } else if (command === 'exportLossDataMore') { this.exportLossDataMore() + } else if (command === 'exportDataMerged') { + this.exportDataMerged() + } else if (command === 'exportLossDataMerged') { + this.exportLossDataMerged() } }, // 加载列设置 diff --git a/klp-ui/src/views/wms/report/js/mergeExcelCells.js b/klp-ui/src/views/wms/report/js/mergeExcelCells.js new file mode 100644 index 000000000..3b6e80994 --- /dev/null +++ b/klp-ui/src/views/wms/report/js/mergeExcelCells.js @@ -0,0 +1,74 @@ +import ExcelJS from 'exceljs' + +/** + * 对异常钢卷报表导出的 Excel 进行二次合并处理 + * 将钢卷信息列(前26列,A-Z)中连续相同值的单元格合并 + * + * 原理: + * 1. 用 row.values 数组代替逐格 getCell,避免 9万+ 次对象创建 + * 2. 合并单元格后用列级别样式统一居中,代替逐格设置 + * + * @param {Blob} blob - 原始 Excel 文件 Blob + * @param {number} mergeColumnCount - 需要合并的钢卷列数,默认 26(A-Z列) + * @returns {Promise} - 合并后的新 Blob + */ +export async function mergeCoilCells(blob, mergeColumnCount = 26) { + const workbook = new ExcelJS.Workbook() + const arrayBuffer = await blob.arrayBuffer() + await workbook.xlsx.load(arrayBuffer) + + const worksheet = workbook.worksheets[0] + const rowCount = worksheet.rowCount + + if (rowCount <= 1) return blob + + // === 第一步:按钢卷身份标识分组 === + // 使用 row.values 数组(1-based),字符拼接一次性比较,避免逐格 getCell + const groups = [] + let groupStart = 2 + let prevFingerprint = rowFingerprint(worksheet.getRow(2), mergeColumnCount) + + for (let row = 3; row <= rowCount; row++) { + const curFingerprint = rowFingerprint(worksheet.getRow(row), mergeColumnCount) + if (curFingerprint !== prevFingerprint) { + groups.push({ start: groupStart, end: row - 1 }) + groupStart = row + prevFingerprint = curFingerprint + } + } + groups.push({ start: groupStart, end: rowCount }) + + // === 第二步:合并单元格 === + for (const group of groups) { + if (group.end > group.start) { + for (let col = 1; col <= mergeColumnCount; col++) { + worksheet.mergeCells(group.start, col, group.end, col) + } + } + } + + // === 第三步:列级别统一居中(替换逐格设置,26 次 vs 9万次) === + for (let col = 1; col <= mergeColumnCount; col++) { + const column = worksheet.getColumn(col) + column.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true } + } + + // === 第四步:写回 Blob === + const buffer = await workbook.xlsx.writeBuffer() + return new Blob([buffer], { + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + }) +} + +/** + * 生成行的"指纹"字符串,用于快速比较两行钢卷列是否相同 + * row.values 是 ExcelJS 的 1-based 数组:values[1]=A列, values[2]=B列 ... + */ +function rowFingerprint(row, colCount) { + const vals = row.values || [] + let fp = '' + for (let i = 1; i <= colCount; i++) { + fp += String(vals[i] ?? '') + '\x00' + } + return fp +} From ae928692d3029fcc0bfbdf12295637fd636feff6 Mon Sep 17 00:00:00 2001 From: jhd <1684074631@qq.com> Date: Wed, 8 Jul 2026 11:03:50 +0800 Subject: [PATCH 18/23] =?UTF-8?q?feat(erp):=20=E5=AE=9E=E7=8E=B0=E8=AF=B7?= =?UTF-8?q?=E8=B4=AD=E5=8D=95=E5=8F=8C=E5=B1=82=E5=AE=A1=E6=89=B9=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在提交审批接口中新增指定一审审批人的参数 - 实现一审和二审的两级审批逻辑,一审为管理层审批,二审固定为陈清鑫 - 添加审批人身份验证,确保只有指定审批人才能进行审批操作 - 在前端界面中增加提交审批选择审批人弹窗 - 更新请购单状态显示,新增一审通过待二审状态(状态值6) - 添加审批进度展示,显示一审人和二审人的审批情况 - 实现基于角色的审批权限控制,管理层可进行一审,特定人员可进行二审 - 新增查询审批人列表的API接口,支持按角色筛选审批人 - 优化审批按钮显示逻辑,根据不同状态和用户身份显示相应操作按钮 --- .../controller/system/SysUserController.java | 18 ++++ .../ErpPurchaseRequisitionController.java | 8 +- .../IErpPurchaseRequisitionService.java | 2 +- .../ErpPurchaseRequisitionServiceImpl.java | 53 ++++++++-- .../klp/system/service/ISysUserService.java | 8 ++ .../service/impl/SysUserServiceImpl.java | 16 +++ klp-ui/src/api/erp/purchaseRequisition.js | 15 ++- .../views/erp/purchaseRequisition/index.vue | 97 ++++++++++++++++--- 8 files changed, 190 insertions(+), 27 deletions(-) diff --git a/klp-admin/src/main/java/com/klp/web/controller/system/SysUserController.java b/klp-admin/src/main/java/com/klp/web/controller/system/SysUserController.java index 9709d53cc..4eb256263 100644 --- a/klp-admin/src/main/java/com/klp/web/controller/system/SysUserController.java +++ b/klp-admin/src/main/java/com/klp/web/controller/system/SysUserController.java @@ -74,6 +74,24 @@ public class SysUserController extends BaseController { return userService.selectPageUserList(user, pageQuery); } + /** + * 根据角色标识查询用户列表(用于选择审批人等场景) + */ + @SaCheckLogin + @GetMapping("/selectUserByRole/{roleKey}") + public R> selectUserByRoleKey(@PathVariable String roleKey) { + return R.ok(userService.selectUserByRoleKey(roleKey)); + } + + /** + * 查询请购审批人列表(角色标识 glc) + */ + @SaCheckLogin + @GetMapping("/approverUsers/list") + public R> approverUsers() { + return R.ok(userService.selectUserByRoleKey("glc")); + } + /** * 导出用户列表 */ diff --git a/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchaseRequisitionController.java b/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchaseRequisitionController.java index ce26fa03a..991173e3e 100644 --- a/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchaseRequisitionController.java +++ b/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchaseRequisitionController.java @@ -85,13 +85,14 @@ public class ErpPurchaseRequisitionController extends BaseController { @Log(title = "请购及采购单", businessType = BusinessType.UPDATE) @SaCheckPermission("erp:purchaseRequisition:approve") @PutMapping("/{reqId}/submit") - public R submitApproval(@NotNull(message = "主键不能为空") @PathVariable Long reqId) { - return toAjax(iErpPurchaseRequisitionService.submitApproval(reqId)); + public R submitApproval(@NotNull(message = "主键不能为空") @PathVariable Long reqId, + @NotNull(message = "审批人不能为空") @RequestParam Long firstApproverId, + @NotEmpty(message = "审批人姓名不能为空") @RequestParam String firstApproverName) { + return toAjax(iErpPurchaseRequisitionService.submitApproval(reqId, firstApproverId, firstApproverName)); } /** 审批通过(审批中 → 已通过) */ @Log(title = "请购及采购单", businessType = BusinessType.UPDATE) - @SaCheckPermission("erp:purchaseRequisition:approve") @PutMapping("/{reqId}/approve") public R approve(@NotNull(message = "主键不能为空") @PathVariable Long reqId) { return toAjax(iErpPurchaseRequisitionService.approve(reqId)); @@ -99,7 +100,6 @@ public class ErpPurchaseRequisitionController extends BaseController { /** 驳回(审批中 → 已驳回) */ @Log(title = "请购及采购单", businessType = BusinessType.UPDATE) - @SaCheckPermission("erp:purchaseRequisition:approve") @PutMapping("/{reqId}/reject") public R reject(@NotNull(message = "主键不能为空") @PathVariable Long reqId) { return toAjax(iErpPurchaseRequisitionService.reject(reqId)); diff --git a/klp-erp/src/main/java/com/klp/erp/service/IErpPurchaseRequisitionService.java b/klp-erp/src/main/java/com/klp/erp/service/IErpPurchaseRequisitionService.java index 1049f5f0c..362673704 100644 --- a/klp-erp/src/main/java/com/klp/erp/service/IErpPurchaseRequisitionService.java +++ b/klp-erp/src/main/java/com/klp/erp/service/IErpPurchaseRequisitionService.java @@ -35,7 +35,7 @@ public interface IErpPurchaseRequisitionService { Boolean deleteWithValidByIds(Collection ids, Boolean isValid); /** 提交审批(草稿 → 审批中) */ - Boolean submitApproval(Long reqId); + Boolean submitApproval(Long reqId, Long firstApproverId, String firstApproverName); /** 审批通过(审批中 → 已通过) */ Boolean approve(Long reqId); diff --git a/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchaseRequisitionServiceImpl.java b/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchaseRequisitionServiceImpl.java index ccf88c09b..187e748fa 100644 --- a/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchaseRequisitionServiceImpl.java +++ b/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchaseRequisitionServiceImpl.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; 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.helper.LoginHelper; import com.klp.common.utils.StringUtils; import com.klp.erp.domain.ErpPurchaseRequisition; import com.klp.erp.domain.ErpPurchaseRequisitionItem; @@ -135,13 +136,14 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio @Override @Transactional(rollbackFor = Exception.class) - public Boolean submitApproval(Long reqId) { + public Boolean submitApproval(Long reqId, Long firstApproverId, String firstApproverName) { ErpPurchaseRequisition entity = baseMapper.selectById(reqId); if (entity == null) return false; if (!"0".equals(entity.getFormStatus())) { throw new RuntimeException("仅草稿状态的请购单可提交审批"); } entity.setFormStatus("1"); + entity.setSignPurchaseHandler(firstApproverName); return baseMapper.updateById(entity) > 0; } @@ -150,11 +152,29 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio public Boolean approve(Long reqId) { ErpPurchaseRequisition entity = baseMapper.selectById(reqId); if (entity == null) return false; - if (!"1".equals(entity.getFormStatus())) { - throw new RuntimeException("仅审批中状态的请购单可通过"); + String currentNickName = LoginHelper.getNickName(); + + if ("1".equals(entity.getFormStatus())) { + // 一审:校验是否指定的一审人 + String approverName = entity.getSignPurchaseHandler(); + if (approverName == null || !approverName.equals(currentNickName)) { + throw new RuntimeException("您不是该请购单指定的审批人"); + } + entity.setFormStatus("6"); + return baseMapper.updateById(entity) > 0; + + } else if ("6".equals(entity.getFormStatus())) { + // 二审:校验是否是陈清鑫 + if (!"陈清鑫".equals(currentNickName)) { + throw new RuntimeException("二审仅限指定审批人操作"); + } + entity.setFormStatus("2"); + entity.setSignRequestGm("陈清鑫"); + return baseMapper.updateById(entity) > 0; + + } else { + throw new RuntimeException("当前状态不允许审批通过"); } - entity.setFormStatus("2"); - return baseMapper.updateById(entity) > 0; } @Override @@ -162,11 +182,28 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio public Boolean reject(Long reqId) { ErpPurchaseRequisition entity = baseMapper.selectById(reqId); if (entity == null) return false; - if (!"1".equals(entity.getFormStatus())) { + String currentNickName = LoginHelper.getNickName(); + + if ("1".equals(entity.getFormStatus())) { + // 一审期间驳回 + String approverName = entity.getSignPurchaseHandler(); + if (approverName == null || !approverName.equals(currentNickName)) { + throw new RuntimeException("您不是该请购单指定的审批人"); + } + entity.setFormStatus("5"); + return baseMapper.updateById(entity) > 0; + + } else if ("6".equals(entity.getFormStatus())) { + // 二审期间驳回:仅陈清鑫可驳回 + if (!"陈清鑫".equals(currentNickName)) { + throw new RuntimeException("二审仅限指定审批人操作"); + } + entity.setFormStatus("5"); + return baseMapper.updateById(entity) > 0; + + } else { throw new RuntimeException("仅审批中状态的请购单可驳回"); } - entity.setFormStatus("5"); - return baseMapper.updateById(entity) > 0; } } diff --git a/klp-system/src/main/java/com/klp/system/service/ISysUserService.java b/klp-system/src/main/java/com/klp/system/service/ISysUserService.java index 9eefe5473..63505c883 100644 --- a/klp-system/src/main/java/com/klp/system/service/ISysUserService.java +++ b/klp-system/src/main/java/com/klp/system/service/ISysUserService.java @@ -44,6 +44,14 @@ public interface ISysUserService { SysUser selectUserByUserName(String userName); Map selectNickNameMapByUserNames(List userNames); + /** + * 根据角色标识查询用户列表(用于选择审批人等场景) + * + * @param roleKey 角色标识 + * @return 用户列表 + */ + List selectUserByRoleKey(String roleKey); + /** * 通过手机号查询用户 * diff --git a/klp-system/src/main/java/com/klp/system/service/impl/SysUserServiceImpl.java b/klp-system/src/main/java/com/klp/system/service/impl/SysUserServiceImpl.java index f3909cfe5..b803182ec 100644 --- a/klp-system/src/main/java/com/klp/system/service/impl/SysUserServiceImpl.java +++ b/klp-system/src/main/java/com/klp/system/service/impl/SysUserServiceImpl.java @@ -34,6 +34,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.HashMap; @@ -168,6 +169,21 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return nickMap; } + @Override + public List selectUserByRoleKey(String roleKey) { + // 查询角色 + SysRole role = roleMapper.selectOne(Wrappers.lambdaQuery() + .eq(SysRole::getRoleKey, roleKey)); + if (role == null) return Collections.emptyList(); + // 查询拥有该角色的用户ID列表 + List userIds = userRoleMapper.selectUserIdsByRoleId(role.getRoleId()); + if (CollUtil.isEmpty(userIds)) return Collections.emptyList(); + // 查询用户详情 + return baseMapper.selectUserList(Wrappers.query() + .in("u.user_id", userIds) + .eq("u.del_flag", UserConstants.USER_NORMAL)); + } + /** * 通过手机号查询用户 * diff --git a/klp-ui/src/api/erp/purchaseRequisition.js b/klp-ui/src/api/erp/purchaseRequisition.js index a3e88392d..add217ac9 100644 --- a/klp-ui/src/api/erp/purchaseRequisition.js +++ b/klp-ui/src/api/erp/purchaseRequisition.js @@ -35,11 +35,12 @@ export function updatePurchaseRequisition(data) { }) } -// 提交审批 -export function submitApproval(reqId) { +// 提交审批(指定一审人) +export function submitApproval(reqId, firstApproverId, firstApproverName) { return request({ url: '/erp/purchaseRequisition/' + reqId + '/submit', - method: 'put' + method: 'put', + params: { firstApproverId, firstApproverName } }) } @@ -76,3 +77,11 @@ export function exportPurchaseRequisition(query) { responseType: 'blob' }) } + +// 查询请购审批人列表(角色标识由后端配置) +export function selectApproverUsers() { + return request({ + url: '/system/user/approverUsers/list', + method: 'get' + }) +} diff --git a/klp-ui/src/views/erp/purchaseRequisition/index.vue b/klp-ui/src/views/erp/purchaseRequisition/index.vue index 0a80ec130..b0ee90e13 100644 --- a/klp-ui/src/views/erp/purchaseRequisition/index.vue +++ b/klp-ui/src/views/erp/purchaseRequisition/index.vue @@ -15,6 +15,7 @@ + @@ -62,11 +63,12 @@ @@ -225,6 +227,7 @@ + @@ -357,9 +360,17 @@
{{ viewForm.remark || '—' }}
+ + +
审批进度
+
+
{{ viewForm.signPurchaseHandler || '待审批' }}
+
{{ viewForm.signRequestGm || '待审批' }}
+
@@ -395,6 +406,26 @@ + + +
+ + + + + + +
+ 请选择管理层审批人进行一审 +
+
+
+ +
+
@@ -554,7 +585,8 @@ import { delPurchaseRequisition, submitApproval, approvePurchase, - rejectPurchase + rejectPurchase, + selectApproverUsers } from '@/api/erp/purchaseRequisition' export default { @@ -589,9 +621,30 @@ export default { approvalReq: {}, approvalRemark: '', approvalLoading: false, + // 提交审批选人 + submitDialogVisible: false, + submitLoading: false, + approverUsers: [], + selectedApproverId: null, + submittingReqId: null, rules: {} } }, + computed: { + currentNickName() { + return this.$store.getters.nickName || '' + }, + canView() { + const permissions = this.$store.getters.permissions || [] + const roles = this.$store.getters.roles || [] + const nickName = this.$store.getters.nickName || '' + // 有查看权限 或 有glc角色 或是陈清鑫 + if (permissions.some(p => p === '*:*:*' || p === 'erp:purchaseRequisition:query')) return true + if (roles.some(r => r === 'admin' || r === 'glc')) return true + if (nickName === '陈清鑫') return true + return false + } + }, created() { this.getList() }, @@ -674,14 +727,35 @@ export default { this.viewForm = res.data || {} }) }, - // 提交审批(单个操作列) + // 提交审批 — 打开选人弹窗 handleSubmitOne(row) { - this.$modal.confirm('确认提交该请购单进行审批?').then(() => { - return submitApproval(row.reqId) - }).then(() => { + this.submittingReqId = row.reqId + this.selectedApproverId = null + this.submitLoading = true + this.submitDialogVisible = true + // 加载管理层审批人(角色标识由后端 erp.approver.role-key 配置) + selectApproverUsers().then(res => { + this.approverUsers = res.data || [] + }).catch(() => { + this.approverUsers = [] + }).finally(() => { + this.submitLoading = false + }) + }, + // 确认提交审批 + doSubmitApproval() { + if (!this.selectedApproverId) return + this.submitLoading = true + // 获取选中的审批人昵称 + const user = this.approverUsers.find(u => u.userId === this.selectedApproverId) + const nickName = user ? user.nickName : '' + submitApproval(this.submittingReqId, this.selectedApproverId, nickName).then(() => { this.$modal.msgSuccess('已提交审批') + this.submitDialogVisible = false this.getList() - }).catch(() => {}) + }).catch(() => {}).finally(() => { + this.submitLoading = false + }) }, // 打开审批弹窗 openApproval(row) { @@ -804,11 +878,11 @@ export default { }, // 状态 statusText(s) { - const map = { '0': '请购草稿', '1': '审批中', '2': '已通过', '3': '采购处理中', '4': '已完成', '5': '已驳回' } + const map = { '0': '请购草稿', '1': '审批中', '6': '一审通过待二审', '2': '已通过', '3': '采购处理中', '4': '已完成', '5': '已驳回' } return map[s] || s || '—' }, statusType(s) { - const map = { '0': 'info', '1': 'warning', '2': 'success', '3': 'warning', '4': 'success', '5': 'danger' } + const map = { '0': 'info', '1': 'warning', '6': 'primary', '2': 'success', '3': 'warning', '4': 'success', '5': 'danger' } return map[s] || 'info' }, // 品检条件 — 数字代码 -> 可读描述(查看弹窗用) @@ -1047,6 +1121,7 @@ $sub: #909399; &.s3 { color: #d6a256; border-color: #ecd4a6; background: #fdf6ec; } &.s4 { color: $accent; border-color: #b9d2e6; background: #eef3f8; } &.s5 { color: #c45656; border-color: #e6c4c4; background: #fbf0f0; } + &.s6 { color: #5b8db8; border-color: #b9d2e6; background: #eef3f8; } } } From cc42108d4f467993ba543a2f80183bcce6abcda8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=98=8A=E5=A4=A9?= <15984976+n2319_0@user.noreply.gitee.com> Date: Wed, 8 Jul 2026 11:25:13 +0800 Subject: [PATCH 19/23] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=BB=B4=E4=BF=9D?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=AD=97=E6=AE=B5=E5=92=8C=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flow/domain/EqpMaintenancePlanDetail.java | 6 + .../domain/bo/EqpMaintenancePlanDetailBo.java | 6 + .../domain/vo/EqpMaintenancePlanDetailVo.java | 40 +- .../flow/EqpMaintenancePlanDetailMapper.xml | 6 + klp-ui/src/utils/enum.js | 12 +- klp-ui/src/views/wms/post/eqp/approval.vue | 27 +- klp-ui/src/views/wms/post/eqp/execute.vue | 21 +- klp-ui/src/views/wms/post/eqp/index.vue | 388 +++++++++++++----- ...707_eqp_maintenance_plan_detail_fields.sql | 8 + 9 files changed, 379 insertions(+), 135 deletions(-) create mode 100644 script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql diff --git a/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java b/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java index 1be5a9ede..68ea2c5fc 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/EqpMaintenancePlanDetail.java @@ -55,6 +55,12 @@ public class EqpMaintenancePlanDetail extends BaseEntity { * 维修内容描述 */ private String repairContent; + private String lineExecutor; + private String equipmentExecutor; + private String plannedCompleteTime; + private String actualCompleteTime; + private String totalHours; + private String acceptanceUser; /** * 维修负责人 */ diff --git a/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java b/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java index f02ccc350..f0709efc8 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/bo/EqpMaintenancePlanDetailBo.java @@ -62,6 +62,12 @@ public class EqpMaintenancePlanDetailBo extends BaseEntity { * 维修内容描述 */ private String repairContent; + private String lineExecutor; + private String equipmentExecutor; + private String plannedCompleteTime; + private String actualCompleteTime; + private String totalHours; + private String acceptanceUser; /** * 维修负责人 diff --git a/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java b/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java index 61569a24a..537f9bb83 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/vo/EqpMaintenancePlanDetailVo.java @@ -25,80 +25,92 @@ public class EqpMaintenancePlanDetailVo { /** * 明细ID */ - @ExcelProperty(value = "明细ID") + @ExcelProperty(value = "编号") private Long detailId; /** * 维修计划ID */ - @ExcelProperty(value = "维修计划ID") private Long planId; /** * 产线名称 */ - @ExcelProperty(value = "产线名称") private String productionLine; /** * 设备部件名称 */ - @ExcelProperty(value = "设备部件名称") private String componentName; /** * 单条维修项计划执行日期 */ - @ExcelProperty(value = "单条维修项计划执行日期") + @ExcelProperty(value = "时间") + @JsonFormat(pattern = "yyyy-MM-dd") private Date itemPlanDate; /** * 明细类型:0=保养 1=维修 */ - @ExcelProperty(value = "明细类型:0=保养 1=维修") + @ExcelProperty(value = "明细类型", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=保养,1=维修") private Long maintenanceCategory; /** * 明细完成状态:0=未开始 1=进行中 2=已完成 */ - @ExcelProperty(value = "明细完成状态:0=未开始 1=进行中 2=已完成") + @ExcelProperty(value = "是否完成", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=否,1=否,2=是") private Long detailStatus; /** * 维修内容描述 */ - @ExcelProperty(value = "维修内容描述") + @ExcelProperty(value = "具体工作内容") private String repairContent; + @ExcelProperty(value = "产线执行人员") + private String lineExecutor; + + @ExcelProperty(value = "设备执行人员") + private String equipmentExecutor; + + @ExcelProperty(value = "预计完成时间") + private String plannedCompleteTime; + + @ExcelProperty(value = "实际完成时间") + private String actualCompleteTime; + + @ExcelProperty(value = "总耗时(h)") + private String totalHours; + + @ExcelProperty(value = "验收人") + private String acceptanceUser; + /** * 维修负责人 */ - @ExcelProperty(value = "维修负责人") private String repairUser; /** * 完成时间(打勾时记录) */ - @ExcelProperty(value = "完成时间", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "打=勾时记录") private Date completeTime; /** * 实际支出金额(元) */ - @ExcelProperty(value = "实际支出金额(元)") private BigDecimal actualCost; /** * 完成进度百分比(0-100) */ - @ExcelProperty(value = "完成进度百分比(0-100)") private Long progressRate; /** * 目标厂家 */ - @ExcelProperty(value = "目标厂家") private String targetManufacturer; /** diff --git a/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml b/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml index a51a88805..6732e384d 100644 --- a/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml +++ b/klp-flow/src/main/resources/mapper/flow/EqpMaintenancePlanDetailMapper.xml @@ -13,6 +13,12 @@ + + + + + + diff --git a/klp-ui/src/utils/enum.js b/klp-ui/src/utils/enum.js index ea440f4fc..4787c34a8 100644 --- a/klp-ui/src/utils/enum.js +++ b/klp-ui/src/utils/enum.js @@ -12,4 +12,14 @@ export const MemoInputStorageKey = { packagingRequirement: 'packagingRequirement', // 打包要求 coilSpec: 'coilSpec', // 钢卷规格 coatingType: 'coatingType', // 钢卷镀层种类 -} \ No newline at end of file + transferNo: 'transferNo', // 调拨单号 + transferName: 'transferName', // 调拨单名称 + maintenanceRepairContent: 'maintenanceRepairContent', // 维修明细-具体工作内容 + maintenanceLineExecutor: 'maintenanceLineExecutor', // 维修明细-产线执行人员 + maintenanceEquipmentExecutor: 'maintenanceEquipmentExecutor', // 维修明细-设备执行人员 + maintenancePlannedCompleteTime: 'maintenancePlannedCompleteTime', // 维修明细-预计完成时间 + maintenanceActualCompleteTime: 'maintenanceActualCompleteTime', // 维修明细-实际完成时间 + maintenanceTotalHours: 'maintenanceTotalHours', // 维修明细-总耗时 + maintenanceAcceptanceUser: 'maintenanceAcceptanceUser', // 维修明细-验收人 + maintenanceRemark: 'maintenanceRemark', // 维修明细-备注 +} diff --git a/klp-ui/src/views/wms/post/eqp/approval.vue b/klp-ui/src/views/wms/post/eqp/approval.vue index 5cdfa9ab2..b937bba68 100644 --- a/klp-ui/src/views/wms/post/eqp/approval.vue +++ b/klp-ui/src/views/wms/post/eqp/approval.vue @@ -103,20 +103,23 @@ 维修明细 · Maintenance Details
- - - - + + - - - - + + - + + + + + + + + + + +
暂无维修明细
diff --git a/klp-ui/src/views/wms/post/eqp/execute.vue b/klp-ui/src/views/wms/post/eqp/execute.vue index ddb6af688..ed50a8a7d 100644 --- a/klp-ui/src/views/wms/post/eqp/execute.vue +++ b/klp-ui/src/views/wms/post/eqp/execute.vue @@ -92,16 +92,19 @@ 维修明细进度 · Detail Progress
- - - - + + - - + + + + + + + + + + @@ -240,18 +321,18 @@ import { listMaintenancePlanDetail, addMaintenancePlanDetail, updateMaintenanceP import { listEquipmentInspectionRecord } from "@/api/mes/eqp/equipmentInspectionRecord"; import { listProductionLine } from "@/api/wms/productionLine"; import DragResizePanel from "@/components/DragResizePanel/index.vue"; +import MemoInput from "@/components/MemoInput/index.vue"; import { parseTime } from '@/utils/klp' export default { name: "EqpMaintenance", - components: { DragResizePanel }, + components: { DragResizePanel, MemoInput }, data() { return { loading: false, detailLoading: false, buttonLoading: false, inspectionLoading: false, - detailButtonLoading: false, total: 0, dataList: [], currentRow: null, @@ -273,11 +354,7 @@ export default { inspectionQueried: false, selectedInspectionRows: [], // 维修明细 - detailList: [], - detailDialogVisible: false, - detailDialogTitle: "", - detailForm: {}, - editingDetailId: null + detailList: [] }; }, created() { @@ -324,7 +401,9 @@ export default { loadDetailList(planId) { var self = this; listMaintenancePlanDetail({ planId: planId, pageNum: 1, pageSize: 999 }).then(function(r) { - self.detailList = r.rows || []; + self.detailList = (r.rows || []).map(function(item) { + return self.decorateDetailRow(item); + }); }); }, // ---- 检修记录查询 ---- @@ -373,9 +452,17 @@ export default { componentName: rec.partName || '', productionLine: self.currentRow.productionLine || rec.productionLine || '', maintenanceCategory: 1, + itemPlanDate: rec.inspectTime ? parseTime(rec.inspectTime, '{y}-{m}-{d}') : parseTime(new Date(), '{y}-{m}-{d}'), repairContent: rec.abnormalDesc || '', + lineExecutor: rec.inspector || '', + equipmentExecutor: '', + plannedCompleteTime: '', + actualCompleteTime: '', + totalHours: '', + acceptanceUser: '', repairUser: rec.inspector || '', - detailStatus: 0 + detailStatus: 0, + remark: rec.remark || '' }); }); Promise.all(promises).then(function() { @@ -464,56 +551,139 @@ export default { }, // ---- 明细管理 ---- handleAddDetail() { - this.detailForm = { - planId: this.currentRow.planId, - componentName: '', - productionLine: this.currentRow.productionLine || '', - maintenanceCategory: 1, - repairContent: '', - repairUser: '', - itemPlanDate: undefined, - targetManufacturer: '', - detailStatus: 0 - }; - this.editingDetailId = null; - this.detailDialogTitle = "添加维修明细"; - this.detailDialogVisible = true; - }, - handleEditDetail(row) { - this.detailForm = Object.assign({}, row); - this.editingDetailId = row.detailId; - this.detailDialogTitle = "编辑维修明细"; - this.detailDialogVisible = true; - }, - submitDetailForm() { - if (!this.detailForm.componentName) { - this.$modal.msgWarning("请输入设备部件名称"); + if (!this.currentRow || !this.currentRow.planId) return; + if (this.getEditingDetailRow()) { + this.$modal.msgWarning("请先保存或取消当前编辑行"); return; } - var self = this; - this.detailButtonLoading = true; - if (this.editingDetailId) { - updateMaintenancePlanDetail(this.detailForm).then(function() { - self.$modal.msgSuccess("修改成功"); - self.detailDialogVisible = false; - self.loadDetailList(self.currentRow.planId); - }).finally(function() { self.detailButtonLoading = false; }); - } else { - addMaintenancePlanDetail(this.detailForm).then(function() { - self.$modal.msgSuccess("添加成功"); - self.detailDialogVisible = false; - self.loadDetailList(self.currentRow.planId); - }).finally(function() { self.detailButtonLoading = false; }); + var row = this.decorateDetailRow(this.getDefaultDetailRow()); + row._isNew = true; + row._editing = true; + row._origin = null; + this.detailList.unshift(row); + }, + handleEditDetail(row) { + if (!row) return; + var editing = this.getEditingDetailRow(); + if (editing && editing !== row) { + this.$modal.msgWarning("请先保存或取消当前编辑行"); + return; } + this.beginDetailEdit(row); + }, + beginDetailEdit(row) { + if (!row) return; + row._origin = JSON.parse(JSON.stringify({ + itemPlanDate: row.itemPlanDate, + repairContent: row.repairContent, + lineExecutor: row.lineExecutor, + equipmentExecutor: row.equipmentExecutor, + plannedCompleteTime: row.plannedCompleteTime, + actualCompleteTime: row.actualCompleteTime, + totalHours: row.totalHours, + acceptanceUser: row.acceptanceUser, + detailStatus: row.detailStatus, + remark: row.remark + })); + row._editing = true; + }, + cancelEditDetail(row) { + if (!row) return; + if (row._isNew) { + this.detailList = this.detailList.filter(function(r) { return r !== row; }); + return; + } + if (row._origin) { + row.itemPlanDate = row._origin.itemPlanDate; + row.repairContent = row._origin.repairContent; + row.lineExecutor = row._origin.lineExecutor; + row.equipmentExecutor = row._origin.equipmentExecutor; + row.plannedCompleteTime = row._origin.plannedCompleteTime; + row.actualCompleteTime = row._origin.actualCompleteTime; + row.totalHours = row._origin.totalHours; + row.acceptanceUser = row._origin.acceptanceUser; + row.detailStatus = row._origin.detailStatus; + row.remark = row._origin.remark; + } + row._editing = false; + row._origin = null; }, handleDeleteDetail(row) { var self = this; + if (!row) return; + if (row._isNew) { + this.detailList = this.detailList.filter(function(r) { return r !== row; }); + return; + } this.$modal.confirm('确认删除该维修明细?').then(function() { return delMaintenancePlanDetail(row.detailId); }).then(function() { self.$modal.msgSuccess("删除成功"); self.loadDetailList(self.currentRow.planId); }).catch(function() { }); + }, + getEditingDetailRow() { + return this.detailList.find(function(r) { return r && r._editing; }) || null; + }, + decorateDetailRow(row) { + var r = row || {}; + if (!r._rowKey) r._rowKey = r.detailId ? ("detail_" + r.detailId) : ("tmp_" + Date.now() + "_" + Math.random().toString(16).slice(2)); + if (typeof r._editing !== 'boolean') r._editing = false; + if (typeof r._isNew !== 'boolean') r._isNew = false; + if (!r._origin) r._origin = null; + if (r.detailStatus === undefined || r.detailStatus === null) r.detailStatus = 0; + return r; + }, + getDefaultDetailRow() { + return { + planId: this.currentRow.planId, + componentName: '', + productionLine: this.currentRow.productionLine || '', + maintenanceCategory: 1, + itemPlanDate: parseTime(new Date(), '{y}-{m}-{d}'), + repairContent: '', + lineExecutor: '', + equipmentExecutor: '', + plannedCompleteTime: '', + actualCompleteTime: '', + totalHours: '', + acceptanceUser: '', + detailStatus: 0, + remark: '' + }; + }, + buildDetailPayload(row) { + return { + detailId: row.detailId, + planId: this.currentRow.planId, + componentName: row.componentName, + productionLine: this.currentRow.productionLine || row.productionLine || '', + maintenanceCategory: row.maintenanceCategory === undefined ? 1 : row.maintenanceCategory, + itemPlanDate: row.itemPlanDate, + repairContent: row.repairContent, + lineExecutor: row.lineExecutor, + equipmentExecutor: row.equipmentExecutor, + plannedCompleteTime: row.plannedCompleteTime, + actualCompleteTime: row.actualCompleteTime, + totalHours: row.totalHours, + acceptanceUser: row.acceptanceUser, + detailStatus: row.detailStatus, + remark: row.remark + }; + }, + saveDetailRow(row) { + if (!row) return; + if (!row.repairContent) { + this.$modal.msgWarning("请输入具体工作内容"); + return; + } + var self = this; + var payload = this.buildDetailPayload(row); + var api = row._isNew || !row.detailId ? addMaintenancePlanDetail : updateMaintenancePlanDetail; + api(payload).then(function() { + self.$modal.msgSuccess(row._isNew || !row.detailId ? "添加成功" : "修改成功"); + self.loadDetailList(self.currentRow.planId); + }); } } }; @@ -530,6 +700,11 @@ export default { .search-row { display: flex; align-items: center; gap: 6px; padding: 0 14px 10px; background: #f5f7fa; } .search-row .el-input { flex: 1; } .list-body { flex: 1; overflow-y: auto; padding: 0 6px; } +.list-body { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } +.list-body::-webkit-scrollbar { width: 8px; height: 8px; } +.list-body::-webkit-scrollbar-track { background: transparent; } +.list-body::-webkit-scrollbar-thumb { background: rgba(144, 147, 153, 0.35); border-radius: 6px; } +.list-body::-webkit-scrollbar-thumb:hover { background: rgba(144, 147, 153, 0.55); } .list-item { display: flex; align-items: center; padding: 10px 12px; margin-bottom: 2px; cursor: pointer; border-radius: 6px; transition: all 0.15s; } .list-item:hover { background: #ebeef5; } .list-item.active { background: #d9ecff; } @@ -546,7 +721,7 @@ export default { /* ========== 右侧面板 ========== */ .right-panel { height: 100%; overflow: hidden; display: flex; flex-direction: column; background: #faf8f5; } .empty-tip { display: flex; align-items: center; justify-content: center; height: 100%; color: #909399; font-size: 14px; gap: 8px; } -.right-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; padding: 12px 16px; } +.right-content { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; padding: 12px 16px; } /* 基本信息栏 */ .info-bar { display: flex; align-items: center; justify-content: space-between; padding: 8px 16px; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; margin-bottom: 10px; flex-shrink: 0; } @@ -563,10 +738,25 @@ export default { .section-count { font-size: 12px; color: #909399; } .section-actions { display: flex; align-items: center; gap: 6px; } .inspection-section .el-table { flex: 1; overflow-y: auto; } +.inspection-section .el-table { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } +.detail-section .el-table { scrollbar-width: thin; scrollbar-color: rgba(144, 147, 153, 0.45) transparent; } +.inspection-section ::v-deep .el-table, +.detail-section ::v-deep .el-table { display: flex; flex-direction: column; height: 100%; } +.inspection-section ::v-deep .el-table__body-wrapper, +.detail-section ::v-deep .el-table__body-wrapper { flex: 1; min-height: 0; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar { width: 8px; height: 8px; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track { background: transparent; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb { background: rgba(144, 147, 153, 0.35); border-radius: 6px; } +.inspection-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover, +.detail-section ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover { background: rgba(144, 147, 153, 0.55); } /* 下半部分:维修明细 */ .detail-section { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; } .detail-section .el-table { flex: 1; overflow-y: auto; } +.cell-pre-wrap { white-space: pre-wrap; word-break: break-all; line-height: 18px; } .empty-data { padding: 24px 0; text-align: center; color: #c0c4cc; font-size: 13px; } diff --git a/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql b/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql new file mode 100644 index 000000000..aaff01765 --- /dev/null +++ b/script/sql/mysql/update/update_20260707_eqp_maintenance_plan_detail_fields.sql @@ -0,0 +1,8 @@ +ALTER TABLE eqp_maintenance_plan_detail + ADD COLUMN line_executor varchar(64) NULL, + ADD COLUMN equipment_executor varchar(64) NULL, + ADD COLUMN planned_complete_time varchar(64) NULL, + ADD COLUMN actual_complete_time varchar(64) NULL, + ADD COLUMN total_hours varchar(64) NULL, + ADD COLUMN acceptance_user varchar(64) NULL; + From 3acb6d7f54b7e5e52d84ac5875a25103b8907b55 Mon Sep 17 00:00:00 2001 From: jhd <1684074631@qq.com> Date: Wed, 8 Jul 2026 11:37:35 +0800 Subject: [PATCH 20/23] =?UTF-8?q?feat(erp):=20=E4=B8=BA=E8=AF=B7=E8=B4=AD?= =?UTF-8?q?=E5=8D=95=E5=A2=9E=E5=8A=A0=E5=AE=A1=E6=89=B9=E6=84=8F=E8=A7=81?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在ErpPurchaseRequisition实体类中添加一审和二审审批意见字段 - 在ErpPurchaseRequisitionBo和ErpPurchaseRequisitionVo中同步添加审批意见字段 - 修改approve和reject方法接口,支持传递审批意见参数 - 在服务实现层将审批意见保存到对应字段中 - 更新前端控制器接收审批意见参数并传递给服务层 - 在前端页面显示审批意见,并调整审批进度布局样式 - 添加数据库表结构变更SQL脚本,增加审批意见字段 --- docs/klp_purchase_requisition_alter_1.sql | 7 +++++++ .../ErpPurchaseRequisitionController.java | 10 ++++++---- .../klp/erp/domain/ErpPurchaseRequisition.java | 6 ++++++ .../erp/domain/bo/ErpPurchaseRequisitionBo.java | 6 ++++++ .../erp/domain/vo/ErpPurchaseRequisitionVo.java | 6 ++++++ .../service/IErpPurchaseRequisitionService.java | 4 ++-- .../impl/ErpPurchaseRequisitionServiceImpl.java | 8 ++++++-- klp-ui/src/api/erp/purchaseRequisition.js | 10 ++++++---- .../src/views/erp/purchaseRequisition/index.vue | 16 +++++++++++----- 9 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 docs/klp_purchase_requisition_alter_1.sql diff --git a/docs/klp_purchase_requisition_alter_1.sql b/docs/klp_purchase_requisition_alter_1.sql new file mode 100644 index 000000000..5f440b189 --- /dev/null +++ b/docs/klp_purchase_requisition_alter_1.sql @@ -0,0 +1,7 @@ +-- ======================================== +-- 电子请购单 — 增量变更 1:增加审批意见字段 +-- ======================================== + +ALTER TABLE `erp_purchase_requisition` + ADD COLUMN `first_approval_opinion` VARCHAR(500) DEFAULT NULL COMMENT '一审审批意见' AFTER `remark`, + ADD COLUMN `second_approval_opinion` VARCHAR(500) DEFAULT NULL COMMENT '二审审批意见' AFTER `first_approval_opinion`; diff --git a/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchaseRequisitionController.java b/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchaseRequisitionController.java index 991173e3e..3f960d69b 100644 --- a/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchaseRequisitionController.java +++ b/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchaseRequisitionController.java @@ -94,14 +94,16 @@ public class ErpPurchaseRequisitionController extends BaseController { /** 审批通过(审批中 → 已通过) */ @Log(title = "请购及采购单", businessType = BusinessType.UPDATE) @PutMapping("/{reqId}/approve") - public R approve(@NotNull(message = "主键不能为空") @PathVariable Long reqId) { - return toAjax(iErpPurchaseRequisitionService.approve(reqId)); + public R approve(@NotNull(message = "主键不能为空") @PathVariable Long reqId, + @RequestParam(required = false) String approvalOpinion) { + return toAjax(iErpPurchaseRequisitionService.approve(reqId, approvalOpinion)); } /** 驳回(审批中 → 已驳回) */ @Log(title = "请购及采购单", businessType = BusinessType.UPDATE) @PutMapping("/{reqId}/reject") - public R reject(@NotNull(message = "主键不能为空") @PathVariable Long reqId) { - return toAjax(iErpPurchaseRequisitionService.reject(reqId)); + public R reject(@NotNull(message = "主键不能为空") @PathVariable Long reqId, + @RequestParam(required = false) String approvalOpinion) { + return toAjax(iErpPurchaseRequisitionService.reject(reqId, approvalOpinion)); } } diff --git a/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchaseRequisition.java b/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchaseRequisition.java index 16a1782f6..8e6b031e4 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchaseRequisition.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchaseRequisition.java @@ -106,6 +106,12 @@ public class ErpPurchaseRequisition extends BaseEntity { @TableLogic private String delFlag; + /** 一审审批意见 */ + private String firstApprovalOpinion; + + /** 二审审批意见 */ + private String secondApprovalOpinion; + /** 备注 */ private String remark; } diff --git a/klp-erp/src/main/java/com/klp/erp/domain/bo/ErpPurchaseRequisitionBo.java b/klp-erp/src/main/java/com/klp/erp/domain/bo/ErpPurchaseRequisitionBo.java index a7d12f3dc..85b719b2f 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/bo/ErpPurchaseRequisitionBo.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/bo/ErpPurchaseRequisitionBo.java @@ -100,6 +100,12 @@ public class ErpPurchaseRequisitionBo extends BaseEntity { /** 状态 */ private String formStatus; + /** 一审审批意见 */ + private String firstApprovalOpinion; + + /** 二审审批意见 */ + private String secondApprovalOpinion; + /** 备注 */ private String remark; diff --git a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchaseRequisitionVo.java b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchaseRequisitionVo.java index 8a715a776..f0714c0dc 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchaseRequisitionVo.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchaseRequisitionVo.java @@ -100,6 +100,12 @@ public class ErpPurchaseRequisitionVo implements Serializable { @ExcelProperty(value = "状态") private String formStatus; + @ExcelProperty(value = "一审审批意见") + private String firstApprovalOpinion; + + @ExcelProperty(value = "二审审批意见") + private String secondApprovalOpinion; + @ExcelProperty(value = "备注") private String remark; diff --git a/klp-erp/src/main/java/com/klp/erp/service/IErpPurchaseRequisitionService.java b/klp-erp/src/main/java/com/klp/erp/service/IErpPurchaseRequisitionService.java index 362673704..a7b7dc641 100644 --- a/klp-erp/src/main/java/com/klp/erp/service/IErpPurchaseRequisitionService.java +++ b/klp-erp/src/main/java/com/klp/erp/service/IErpPurchaseRequisitionService.java @@ -38,8 +38,8 @@ public interface IErpPurchaseRequisitionService { Boolean submitApproval(Long reqId, Long firstApproverId, String firstApproverName); /** 审批通过(审批中 → 已通过) */ - Boolean approve(Long reqId); + Boolean approve(Long reqId, String approvalOpinion); /** 驳回(审批中 → 已驳回) */ - Boolean reject(Long reqId); + Boolean reject(Long reqId, String approvalOpinion); } diff --git a/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchaseRequisitionServiceImpl.java b/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchaseRequisitionServiceImpl.java index 187e748fa..c4f61006c 100644 --- a/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchaseRequisitionServiceImpl.java +++ b/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchaseRequisitionServiceImpl.java @@ -149,7 +149,7 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio @Override @Transactional(rollbackFor = Exception.class) - public Boolean approve(Long reqId) { + public Boolean approve(Long reqId, String approvalOpinion) { ErpPurchaseRequisition entity = baseMapper.selectById(reqId); if (entity == null) return false; String currentNickName = LoginHelper.getNickName(); @@ -161,6 +161,7 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio throw new RuntimeException("您不是该请购单指定的审批人"); } entity.setFormStatus("6"); + entity.setFirstApprovalOpinion(approvalOpinion); return baseMapper.updateById(entity) > 0; } else if ("6".equals(entity.getFormStatus())) { @@ -170,6 +171,7 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio } entity.setFormStatus("2"); entity.setSignRequestGm("陈清鑫"); + entity.setSecondApprovalOpinion(approvalOpinion); return baseMapper.updateById(entity) > 0; } else { @@ -179,7 +181,7 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio @Override @Transactional(rollbackFor = Exception.class) - public Boolean reject(Long reqId) { + public Boolean reject(Long reqId, String approvalOpinion) { ErpPurchaseRequisition entity = baseMapper.selectById(reqId); if (entity == null) return false; String currentNickName = LoginHelper.getNickName(); @@ -191,6 +193,7 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio throw new RuntimeException("您不是该请购单指定的审批人"); } entity.setFormStatus("5"); + entity.setFirstApprovalOpinion(approvalOpinion); return baseMapper.updateById(entity) > 0; } else if ("6".equals(entity.getFormStatus())) { @@ -199,6 +202,7 @@ public class ErpPurchaseRequisitionServiceImpl implements IErpPurchaseRequisitio throw new RuntimeException("二审仅限指定审批人操作"); } entity.setFormStatus("5"); + entity.setSecondApprovalOpinion(approvalOpinion); return baseMapper.updateById(entity) > 0; } else { diff --git a/klp-ui/src/api/erp/purchaseRequisition.js b/klp-ui/src/api/erp/purchaseRequisition.js index add217ac9..8f408a9e7 100644 --- a/klp-ui/src/api/erp/purchaseRequisition.js +++ b/klp-ui/src/api/erp/purchaseRequisition.js @@ -45,18 +45,20 @@ export function submitApproval(reqId, firstApproverId, firstApproverName) { } // 审批通过 -export function approvePurchase(reqId) { +export function approvePurchase(reqId, approvalOpinion) { return request({ url: '/erp/purchaseRequisition/' + reqId + '/approve', - method: 'put' + method: 'put', + params: { approvalOpinion } }) } // 驳回 -export function rejectPurchase(reqId) { +export function rejectPurchase(reqId, approvalOpinion) { return request({ url: '/erp/purchaseRequisition/' + reqId + '/reject', - method: 'put' + method: 'put', + params: { approvalOpinion } }) } diff --git a/klp-ui/src/views/erp/purchaseRequisition/index.vue b/klp-ui/src/views/erp/purchaseRequisition/index.vue index b0ee90e13..07597349f 100644 --- a/klp-ui/src/views/erp/purchaseRequisition/index.vue +++ b/klp-ui/src/views/erp/purchaseRequisition/index.vue @@ -363,9 +363,15 @@
审批进度
-
-
{{ viewForm.signPurchaseHandler || '待审批' }}
-
{{ viewForm.signRequestGm || '待审批' }}
+
+
+
{{ viewForm.signPurchaseHandler || '待审批' }}
+
意见:{{ viewForm.firstApprovalOpinion }}
+
+
+
{{ viewForm.signRequestGm || '待审批' }}
+
意见:{{ viewForm.secondApprovalOpinion }}
+