Compare commits

...

349 Commits

Author SHA1 Message Date
0968dcaded Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-13 16:16:38 +08:00
cced2ff4aa feat(cost): 添加单价字段和使用单价标识功能
- 在CostProdMetric实体类中添加usePrice字段,用于标识是否使用单价
- 更新CostProdMetricBo、CostProdMetricVo数据传输对象,增加单价相关属性
- 修改CostProdMetricMapper.xml映射文件,添加usePrice字段映射配置
- 扩展CostProdMetricServiceImpl查询逻辑,支持按是否使用单价进行筛选
- 更新前端metric.vue页面,添加单价输入框和是否使用单价下拉选择组件
- 实现表格中单价列的显示和编辑功能,并增加条件查询支持
2026-06-13 16:16:30 +08:00
f197462b11 refactor(mes/qc): 重构质检模块接口与页面,迁移is模块业务到qc模块
1.  新增qc模块下检验主、检验明细、拉伸试验相关接口文件
2.  删除原is模块下的检验任务、样品库存、检验委托单接口与页面文件
3.  调整待办页面的检验任务标签页引用路径
4.  优化质检模板页面的检查项相关交互逻辑
2026-06-13 15:51:15 +08:00
9559e5810e refactor(domain): 重构拉伸检验细节实体的弯曲试验
- 将 bendTest90 字段重命名为 bendTest,统一弯曲试验结果字段
- 将 bendTest180 字段重命名为 bendTestReverse,明确表示反向弯曲试验
- 更新数据库映射文件中的字段映射关系
- 修改服务层查询条件中对应的字段引用
- 更新 Excel 导出注解中的字段描述和值映射
2026-06-13 14:34:24 +08:00
92ad229104 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-13 13:30:56 +08:00
ee1cb31321 feat(mes/eqp): 新增设备监控模拟页面
该页面实现了设备状态统计看板、多条件筛选搜索、自动刷新、设备卡片展示、详情弹窗查看功能,使用mock数据模拟真实设备运行状态和参数变化
2026-06-13 13:30:52 +08:00
f0de25a3a2 feat(inspection): 添加检验模块日期范围筛选功能
- 在WmsInspectionMainBo中增加inspectionDateStart和inspectionDateEnd字段用于日期范围筛选
- 在WmsInspectionMainServiceImpl中实现日期范围查询逻辑
- 在WmsInspectionTensileDetailBo中增加productionDateStart、productionDateEnd、testDateStart和testDateEnd字段
- 在WmsInspectionTensileDetailServiceImpl中实现生产日期和试验日期范围查询逻辑
- 添加DateTimeFormat注解支持日期格式化处理
2026-06-13 13:08:11 +08:00
0d40774194 feat(wms): 添加检验管理模块功能
- 新增检验项目明细相关实体类、业务对象、视图对象及服务接口
- 实现检验项目明细的增删改查、分页查询及数据校验功能
- 新增检验主记录相关实体类、业务对象、视图对象及服务接口
- 实现检验主记录的增删改查、分页查询及数据校验功能
- 新增金属材料室温拉伸试验相关实体类、业务对象、视图对象及服务接口
- 实现拉伸试验记录的增删改查、分页查询及数据校验功能
- 配置MyBatis映射文件及Excel导出功能
- 添加相应的控制器及参数验证规则
2026-06-13 13:02:43 +08:00
948e62daae fix(wms/report/comparison): 修复库存对比报表的查询参数错误
将原有的actionId、actionIds查询参数修正为coilId、coilIds,匹配接口实际需要的入参字段
2026-06-13 11:23:36 +08:00
48d12fe056 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-13 11:15:42 +08:00
6edc6e1100 feat(wms-report): 新增对比报表页面和尺寸异常统计功能
1. 新增comparison.vue对比报表页面,支持基期/当期数据对比、快速环比查询、明细表格查看和列配置
2. 在action.vue报表中添加尺寸异常统计模块,统计长度和厚度异常的卷数、总重及占比
3. 新增告警阈值配置获取逻辑,从系统配置中读取长度和厚度异常阈值
2026-06-13 11:15:38 +08:00
12ea9b0b83 refactor(wms/coil/label): 为热卷号添加动态字体大小适配
移除了硬编码的字体样式,根据热卷号长度动态调整字号,避免长文本溢出标签
2026-06-13 11:14:25 +08:00
c149216ebd refactor: 多页面UI优化、接口清理与文案调整
1. 移除质检模板页面未使用的getCheckItem接口导入
2. 给成本综合页面表格添加固定高度适配布局
3. 更新物料告警页面的表格列文案:理论值→推论值、实测值→实际值、实际偏差值→实际偏差
4. 重构重定向菜单页面的样式,优化布局与视觉效果
2026-06-13 11:14:14 +08:00
325a93fd84 refactor: 将“理论长度/厚度”统一改为“推论长度/厚度”
修改了CoilSelector组件、CoilInfo组件和报表列设置中的相关文案,将统一术语表述为“推论”,替代原有的“理论”表述。
2026-06-13 11:13:49 +08:00
f0656b57d4 fix(wms): 解决材料厚度预警中的精度比较问题
- 统一将理论厚度和规格厚度四舍五入到3位小数后再进行比较
- 避免因高精度尾数导致的比较结果与存储值不一致问题
- 对阈值也进行相同的精度处理确保比较逻辑正确
- 修复偏差值计算中重复精度转换的问题
- 优化偏差率计算中的除法精度控制
2026-06-13 10:22:22 +08:00
9c7d2dca65 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-12 16:00:45 +08:00
36b1e3da82 fix(warning): 解决退火工序告警处理问题
- 退火工序没有actionId时不创建代操作记录,直接设置actionType=600
- 当actionId为空时使用bo中的actionType作为兜底方案
- 确保退火工序的告警能够正确关联到对应的操作类型
2026-06-12 16:00:34 +08:00
c83eb79d25 fix(wms/coil/label): 修正标签页生产日期字段的时间来源
将多个标签渲染组件中的生产日期从updateTime改为createTime,统一展示正确的创建时间
2026-06-12 15:30:27 +08:00
e0cf4b46b6 feat(mes/qc): 增加物理性质和化学成分同时导入
新增了通用的综合导入组件,支持同时导入化学成分和物理性能数据,并在理化证书页面添加了对应的综合导入按钮和逻辑,实现一站式批量导入两种类型的质检数据。
2026-06-12 13:43:17 +08:00
00972112d2 feat: 多模块新增功能与优化体验
1. 隐藏客户录入页的客户编码字段
2. 为WmsMaterialWarningBo添加日期格式化注解
3. 合同产品选择时自动匹配默认材质
4. 物料告警页新增今日筛选、行样式区分与偏差率展示优化
5. 合同页新增快速新增客户功能
2026-06-12 13:31:58 +08:00
2559dc27cb feat(crm): 添加客户编码自动生成功能
- 新增 selectMaxCustomerCode 方法查询最大客户编码
- 实现客户编码自动生成逻辑,支持纯数字和带前缀格式
- 添加正则表达式解析编码规则并递增末尾数字
- 集成编码生成功能到客户插入业务流程中
2026-06-12 13:17:33 +08:00
7a0d7e1b12 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-12 13:03:34 +08:00
1cd2cf2b9a feat(wms): 添加物料预警创建时间范围查询功能
- 在WmsMaterialWarningBo中新增createStartTime和createEndTime字段
- 为新增字段添加JSON格式化注解和文档注释
- 在WmsMaterialWarningServiceImpl中实现时间范围查询逻辑
- 使用ge和le条件进行创建时间范围过滤
- 保持按创建时间倒序排列的排序规则
2026-06-12 13:03:25 +08:00
98116fa042 refactor: 多页面UI优化与功能完善
1. 优化合同页面默认备注内容
2. 修复分卷编辑接口参数缺失问题
3. 新增分卷、合卷、加工菜单路由
4. 重构导航栏默认显示逻辑
5. 升级重定向菜单页面样式与布局
6. 优化告警页面查询与展示字段
7. 重构全局搜索组件为弹窗模式
8. 优化报表页面代码格式与接口参数
2026-06-12 11:25:15 +08:00
d3c6790603 refactor(WmsMaterialWarningVo): 继承BaseEntity并移除钢卷信息的JSON忽略注解
- 继承com.klp.common.core.domain.BaseEntity类
- 移除coilVo字段的@JsonIgnore注解
- 更新类结构以支持基础实体功能
2026-06-11 17:23:48 +08:00
c1e3fa5141 fix(wms): 修复钢卷警告检查逻辑
- 注释掉新增钢卷时的长度/厚度偏差检查
- 添加actionId为空判断条件避免警告插入异常
- 优化更新钢卷时的警告检查逻辑
2026-06-11 16:49:15 +08:00
f319308196 refactor(domain): 移除WmsCoilAbnormalExportVo中的废弃字段
- 注释掉parentAbnormalId字段以优化数据结构
- 移除sourceSystem字段减少不必要的数据传输
- 删除processSource字段简化对象属性
- 保留plateSurface字段用于表列宽度设置
- 为后续代码清理和重构做准备
2026-06-11 16:25:06 +08:00
185745b7da Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-11 15:31:26 +08:00
7440706e2e style(sidebar): 优化侧边菜单样式与标识逻辑
1.  移除原有二级菜单叶子节点的小圆点样式
2.  新增子菜单标识图标组件,为有子级的菜单添加折叠箭头标识
3.  调整菜单标题渲染逻辑,统一标题样式处理
4.  修复菜单容器的定位样式问题
2026-06-11 15:31:23 +08:00
0adb29139e 修复厚度偏差曲线 2026-06-11 15:24:46 +08:00
2148a068f8 修复厚度偏差曲线 2026-06-11 15:10:56 +08:00
e1bb9e5431 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-11 15:02:08 +08:00
8b2039f06a 修复厚度偏差曲线 2026-06-11 14:59:31 +08:00
9761faa2d2 feat(wms, crm): 新增导出模式选择并修复canvas图片缩放问题
1. 为Wms异常报表页面新增多行/单行导出切换功能
2. 拆分导出菜单为单行、多行两种导出选项
3. 修复ContractExportDialog中图片缩放比例的冗余限制
2026-06-11 14:49:31 +08:00
d5f00a4b0b Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-11 14:02:52 +08:00
b9fb4b4611 refactor(wms/coil): 重构钢卷详情页面,拆分组件并优化页面结构
1.  将原钢卷详情页面拆分为多个独立组件,按功能模块划分
2.  调整路由指向,将页面入口指向新的页面文件
3.  新增状态工具类,封装通用格式化和样式
2026-06-11 14:02:49 +08:00
7d76ef0c52 feat(wms): 添加异常报表导出功能
- 在WmsMaterialCoilBo中新增abnormalExportCount字段用于控制导出格式
- 实现异常报表的Excel导出功能,支持两种导出模式
- 添加extracted方法处理导出逻辑,构建EasyExcel导出数据
- 创建createExportVo方法组装导出DTO对象,包含钢卷基本信息和异常信息
- 集成EasyExcel实现报表导出,设置响应头和文件下载格式
- 处理无异常信息钢卷的空数据行创建逻辑
2026-06-11 11:49:28 +08:00
ea71a6dd93 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-11 11:39:44 +08:00
b9b6ae7e79 fix(wms): 修复钢卷号重复校验问题
- 添加注释说明子卷与母卷钢卷号冲突的处理逻辑
- 在查询条件中增加exclusiveStatus字段过滤,避免正在处理的数据被误判为重复
- 修复入场钢卷号、当前钢卷号和供应商钢卷号的重复检查逻辑
- 确保历史数据和排他状态数据不会影响重复性校验结果
2026-06-11 11:39:29 +08:00
20a75aec4b Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-11 11:28:57 +08:00
3ad7bf40b5 feat: 新增二级菜单子导航系统(SubNav + redirectMenu)
- 新增 SubNav 组件:Navbar 下方水平子导航条,展示当前二级菜单下的三级页面,支持滚动和下拉分组
- 新增 redirectMenu 页面:点击二级菜单时卡片式展示子页面列表
- SidebarItem 深度 >=1 时改为叶子节点渲染(小圆点标记),激活高亮回退到二级菜单
- Navbar 布局重构为 Flexbox,面包屑/SubNav 根据场景切换
- 新增 productionLine Vuex 模块,轧辊研磨页改为 store 方式读取产线数据
- Sidebar activeMenu 逻辑增强:自动定位当前页所属二级菜单
2026-06-11 11:28:42 +08:00
196e628665 feat(WmsCoilAbnormal): 添加钢卷ID集合批量查询功能
- 在WmsCoilAbnormalBo中新增coilIds字段用于批量查询
- 实现逗号分隔的coilIds批量查询逻辑
- 使用Stream API处理字符串分割和类型转换
- 添加空值过滤确保查询条件的有效性
- 集成到现有的查询条件构建流程中
2026-06-11 10:24:55 +08:00
7c61c42eb5 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-11 09:49:54 +08:00
1223b634b7 refactor(wms): 移除销售人员相关字段
- 从WmsMaterialCoilExportVo中移除saleName私有字段
- 从WmsMaterialCoilVo中移除saleId和saleName私有字段
- 从WmsMaterialCoilMapper.xml的多个查询中移除sale_name映射
- 从WmsMaterialCoilMapper.xml的关联查询中移除sys_user表连接
- 移除与销售人员相关的数据库字段映射和关联关系
2026-06-11 09:49:42 +08:00
87913ba0a0 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-11 09:29:49 +08:00
eab45a8706 feat: 合同新增自动补全交货日期功能
- 签订日期变更时自动计算交货日期(签约 + 1天 + 30天 → 按5日取整)
- 选择合同模板或点击「自动补全交货日期」时自动替换合同内容中的交货时间占位符
- 新增 DC01-H 材质选项
- 修正按钮文案「管理合同」→「管理合同模板」
2026-06-11 09:29:33 +08:00
a9a7a0889e Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-10 17:45:05 +08:00
cd2e4016a6 feat(warning): 添加产线类型字段支持告警功能
- 在 WmsMaterialWarning 实体中新增 actionType 字段
- 在 WmsMaterialWarningBo 和 WmsMaterialWarningVo 中添加 actionType 属性
- 更新 WmsMaterialWarningMapper.xml 映射文件以包含 actionType 字段
- 在 WmsMaterialWarningServiceImpl 中注入 WmsCoilPendingActionMapper
- 实现告警查询时根据产线类型过滤的功能
- 在告警插入前查询并设置对应的产线类型信息
- 完善告警服务中的厚度和长度检查逻辑
2026-06-10 17:44:56 +08:00
87d72b2a0d feat(wms/coil): 增加排产厚度字段
1. 新增排产厚度字段到钢卷信息列表、报表列配置、分条/合并/录入页面
2. 优化部分代码格式与换行,修复多余空格问题
3. 调整表单布局,将排产厚度表单项加入对应页面
2026-06-10 17:22:12 +08:00
4342215c00 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-10 17:11:08 +08:00
7bf7d24f29 feat(wms/coil): 新增异常继承功能并优化钢卷列表页面
1.  为异常管理弹窗添加继承异常按钮和继承弹窗
2.  新增罩式退火原料库选项
3.  优化钢卷列表表格样式与列配置,新增标签预览、打印、数字钢卷、追溯功能
4.  复用生产工序配置常量统一维护
2026-06-10 17:11:05 +08:00
4da8d8d297 feat(wms): 添加排产厚度字段支持
- 在 WmsMaterialCoil 实体类中新增 scheduleThickness 字段
- 在 WmsMaterialCoilBo 业务对象中新增 scheduleThickness 字段
- 在 WmsMaterialCoilController 控制器中添加排产厚度列映射
- 在 WmsMaterialCoilExportVo 导出对象中添加 Excel 导出支持
- 在 WmsMaterialCoilMapper.xml 中添加数据库映射配置
- 在 WmsMaterialCoilServiceImpl 服务实现中添加查询条件支持
- 修复钢卷号重复检查逻辑中的数据类型判断问题
- 在 WmsMaterialCoilVo 视图对象中添加排产厚度字段
2026-06-10 16:49:00 +08:00
c4eab467ee feat(wms): 添加钢卷号重复检查功能
- 在新增钢卷时检查当前钢卷号是否重复
- 在简单更新时检查当前钢卷号是否重复并排除自身
- 在单个更新时检查当前钢卷号是否重复并排除自身
- 在分卷操作时检查每个子钢卷号是否重复
- 在合卷操作时检查新钢卷号是否重复
- 在子钢卷创建时检查子钢卷号是否重复
- 在退货操作时检查当前钢卷号是否重复并排除自身
- 修复历史钢卷恢复时的重复检查参数传递问题
2026-06-10 15:54:01 +08:00
fd50118161 refactor(contract/export/preview): 优化合同打印导出功能,添加页码和修复样式
1.  移除coilTable的异常行高亮逻辑
2.  修复导航栏告警badge的显示逻辑
3.  为合同导出和预览添加页码标注,调整打印样式
4.  移除冗余的合同打印预览代码
2026-06-10 11:29:41 +08:00
cc63aa80b2 fix: 修复/优化多个业务页面的逻辑与配置
1. 修正物料选项中的BX51D+Z为DX51D+Z
2. 给L2匹配面板的标准化方法添加日志与start_date/end_date字段解析
3. 优化卷材页面的日期赋值逻辑并添加调试日志
4. 简化异常表格的图片组件写法,新增继承来源列
2026-06-10 09:21:34 +08:00
c95ea7db61 feat(mes/roll/grind): 磨辊间增加机组字段 2026-06-09 17:55:42 +08:00
f50c240bbe Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-09 17:47:46 +08:00
66278e635b feat(roll): 添加机架字段支持
- 在MesRollInfo实体类中新增frame字段
- 在MesRollInfoBo业务对象中添加frame字段定义
- 实现机架字段的查询过滤功能
- 在MesRollInfoVo视图对象中增加frame字段映射
- 完成机架数据的Excel导出功能
2026-06-09 17:47:35 +08:00
74d0ba57e2 feat(crm/contract): 优化合同产品材质输入与导出样式
1. 将材质输入框改为可搜索创建的选择器,新增冷轧卷(花纹)选项和SPCC等材质选项
2. 优化合同导出表格的边框、内边距和字体样式,统一表格样式
2026-06-09 17:42:28 +08:00
e00d1357b0 refactor(wms): 优化钢卷告警数据查询逻辑解决循环依赖
- 将钢卷信息批量查询逻辑从服务层迁移到控制器层
- 在控制器中实现钢卷ID收集和批量查询功能
- 通过Map映射方式关联钢卷信息到告警数据
- 移除服务层中的WmsMaterialCoilService依赖注入
- 提高数据查询效率和代码结构清晰度
2026-06-09 17:08:01 +08:00
b9f87c6cc4 feat(warning): 添加物料预警按创建时间倒序排序功能
- 实现物料预警列表按创建时间倒序排列
- 优化查询逻辑以支持时间排序功能
2026-06-09 10:04:36 +08:00
7c9c99bf45 feat(wms): 添加钢卷警告信息关联查询功能
- 在 WmsMaterialWarningBo 中新增 coilIds 字段用于批量过滤
- 在 WmsMaterialWarningServiceImpl 中实现批量钢卷信息查询和填充逻辑
- 添加按逗号分隔的钢卷ID集合过滤功能
- 在 WmsMaterialWarningVo 中增加 coilVo 关联字段并设置为忽略导出
- 实现了钢卷警告与钢卷信息的关联显示功能
- 优化了查询性能通过批量获取钢卷数据减少数据库访问次数
2026-06-09 09:58:35 +08:00
fdb13b7261 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-09 09:41:31 +08:00
74a3803290 refactor(WmsMaterialCoilService): 修复理论厚度和长度沿用老数据导致重复告警
- 移除理论厚度为空的条件判断,统一实际长度不为空时进行计算
- 移除理论长度为空的条件判断,改为直接计算并设置理论长度
- 保持原有的体积、宽度和厚度计算公式不变
- 简化代码结构,减少不必要的条件分支
2026-06-09 09:41:14 +08:00
76497eece7 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-09 09:02:47 +08:00
d231d3619a feat(wms/report): add length/thickness diff columns and abnormal alert
1. 调整产品内容工具函数,移除冗余的quantity和taxPrice字段返回
2. 重新编排报表列配置,新增长度/厚度差值列并调整字段顺序
3. 实现差值计算逻辑与异常标红展示,从配置获取告警阈值
2026-06-09 09:02:44 +08:00
20966157c5 fix(wms): 修正材料预警服务中的数值精度计算问题
- 为理论值、实际值、允许偏差和偏差值设置统一的3位小数精度
- 将偏差率计算精度从4位小数调整为1位小数
- 修正厚度偏差计算公式中的减法运算顺序
- 在警告消息中应用相同的数值精度格式化
- 确保所有BigDecimal运算都使用HALF_UP舍入模式
2026-06-08 18:02:52 +08:00
59e58e5206 feat(warning): 更新钢卷告警检查功能支持动态阈值配置
- 在 WmsMaterialCoilBo 中新增 specThickness 字段用于存储规格厚度
- 修改 checkAndInsertWarnings 方法签名以传递 BO 对象
- 将长度和厚度告警阈值改为从系统配置表动态读取
- 长度告警阈值配置键为 material.warning.length,默认值 0.1
- 厚度告警阈值配置键为 material.warning.thickness,默认值 -0.01
- 厚度检查逻辑改为理论厚度与规格厚度对比
- 钢卷创建和更新流程中传递 BO 对象到告警检查方法
- 优化告警消息内容以反映阈值检查而非固定比例
- 移除原有的实测厚度检查规则,统一使用规格厚度作为参考标准
2026-06-08 17:45:10 +08:00
59ceeed4a4 fix(crm/contract): 优化合同预览与导出的样式及重复渲染问题
1.  为产品内容组件添加值相等判断,避免重复解析内容
2.  统一合同预览和导出弹窗的表格边框样式为2px粗边框
3.  将合同预览的字体改为黑体并调整字重,优化显示效果
4.  调整表格字体粗细的配置标准
2026-06-08 16:31:17 +08:00
fac59f4346 feat: 合同导出新增附件图片配置功能
- 新增附件图片加载区域(从 businessAnnex/techAnnex 等字段提取 OSS 图片)
- 支持图片勾选显隐、拖拽排序(上移/下移)
- 导出 HTML 预览和 PDF 均支持图片附件页渲染
- @open 重构为 onDialogOpen,自动拉取附件列表
- 新增 loadImage 辅助方法,PDF 导出支持 JPEG 图片嵌入
2026-06-08 11:21:25 +08:00
f6a74e58ea refactor(wms/coil): 抽象排产单组件,复用排产单展示逻辑
1.  新增PlanSheetViewer通用排产单展示组件,支持图片、excel、普通文件预览和空状态
2.  改造TimeInput组件,修复绑定属性写法
3.  替换typing.vue、stepSplit.vue、split.vue、merge.vue中的旧排产单代码,统一使用新组件
4.  删除冗余的排产单相关API调用和本地数据逻辑
2026-06-08 10:22:30 +08:00
857a3948d6 feat(wms): 新增钢卷通用维度告警管理功能
1. 新增告警信息路由页面与API接口
2. 在导航栏添加告警入口与未读红点提示
3. 实现告警列表查询、处理、忽略、删除与导出功能
4. 每分钟自动刷新告警状态检查
2026-06-08 10:05:52 +08:00
47b3fb24b7 feat: 新增阿里妈妈数黑体字体并更新标签样式
1. 新增阿里妈妈数黑体字体文件及授权说明文档
2. 全局替换标签默认字体为阿里妈妈数黑体
3. 统一调整多个标签页的卷号/原料号字体大小为1em
4. 修复表单输入框的v-model.number类型绑定问题
5. 删除废弃的盐雾试验、力学性能、样品标签预览组件
2026-06-08 09:05:15 +08:00
97e0df7ae1 refactor(aps/planSheet): 重构排产单详情页与列表页,替换可编辑表格为文件上传功能
1. 移除原排产单明细可编辑表格,替换为文件上传预览区域
2. 重构PlanSheetList组件,优化排产单筛选与展示UI
3. 新增排产单附件上传、预览、重新上传功能
4. 优化排产单列表的筛选、分页与操作交互
2026-06-06 17:56:13 +08:00
7c87670896 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-06 17:15:40 +08:00
cd3cc85c0a feat: 合同导出弹窗新增导出行配置(合计行/大写金额行/备注行可选)
- 新增 rowConfigs 配置,支持控制合计行、大写金额行、备注行显隐
- 新增全选/半选逻辑,与列配置交互风格一致
- 导出 HTML 模板根据行配置动态渲染
2026-06-06 17:15:31 +08:00
d70bb77755 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-06 17:11:09 +08:00
b00db10a37 feat(aps): 添加排产文件字段支持
- 在 ApsPlanSheet 实体类中新增 apsUrl 字段用于存储排产文件路径
- 在 ApsPlanSheetBo 业务对象中添加 apsUrl 属性定义
- 更新 MyBatis 映射文件 ApsPlanSheetMapper.xml 添加字段映射
- 在 ApsPlanSheetVo 视图对象中增加 apsUrl 字段并配置 Excel 导出
- 为 deliveryWaybillDetail 查询添加按创建时间倒序排序功能
2026-06-06 17:10:59 +08:00
dbeb99d9e5 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-06 17:08:51 +08:00
1a2fc9852d feat: 新增考勤模板管理功能
- 后端新增 WmsAttendanceTemplate CRUD(Controller/Service/Mapper/Domain)
- 前端新增 attendanceTemplate API 对接
- 前端新增 AttendanceTemplateManager 组件(拖拽排序 + 模板编辑)
- 优化考勤 drag.vue 页面交互
2026-06-06 17:08:31 +08:00
7aaa59cee1 feat(wms): 添加钢卷长度厚度偏差自动告警功能
- 在IWmsMaterialWarningService接口中新增checkAndInsertWarnings方法定义
- 在WmsMaterialCoilServiceImpl中注入materialWarningService依赖
- 在钢卷新增、更新、拆分等操作后自动触发偏差检查和告警插入
- 实现doCheckAndInsertWarnings方法进行长度和厚度偏差计算
- 添加checkLength方法验证长度偏差是否超过10%
- 添加checkThickness方法验证厚度偏差包括偏薄ERROR和偏厚WARNING
- 实现批量插入告警记录并添加异常处理和日志记录
2026-06-06 16:24:35 +08:00
cbebd5b6d6 feat(wms): 添加钢卷通用告警功能
- 创建 WmsMaterialWarning 实体类定义告警数据结构
- 实现 IWmsMaterialWarningService 接口提供告警业务方法
- 开发 WmsMaterialWarningController 控制器支持增删改查操作
- 设计 WmsMaterialWarningBo 和 WmsMaterialWarningVo 数据传输对象
- 配置 WmsMaterialWarningMapper 数据访问层和 XML 映射文件
- 实现 WmsMaterialWarningServiceImpl 业务逻辑处理类
- 添加告警类型、级别、状态等字段支持长度/厚度/宽度维度监控
- 集成 Excel 导出功能便于告警数据统计分析
2026-06-06 15:52:29 +08:00
24a9784035 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-06 15:24:16 +08:00
de7ec604dd fix(wms): 修复理论长度计算为空的问题
- 移除实际宽度比较条件,简化理论厚度计算判断逻辑
- 保持体积计算公式不变,仅调整条件判断流程
- 确保在缺少理论厚度且有实际长度时能正确计算厚度值
2026-06-06 15:23:50 +08:00
696f6d9ee0 fix(crm/contract): 修复合同状态更新调用错误的接口
移除了多余的created钩子中调用字典列表的代码,将更新合同状态的接口从updateContract改为updateOrder
2026-06-06 15:12:42 +08:00
050dd1a965 feat(crm): 合同含税总金额自动填入订单总金额 & 移除冗余页面
- feat(crm/contract): 含税总额变化后自动填写订单总金额(可配置开关)
- fix(crm/receive): 修复金额单位错误(万元→元);清理未使用导入
- fix(contract/product): 产品备注设置默认值
- chore: 移除已废弃的 OrderDashboard 组件和 finance/order 页面
- feat(wms/hrm): 新增考勤异常管理页面(attendanceAbnormal.vue)
- chore: 移除 trae git 提交规则配置
2026-06-06 13:01:38 +08:00
724c1dd16f refactor(order): 调整订单列表排序规则
- 移除状态排序逻辑
- 修改排序规则为合同号倒序排列
- 更新注释说明新的排序方式
- 保持置顶优先的排序策略不变
2026-06-06 12:58:12 +08:00
0e85153b3d chore(wms/order): 删除订单模块冗余的页面和组件文件 2026-06-06 11:44:26 +08:00
af728f8ea6 refactor(crm/contract): 抽取合同导出预览组件到独立文件 2026-06-06 10:49:02 +08:00
7e07b6f970 feat(wms/attendance-check): 新增异常考勤筛选功能
1. 在考勤审核查询条件中增加异常标识字段abnormal,用于筛选异常考勤记录
2. 在服务层实现异常筛选逻辑:当abnormal为true时,查询整体状态不为"normal"的考勤记录

调整前,考勤审核查询无法直接筛选异常考勤;调整后,支持通过abnormal字段快速过滤出异常状态的考勤记录,提升审核效率。
2026-06-06 10:13:41 +08:00
8a0f5e65bb feat(wms/attendance): add batch delete attendance schedule function
1. 修改删除排班接口为POST请求方式并调整接口路径为/wms/attendanceSchedule/remove,传递删除id数据
2. 在排班页面添加多选列和批量删除按钮,实现批量删除排班记录功能,包含选中校验、删除确认和操作反馈
2026-06-05 17:14:30 +08:00
1947a5c2d5 fix(wms/attendance-schedule): 调整批量删除接口参数类型与逻辑
1. 接口参数调整:将批量删除接口的路径参数从Long数组改为接收逗号分隔的字符串,并修改为@RequestBody接收
2. 服务层逻辑重构:将deleteWithValidByIds方法参数从Collection<Long>改为String,内部实现字符串解析与转换
3. 新增参数校验:在服务层添加字符串解析逻辑,过滤空值并转换为Long列表,避免空列表操作

调整前,批量删除依赖路径参数数组,存在URL长度限制且类型转换复杂;调整后,通过请求体接收字符串参数,服务层统一解析处理,提升接口健壮性与兼容性。
2026-06-05 16:46:23 +08:00
d8498728ee Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-05 15:51:31 +08:00
53e948b3e0 refactor(contractList): 移除旧的PDF导出逻辑,改用浏览器原生打印 2026-06-05 15:51:28 +08:00
3ebc0cb86a Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-05 11:07:33 +08:00
8059b0a0bb feat(wms/material-coil): 优化钢卷异常导出功能,支持动态表头与横向拼接
1. 重构异常导出逻辑:将原纵向展开(每个异常一行)改为横向拼接(每个钢卷一行),动态计算最大异常数并生成对应表头组
2. 移除冗余代码:删除原createExportVo方法和parseDateFromObject方法,简化导出结构
3. 调整数据格式:使用List<List<Object>>存储行数据,直接填充钢卷信息、改判原因及N组异常字段

调整前,导出文件为每个异常生成独立行,导致数据冗余且结构松散;调整后,每个钢卷仅占一行,异常信息横向拼接为动态列组,提升数据紧凑性与可读性,支持大规模异常数据导出。
2026-06-05 11:07:20 +08:00
1792196dc7 fix(wms/coil): 修复位置比较时的类型校验问题
将位置字段转为整数再进行大小比较,同时添加了调试日志用于排查异常数据问题
2026-06-05 11:05:32 +08:00
d8051abf8e feat(cost): 新增钢卷囤积成本统计页面及相关接口
新增了钢卷囤积成本统计的API接口,包括囤积统计和明细列表接口,同时新建了对应的页面页面,包含筛选查询、统计卡片、维度对比图表和明细表格功能,实现钢卷囤积成本的可视化管理。
2026-06-05 10:45:46 +08:00
5e0cb69bb8 feat(wms/coil): 为钢卷相关页面添加异常继承功能
本次修改在typing.vue、merge.vue、split.vue和stepSplit.vue四个钢卷相关页面中,新增了异常继承的完整功能:
1.  重构异常信息展示区域,添加继承标记样式
2.  新增继承异常按钮,打开异常选择弹窗
3.  实现从源钢卷拉取异常列表、批量选择继承异常的功能
4.  继承的异常会标记来源并使用特殊样式展示
2026-06-05 10:45:37 +08:00
37a69b563b Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-05 10:45:01 +08:00
66f0b3fdd7 fix(wms): 修复三处业务显示与逻辑不一致问题
1. 修复异常报表接口数据字段使用错误,将rows改为data
2. 调整标签渲染PDF的图片缩放和位置,避免内容超出页面
3. 修改考勤审核页面的请假天数列标题为请假小时,匹配实际展示数据
2026-06-05 10:44:56 +08:00
5e0dc848bb fix(wms-warehouse): 修复仓库页面容器高度溢出和导出二维码逻辑 2026-06-05 10:41:49 +08:00
a5323aea76 fix(crm/contract): 优化合同预览与导出功能
1.  隐藏打印预览按钮
2.  调整合同预览页面样式间距与logo位置
3.  修改合同金额字段保留小数位数为3位
4.  优化PDF导出分页逻辑,按空白行自动分页
2026-06-05 10:41:33 +08:00
cac747d158 fix(wms/material-coil): 移除钢卷查询中不必要的用户与异常统计关联
在WmsMaterialCoilMapper.xml的钢卷分页查询SQL中,移除了与sys_user表的左连接(通过sale_id关联)以及wms_coil_abnormal异常统计的子查询关联。调整前,查询包含冗余关联,可能影响性能且非必需;调整后,简化了SQL结构,提升查询效率。
2026-06-05 10:02:32 +08:00
705d929d6e feat(wms/material-coil): 优化钢卷囤积统计查询性能
1. 重构囤积统计方法:将原Java循环计算逻辑替换为单SQL聚合查询,通过JSON_EXTRACT解析二维码步骤创建时间,一次性计算平均囤积周期与成本
2. 移除原低效实现:删除getHoardingStatistics方法中的批量查询与循环解析代码,消除N+1性能问题
3. 新增Mapper方法与XML映射:添加selectHoardingStatistics接口及对应SQL,支持与分页查询相同的条件筛选

调整前,统计需先查询钢卷列表再批量获取二维码并循环解析,存在性能瓶颈;调整后,通过单SQL完成所有聚合计算,大幅提升查询效率,支持大规模数据统计。
2026-06-04 17:06:08 +08:00
29c21fd64f Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-04 15:46:02 +08:00
5236500f04 feat(wms/material-coil): 新增钢卷囤积统计与二维码详情查询功能
1. 新增囤积统计接口:计算已发货钢卷的平均囤积周期和平均囤积成本
   - 囤积周期 = 发货时间 - 二维码第一步创建时间
   - 囤积成本 = 囤积天数 × 钢卷净重 × 1元/吨/天
   - 支持与分页列表相同的查询条件筛选

2. 新增二维码详情查询接口:在分页查询基础上填充完整的二维码记录信息
   - 前端可通过 qrcodeRecord.content 获取二维码JSON内容
   - 采用批量查询避免N+1性能问题

调整前,钢卷查询无法获取二维码详细内容,也无法统计囤积相关指标;调整后,支持二维码内容查看和囤积成本分析,为仓储成本核算提供数据支持。
2026-06-04 15:45:51 +08:00
600867f386 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-04 14:28:38 +08:00
8183bae824 fix(crm): 统一销售金额单位为元并优化金额精度
1. 修改客户等级图表、销售报告页面的金额单位从万元改为元
2. 将金额计算和展示的精度从两位小数调整为三位小数
3. 新增合同默认编码和签订地点的默认值
2026-06-04 14:28:33 +08:00
37d6830947 fix(wms/delivery): 清除运单明细查询中的时间条件干扰
在WmsDeliveryWaybillDetailController的运单明细查询方法中,startTime/endTime参数已用于运单delivery_time筛选。为避免其被误用作钢卷update_time的查询条件,在查询前将bo中的startTime和endTime字段显式置为null。调整前,时间条件可能干扰钢卷维度的查询结果;调整后,确保运单交付时间筛选与钢卷更新时间筛选互不干扰,提升查询准确性。
2026-06-04 14:09:25 +08:00
c71dfe3ff2 feat(wms/coil): 新增钢卷异常管理相关页面与功能
1. 新增钢卷异常列表基础页、明细页、钢卷维度异常页和继承扩展页
2. 在异常管理表格中新增继承来源列
3. 完善异常增删改查、判级以及继承功能
2026-06-04 13:36:01 +08:00
ff139759d4 feat(wms/coil/abnormal): 新增钢卷异常记录的父异常ID字段
在WmsCoilAbnormal实体及相关业务对象中新增parentAbnormalId字段,用于记录异常继承关系。调整涉及数据库映射、Java实体类、业务对象、查询条件及导出映射。调整前,异常记录缺少父异常关联信息;调整后,支持按父异常ID进行筛选与关联追溯,提升异常链分析能力。
2026-06-04 13:19:33 +08:00
5176c80344 refactor(mes/wms): 优化多处日期处理与表格列展示
1. 移除磨工页面字典表格的"值"列
2. 修复TimeInput组件日期格式化逻辑,补全月份日期补零处理
3. 为卷料录入页面添加日期格式化方法,替换直接赋值逻辑并新增生产时长计算
2026-06-04 11:10:34 +08:00
31f7a9c0cb Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-04 10:59:17 +08:00
9d208770d8 feat(service): 添加按热卷号查询计划详情功能
- 在 SqlServerApiBusinessService 中实现按热卷号查询计划详情方法
- 新增调用查询扩展卷数据接口并整合到返回结果中
- 修改 PlanDetailView 构造函数以支持扩展卷数据列表
- 添加 excoilRows 属性和相应的 getter 方法
- 提供新的 fromExecuteSqlResponse 静态工厂方法处理双响应对象
- 在 SqlServerApiClient 中新增 queryExcoilByHotCoilId 查询接口
2026-06-04 10:59:07 +08:00
31d8d1ee16 feat: 多个页面优化与功能增强
1. 磨削页面:添加操作人权限控制,自动填充上次硬度值,移除字典值字段
2. 质保书页面:新增质保书类型筛选与表单字段,移除模板选择弹窗
3. 成本综合页面:添加产线校验、录入/查看切换、表格列控制与快捷操作
4. 质保书条目页面:新增类型筛选与表单字段,移除模板选择弹窗
2026-06-04 10:26:09 +08:00
b4fbb8dfc8 feat(qc/certificate): 新增证书类型字段
在QcCertificate实体及相关业务对象中新增certificateType字段,用于标识出厂合格证、检测报告、质保书等证书类型。调整涉及数据库映射、查询条件及导出映射。调整前,证书记录缺少类型分类;调整后,支持按证书类型进行筛选与统计,提升证书管理能力。
2026-06-03 17:21:12 +08:00
40ebca2573 feat(mes/eqp/check): add inspector summary statistics table
新增按实际巡检人维度的巡检汇总统计表格,展示巡检人、巡检次数、通过/不通过数量及通过率
2026-06-03 16:59:03 +08:00
ec08a360a0 feat(qc/inspection): 新增检验任务方案选择的公司和默认选中参数
1.  给SchemeSelect组件新增company和scheme两个props
2.  组件内新增模板单位查询参数并关联传入的company值
3.  组件挂载/重置时自动匹配并选中传入的默认方案
4.  同步更新表单内的归属公司和任务类型字段初始化
2026-06-03 16:54:37 +08:00
977ea2b021 refactor(wms/report): 移除actionIds相关导出逻辑 2026-06-03 16:44:44 +08:00
e507887a27 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-03 16:31:54 +08:00
12a887e074 refactor(wms-report): 统一报表页面模板,提取公共逻辑为action-template
1.  将merge、repair下的多个报表页面重构为使用action-template组件
2.  提取自定义导出功能为公共组件CustomExport并复用至receive.vue和action-template
3.  统一报表页面的查询、导出、列配置等公共逻辑
2026-06-03 16:31:51 +08:00
577de8eb64 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-03 16:31:32 +08:00
03add7c96b 模架厚度修复 2026-06-03 16:30:48 +08:00
42e5b6dd2b feat(wms/coil/abnormal): 新增钢卷异常记录数据来源与工序来源
在WmsCoilAbnormal实体及相关业务对象中新增以下字段:
1. 数据来源(sourceSystem):标识数据来自二级系统同步或三级本地录入
2. 工序来源(processSource):记录异常发生的具体工序(如粗轧、精轧等)

调整涉及数据库表结构、Java实体类、业务对象、查询条件及导出映射。调整前,异常记录缺少数据来源和工序信息;调整后,新增字段支持按数据来源和工序进行筛选与统计,提升异常追溯与分析能力。同时为物料钢卷服务中的相关DTO预留字段映射注释。
2026-06-03 15:48:25 +08:00
88149561c5 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-03 15:12:34 +08:00
51bb7593c7 feat(mes/wms): 新增磨辊人管理与免验规则优化
1. 优化wms产线免验逻辑,新增镀铬产线免验支持
2. 新增磨辊人统计报表导出功能
3. 新增磨辊操作人字典维护功能
2026-06-03 15:12:31 +08:00
c34fc1e477 fix(wms/coil): 修正操作类型校验逻辑,增加对类型505的排除
在钢卷操作校验逻辑中,原代码仅排除了操作类型501(入库)对子卷操作类型的校验。调整后,增加对操作类型505(出库)的排除,确保在入库和出库操作中,子卷的操作类型字段不会因非空而被错误校验,避免因校验不匹配导致的业务异常。
2026-06-03 15:06:25 +08:00
9bd6077599 feat(wms/report): 新增自定义报表导出列配置缓存功能
在入库报表页面中新增导出列配置的本地缓存功能,用户自定义的列顺序将被保存至localStorage,避免重复配置。调整前,每次打开自定义导出弹窗均需重新选择列;调整后,自动读取上次保存的配置,提升用户体验。
2026-06-03 15:01:16 +08:00
6fe1f668d3 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-03 14:53:14 +08:00
53b991242c feat(mes/roll/report): 优化磨辊人员统计报表,按辊型拆分统计数据
该提交重构了磨辊报表的操作人员统计模块,将原有的总统计拆分为中间辊(CR)、支撑辊(BR)、工作辊(WR)的分项统计,并增加了合计栏,同时完善了辊型识别逻辑,新增了对应的数据计算和表格展示。
2026-06-03 14:07:46 +08:00
91017f7c84 refactor(wms/report): 重构镀锌、酸轧线报表页面,统一使用通用模板组件
1.  新增了zinc_old和zha_old旧版报表备份目录,保留原有实现
2.  将所有报表页面替换为通用的ActionTemplate组件
3.  为镀锌线、酸轧线的各类报表配置了固定的生产线、仓库选项和操作类型
4.  移除了动态加载报表配置的逻辑,改为硬编码固定配置
2026-06-03 14:07:35 +08:00
7b80ef035a fix(mes/roll): 修正磨削记录查询排序逻辑
1. 将磨削记录列表的默认排序由升序改为降序,确保最新记录优先展示
2. 移除冗余的grind_id排序条件,简化排序规则
2026-06-03 11:36:36 +08:00
e54efab7c8 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-02 16:49:16 +08:00
715c1b9728 fix(qc/inspection): 修复产品检验入场卷号校验逻辑
1. 移除表单内置的入场卷号校验规则,改为手动校验
2. 添加失焦校验和实时错误提示
3. 优化两个页面的卷号选择表单结构
2026-06-02 16:49:13 +08:00
jhd
8723924002 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-02 15:44:19 +08:00
jhd
cbaa47b34e 地图获取省份逻辑 2026-06-02 15:44:01 +08:00
fe24426f59 refactor(crm/contract): 简化产品内容组件并优化合同打印样式 2026-06-02 15:40:47 +08:00
ef04d73e0c feat(cost/comprehensive): 新增产线自动填充和数据一键获取功能
1.  新增产线名称转换方法,统一展示产线中文名
2.  为详情输入框添加自动获取数据按钮,支持原料、产出、辅料、轧辊四类数据自动查询
3.  改造报表表单的产线选择器,使用正式产线数据而非硬编码选项
4.  完善报表编辑时的产线数据映射逻辑
5.  新增自动加载状态管理,避免重复请求
2026-06-02 14:45:04 +08:00
b7d47a5d9d feat(mes/roll): 扩展磨削记录查询功能,新增班组与轧辊类型筛选
在磨削记录查询接口中新增以下筛选条件:
1. 班组(team)
2. 轧辊类型(rollType)

调整涉及服务接口、控制器、Mapper及XML映射文件,将原有的时间范围和产线筛选扩展为支持多维度查询。调整前,查询仅支持按轧辊ID、产线ID和时间范围筛选;调整后,新增班组和轧辊类型条件,提升查询灵活性与业务分析能力。同时优化SQL查询,通过关联mes_roll_info表获取轧辊类型,并在返回结果中新增rollType字段。
2026-06-02 14:22:55 +08:00
jhd
021c1c908a Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-02 13:52:06 +08:00
cd3b25fa30 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-02 13:35:43 +08:00
3106b2c530 feat(wms/report): 新增理论厚度、理论长度与镀铬卷号字段至钢卷报表
在钢卷入库报表中新增以下字段:
1. 理论厚度(theoreticalThickness)
2. 理论长度(theoreticalLength)
3. 镀铬卷号(chromePlateCoilNo)

调整涉及前端报表展示列配置、后端导出列映射及理论计算公式注释修正。调整前,报表仅展示物理属性与材质属性的基础字段;调整后,新增理论计算字段与镀铬卷号,提升报表信息完整性与业务分析能力。同时修正理论计算公式注释中的单位转换符号,将除1000更正为乘1000,确保公式表述准确。
2026-06-02 13:35:29 +08:00
f4e6b24c92 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-02 13:23:01 +08:00
d6620e2449 feat: 新增质保书模板功能,优化标签样式与钢卷信息展示 2026-06-02 13:22:58 +08:00
b59bb1789e fix(wms/coil): 修复理论厚度与长度计算中宽度为零的除零异常
在钢卷理论计算逻辑中,当实际宽度为零时,计算理论厚度和理论长度会导致除零异常。调整前,仅校验实际长度不为空;调整后,增加实际宽度大于零的校验,避免无效计算。同时修正理论厚度和理论长度的计算公式,统一使用乘1000替代除1000,确保计算精度和单位转换正确。
2026-06-02 11:48:44 +08:00
4295a28f33 feat(wms/coil): 新增已绑定钢卷列表按发货计划创建时间倒序排序功能
在钢卷查询业务中,当查询已绑定钢卷列表且未指定计划ID(planId)时,新增按关联的发货计划创建时间倒序排序功能,确保较新的计划优先展示。

主要改动:
1. 在WmsMaterialCoilBo中新增orderByPlanDesc布尔字段,用于控制排序逻辑
2. 在WmsMaterialCoilMapper中新增selectVoPagePlusPlanOrder方法及对应的XML映射,通过关联发货计划表支持按计划创建时间排序
3. 在WmsMaterialCoilServiceImpl中调整查询逻辑:当orderByPlanDesc为true时调用新的查询方法,并在查询条件中补充排序规则
4. 在WmsDeliveryWaybillDetailController中设置orderByPlanDesc条件:当planId为空时启用该排序
5. 重构XML映射文件,提取公共SQL片段以提高可维护性

调整前,已绑定钢卷列表在无planId时仅按状态排序;调整后,新增按发货计划创建时间倒序排序,便于用户快速查看最新计划相关的钢卷。
2026-06-02 11:11:55 +08:00
8572a60044 feat(qc): 新增质量检验证书原料卷号、表面处理与调质度字段
在质量检验证书项(QcCertificateItem)中新增以下字段:
1. 原料卷号(rawCoilNo)
2. 表面处理(surfaceTreatment)
3. 调质度(temperDegree)

调整涉及实体类、业务对象、值对象及映射文件,确保字段在查询条件、导出模板中生效。
2026-06-02 11:02:56 +08:00
29328d70e9 提交3d钢卷,追溯和意库内容 2026-06-02 10:08:47 +08:00
12545f7c8b 提交3d钢卷 2026-06-02 09:27:47 +08:00
6ec4275088 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-02 09:13:56 +08:00
14dbd633b5 feat(qc): 新增化学成分与物理性能检验字段
在质量检验证书项(QcCertificateItem)中新增以下字段:
1. 化学成分:铝(Al)、钛(Ti)、铬(Cr)、镍(Ni)、铜(Cu)、氮(N)、铁(Fe)、硼(B)
2. 物理性能:规定塑性延伸强度(plasticExtensionStrength)
3. 镀层信息:镀层表面结构(coatingSurfaceStructure)、镀层重量(coatingMass)

调整涉及实体类、业务对象、值对象及映射文件,确保字段在查询条件、导出模板中生效。
2026-06-02 09:13:46 +08:00
8d68d2bdee Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-02 08:56:34 +08:00
6b8eac4139 feat(contract): 新增合同打印功能,重构产品金额计算逻辑
1. 新增合同打印预览功能,支持A4格式打印,包含合同完整信息和产品明细
2. 新增多个产品金额计算工具函数,统一管理产品税额、无税单价等字段计算
3. 重构产品内容组件,新增税率除数、无税单价、税额列,实现字段联动自动计算
4. 新增合同logo静态资源,优化表格布局和样式
2026-06-02 08:56:31 +08:00
13780c635b fix(attendance): 调整考勤漏打卡判定时间阈值至两小时
将漏打卡判定阈值从30分钟延长至120分钟,即上班打卡晚于理论上班时间两小时以上或下班打卡早于理论下班时间两小时以上才标记为漏打卡。调整前,30分钟即触发漏打卡状态;调整后,放宽判定标准,减少因短暂延误导致的误判。
2026-06-02 08:18:46 +08:00
a425a9052a fix(wms/coil): 为镀铬操作类型豁免分卷净重与规格厚度校验
在钢卷分卷和批量分卷的业务逻辑中,当操作类型为501(镀铬)时,豁免以下校验:
1. 子卷净重不超过母卷净重的校验
2. 子卷规格厚度不超过母卷规格厚度的校验
3. 批量分卷时所有子卷总重不超过母卷净重的校验

调整前,所有分卷操作均强制进行净重和规格厚度校验;调整后,镀铬操作类型(501)可跳过这些校验,以适应镀铬产线的特殊业务场景。
2026-06-02 08:02:04 +08:00
f64da15bc3 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-01 17:11:43 +08:00
b134539e53 提交3d钢卷初版 2026-06-01 17:11:36 +08:00
effc1f6f2e Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-01 16:40:15 +08:00
ca285f78c6 feat(qc): 新增厂家卷号匹配功能,优化卷号录入体验
本次改动在检验任务、化学成分报告、物理性能报告模块中:
1. 支持通过入场卷号和厂家卷号双向搜索匹配
2. 新增多选卷号标签式展示与删除功能
3. 新增批量导入时厂家卷号自动匹配入场卷号的逻辑,包含多匹配结果弹窗选择
4. 在表格中新增厂家卷号展示列,更新导入模板支持厂家卷号字段
2026-06-01 16:40:13 +08:00
0cfffcc60d feat(wms/coil): 新增钢卷理论长度字段并优化理论计算逻辑
1. 在钢卷物料实体类、业务对象、值对象及导出VO中新增理论长度(theoreticalLength)字段,并在映射文件中补充数据库映射关系
2. 重构理论计算工具方法,将原有的calculateTheoreticalThickness方法扩展为calculateTheoretical,支持同时计算理论厚度和理论长度
3. 理论长度计算公式:理论长度 = 净重(吨) × 1000 / 7.85 / 规格厚度(mm) / 规格宽度(mm) / 1000
4. 优化规格信息提取逻辑,统一从物品规格中解析厚度和宽度,避免重复代码
5. 在新增、修改、分卷、批量分卷等业务方法中调用新的计算逻辑,确保理论长度字段的自动填充
2026-06-01 16:21:41 +08:00
37b2987279 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-01 16:10:27 +08:00
59bdcf96dc style(mes/roll/grind): 调整磨削记录查询排序为降序
将磨削记录的默认排序从按磨削时间升序改为降序,确保最新的磨削记录显示在列表前面,便于用户优先查看最近的操作记录。
2026-06-01 16:10:18 +08:00
8f602d80a9 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-06-01 15:56:51 +08:00
7bddfad80f feat(eqp/check): 新增设备巡检负责人筛选页面及相关优化
1.  新增person.vue页面,支持按负责人筛选巡检部位
2.  在设备巡检列表页展示负责人信息并添加样式
3.  修复产线绑定字段错误,将lineId改为productionLine
4.  移除磨工页面输入框的number类型限制
2026-06-01 15:56:48 +08:00
8b1d7ed280 feat(wms/report): 新增自定义导出列顺序功能并优化导出弹窗布局
1. 在ExcelUtil工具类中新增exportExcelOrdered方法,支持按指定顺序的列动态生成表头和数据行进行导出
2. 重构接收报表页面的自定义导出弹窗:将布局拆分为左侧可选列面板和右侧导出顺序面板,支持拖拽排序
3. 新增后端/exportCustomOrdered接口,接收有序字段列表并调用新的导出方法
4. 优化弹窗样式:调整宽度、间距、滚动区域,新增顺序序号和移除按钮
5. 移除原有的/exportCustom接口,统一使用新的有序导出逻辑
2026-06-01 15:14:34 +08:00
285775c733 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-01 14:39:03 +08:00
7e6bc1e8b4 fix(attendance): 优化考勤状态识别逻辑并补充漏打卡处理
1. 在考勤状态筛选、汇总卡片和图例中将“迟到/早退”标签更新为“迟到/早退/缺卡”,以包含漏打卡情况
2. 后端服务中,在考勤状态常量列表新增“missed_start”、“missed_end”、“missed”三种漏打卡状态
3. 重构上下班打卡时间判断逻辑:当打卡时间晚于理论上班时间或早于理论下班时间超过30分钟时,标记为漏打卡(上班漏打卡或下班漏打卡)
4. 调整状态覆盖逻辑:上班漏打卡或下班漏打卡状态会覆盖原有的迟到/早退状态;若上下班均漏打卡则标记为全天漏打卡(missed)
5. 更新考勤记录处理:当标记为漏打卡时,对应的首次或末次打卡时间字段设为null
6. 优化旷工判定逻辑:单独处理上午段(P1)或下午段(P2)漏打卡的情况,分别标记为半天旷工(absent_half)
7. 前端新增漏打卡状态对应的日历样式(状态色块为#e6a23c)和状态描述文本(“上班漏打卡”、“下班漏打卡”)
2026-06-01 14:38:56 +08:00
bf3967d7b5 feat(wms/coil): 新增镀铬卷号字段与分条校验规则优化
1.  在CoilCard中将长度标签改为参考长度
2.  新增镀铬卷号列到钢卷选择器表格与可选列配置
3.  在钢卷更新和分条页面添加净重、厚度校验规则,区分镀锌/酸轧/镀铬产线豁免情况
4.  优化分条页面的代码格式与组件注册顺序,新增镀铬操作类型判断
5.  分条表单新增镀铬卷号输入项,支持从源卷复制镀铬卷号信息
2026-06-01 14:31:06 +08:00
a0cd885fc7 feat(wms/attendance): 优化考勤同步功能,新增月份选择和超时配置
1. 重构syncRecords接口,支持传入开始和结束时间参数并新增60s超时配置
2. 升级考勤同步页面:新增同步弹窗、月份选择器,替换原有基于最后同步时间的同步逻辑
3. 优化搜索表单和详情表单的标签与占位符,调整表单宽度提升可读性
4. 移除无用的最后同步时间查询逻辑
2026-06-01 14:12:06 +08:00
481188f654 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-06-01 13:51:00 +08:00
c8fe545950 feat(wms/coil): 为钢卷物料新增理论厚度与镀铬卷号字段并实现自动计算
1. 在钢卷物料实体类、业务对象、值对象及导出VO中新增理论厚度(theoreticalThickness)和镀铬卷号(chromePlateCoilNo)字段
2. 在映射文件中补充新增字段的数据库映射关系
3. 在服务实现类中添加理论厚度自动计算逻辑:根据净重、实测长度和物品规格宽度,使用公式“理论厚度 = 净重(吨) × 1000 / (7.85 × 实测长度(mm) × 宽度(mm))”自动计算并保留3位小数
4. 新增工具方法用于从物品规格中提取厚度和宽度信息
5. 在新增、修改、分卷、批量分卷等业务方法中调用理论厚度计算逻辑
6. 在分卷和批量分卷时增加子卷净重和规格厚度不超过母卷的业务校验
2026-06-01 13:50:48 +08:00
94840b2153 feat(mes/roll/grind): 实现轧辊增删改查功能
1. 新增轧辊列表头部新增按钮和轧辊明细面板的修改、删除按钮
2. 增加轧辊新增/编辑弹窗,包含完整的轧辊信息表单和校验
3. 对接轧辊CRUD后端接口,实现新增、修改、删除逻辑
4. 调整左侧轧辊面板宽度适配新增内容
2026-06-01 12:58:35 +08:00
c5ce33f71a feat(mes/roll): 重构轧辊磨削页面布局并补充备注字段
1.  重构轧辊磨削页面的整体布局,调整为左侧产线Tab+右侧主体的结构
2.  在实体类和BO类中新增remark备注字段
3.  移除运单页面的冗余备注搜索框
4.  优化轧辊列表的检索和展示逻辑,新增厂家筛选选项
5.  补充磨削班组的下拉选择选项,新增字典配置
6.  优化页面样式和交互细节
2026-06-01 11:27:05 +08:00
43f4692a72 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-30 18:00:04 +08:00
9af5284ff3 feat: 多页面功能优化与新增 2026-05-30 18:00:01 +08:00
62da44382a fix(wms/attendance): 优化午休打卡模式识别逻辑
1. 重构打卡记录分割逻辑,将原简单中值法改为基于时间区间和间隔检测的智能分割
2. 新增午休打卡模式检测:支持区间内长间隔、提前下班+午饭回来、午休晚归三种场景识别
3. 当检测到午休打卡模式时,按实际打卡间隔进行合理分割;未检测到时回退使用原中值法
4. 提升考勤统计的准确性,避免因午休打卡时间分布不均导致的上下班时段误判
2026-05-30 17:38:13 +08:00
6a5220ad78 feat(mes/roll/grind): 增加厂家搜索筛选和CR类型选项
1. 新增厂家搜索输入框和筛选逻辑
2. 新增CR类型的单选筛选按钮
3. 在辊子列表中展示厂家信息
4. 优化有效当前辊径的默认返回逻辑
2026-05-30 15:05:43 +08:00
3b7ae10499 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-30 14:31:23 +08:00
6044413384 fix(wms): 统一发货单导出逻辑并修复弹窗拦截问题
1. 替换原有的window.open弹窗导出为a标签下载,解决浏览器拦截弹窗的问题
2. 统一使用Date.now()替代new Date().getTime()优化代码
3. 新增释放URL对象的代码避免内存泄漏
4. 调整线圈页面批量移出发货单按钮的显示条件
2026-05-30 14:31:20 +08:00
91d1236c37 feat(cost): 为成本项新增查询条件
- 在CostItem实体类、Bo业务对象和Vo视图对象中新增queryCondition字段,用于存储JSON格式的查询条件
- 更新CostItemMapper.xml映射文件以支持新字段的数据映射
- 在CostItemServiceImpl服务实现中添加新字段的查询条件支持,实现按查询条件过滤成本项的功能
2026-05-30 13:44:31 +08:00
020863d1ef feat(qc): 添加化学成分和物理性能检测字段
- 在QcChemicalItem实体类中新增铝、钛、铬、镍、铜、氮、铁、硼等化学成分字段
- 在QcChemicalItemBo业务对象中同步添加对应的化学成分属性
- 更新QcChemicalItemMapper.xml映射文件以支持新字段的数据映射
- 在QcChemicalItemServiceImpl服务实现中添加新字段的查询条件支持
- 在QcChemicalItemVo视图对象中添加化学成分字段并配置Excel导出
- 在QcPhysicalItem实体类中新增规定塑性延伸强度、镀层表面结构、镀层重量等物理性能字段
- 在QcPhysicalItemBo业务对象中添加对应的物理性能属性
- 更新QcPhysicalItemMapper.xml映射文件以支持新的物理性能字段映射
- 在QcPhysicalItemServiceImpl服务实现中添加新物理性能字段的查询条件支持
- 在QcPhysicalItemVo视图对象中添加物理性能字段并配置Excel导出功能
2026-05-30 11:04:02 +08:00
jhd
6832209e98 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-30 10:47:52 +08:00
3a0f729669 feat(attendanceCheck): 新增员工考勤详情弹窗功能
1.  为员工列表列添加详情按钮,点击可查看个人考勤详情
2.  新增个人考勤汇总卡片,展示考勤统计数据
3.  支持表格和日历两种明细视图,根据天数自动切换
4.  添加考勤日历视图样式与状态标识
5.  补充相关计算属性与工具方法支撑新功能
2026-05-29 17:13:57 +08:00
aad568f320 feat(mes,wms): 新增设备送检审批流程及相关功能
1. 新增设备送检审批的API接口层
2. 在待办页面添加设备送检审批标签页
3. 完善设备巡检日报的送检提交功能
4. 修复报表模板查询的参数传递问题
5. 优化设备送检审批单的业务逻辑处理
2026-05-29 17:05:23 +08:00
d6099a781f Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-29 16:27:28 +08:00
e23098b766 feat(wms/report): 给成品线圈查询添加按创建时间筛选条件,并增加备注搜索项
1.  在wms报表模板页面的成品线圈查询中,补充byCreateTimeStart和byCreateTimeEnd参数,替换原有的startTime和endTime参数
2.  在CoilSelector组件中新增备注搜索输入框,仅在orderBy存在时显示
2026-05-29 16:27:25 +08:00
37ea2b7d78 feat(qc): 为质检任务新增厂家卷号字段
在质检任务实体、业务对象、值对象及映射文件中新增supplierCoilNos字段,用于记录厂家卷号集合(多个使用英文逗号分隔)。同时,在服务实现类中为查询条件添加对该字段的模糊匹配支持,实现按厂家卷号过滤质检任务的功能。
2026-05-29 16:19:04 +08:00
c707a0356f Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-29 16:10:09 +08:00
484f63f9cc feat(wms/coil): 新增钢卷物料个性化导出功能
1.  后端新增导出列元数据接口 `/exportColumns`,返回字段名与中文列名的映射。
2.  后端新增个性化导出接口 `/exportCustom`,支持通过 `columns` 参数指定导出的字段集合,利用增强的 `ExcelUtil.exportExcel` 方法实现按需导出。
3.  前端钢卷接收报表页面新增自定义导出弹窗,支持按列分组展示、搜索、全选/反选/清空列,并调用新接口实现仅导出选中列的数据。
4.  在导出VO中补充“班组”字段的Excel映射注解。
2026-05-29 16:09:58 +08:00
1f32171800 feat(aps): 新增排产单明细批量导入功能 2026-05-29 16:00:20 +08:00
jhd
5a16a9d2b1 wip在产大屏 2026-05-29 15:53:26 +08:00
6147ad2252 feat(aps/plan): 为排产单明细新增排产日期字段
在排产单明细实体、业务对象、值对象及映射文件中新增detailDate字段,用于记录排产日期(字符串格式,如'2025-12-29')。同时,在服务实现类中为查询条件添加对该字段的筛选支持,实现按排产日期过滤排产单明细的功能。
2026-05-29 15:40:46 +08:00
5e9bf6069e feat(mes/eqp): 新增设备巡检审批功能
新增设备巡检审批(按产线+时间范围审批)模块,包含以下内容:
1. 新增EqpEquipmentInspectionApproval实体类、Bo、Vo,定义审批相关字段
2. 新增EqpEquipmentInspectionApprovalController,提供增删改查及导出接口
3. 新增EqpEquipmentInspectionApprovalMapper及XML映射文件
4. 新增IEqpEquipmentInspectionApprovalService接口及ServiceImpl实现类,实现分页查询、新增、修改、删除等业务逻辑
5. 支持按产线、时间范围、申请人、审批状态等条件进行筛选查询
2026-05-29 15:24:52 +08:00
3cc37ae3d3 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-29 14:33:51 +08:00
5b4ea8f486 feat(aps/plan): 新增批量新增排产单明细接口
1. 在ApsPlanDetailController中新增batchAdd接口,支持批量新增排产单明细
2. 在ApsPlanDetailServiceImpl中实现insertBatchByBo方法,批量插入前进行实体校验
3. 在IApsPlanDetailService中声明批量新增接口方法
2026-05-29 14:33:19 +08:00
b8ed505971 feat(wms,crm,cost): 完成多模块功能更新与优化
1. 新增发货单明细统计接口调用
2. 移除成本页面复制配置按钮
3. 隐藏CRM合同订单编辑标签页
4. 优化发货单页面订单编号自动补全功能
5. 新增钢卷管理发货计划筛选与批量移单功能
2026-05-29 14:28:56 +08:00
6f488c74fc feat(wms/delivery): 新增根据发货计划ID查询已绑定钢卷功能,优化钢卷查询备注匹配
1. 在发货计划明细服务层新增getBoundCoilIdsByPlanId接口,支持根据计划ID和时间段筛选已绑定的钢卷ID列表
2. 在发货计划明细控制器中扩展已绑定钢卷查询接口,新增planId参数,优先按计划ID查询,兼容原有时间段查询逻辑
3. 在钢卷服务实现中为钢卷查询条件增加remark字段的模糊匹配支持,提升查询灵活性
2026-05-29 14:01:44 +08:00
1b65444ab3 refactor(wms/coil): 统一排产单表格展示样式并优化页面布局 2026-05-29 13:00:33 +08:00
125e07eed4 feat(mes/eqp/check): 替换字典选型为动态产线下拉选单
1. 统一替换页面中原有的dict-select为通过接口获取的动态产线列表
2. 新增产线默认选中酸轧线的逻辑
3. 修复产线参数传递不匹配的问题,同步前后端参数字段
2026-05-29 11:41:48 +08:00
82a54e3200 refactor(mes/eqp): 将设备巡检记录的产线字段类型从字符串改为长整型
1. 在EqpEquipmentInspectionRecordBo中将productionLine字段类型由String改为Long
2. 在EqpEquipmentInspectionRecordServiceImpl的查询条件中,将字符串非空判断改为Long非空判断
3. 统一前后端数据类型,为后续关联产线主键做准备
2026-05-29 11:16:22 +08:00
327ae685c1 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-29 11:15:14 +08:00
df643a8e4e refactor(mes/eqp): 将设备备件的产线字段类型从字符串改为长整型
1. 在EqpEquipmentPart实体类、Bo和Vo中将productionLine字段类型由String改为Long
2. 在EqpEquipmentPartServiceImpl的查询条件中,将字符串非空判断改为Long非空判断
3. 统一前后端数据类型,为后续关联产线主键做准备
2026-05-29 11:15:05 +08:00
8684bc4a63 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-29 10:51:19 +08:00
c53befe9d6 feat(eqp): add production line and inspect part query, enhance daily check statistics
1. 新增巡检记录BO和VO的产线、巡检部位字段
2. 关联设备部件表补充查询巡检部位和产线数据
3. 增加按产线过滤巡检记录的查询条件
4. 优化日巡检页面:替换日期选择器为时间段选择,新增负责人汇总统计、应检/实检差异统计和完成率指标
2026-05-29 10:51:16 +08:00
5f9876343c fix(wms/coil): 修复待操作记录开始操作时的状态校验问题
1. 在开始操作前增加待操作记录存在性检查,若记录不存在则抛出异常
2. 增加状态校验逻辑,防止对已完成(状态为2)的记录再次开始操作
3. 重构代码结构,将直接更新改为先查询后更新,确保状态变更的准确性
4. 添加事务注解保证操作原子性
2026-05-29 10:16:00 +08:00
1f4dcea63a feat(wms/coil): 新增排产单展示功能,优化多页面布局与样式
1.  为分步加工弹窗添加全屏属性
2.  在typing、merge、stepSplit、split页面新增排产单列表与详情展示,支持多排产单切换
3.  重构split页面表单布局为双列样式,优化页面结构
2026-05-28 17:43:04 +08:00
8e6ae90690 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-28 17:21:10 +08:00
f33170de75 feat(wms/coil): 在钢卷录入页面新增排产计划展示功能
1. 在钢卷录入页面新增排产计划卡片,根据当前操作类型动态显示对应产线的计划
2. 新增产线名称映射表,支持酸轧线、镀锌线、脱脂线、拉矫线、双机架线、镀铬线和分条线
3. 调用APS模块的排产计划和计划明细接口获取数据,并在表格中展示订单号、合同号、客户、成品信息等详细列
4. 优化原料信息组件显示列数,提升页面信息展示密度
2026-05-28 17:20:56 +08:00
7e8509e2e3 refactor(多个页面): 优化页面布局与交互体验 2026-05-28 16:31:14 +08:00
56622548cf Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-28 16:09:28 +08:00
31d6b02f8b feat(mes/eqp): 为设备备件新增负责人字段
1. 在EqpEquipmentPart实体类、Bo和Vo中新增responsiblePerson字段
2. 在EqpEquipmentPartMapper.xml中增加responsible_person列映射
3. 在EqpEquipmentPartServiceImpl的查询条件中增加负责人模糊筛选
4. 在前端备件管理页面新增负责人查询输入框、表格列和表单字段
2026-05-28 16:09:17 +08:00
9cfb96f2c3 feat(mes/qc/inspection/task): 添加工单附件管理功能 2026-05-28 15:25:03 +08:00
73e98af96e feat(wms/coil): 添加缺陷图片上传与展示功能
1. 新增ImageUpload组件支持url模式绑定
2. 在异常表单中添加主缺陷对应的图片上传控件
3. 在异常表格和管理页面中新增缺陷图片展示列
4. 同步更新表单数据默认值与表格初始化逻辑
2026-05-28 15:11:01 +08:00
d9f9c948cc feat(wms/acid): 出口卷实绩新增筛选条件并优化搜索功能
1.  为出口卷实绩接口新增钢卷号模糊搜索和时间范围过滤能力
2.  给入场/当前卷号输入框添加清除按钮
3.  优化酸洗实绩页面的布局样式
4.  重构实绩列表分页和搜索逻辑
2026-05-28 13:24:58 +08:00
1c272792f7 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-28 13:03:12 +08:00
4fcbf10afd refactor(wms/mes/cost): 优化多页面表单与表格交互逻辑
1. 调整质检任务表单的任务类型与入场卷号展示顺序,根据任务类型动态显示入场卷号字段并优化校验规则
2. 替换wms报表页面的pendingAction接口为轻量版listLightPendingAction
3. 给成本综合页面的表格拖拽排序功能新增置于最上/最下按钮,完善拖拽交互与样式
2026-05-28 13:03:09 +08:00
e4f1c8d2b1 feat(wms/move): 新增调拨记录的入场卷号和当前卷号筛选功能
1. 前端在移库操作和记录页面新增入场卷号和当前卷号查询字段,并添加清空按钮
2. 后端在WmsTransferOrderItemBo中新增enterCoilNo和currentCoilNo字段
3. 在WmsTransferOrderItemServiceImpl中实现根据入场/当前钢卷号查询钢卷ID并过滤移库记录的逻辑
4. 优化查询条件处理,当无匹配钢卷时返回空结果集
2026-05-28 10:56:57 +08:00
6de1bbfe0b feat(wms/attendance): 新增批量单元格编辑排班功能
1. 新增批量修改排班班次的API接口
2. 重构排班页面工具栏,新增部门和员工姓名筛选功能
3. 新增批量编辑模式,支持选择多个已有排班单元格进行批量修改
4. 新增批量编辑弹窗,可统一修改所选排班的班次
5. 优化页面样式布局,添加批量操作相关的交互样式
2026-05-27 17:51:34 +08:00
d0a15032f2 feat(wms/attendance): 新增排班班次批量修改功能
在IWmsAttendanceScheduleService接口、WmsAttendanceScheduleController控制器和WmsAttendanceScheduleServiceImpl服务实现类中新增batchUpdateShiftByIds方法,支持通过主键ID列表批量更新排班记录的班次。新增BatchUpdateScheduleItemBo业务对象用于接收批量更新项,包含scheduleId和shiftId字段并进行非空校验。Controller层提供/batchUpdateShift端点,使用PUT请求并应用防重复提交和操作日志注解。Service层实现遍历列表并利用MyBatis-Plus的UpdateWrapper进行批量更新,确保事务一致性。
2026-05-27 17:43:41 +08:00
d2f6086093 feat(qc/wms): 为质检任务和钢卷异常新增附件路径字段
在QcInspectionTask和WmsCoilAbnormal的实体类、BO和VO中新增attachmentFiles字段,用于存储多个附件路径(英文逗号分隔)。同时更新对应的Mapper XML映射文件,确保字段能够正确映射到数据库列。
2026-05-27 17:39:35 +08:00
2aaef6bb86 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-27 17:13:02 +08:00
6b36697e56 feat(wms/attendance): 为考勤排班查询新增员工姓名和部门名称模糊筛选
在WmsAttendanceScheduleBo中新增employeeName和employeeDept字段用于接收模糊查询条件。在WmsAttendanceScheduleServiceImpl中新增resolveEmployeeNameAndDept私有方法,根据姓名和部门条件查询员工ID集合,并自动设置到bo的userIds字段中,实现通过员工姓名和部门名称进行模糊筛选考勤排班数据。
2026-05-27 17:12:54 +08:00
1697942d98 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-27 17:05:58 +08:00
05676c7c04 refactor(wms-report): 统一报表页面模板,抽离公共逻辑 2026-05-27 17:05:55 +08:00
50298c3ec9 fix(wms/material): 扩展钢卷重量校验至净重字段
在WmsMaterialCoilServiceImpl的validateCoilWeight私有方法中,新增对钢卷净重(netWeight)的校验逻辑,确保净重同样不超过100吨。同时将方法参数从仅接收毛重(grossWeight)调整为同时接收毛重和净重,并在所有调用该方法的地方(包括新增、修改、拆分、合并、移库、入库等操作)同步更新参数传递。校验失败时抛出运行时异常并分别提示毛重或净重超限。
2026-05-27 17:02:51 +08:00
17af108940 fix(wms/material): 修正钢卷长度字段为整型
将WmsMaterialCoil及相关BO/VO中的length和actualLength字段从BigDecimal改为Long类型,并在WmsCoilPendingActionServiceImpl和WmsCoilWarehouseOperationLogServiceImpl中相应调整赋值逻辑,确保类型转换时进行空值检查,避免空指针异常。
2026-05-27 16:57:17 +08:00
11c1594169 fix(wms/material): 新增钢卷重量校验,防止超过100吨
在WmsMaterialCoilServiceImpl的多个方法中新增validateCoilWeight私有方法,用于校验钢卷毛重是否超过100吨。在校验失败时抛出运行时异常提示具体重量。此校验已应用于新增、修改、拆分、合并、移库、入库等涉及钢卷重量变更的操作中,确保数据有效性。
2026-05-27 16:41:57 +08:00
d8a39f67c8 feat(wms/attendance): 新增考勤连续旷工天数计算功能,为保证速度把步骤拆分成两步
1. 前端新增“计算连续旷工”按钮,调用后端重算接口并优化加载状态管理
2. 后端新增recalcContinuousAbsent方法及接口,支持按指定员工或时间范围重算连续旷工天数
3. 优化考勤检查页面按钮布局,明确“生成考勤结果”操作
2026-05-27 14:57:49 +08:00
405f388702 feat(wms/attendance): 新增考勤检查部门筛选功能,优化跨天排班逻辑与打卡记录批量查询
1. 前端新增部门筛选下拉框,支持按部门筛选员工并自动勾选,优化穿梭框数据映射逻辑
2. 后端实现跨天排班重叠检测机制,正向跨天夜班被反向跨天班覆盖时跳过下班打卡校验
3. 重构打卡记录查询为批量预取模式,通过单次SQL查询提升性能,支持按员工姓名集合和时间范围精确检索
4. 优化考勤检查记录构建逻辑,调整时段时间计算方式,完善全天缺勤状态判断规则
2026-05-27 14:16:34 +08:00
e95e9adfcd feat(cost): 新增生产月报复制功能,修复考勤校验参数问题,优化表格列操作 2026-05-27 13:19:55 +08:00
454d8de6a2 feat(cost&wms): 新增成本模块与考勤优化功能
1. 新增成本相关业务模块:成本项目配置、成本单价历史、生产月报、生产指标明细、生产成本明细的CRUD接口与页面
2. 为生产月报实体增加列配置字段及数据库映射
3. 优化考勤查询接口,将get请求改为post并使用body传参
4. 考勤页面增加部门筛选、员工多选筛选和打卡记录展示功能
2026-05-26 17:49:32 +08:00
b9da496f79 fix(wms/attendance): 统一考勤查询时间字段格式为完整时分秒
将WmsAttendanceCheckVo中所有时间字段的@JsonFormat注解从"yyyy-MM-dd HH:mm"改为"yyyy-MM-dd HH:mm:ss",确保前后端时间数据格式一致,避免因秒数缺失导致的解析或显示问题。
2026-05-26 17:12:41 +08:00
c8ac535ffb feat(wms/attendance): 将考勤查询列表接口改为POST请求并支持员工ID集合筛选
在WmsAttendanceCheckBo中新增userIds字段用于接收员工ID集合查询条件。将WmsAttendanceCheckController的/list接口从GET改为POST,并添加@RequestBody注解以支持JSON参数传递。在WmsAttendanceCheckServiceImpl的查询条件构建中增加对userIds字段的筛选逻辑,实现按指定员工范围查询考勤数据。
2026-05-26 17:01:43 +08:00
281023a2a1 feat(wms/attendance): 为考勤查询新增员工ID集合筛选功能
在AttendanceCheckBo中新增userIds字段,用于接收员工ID集合查询条件。同步更新WmsAttendanceScheduleBo、Mapper接口及XML映射,在查询排班时支持按userIds进行筛选。Service层将考勤查询条件中的userIds传递至排班查询逻辑,实现考勤数据按指定员工范围过滤。
2026-05-26 16:39:33 +08:00
b788074af7 feat(cost): 新增生产成本明细批量保存功能,支持先删除再插入
在CostProdDetailBo中新增detailIds和prodDetailList字段,分别用于接收待删除ID集合和待插入数据集合。新增批量保存接口batchSaveWithDelete,在Service层实现事务性批量操作:先根据detailIds删除指定记录,再将prodDetailList中的数据批量插入。Controller层新增/batch端点调用该服务,提供完整的前后端批量处理能力。
2026-05-26 14:35:18 +08:00
de744c861b feat(cost): 修改生产成本明细新增接口返回新增记录的ID
将CostProdDetailController的add方法返回值从R<Void>改为R<Long>,并返回新增记录的detailId。同时将ICostProdDetailService和CostProdDetailServiceImpl的insertByBo方法返回值从Boolean改为Long,直接返回新增记录的ID,便于前端获取新增数据标识。
2026-05-26 14:12:13 +08:00
6f3bd2165f refactor(wms/report/zha): 统一从configJson解析报表配置参数
将多个页面中直接从res.rows[0]读取参数的逻辑,改为先解析configJson字段再取值,优化代码一致性和可维护性
2026-05-26 09:13:06 +08:00
6f7a85025d feat(mes/roll): 新增轧辊磨削记录通用查询和报表页面
1. 新增通用查询接口,支持按轧辊ID、产线ID、时间范围筛选磨削记录
2. 重构后端列表接口,支持不传轧辊ID查询全部记录
3. 修复硬度字段类型转换问题,将未倒角转为0数值
4. 新增磨辊报表页面,支持统计分析和图表展示
2026-05-25 17:31:46 +08:00
95c23462c9 feat(wms/report): 新增报表配置动态加载功能,替换本地静态配置
1.  新增wms报表通用配置的CRUD接口文件
2.  替换所有酸轧报表页面的本地静态配置为从后台接口动态获取
3.  添加加载状态提示,优化页面初始加载体验
2026-05-25 16:19:00 +08:00
9b5ae03c37 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-25 15:39:07 +08:00
501abc4821 feat(wms/attendance): 新增批量修改排班功能,优化设备巡检表格展示
1. 新增批量修改排班API接口和页面弹窗功能
2. 设备巡检表格移除固定宽度并添加溢出提示,新增现场图像展示列
2026-05-25 15:39:03 +08:00
bd67df3c05 feat(mes/eqp): 为设备巡检记录分页查询新增时间范围筛选及关联信息
- 在EqpEquipmentInspectionRecordBo中新增startInspectTime和endInspectTime字段,并添加日期格式化注解,支持按巡检时间范围查询
- 新增Mapper方法selectVoPagePlus及对应的XML映射,通过左连接关联检验清单表以获取checkContent和checkStandard字段
- 在Service层新增buildQueryWrapperPlus方法构建查询条件,支持对新增的时间范围字段进行筛选
- 在EqpEquipmentInspectionRecordVo中新增checkContent和checkStandard字段,用于在分页查询结果中展示关联的检验内容和标准
2026-05-25 15:06:55 +08:00
015ec7d70b feat(mes/eqp): 新增设备巡检管理模块及相关组件
本次提交新增了完整的设备巡检管理功能:
1.  新增QRCode组件,支持带文字描述的二维码展示
2.  新增检验部位、设备检验清单、巡检记录的CRUD API
3.  新增检验清单选择器组件
4.  新增巡检部位管理、检验清单管理、巡检记录管理页面
5.  新增设备巡检总览页面,支持拖拽分栏管理部位和检验清单,附带二维码生成打印功能
6.  新增单日设备巡检日报页面
2026-05-25 14:45:59 +08:00
3d13302370 fix(cost): 修正生产月报查询条件,优化日期匹配逻辑
- 将生产月报查询条件从精确日期匹配改为按月匹配,使用 DATE_FORMAT 函数处理 report_date 字段
- 修复原逻辑中因日期格式不匹配导致的查询结果不准确问题
- 调整后支持按年月(如 '2026-05')查询生产月报数据,提高查询灵活性
2026-05-25 14:17:15 +08:00
1df397f821 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-25 14:14:54 +08:00
e04a4a0b99 feat(cost): 新增生产成本管理模块基础功能
- 新增成本项目配置(CostItem)实体、Bo、Vo、Mapper、Service及Controller,提供增删改查和分页查询服务
- 新增成本单价历史(CostPrice)实体、Bo、Vo、Mapper、Service及Controller,管理成本项目单价历史记录
- 新增生产成本明细(CostProdDetail)实体、Bo、Vo、Mapper、Service及Controller,记录生产消耗明细
- 新增生产指标明细(CostProdMetric)实体、Bo、Vo、Mapper、Service及Controller,管理生产指标计算
- 新增生产月报(CostProdReport)实体、Bo、Vo、Mapper、Service及Controller,提供生产月报管理功能
- 在klp-admin模块pom.xml中引入klp-cost模块依赖,并添加klp-cost模块到项目主pom.xml
2026-05-25 14:14:45 +08:00
jhd
8b3ace4d1b Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-25 14:14:29 +08:00
jhd
85bb87e9fb 财务状态bug修复 2026-05-25 14:13:54 +08:00
cb18132ec6 feat(wms/report): 新增WMS报表通用配置管理功能
- 新增WmsReportConfig实体类、Bo、Vo和Mapper,定义报表配置的数据结构
- 新增IWmsReportConfigService接口及WmsReportConfigServiceImpl实现类,提供增删改查和分页查询服务
- 新增WmsReportConfigController控制器,提供配置列表、详情、新增、修改、删除和导出的API接口
- 在WmsReportConfigMapper.xml中映射数据库字段与实体属性
2026-05-25 13:03:43 +08:00
0179cf986b feat(mes/eqp): 为设备巡检记录新增巡检照片字段
- 在EqpEquipmentInspectionRecord实体类、Bo和Vo中新增photo字段,用于存储以英文逗号分隔的巡检照片URL
- 在EqpEquipmentInspectionRecordMapper.xml中映射photo字段到数据库查询结果
- 在EqpEquipmentInspectionRecordServiceImpl的查询条件中增加对photo字段的过滤支持
2026-05-25 11:46:05 +08:00
69ea51ec93 feat(wms/attendance): 新增排班批量修改功能
- 新增BatchUpdateScheduleBo类,用于接收批量修改排班的请求参数
- 在IWmsAttendanceScheduleService接口中定义batchUpdateSchedule方法
- 在WmsAttendanceScheduleController中新增批量修改排班的API接口
- 在WmsAttendanceScheduleServiceImpl中实现批量修改排班逻辑,支持更新已有记录和插入新记录
2026-05-25 11:26:13 +08:00
3d92528179 fix(wms/attendance): 修正倒班排班生成逻辑,优化交接班日判断
- 将排班生成逻辑从基于累计天数切换为基于日期判断,每月1日、11日、21日(非31日)作为交接班日
- 调整交接班处理逻辑,统一班次标识切换方式,避免重复切换错误
- 优化代码注释和变量命名,提升可读性
- 修复批量插入结果判断变量名错误
2026-05-25 11:14:19 +08:00
cd099f2e6b Merge remote-tracking branch 'origin/0.8.X' into 0.8.X
# Conflicts:
#	klp-admin/src/main/resources/application-prod.yml
2026-05-23 19:35:22 +08:00
35ad50a79d 同步规程同步代码和录入监测代码 2026-05-23 19:34:52 +08:00
af6eb19952 fix(crm): 修正应收表格合同编号绑定字段错误
将合同编号列的prop从contractCode改为orderCode,匹配实际数据源字段
2026-05-23 18:13:13 +08:00
jhd
faa3784eae Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-23 16:46:53 +08:00
jhd
dc3f20ebc9 增加财务状态页面 客户管理财务状态优化 2026-05-23 16:46:40 +08:00
13ad671b29 feat(KLPService选择组件): 新增分页控制参数,支持全量加载选项
1. 为CustomerSelect和OrderSelect组件新增pager参数,默认开启分页模式
2. 分页模式下保持每页10条的远程搜索逻辑,非分页模式下加载全量10000条数据
3. 调整OrderSelect组件的加载状态绑定方式,统一使用v-loading指令
4. 为OrderSelect新增mounted钩子,非分页模式下初始化加载全量订单数据
2026-05-23 16:25:53 +08:00
jhd
eb8e797a4d Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-23 16:21:20 +08:00
jhd
09535d884c 增加财务状态页面 客户管理财务状态优化 2026-05-23 16:20:52 +08:00
50192174e8 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-23 14:48:26 +08:00
a33db26838 feat(attendance): 新增考勤模板管理功能,支持模板的增删改查和导入导出
1. 新增AttendanceTemplateManager组件,实现考勤模板的本地管理
2. 在排班页面添加模板管理入口和相关操作按钮
3. 支持将班次配置保存为模板、从模板快速导入人员
4. 优化班次选择器的交互体验,添加清空功能
5. 新增单个班次的人员导入导出功能
2026-05-23 14:48:22 +08:00
jhd
74c7618e9a 入场卷号输入优化 2026-05-23 13:35:46 +08:00
jhd
40067a3680 入场卷号输入优化 2026-05-23 11:53:05 +08:00
a81032dedf Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-23 11:04:35 +08:00
b34dad1237 perf: 优化生产环境数据库连接池配置
- 将主数据源连接池最大连接数从20提升至100
- 将Redis连接池大小从64提升至128
- 提升系统在高并发场景下的数据库和缓存连接处理能力
2026-05-23 11:00:14 +08:00
王文昊
6f5d09beef feat (wms/move):新增钢卷匹配进度展示
为入库钢卷功能添加匹配进度界面及对应状态、业务逻辑,实时展示匹配状态、进度占比与当前匹配项结果
2026-05-23 10:03:19 +08:00
e9de87a7b6 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-23 09:18:29 +08:00
a5b1a19a2b fix(mes/roll/grind): 修复当前辊径显示和取值逻辑
将当前辊径取值改为优先使用有效当前辊径计算逻辑,统一磨削前辊径取值
2026-05-23 09:18:24 +08:00
26f285ec80 feat(wms/receivable): 在应收货物计划查询中补充订单编号和订单名称字段
- 在应收货物计划查询SQL中新增订单编号orderCode和订单名称orderName字段映射
- 关联crm_order表以获取订单信息,确保数据完整性
- 在应收货物计划VO类中补充订单编号和订单名称字段定义
2026-05-22 17:46:11 +08:00
王文昊
3718132a59 refactor(crm): 优化订单明细查询逻辑,移除内存排序并迁移到SQL层
1. 新增联表分页查询方法,在数据库层完成排序和分页
2. 移除前端页面冗余的合同信息缓存和内存排序逻辑
3. 新增钢卷导入组件,支持调拨单钢批量化导入
4. 补充订单明细VO类的联表查询字段
2026-05-22 17:03:13 +08:00
be75c1a4b8 feat(wms): add transfer remark field and re-label function
1. 新增调拨备注字段transferRemark到调拨单itemBO
2. 新增执行后重贴标签的复选框和备注输入框
3. 调整调拨确认时传递调拨备注参数
4. 注释调旧的调拨类型获取逻辑,改用传入的调拨备注作为调拨类型
2026-05-22 16:19:24 +08:00
d81773b1ab feat(attendance): 为排班表格添加高度适配,隐藏部分操作按钮并添加提交加载状态 2026-05-22 16:19:00 +08:00
749ae46490 fix(wms/receivable): 修正应收货物计划查询客户信息字段映射
- 将客户名称查询字段从c.name调整为c.company_name以匹配CRM客户表结构
- 新增客户编号customerCode字段映射,补充客户信息完整性
- 调整关联表从wms_customer切换为crm_customer确保数据一致性
2026-05-22 16:09:50 +08:00
e084576f1e perf(wms/attendance): 优化排班生成性能,批量查询已存在日期并重构逻辑
- 将单日排班存在性检查改为批量查询整个日期范围内的已存在排班日期集合
- 移除冗余的日期检查逻辑,统一使用批量查询结果进行过滤
- 简化倒班日判断和班次切换逻辑,移除注释掉的复杂处理代码
- 优化导入语句,使用通配符和流式处理提高代码简洁性
2026-05-22 16:03:24 +08:00
30f9b533b2 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-22 15:30:18 +08:00
b7016b3591 feat(eqp): 添加设备检验清单部位名称填充功能
- 在EqpEquipmentChecklistBo中新增partIds字段用于批量查询
- 实现检验清单查询时自动填充检验部位名称的功能
- 重构设备部件服务中的检验清单列表获取逻辑
- 优化设备部件页面数据加载性能通过批量查询方式
- 移除手动设置部位名称的冗余代码实现自动关联
2026-05-22 15:30:01 +08:00
jhd
0a286023c7 排班优化 2026-05-22 15:28:48 +08:00
2fb5b58c99 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-22 14:56:21 +08:00
7b2881c45f refactor(eqp): 查询设备附带巡检部位 2026-05-22 14:56:10 +08:00
bb5c09fd6d Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-22 14:26:11 +08:00
b14f4f69c7 fix(grind): 修正磨削次数显示逻辑为表格数据长度 2026-05-22 14:26:07 +08:00
c2b7a08414 refactor: 注释掉出口卷数据同步相关代码并优化钢卷对比默认查询逻辑
本次提交主要变更:
1.  注释掉所有出口卷数据同步的接口、服务实现和相关工具方法
2.  优化钢卷对比页面的默认时间逻辑,移除默认7天前的起始时间,改为默认查询今日全天数据
3.  新增日期格式化工具方法统一处理时间字符串拼接
4.  完善钢卷对比接口的注释和字段映射逻辑
2026-05-22 14:01:16 +08:00
80fbe70ab7 fix(wms/coil/info): 调整入库天数计算的截止日期逻辑
根据卷料状态切换使用当前时间或出库时间作为计算截止日期
2026-05-22 13:07:53 +08:00
a9edc8fcf3 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-22 13:02:57 +08:00
903c354add feat(wms): 新增应收货物计划批量删除和清空功能,优化表格配置
1. 后端添加批量删除应收计划接口
2. 前端新增批量删除、清空按钮和多选功能
3. 优化表格高度和字段文案,调整分页查询大小
2026-05-22 13:02:53 +08:00
jhd
fe5188e8fc 多选框右侧显示bug 2026-05-22 12:08:28 +08:00
35e4e4bbb0 feat(wms/delivery): 新增多类型发货单打印组件及适配逻辑
1. 新增WayBillPrinter包装组件,根据商品类型和printType自动切换打印模板
2. 新增锌层、铬料专用的发货单打印模板ZincWayBill1/2、DugeWayBill1/2
3. 优化发货单页面,替换原有固定打印组件为动态匹配的打印组件
4. 补充获取zincLayer和temperGrade字段的逻辑
2026-05-22 10:46:45 +08:00
王文昊
efc6a9f0df refactor(crm order item): 移排序逻辑到后端并简化前端代码
1. 将原前端的分组排序逻辑迁移到后端service实现
2. 后端实现三级排序:交货日期倒序→订单ID升序→创建时间倒序,保证跨页排序一致性和合同组连续排列
3. 移除前端冗余的groupSort方法和排序状态变量,简化前端页面逻辑
4. 更新前端排序提示文案为固定描述
2026-05-22 02:46:43 +08:00
jhd
049c3353b3 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-21 19:09:31 +08:00
jhd
b9d8c17953 多选框组件重写 2026-05-21 19:08:51 +08:00
jhd
ae6878c00b 重复名称可选 2026-05-21 18:33:44 +08:00
a3d80b09cb Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-21 18:02:47 +08:00
0abd3668ad feat(eqp): 添加巡检加产线和产线段 2026-05-21 18:02:39 +08:00
66dae17caf Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-21 18:00:43 +08:00
cb23f659b9 chore(wms/move/batch): 调整批量移库页面分页大小为50 2026-05-21 18:00:38 +08:00
d60508364b feat(eqp): 添加级联插入功能 2026-05-21 17:53:57 +08:00
王文昊
5a4ab2f65e feat(crm/order-item): add order grouping sort and row highlight
1. 新增订单明细创建时间字段到VO类并配置JSON格式化
2. 实现按交货日期倒序+创建时间倒序的分组排序逻辑
3. 添加表格分组交替背景色样式与排序状态提示
2026-05-21 17:07:00 +08:00
8f3d08334e Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-21 16:49:28 +08:00
110f862f15 feat(eqp): 添加检验部位关联检验清单功能
- 引入 EqpEquipmentChecklistVo 和 EqpEquipmentChecklist 实体类
- 添加 EqpEquipmentChecklistMapper 数据访问层依赖
- 在查询检验部位分页列表时关联查询检验清单数据
- 将检验清单列表映射到检验部位视图对象中
- 优化导入包使用通配符简化代码
- 在 EqpEquipmentPartVo 中添加 checklistList 字段存储关联清单数据
2026-05-21 16:49:20 +08:00
2590876da3 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-21 16:48:04 +08:00
eeda1dc8d9 feat(wms/coil/info): 新增钢卷成本信息展示模块
新增囤积成本、囤积天数、钢卷净重的展示卡片,计算并展示钢卷的囤积成本,通过入库时间计算实际囤积天数,优化页面数据展示维度
2026-05-21 16:47:59 +08:00
6442a1ff32 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-21 16:44:18 +08:00
a05ecbf3a7 feat(eqp): 添加设备检验相关功能模块
- 新增设备检验清单实体类及业务对象
- 实现设备检验清单控制器、服务层和数据访问层
- 添加设备巡检记录相关实体、控制器和服务实现
- 集成检验部位管理功能模块
- 配置MyBatis映射文件和数据传输对象
- 实现分页查询、新增、修改、删除和导出功能
- 添加数据验证和业务逻辑处理
2026-05-21 16:44:10 +08:00
92e01a029d Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-21 16:35:07 +08:00
67410af985 feat(qc): 新增入场钢卷号字段并优化质检相关流程
1. 在质检任务相关BO、VO、实体类中新增enterCoilNos字段
2. 调整检验任务查询逻辑,支持按入场钢卷号筛选
3. 优化钢卷相关页面的字段展示和表单校验
4. 简化理化导入流程,移除钢卷匹配步骤
2026-05-21 16:35:03 +08:00
e531ce019d refactor(mes-excoil): 优化外部卷材数据同步性能(只插入不更新)
- 添加空数据检查并返回默认结果
- 实现批量数据转换提升处理效率
- 采用批量查询替代逐条查询减少数据库访问
- 分离新增和更新操作支持批量处理
- 实现分批插入和更新避免大数据量问题
- 每批处理500条记录确保系统稳定性
2026-05-21 15:35:15 +08:00
b580d1798e Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-21 15:26:54 +08:00
baed852ff4 feat(excoil): 添加出口卷数据同步功能
- 新增 MesExCoil 实体类定义数据库表结构
- 创建 MesExCoilBo 业务对象用于数据传输
- 实现 IMesExCoilService 接口及 MesExCoilServiceImpl 服务类
- 添加 MesExCoilController 控制器提供 REST API 接口
- 集成 MyBatis Plus 持久层框架实现数据库操作
- 实现出入口厚度、宽度、重量等完整字段映射
- 添加同步 L2 系统出口卷实绩数据功能
- 支持首次全量同步和后续增量同步模式
- 实现数据校验、分页查询、导出等功能
- 配置数据写入时间和同步时间字段处理
2026-05-21 15:26:46 +08:00
25e46a9867 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-21 15:16:48 +08:00
ddc1caa065 feat(wms): 新增调拨批量确认功能,优化调拨查询与表格展示
1.  新增批量确认调拨单接口及前端实现
2.  调整调拨单号查询为模糊匹配
3.  新增调拨单号远程搜索功能
4.  优化调拨表格列宽与操作栏展示
5.  新增调拨记录删除功能
6.  新增调拨执行页面do.vue
7.  优化调拨管理页面代码格式
2026-05-21 15:16:44 +08:00
52cbc21088 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-21 14:29:28 +08:00
d982efc866 feat(wms): 新增钢卷对比功能实现数据同步状态监控
- 在 SqlServerApiBusinessService 中新增按时间段查询出口卷实绩方法
- 在 SqlServerApiClient 中实现 queryExcoilByTimeRange 数据查询接口
- 在 SqlServerApiController 中添加 /excoil/by-time 时间段查询端点
- 新增 CoilComparisonController 实现钢卷数据对比和匹配状态逻辑
- 创建前端 coilComparison API 接口文件并导出 getExcoilStatus 方法
- 开发钢卷对比页面界面,包含产线切换标签页和时间范围筛选功能
- 实现钢卷加工状态、入库状态和匹配状态的数据展示和标记功能
2026-05-21 14:29:14 +08:00
6b58f37616 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X
# Conflicts:
#	klp-ui/src/views/micro/pages/acid/components/ActualPerformance.vue
2026-05-21 13:41:43 +08:00
eb5601ade3 修复酸轧实绩提交问题,规程重新完成逻辑 2026-05-21 13:41:21 +08:00
613acfc998 fix(acid/actual-performance): 优化工艺曲线加载逻辑并添加加载状态
1.  添加了加载遮罩来提示用户正在获取工艺曲线数据
2.  将openQualityReport改为异步方法,并行获取多个接口数据
3.  统一处理异常情况并提示用户加载失败
4.  优化了数据获取和复用逻辑,减少不必要的接口请求
2026-05-21 13:39:27 +08:00
96b49e71f4 feat(KLPService选择组件): 新增默认查询参数支持并优化钢卷录入页面
1. 为ProductSelect和RawMaterialSelect组件新增defaultQueryParams属性,支持传入默认查询参数合并到请求参数中
2. 优化钢卷录入页面:默认选中成品类型,根据解析的钢卷数据自动设置物料选择器的查询参数
3. 移除页面冗余空行和注释代码
2026-05-21 13:38:35 +08:00
75954a3a9c Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-21 13:38:03 +08:00
1cbc8da78c fix(wms): 调整退火绩效和异常报表默认查询时间为昨日到今日
统一两个报表页面的默认查询时间范围,将初始默认时间改为昨日00:00:00到当日00:00:00,简化了异常报表的时间处理逻辑,移除冗余的日期范围工具函数。
2026-05-21 13:37:58 +08:00
2fc8cf02d1 feat(wms): 更新历史钢卷操作页面表格字段和显示逻辑
- 添加物品名称、材质、规格、生产厂家、锌层等物料信息列
- 新增创建人和完成时间列,完善操作记录信息
- 替换字典标签为映射值显示,优化操作类型和状态展示
- 集成操作状态标签颜色映射,提升视觉效果
- 移除字典依赖改为本地映射数据,提高性能
- 调整各列宽度以适应内容,优化表格布局
- 添加操作状态标签类型映射方法
2026-05-21 13:04:04 +08:00
a189c3904d Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-21 11:04:54 +08:00
531fccb22b feat(transfer): 添加批量确认调拨功能
- 在服务接口中新增批量确认调拨方法
- 在控制器中实现批量确认调拨的API端点
- 在服务实现中添加批量处理逻辑,循环调用单个确认方法
- 添加参数校验和空值检查机制
- 集成日志记录和重复提交防护功能
2026-05-21 11:04:44 +08:00
015a3622d7 refactor(wms/coil): 拆分锁定异常页面,将分条退火锁定功能独立为新页面
1.  从typeError.vue中注释掉分条锁定、退火锁定的单选按钮
2.  新增lock.vue页面实现分条/退火锁定钢卷的管理功能
2026-05-21 10:58:25 +08:00
7b47403ae8 style(styles): 为el-table添加自定义滚动条样式 2026-05-21 10:12:57 +08:00
10398f83b6 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-21 08:59:48 +08:00
7b75940258 feat(wms): 多模块优化调整
1. 新增镀锌待打包仓库选项
2. 注释发货单为空打印校验逻辑
3. 优化钢卷查询API参数处理
4. 调整报表接口调用与数据解析
5. 移除发货单模板中的原料厂家列
2026-05-21 08:59:44 +08:00
bb96f2a9e4 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-20 14:27:10 +08:00
a91ee6d956 feat(WmsMaterialCoil): 添加卷料报表中的创建时间字段
- 在 WmsMaterialCoilMapper.xml 查询中新增 createTime 字段映射
- 在 WmsMaterialCoilReportVo 中添加 createTime 属性
- 更新数据库查询以包含卷料创建时间信息
- 为报表功能提供更完整的时间维度数据支持
2026-05-20 14:26:55 +08:00
2c9cc6241f Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-20 14:07:25 +08:00
15beca11c8 修复酸轧实绩提交问题 2026-05-20 14:05:18 +08:00
ca21fe33f3 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-20 13:57:14 +08:00
724dd272ca feat(wms/report): 优化发货报表页面,实现分页查询和统计功能
1. 新增轻量钢卷列表接口用于全量数据统计
2. 拆分接口为分页明细查询和全量统计查询
3. 为表格组件添加服务端分页支持
4. 移除默认的全量查询配置,新增分页状态管理
5. 注释掉表格的筛选排序功能暂时隐藏
2026-05-20 13:57:09 +08:00
54cf9046e7 refactor(wms): 将钢卷物料报表查询接口从GET改为POST
- 将 /listForReport 接口的请求方法从 GET 改为 POST
- 修改参数传递方式从URL参数改为请求体传参
- 保持原有的查询逻辑和返回数据结构不变
2026-05-20 13:22:25 +08:00
cd7ca23f28 fix(wms/report): 修复逻辑库位查询参数传递问题 2026-05-20 09:31:13 +08:00
519ee13b32 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-19 17:55:07 +08:00
2813167751 refactor(wms): 移除报表汇总功能并添加钢卷业务规则工具类
- 移除了报表汇总相关的方法、控制器接口和实现代码
- 新增 CoilBusinessRuleUtils 工具类处理特殊业务逻辑
- 在钢卷更新流程中集成特殊业务规则处理
- 自动调整逻辑库区等字段的业务规则实现
2026-05-19 17:54:46 +08:00
439857682b Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-19 17:54:32 +08:00
1d1c27bf40 fix(CoilSelector,acid): 调整表格高度并修复侧边菜单排序问题
1. 修复CoilSelector组件表格高度计算,使用calc适配排序状态下的布局
2. 调整acid页面侧边菜单的菜单项顺序,将跟踪菜单移至正确位置
2026-05-19 17:54:27 +08:00
53a180787b 1完成酸轧轧辊调整
2完成双机架工艺规格串联
3完成双机架计划串联
4完成双机架wip快捷录入检索
5完成双机架实绩串联
2026-05-19 17:13:37 +08:00
417783e64a fix(wms/report): 注释调warehouseIds参数传递,暂不按仓库过滤报表数据 2026-05-19 16:57:42 +08:00
4a8fc4904f feat(wms-report): 新增品质筛选条件并优化部分查询组件
1.  多个报表页面新增品质筛选下拉选择器
2.  统一添加coil_quality_status字典依赖
3.  替换部分旧的逻辑库位选择组件为warehouse-select
4.  调整部分表单字段的prop属性和代码格式
2026-05-19 16:42:16 +08:00
df25151fa5 style(wms/waybill): 格式化代码换行与缩进
修复多处代码行过长导致的可读性问题,调整长属性和标签的换行格式,同时补充打印前检查发货单非空的逻辑
2026-05-19 16:26:23 +08:00
6343f66ff7 feat(wms/coil/do/split): 新增镀锌待打包仓库选项 2026-05-19 16:25:47 +08:00
ccd7d0a562 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-05-19 15:39:59 +08:00
9a58fa2b30 fix(wms/coil): 注释待操作列表完成标记逻辑并传递actionId
临时注释了根据actionId完成待操作任务的代码,同时在调用接口时传入当前actionId参数
2026-05-19 15:39:53 +08:00
4575b6f342 feat(wms): 添加钢卷操作记录完成回调功能
- 在批量或单个更新后统一处理返回结果
- 添加 actionId 验证逻辑以确保操作记录存在
- 集成 coilPendingActionService.completeAction 接口调用
- 实现更新成功后的操作记录状态同步
- 优化方法结构以支持操作完成后的后续处理
2026-05-19 15:37:53 +08:00
210d7ab4a4 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-05-19 15:34:25 +08:00
e745208870 feat(wms): 添加历史钢卷待完成操作功能
- 新增查询历史钢卷待完成操作列表接口
- 在后端服务中添加按创建时间和扫描时间倒序排序
- 实现用户名到昵称的映射显示功能
- 创建新的stale.vue页面展示历史钢卷操作列表
- 添加完成和取消历史钢卷操作的功能按钮
- 集成字典标签显示操作类型和状态信息
2026-05-19 15:34:12 +08:00
621 changed files with 63736 additions and 15994 deletions

5
.gitignore vendored
View File

@@ -45,6 +45,11 @@ nbdist/
!*/build/*.html
!*/build/*.xml
######################################################################
# AI Assistant Configuration
.trae/
.reasonix/skills/
######################################################################
# Personal Scripts & Tables (not for commit)
*.xlsx

81
docs/double-rack-ddl.sql Normal file
View File

@@ -0,0 +1,81 @@
-- 双机架 (double-rack) 数据库 DDL
-- 在 jdbc:mysql://140.143.206.120:13306/double-rack 上执行
-- 工艺方案主表
CREATE TABLE IF NOT EXISTS `mill_process_recipe` (
`recipe_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`recipe_no` VARCHAR(64) NOT NULL COMMENT '方案记录号(唯一)',
`alloy_no` VARCHAR(32) NOT NULL COMMENT '合金号',
`pass_count` INT NOT NULL DEFAULT 0 COMMENT '道次数量',
`in_thick` DECIMAL(8,3) DEFAULT NULL COMMENT '原料厚度(mm)',
`out_thick` DECIMAL(8,3) DEFAULT NULL COMMENT '成品厚度(mm)',
`out_width` DECIMAL(8,1) DEFAULT NULL COMMENT '成品宽度(mm)',
`status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '状态: 0-正常 1-停用',
`del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标志: 0-存在 2-删除',
`create_by` VARCHAR(64) DEFAULT NULL,
`create_time` DATETIME DEFAULT NULL,
`update_by` VARCHAR(64) DEFAULT NULL,
`update_time` DATETIME DEFAULT NULL,
`remark` VARCHAR(512) DEFAULT NULL,
PRIMARY KEY (`recipe_id`),
UNIQUE KEY `uk_recipe_no` (`recipe_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='双机架工艺方案主表';
-- 工艺方案道次表
CREATE TABLE IF NOT EXISTS `mill_process_pass` (
`pass_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`recipe_id` BIGINT NOT NULL COMMENT '关联方案ID',
`pass_no` INT NOT NULL COMMENT '道次序号',
`in_thick` DECIMAL(8,3) DEFAULT NULL COMMENT '入口厚度(mm)',
`out_thick` DECIMAL(8,3) DEFAULT NULL COMMENT '出口厚度(mm)',
`width` DECIMAL(8,1) DEFAULT NULL COMMENT '宽度(mm)',
`roll_force` DECIMAL(10,2) DEFAULT NULL COMMENT '轧制力(kN)',
`in_tension` DECIMAL(10,2) DEFAULT NULL COMMENT '入口张力(kN)',
`out_tension` DECIMAL(10,2) DEFAULT NULL COMMENT '出口张力(kN)',
`max_speed` DECIMAL(8,2) DEFAULT NULL COMMENT '最高速度(m/min)',
`in_unit_tension` DECIMAL(10,4) DEFAULT NULL COMMENT '入口单位张力(N/mm²)',
`out_unit_tension` DECIMAL(10,4) DEFAULT NULL COMMENT '出口单位张力(N/mm²)',
`reduction` DECIMAL(8,3) DEFAULT NULL COMMENT '压下量(mm)',
`total_reduction` DECIMAL(8,3) DEFAULT NULL COMMENT '总压下量(mm)',
`del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标志',
`create_by` VARCHAR(64) DEFAULT NULL,
`create_time` DATETIME DEFAULT NULL,
`update_by` VARCHAR(64) DEFAULT NULL,
`update_time` DATETIME DEFAULT NULL,
`remark` VARCHAR(512) DEFAULT NULL,
PRIMARY KEY (`pass_id`),
KEY `idx_recipe_id` (`recipe_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='双机架工艺方案道次表';
-- 生产计划表(轧制队列)
CREATE TABLE IF NOT EXISTS `mill_production_plan` (
`plan_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`plan_no` VARCHAR(64) NOT NULL COMMENT '计划号',
`plan_status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '计划状态: 0-待生产 1-生产中 2-完成 3-撤销',
`prod_status` VARCHAR(16) NOT NULL DEFAULT 'Idle' COMMENT '生产状态: Idle/Rolling/NextCoil/Done/Error',
`sort_no` INT NOT NULL DEFAULT 0 COMMENT '队列序号',
`in_mat_no` VARCHAR(64) DEFAULT NULL COMMENT '钢卷编号(入场钢卷号)',
`sg_sign` VARCHAR(64) DEFAULT NULL COMMENT '合金牌号',
`in_mat_thick` DECIMAL(8,3) DEFAULT NULL COMMENT '采料厚度(mm)',
`in_mat_width` DECIMAL(8,1) DEFAULT NULL COMMENT '采料宽度(mm)',
`in_mat_wt` DECIMAL(10,3) DEFAULT NULL COMMENT '采料重量(t)',
`in_mat_len` DECIMAL(10,2) DEFAULT NULL COMMENT '采料长度(m)',
`in_mat_in_dia` DECIMAL(8,1) DEFAULT NULL COMMENT '采料内径(mm)',
`in_mat_dia` DECIMAL(8,1) DEFAULT NULL COMMENT '采料外径(mm)',
`out_thick` DECIMAL(8,3) DEFAULT NULL COMMENT '成品厚度(mm)',
`pass_count` INT NOT NULL DEFAULT 0 COMMENT '道次数',
`recipe_id` BIGINT DEFAULT NULL COMMENT '关联工艺方案ID',
`recipe_no` VARCHAR(64) DEFAULT NULL COMMENT '工艺方案号',
`enter_coil_no` VARCHAR(64) DEFAULT NULL COMMENT '关联三级入场钢卷号',
`current_coil_no` VARCHAR(64) DEFAULT NULL COMMENT '关联三级当前钢卷号',
`del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标志',
`create_by` VARCHAR(64) DEFAULT NULL,
`create_time` DATETIME DEFAULT NULL,
`update_by` VARCHAR(64) DEFAULT NULL,
`update_time` DATETIME DEFAULT NULL,
`remark` VARCHAR(512) DEFAULT NULL,
PRIMARY KEY (`plan_id`),
KEY `idx_in_mat_no` (`in_mat_no`),
KEY `idx_enter_coil_no` (`enter_coil_no`),
KEY `idx_current_coil_no` (`current_coil_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='双机架生产计划表(轧制队列)';

16
docs/spec-match-ddl.sql Normal file
View File

@@ -0,0 +1,16 @@
-- 规程版本新增匹配条件字段
ALTER TABLE wms_process_spec_version
ADD COLUMN match_entry_thick_min DECIMAL(8,3) NULL COMMENT '来料厚度下限(mm)',
ADD COLUMN match_entry_thick_max DECIMAL(8,3) NULL COMMENT '来料厚度上限(mm)',
ADD COLUMN match_exit_thick_min DECIMAL(8,3) NULL COMMENT '出口厚度下限(mm)',
ADD COLUMN match_exit_thick_max DECIMAL(8,3) NULL COMMENT '出口厚度上限(mm)',
ADD COLUMN match_entry_width_min DECIMAL(8,2) NULL COMMENT '来料宽度下限(mm)',
ADD COLUMN match_entry_width_max DECIMAL(8,2) NULL COMMENT '来料宽度上限(mm)',
ADD COLUMN match_exit_width_min DECIMAL(8,2) NULL COMMENT '出口宽度下限(mm)',
ADD COLUMN match_exit_width_max DECIMAL(8,2) NULL COMMENT '出口宽度上限(mm)',
ADD COLUMN match_steel_grade VARCHAR(100) NULL COMMENT '钢种关键字(模糊匹配)';
-- 钢卷主表新增规程绑定字段
ALTER TABLE wms_material_coil
ADD COLUMN spec_id BIGINT NULL COMMENT '绑定的规程ID',
ADD COLUMN version_id BIGINT NULL COMMENT '绑定的规程版本ID';

128
docs/spec-sample-data.sql Normal file
View File

@@ -0,0 +1,128 @@
-- ============================================================
-- 规程匹配测试样本数据
-- 执行前请确认SELECT spec_id, spec_code FROM wms_process_spec;
-- SELECT * FROM wms_production_line WHERE line_id = 1;
-- ============================================================
-- 先查看现有规程,避免重复
-- SELECT * FROM wms_process_spec WHERE line_id = 1;
-- SELECT * FROM wms_process_spec_version WHERE is_active = 1;
-- ─────────────────────────────────────────────────
-- 规程1酸轧通用规程宽范围覆盖大多数钢卷
-- ─────────────────────────────────────────────────
INSERT INTO wms_process_spec (
spec_code, spec_name, spec_type, line_id,
product_type, is_enabled, del_flag,
remark, create_by, create_time, update_by, update_time
) VALUES (
'ACL-STD-001', '酸轧通用规程', 'PROCESS', 1,
'CR', 1, 0,
'通用匹配规程,覆盖常规酸轧来料范围', 'admin', NOW(), 'admin', NOW()
);
-- 获取刚插入的 spec_id
SET @spec_id_std = LAST_INSERT_ID();
-- 版本V1生效版本宽范围
INSERT INTO wms_process_spec_version (
spec_id, version_code, is_active, status, del_flag,
match_entry_thick_min, match_entry_thick_max,
match_exit_thick_min, match_exit_thick_max,
match_entry_width_min, match_entry_width_max,
match_exit_width_min, match_exit_width_max,
match_steel_grade,
remark, create_by, create_time, update_by, update_time
) VALUES (
@spec_id_std, 'V1.0', 1, 1, 0,
1.500, 8.000, -- 来料厚度范围 mm热卷厚度典型值 2~6mm留余量
0.200, 4.000, -- 出口厚度范围 mm冷轧成品典型值 0.3~2mm
700.00, 1700.00, -- 来料宽度范围 mm
700.00, 1700.00, -- 出口宽度范围 mm
NULL, -- 钢种为空 = 不限钢种
'通用版本,宽范围覆盖', 'admin', NOW(), 'admin', NOW()
);
-- ─────────────────────────────────────────────────
-- 规程2酸轧薄规格规程出口厚度 ≤ 1.0mm
-- ─────────────────────────────────────────────────
INSERT INTO wms_process_spec (
spec_code, spec_name, spec_type, line_id,
product_type, is_enabled, del_flag,
remark, create_by, create_time, update_by, update_time
) VALUES (
'ACL-THIN-001', '酸轧薄规格规程', 'PROCESS', 1,
'CR', 1, 0,
'薄规格产品专用出口厚度不超过1.0mm', 'admin', NOW(), 'admin', NOW()
);
SET @spec_id_thin = LAST_INSERT_ID();
-- 版本V1生效版本出口厚度 ≤ 1.0mm
INSERT INTO wms_process_spec_version (
spec_id, version_code, is_active, status, del_flag,
match_entry_thick_min, match_entry_thick_max,
match_exit_thick_min, match_exit_thick_max,
match_entry_width_min, match_entry_width_max,
match_exit_width_min, match_exit_width_max,
match_steel_grade,
remark, create_by, create_time, update_by, update_time
) VALUES (
@spec_id_thin, 'V1.0', 1, 1, 0,
2.000, 5.000, -- 来料厚度
0.200, 1.000, -- 出口厚度(薄规格)
800.00, 1500.00, -- 来料宽度
800.00, 1500.00, -- 出口宽度
NULL, -- 不限钢种
'薄规格专用版本', 'admin', NOW(), 'admin', NOW()
);
-- ─────────────────────────────────────────────────
-- 规程3高强钢规程含钢种匹配
-- ─────────────────────────────────────────────────
INSERT INTO wms_process_spec (
spec_code, spec_name, spec_type, line_id,
product_type, is_enabled, del_flag,
remark, create_by, create_time, update_by, update_time
) VALUES (
'ACL-HSS-001', '酸轧高强钢规程', 'PROCESS', 1,
'CR', 1, 0,
'高强度结构钢专用规程', 'admin', NOW(), 'admin', NOW()
);
SET @spec_id_hss = LAST_INSERT_ID();
INSERT INTO wms_process_spec_version (
spec_id, version_code, is_active, status, del_flag,
match_entry_thick_min, match_entry_thick_max,
match_exit_thick_min, match_exit_thick_max,
match_entry_width_min, match_entry_width_max,
match_exit_width_min, match_exit_width_max,
match_steel_grade,
remark, create_by, create_time, update_by, update_time
) VALUES (
@spec_id_hss, 'V1.0', 1, 1, 0,
2.500, 7.000,
0.500, 2.500,
900.00, 1600.00,
900.00, 1600.00,
'Q', -- 匹配钢种含 "Q" 的Q235、Q345、Q420 等)
'高强钢版本钢种含Q', 'admin', NOW(), 'admin', NOW()
);
-- ─────────────────────────────────────────────────
-- 验证查询
-- ─────────────────────────────────────────────────
SELECT
s.spec_id, s.spec_code, s.spec_name, s.line_id,
v.version_id, v.version_code, v.is_active,
v.match_entry_thick_min, v.match_entry_thick_max,
v.match_exit_thick_min, v.match_exit_thick_max,
v.match_entry_width_min, v.match_entry_width_max,
v.match_steel_grade
FROM wms_process_spec s
JOIN wms_process_spec_version v ON s.spec_id = v.spec_id
WHERE s.line_id = 1
AND s.del_flag = 0
AND v.del_flag = 0
ORDER BY s.spec_id, v.version_code;

View File

@@ -124,6 +124,11 @@
<artifactId>klp-aps</artifactId>
</dependency>
<dependency>
<groupId>com.klp</groupId>
<artifactId>klp-cost</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -361,6 +361,68 @@ public class SqlServerApiClient {
);
}
public ExecuteSqlResponse queryExcoilByHotCoilId(String hotCoilId) {
return executeSql(
"oracle",
"select * from JXPLTCM.PLTCM_PDO_EXCOIL where HOT_COILID = :hotCoilId",
singletonParam("hotCoilId", hotCoilId)
);
}
public ExecuteSqlResponse queryPlanListByHotCoilIdLike(String hotCoilId, int page, int pageSize) {
int endRow = page * pageSize;
int startRow = endRow - pageSize;
Map<String, Object> params = new java.util.HashMap<>();
params.put("startRow", startRow);
params.put("endRow", endRow);
params.put("hotCoilId", "%" + hotCoilId + "%");
return executeSql(
"oracle",
"select * from (select t.*, ROWNUM rn from (select * from JXPLTCM.PLTCM_PDI_PLAN where HOT_COILID LIKE :hotCoilId order by INSDATE desc) t where ROWNUM <= :endRow) where rn > :startRow",
params
);
}
public ExecuteSqlResponse queryPlanCountByHotCoilIdLike(String hotCoilId) {
return executeSql(
"oracle",
"select count(*) as total from JXPLTCM.PLTCM_PDI_PLAN where HOT_COILID LIKE :hotCoilId",
singletonParam("hotCoilId", "%" + hotCoilId + "%")
);
}
/**
* 批量按 EXCOILID 查询出口卷上线/下线时间PLTCM_PDO_EXCOIL
*/
public ExecuteSqlResponse queryExcoilTimesByCoilIds(List<String> coilIds) {
if (coilIds == null || coilIds.isEmpty()) {
return new ExecuteSqlResponse();
}
String inList = coilIds.stream()
.filter(id -> id != null && !id.trim().isEmpty())
.map(id -> "'" + id.replace("'", "''") + "'")
.collect(java.util.stream.Collectors.joining(", "));
if (inList.isEmpty()) return new ExecuteSqlResponse();
String sql = "SELECT EXCOILID, START_DATE, END_DATE FROM JXPLTCM.PLTCM_PDO_EXCOIL WHERE EXCOILID IN (" + inList + ")";
return executeSql("oracle", sql, emptyParams());
}
/**
* 批量按 HOT_COILID 查询计划数据IN 子句,一次 Oracle 调用获取整页数据)
*/
public ExecuteSqlResponse queryPlanDimsByHotCoilIds(List<String> hotCoilIds) {
if (hotCoilIds == null || hotCoilIds.isEmpty()) {
return new ExecuteSqlResponse();
}
String inList = hotCoilIds.stream()
.map(id -> "'" + id.replace("'", "''") + "'")
.collect(java.util.stream.Collectors.joining(", "));
String sql = "SELECT HOT_COILID, ENTRY_THICK, EXIT_THICK, ENTRY_WIDTH, EXIT_WIDTH, GRADE, PROCESS_CODE, COILID " +
"FROM JXPLTCM.PLTCM_PDI_PLAN WHERE HOT_COILID IN (" + inList + ")";
return executeSql("oracle", sql, emptyParams());
}
public ExecuteSqlResponse queryProSegByEncoilId(String encoilId) {
return executeSql(
"oracle",
@@ -413,25 +475,77 @@ public class SqlServerApiClient {
return executeSql("oracle", sql.toString(), params);
}
public ExecuteSqlResponse queryExcoilList(int page, int pageSize) {
public ExecuteSqlResponse queryExcoilByTimeRange(String startTime, String endTime) {
Map<String, Object> params = new java.util.HashMap<>();
StringBuilder sql = new StringBuilder("SELECT * FROM JXPLTCM.PLTCM_PDO_EXCOIL WHERE 1=1");
if (startTime != null && !startTime.trim().isEmpty()) {
sql.append(" AND END_DATE >= TO_DATE(:startTime, 'YYYY-MM-DD HH24:MI:SS')");
params.put("startTime", startTime.trim());
}
if (endTime != null && !endTime.trim().isEmpty()) {
sql.append(" AND END_DATE <= TO_DATE(:endTime, 'YYYY-MM-DD HH24:MI:SS')");
params.put("endTime", endTime.trim());
}
sql.append(" ORDER BY END_DATE DESC");
return executeSql("oracle", sql.toString(), params);
}
// public ExecuteSqlResponse queryExcoilByInsdateRange(String startTime, String endTime) {
// Map<String, Object> params = new java.util.HashMap<>();
// StringBuilder sql = new StringBuilder("SELECT * FROM JXPLTCM.PLTCM_PDO_EXCOIL WHERE 1=1");
// if (startTime != null && !startTime.trim().isEmpty()) {
// sql.append(" AND INSDATE > TO_DATE(:startTime, 'YYYY-MM-DD HH24:MI:SS')");
// params.put("startTime", startTime.trim());
// }
// if (endTime != null && !endTime.trim().isEmpty()) {
// sql.append(" AND INSDATE <= TO_DATE(:endTime, 'YYYY-MM-DD HH24:MI:SS')");
// params.put("endTime", endTime.trim());
// }
// sql.append(" ORDER BY INSDATE ASC");
// return executeSql("oracle", sql.toString(), params);
// }
public ExecuteSqlResponse queryExcoilList(int page, int pageSize, String coilId, String startDate, String endDate) {
int endRow = page * pageSize;
int startRow = endRow - pageSize;
Map<String, Object> params = new java.util.HashMap<>();
params.put("startRow", startRow);
params.put("endRow", endRow);
return executeSql(
"oracle",
"select * from (select t.*, ROWNUM rn from (select * from JXPLTCM.PLTCM_PDO_EXCOIL order by END_DATE desc) t where ROWNUM <= :endRow) where rn > :startRow",
params
);
StringBuilder where = new StringBuilder();
if (coilId != null && !coilId.trim().isEmpty()) {
where.append(" AND UPPER(EXCOILID) LIKE '%' || UPPER(:coilId) || '%'");
params.put("coilId", coilId.trim());
}
if (startDate != null && !startDate.trim().isEmpty()) {
where.append(" AND END_DATE >= TO_DATE(:startDate, 'YYYY-MM-DD HH24:MI:SS')");
params.put("startDate", startDate.trim());
}
if (endDate != null && !endDate.trim().isEmpty()) {
where.append(" AND END_DATE <= TO_DATE(:endDate, 'YYYY-MM-DD HH24:MI:SS')");
params.put("endDate", endDate.trim());
}
String sql = "select * from (select t.*, ROWNUM rn from (select * from JXPLTCM.PLTCM_PDO_EXCOIL WHERE 1=1"
+ where.toString() + " order by END_DATE desc) t where ROWNUM <= :endRow) where rn > :startRow";
return executeSql("oracle", sql, params);
}
public ExecuteSqlResponse queryExcoilCount() {
return executeSql(
"oracle",
"select count(*) as total from JXPLTCM.PLTCM_PDO_EXCOIL",
emptyParams()
);
public ExecuteSqlResponse queryExcoilCount(String coilId, String startDate, String endDate) {
Map<String, Object> params = new java.util.HashMap<>();
StringBuilder where = new StringBuilder();
if (coilId != null && !coilId.trim().isEmpty()) {
where.append(" AND UPPER(EXCOILID) LIKE '%' || UPPER(:coilId) || '%'");
params.put("coilId", coilId.trim());
}
if (startDate != null && !startDate.trim().isEmpty()) {
where.append(" AND END_DATE >= TO_DATE(:startDate, 'YYYY-MM-DD HH24:MI:SS')");
params.put("startDate", startDate.trim());
}
if (endDate != null && !endDate.trim().isEmpty()) {
where.append(" AND END_DATE <= TO_DATE(:endDate, 'YYYY-MM-DD HH24:MI:SS')");
params.put("endDate", endDate.trim());
}
String sql = "select count(*) as total from JXPLTCM.PLTCM_PDO_EXCOIL WHERE 1=1" + where.toString();
return executeSql("oracle", sql, params);
}
public ExecuteSqlResponse queryPresetSetupByCoilId(String coilId) {

View File

@@ -0,0 +1,177 @@
package com.klp.framework.controller;
import com.klp.common.core.domain.R;
import com.klp.domain.bo.WmsMaterialCoilBo;
import com.klp.domain.vo.WmsMaterialCoilVo;
import com.klp.framework.service.SqlServerApiBusinessService;
import com.klp.service.IWmsMaterialCoilService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/coil-comparison")
public class CoilComparisonController {
private final SqlServerApiBusinessService sqlServerService;
private final IWmsMaterialCoilService wmsMaterialCoilService;
/**
* 获取钢卷状态信息接口
* 根据时间范围、产线类型查询钢卷状态,并关联本地系统中的钢卷信息
*
* @param startTime 开始时间(可选)
* @param endTime 结束时间(可选)
* @param lineType 产线类型(可选)
* @return 返回包含钢卷状态信息的列表,每个钢卷信息包含外系统和本系统的相关数据
*/
@GetMapping("/excoil-status")
public R<List<Map<String, Object>>> getExcoilStatus(
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime,
@RequestParam(required = false) String lineType) {
// 默认时间为今天
if (startTime == null || startTime.trim().isEmpty()) {
startTime = LocalDate.now().toString() + " 00:00:00";
}
if (endTime == null || endTime.trim().isEmpty()) {
endTime = LocalDate.now().toString() + " 23:59:59";
}
// 从SQL Server服务获取指定时间范围内的钢卷数据
List<Map<String, Object>> excoilRows = sqlServerService.getExcoilByTimeRange(startTime, endTime);
// 构建查询条件,查询本地系统中的热轧卷板原料信息
WmsMaterialCoilBo bo = new WmsMaterialCoilBo();
bo.setItemType("raw_material");
bo.setMaterialType("原料");
bo.setItemName("热轧卷板");
bo.setSelectType("raw_material");
List<WmsMaterialCoilVo> localCoils = wmsMaterialCoilService.queryList(bo);
// 将本地钢卷数据以钢卷号为key存入Map便于后续查找
Map<String, WmsMaterialCoilVo> localMap = new HashMap<>();
for (WmsMaterialCoilVo coil : localCoils) {
if (coil.getEnterCoilNo() != null) {
localMap.put(coil.getEnterCoilNo(), coil);
}
}
// 处理结果集,将外系统和本地系统的钢卷信息合并
List<Map<String, Object>> result = new ArrayList<>();
for (Map<String, Object> excoil : excoilRows) {
// 获取热轧卷ID
String hotCoilId = excoil.get("hot_coilid") != null ? String.valueOf(excoil.get("hot_coilid")) : null;
// 创建结果项
Map<String, Object> item = new LinkedHashMap<>();
// 添加外系统基本信息
item.put("excoilId", excoil.get("encoilid"));
item.put("hotCoilId", hotCoilId);
item.put("endDate", excoil.get("end_date"));
item.put("startDate", excoil.get("start_date"));
item.put("excoilid", excoil.get("excoilid"));
item.put("grade", excoil.get("grade"));
item.put("status", excoil.get("status"));
item.put("shift", excoil.get("shift"));
item.put("crew", excoil.get("crew"));
item.put("entryThick", excoil.get("entry_thick"));
item.put("entryWeight", excoil.get("entry_weight"));
item.put("entryWidth", excoil.get("entry_width"));
item.put("exitThick", excoil.get("exit_thick"));
item.put("exitWidth", excoil.get("exit_width"));
item.put("exitLength", excoil.get("exit_length"));
item.put("exitNegDev", excoil.get("exit_neg_dev"));
item.put("exitPosDev", excoil.get("exit_pos_dev"));
item.put("calcExitWeight", excoil.get("calc_exit_weight"));
item.put("measExitWeight", excoil.get("meas_exit_weight"));
item.put("quality", excoil.get("quality"));
item.put("shapeQuality", excoil.get("shape_quality"));
item.put("orderQuality", excoil.get("order_quality"));
item.put("productType", excoil.get("product_type"));
item.put("parkType", excoil.get("park_type"));
item.put("sideTrim", excoil.get("side_trim"));
item.put("innerDiameter", excoil.get("inner_diameter"));
item.put("outerDiameter", excoil.get("outer_diameter"));
item.put("headpos", excoil.get("headpos"));
item.put("tailpos", excoil.get("tailpos"));
item.put("subid", excoil.get("subid"));
item.put("rn", excoil.get("rn"));
item.put("comments", excoil.get("comments"));
item.put("reportFlag", excoil.get("report_flag"));
item.put("usedEntryWeight", excoil.get("used_entry_weight"));
item.put("onlineDate", excoil.get("online_date"));
item.put("insdate", excoil.get("insdate"));
item.put("weldedDate", excoil.get("welded_date"));
// 如果存在热轧卷ID则尝试匹配本地系统数据
if (hotCoilId != null) {
WmsMaterialCoilVo matched = localMap.get(hotCoilId);
if (matched != null) {
// 匹配成功,添加本地系统数据
item.put("enterCoilNo", matched.getEnterCoilNo());
item.put("currentCoilNo", matched.getCurrentCoilNo());
item.put("supplierCoilNo", matched.getSupplierCoilNo());
item.put("dataType", matched.getDataType());
item.put("itemName", matched.getItemName());
item.put("itemCode", matched.getItemCode());
item.put("specification", matched.getSpecification());
item.put("material", matched.getMaterial());
item.put("manufacturer", matched.getManufacturer());
item.put("coilStatus", matched.getStatus());
item.put("warehouseName", matched.getWarehouseName());
// 根据数据类型设置匹配状态
if (matched.getDataType() != null && matched.getDataType() == 0) {
item.put("matchStatus", 0);
item.put("matchStatusDesc", "已加工");
} else {
item.put("matchStatus", 1);
item.put("matchStatusDesc", "未加工");
}
} else {
// 未匹配到本地数据,设置为未入库状态
item.put("enterCoilNo", null);
item.put("currentCoilNo", null);
item.put("supplierCoilNo", null);
item.put("dataType", null);
item.put("itemName", null);
item.put("itemCode", null);
item.put("specification", null);
item.put("material", null);
item.put("manufacturer", null);
item.put("coilStatus", null);
item.put("warehouseName", null);
item.put("matchStatus", 2);
item.put("matchStatusDesc", "未入库");
}
} else {
// 热轧卷ID为空设置为未入库状态
item.put("enterCoilNo", null);
item.put("currentCoilNo", null);
item.put("supplierCoilNo", null);
item.put("dataType", null);
item.put("itemName", null);
item.put("itemCode", null);
item.put("specification", null);
item.put("material", null);
item.put("manufacturer", null);
item.put("coilStatus", null);
item.put("warehouseName", null);
item.put("matchStatus", 2);
item.put("matchStatusDesc", "未入库");
}
result.add(item);
}
return R.ok(result);
}
}

View File

@@ -66,6 +66,51 @@ public class SqlServerApiBusinessService {
return PlanListView.fromExecuteSqlResponse(client.queryPlanListByStatus(status));
}
public PlanListView getPlanListByHotCoilIdLike(String hotCoilId, int page, int pageSize) {
return PlanListView.fromExecuteSqlResponse(client.queryPlanListByHotCoilIdLike(hotCoilId, page, pageSize));
}
public long getPlanCountByHotCoilIdLike(String hotCoilId) {
List<Map<String, Object>> rows = asRowList(client.queryPlanCountByHotCoilIdLike(hotCoilId));
if (rows.isEmpty()) return 0L;
Object total = rows.get(0).get("total");
Number n = asNumber(total);
return n == null ? 0L : n.longValue();
}
/**
* 批量获取 L2 计划维度数据(来回料厚/宽、钢种),一次 Oracle 调用覆盖整页。
* 返回 Map&lt;hotCoilId, firstRow&gt;,同一 HOT_COILID 只保留第一行。
*/
/**
* 批量查询出口卷上线/下线时间,返回 Map&lt;excoilId, {START_DATE, END_DATE}&gt;
*/
public Map<String, Map<String, Object>> getExcoilTimesByCoilIds(List<String> coilIds) {
if (coilIds == null || coilIds.isEmpty()) return Collections.emptyMap();
List<Map<String, Object>> rows = asRowList(client.queryExcoilTimesByCoilIds(coilIds));
Map<String, Map<String, Object>> result = new LinkedHashMap<>();
for (Map<String, Object> row : rows) {
Object id = row.getOrDefault("EXCOILID", row.get("excoilid"));
if (id != null) result.putIfAbsent(id.toString().trim(), row);
}
return result;
}
public Map<String, Map<String, Object>> getPlanDimsByHotCoilIds(List<String> hotCoilIds) {
if (hotCoilIds == null || hotCoilIds.isEmpty()) {
return Collections.emptyMap();
}
List<Map<String, Object>> rows = asRowList(client.queryPlanDimsByHotCoilIds(hotCoilIds));
Map<String, Map<String, Object>> result = new LinkedHashMap<>();
for (Map<String, Object> row : rows) {
Object hcId = row.getOrDefault("HOT_COILID", row.get("hot_coilid"));
if (hcId != null) {
result.putIfAbsent(hcId.toString().trim(), row);
}
}
return result;
}
/**
* 计划详情:按成品卷号查询单条计划。
*/
@@ -77,7 +122,10 @@ public class SqlServerApiBusinessService {
* 计划详情:按热卷号查询。
*/
public PlanDetailView getPlanByHotCoilId(String hotCoilId) {
return PlanDetailView.fromExecuteSqlResponse(hotCoilId, client.queryPlanByHotCoilId(hotCoilId));
SqlServerApiClient.ExecuteSqlResponse planResponse = client.queryPlanByHotCoilId(hotCoilId);
SqlServerApiClient.ExecuteSqlResponse excoilResponse = null;
excoilResponse = client.queryExcoilByHotCoilId(hotCoilId);
return PlanDetailView.fromExecuteSqlResponse(hotCoilId, planResponse, excoilResponse);
}
/**
@@ -154,18 +202,32 @@ public class SqlServerApiBusinessService {
public List<Map<String, Object>> getExitTrace() { return exitTrace; }
}
/**
* 出口卷实绩列表(按时间段),来自 PLTCM_PDO_EXCOIL。
*/
public List<Map<String, Object>> getExcoilByTimeRange(String startTime, String endTime) {
return asRowList(client.queryExcoilByTimeRange(startTime, endTime));
}
// /**
// * 出口卷实绩列表(按数据写入时间),用于增量同步。
// */
// public List<Map<String, Object>> getExcoilByInsdateRange(String startTime, String endTime) {
// return asRowList(client.queryExcoilByInsdateRange(startTime, endTime));
// }
/**
* 出口卷实绩列表(分页),来自 PLTCM_PDO_EXCOIL。
*/
public ExcoilPageView getExcoilList(int page, int pageSize) {
return new ExcoilPageView(asRowList(client.queryExcoilList(page, pageSize)));
public ExcoilPageView getExcoilList(int page, int pageSize, String coilId, String startDate, String endDate) {
return new ExcoilPageView(asRowList(client.queryExcoilList(page, pageSize, coilId, startDate, endDate)));
}
/**
* 出口卷实绩总数。
* 出口卷实绩总数(支持钢卷号模糊搜索和时间范围过滤)
*/
public long getExcoilCount() {
List<Map<String, Object>> rows = asRowList(client.queryExcoilCount());
public long getExcoilCount(String coilId, String startDate, String endDate) {
List<Map<String, Object>> rows = asRowList(client.queryExcoilCount(coilId, startDate, endDate));
if (rows.isEmpty()) return 0L;
Number n = asNumber(rows.get(0).get("total"));
return n == null ? 0L : n.longValue();
@@ -190,6 +252,49 @@ public class SqlServerApiBusinessService {
);
}
/**
* 测试用:统计 V_VBDA_GAUGE 中各 THICK 列的非空/非零数量,
* 用于排查"末架出口厚度恒为 0"问题——确认实际数据落在哪一列。
*/
public Map<String, Object> getGaugeStats(String matId) {
List<Map<String, Object>> rows = asRowList(client.queryGaugeByMatId(matId));
String[] cols = {"THICK0", "THICK1", "THICK4", "THICK5",
"THICK0REF", "THICK1REF", "THICK4REF", "THICK5REF"};
Map<String, Object> stats = new LinkedHashMap<>();
for (String col : cols) {
long nonNull = 0, nonZero = 0;
Double min = null, max = null;
for (Map<String, Object> r : rows) {
Object raw = r.get(col);
if (raw == null) raw = r.get(col.toLowerCase());
if (raw == null) continue;
nonNull++;
Number n = asNumber(raw);
if (n == null) continue;
double d = n.doubleValue();
if (d != 0.0) nonZero++;
if (min == null || d < min) min = d;
if (max == null || d > max) max = d;
}
Map<String, Object> info = new LinkedHashMap<>();
info.put("nonNullCount", nonNull);
info.put("nonZeroCount", nonZero);
info.put("min", min);
info.put("max", max);
stats.put(col, info);
}
Map<String, Object> result = new LinkedHashMap<>();
result.put("matId", matId);
result.put("totalRows", rows.size());
result.put("columnStats", stats);
List<Map<String, Object>> samples = new ArrayList<>();
if (!rows.isEmpty()) samples.add(rows.get(0));
if (rows.size() > 1) samples.add(rows.get(rows.size() / 2));
if (rows.size() > 2) samples.add(rows.get(rows.size() - 1));
result.put("sampleRows", samples);
return result;
}
/**
* 轧辊数据:返回全部在辊/备辊数据。
*/
@@ -319,11 +424,13 @@ public class SqlServerApiBusinessService {
private final String coilId;
private final List<Map<String, Object>> rows;
private final Map<String, Object> firstRow;
private final List<Map<String, Object>> excoilRows;
public PlanDetailView(String coilId, List<Map<String, Object>> rows, Map<String, Object> firstRow) {
public PlanDetailView(String coilId, List<Map<String, Object>> rows, Map<String, Object> firstRow, List<Map<String, Object>> excoilRows) {
this.coilId = coilId;
this.rows = rows;
this.firstRow = firstRow;
this.excoilRows = excoilRows;
}
public String getCoilId() {
@@ -338,10 +445,21 @@ public class SqlServerApiBusinessService {
return firstRow;
}
public List<Map<String, Object>> getExcoilRows() {
return excoilRows;
}
public static PlanDetailView fromExecuteSqlResponse(String coilId, SqlServerApiClient.ExecuteSqlResponse response) {
List<Map<String, Object>> rows = asRowList(response);
Map<String, Object> firstRow = rows.isEmpty() ? Collections.<String, Object>emptyMap() : rows.get(0);
return new PlanDetailView(coilId, rows, firstRow);
return new PlanDetailView(coilId, rows, firstRow, Collections.<Map<String, Object>>emptyList());
}
public static PlanDetailView fromExecuteSqlResponse(String coilId, SqlServerApiClient.ExecuteSqlResponse response, SqlServerApiClient.ExecuteSqlResponse excoilResponse) {
List<Map<String, Object>> rows = asRowList(response);
Map<String, Object> firstRow = rows.isEmpty() ? Collections.<String, Object>emptyMap() : rows.get(0);
List<Map<String, Object>> excoilRows = asRowList(excoilResponse);
return new PlanDetailView(coilId, rows, firstRow, excoilRows);
}
}

View File

@@ -94,6 +94,15 @@ public class SqlServerApiController {
return R.ok(businessService.getRealtimeData(matId));
}
/**
* 测试用V_VBDA_GAUGE 各 THICK 列非空/非零统计 + 样本行。
* 用于定位"末架出口厚度恒为 0"问题。
*/
@GetMapping("/test/gauge-stats/{matId}")
public R<Map<String, Object>> testGaugeStats(@PathVariable String matId) {
return R.ok(businessService.getGaugeStats(matId));
}
/**
* 轧辊数据type / status 均可选,不传则返回全量。
*/
@@ -155,23 +164,52 @@ public class SqlServerApiController {
return R.ok(businessService.getRollHistoryList(page, pageSize, rollId, standId));
}
/**
* 出口卷实绩列表(按下线时间),来自 PLTCM_PDO_EXCOIL。
* startTime / endTime 格式yyyy-MM-dd HH:mm:ss
*/
@GetMapping("/excoil/by-time")
public R<List<Map<String, Object>>> excoilByTime(
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime) {
return R.ok(businessService.getExcoilByTimeRange(startTime, endTime));
}
// /**
// * 出口卷实绩列表(按数据写入时间),用于增量同步。
// * startTimeexclusive/ endTimeinclusive格式yyyy-MM-dd HH:mm:ss
// */
// @GetMapping("/excoil/by-insdate")
// public R<List<Map<String, Object>>> excoilByInsdate(
// @RequestParam(required = false) String startTime,
// @RequestParam(required = false) String endTime) {
// return R.ok(businessService.getExcoilByInsdateRange(startTime, endTime));
// }
/**
* 出口卷实绩列表(分页),来自 PLTCM_PDO_EXCOIL。
* 支持 coilId 模糊搜索、startDate/endDate 时间范围过滤。
*/
@GetMapping("/excoil")
public R<SqlServerApiBusinessService.ExcoilPageView> excoilList(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "50") int pageSize) {
return R.ok(businessService.getExcoilList(page, pageSize));
@RequestParam(defaultValue = "50") int pageSize,
@RequestParam(required = false) String coilId,
@RequestParam(required = false) String startDate,
@RequestParam(required = false) String endDate) {
return R.ok(businessService.getExcoilList(page, pageSize, coilId, startDate, endDate));
}
/**
* 出口卷实绩总数。
* 出口卷实绩总数(支持钢卷号模糊搜索和时间范围过滤)
*/
@GetMapping("/excoil/count")
public R<Map<String, Long>> excoilCount() {
public R<Map<String, Long>> excoilCount(
@RequestParam(required = false) String coilId,
@RequestParam(required = false) String startDate,
@RequestParam(required = false) String endDate) {
Map<String, Long> result = new HashMap<>();
result.put("total", businessService.getExcoilCount());
result.put("total", businessService.getExcoilCount(coilId, startDate, endDate));
return R.ok(result);
}

View File

@@ -0,0 +1,502 @@
package com.klp.wms;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.R;
import com.klp.domain.WmsCoilPendingAction;
import com.klp.domain.WmsProductionLine;
import com.klp.domain.bo.WmsMaterialCoilBo;
import com.klp.domain.vo.WmsCoilPendingActionVo;
import com.klp.domain.vo.WmsMaterialCoilVo;
import com.klp.domain.vo.WmsProcessSpecVersionVo;
import com.klp.framework.service.SqlServerApiBusinessService;
import com.klp.mapper.WmsCoilPendingActionMapper;
import com.klp.mapper.WmsProductionLineMapper;
import com.klp.service.IWmsMaterialCoilService;
import com.klp.service.IWmsProcessSpecVersionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* 规程同步接口(跨模块:同时依赖 klp-admin 的 L2 服务和 klp-wms 的规程/钢卷服务)
*/
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/specSync")
public class WmsSpecSyncController extends BaseController {
private final SqlServerApiBusinessService sqlServerApiBusinessService;
private final IWmsProcessSpecVersionService specVersionService;
private final IWmsMaterialCoilService materialCoilService;
private final WmsProductionLineMapper productionLineMapper;
private final WmsCoilPendingActionMapper pendingActionMapper;
/**
* 根据热卷号匹配最佳规程版本(供 typing.vue 在 L2 填入后调用)
*/
@GetMapping("/matchBest")
public R<WmsProcessSpecVersionVo> matchBest(@RequestParam String hotCoilId,
@RequestParam(required = false) Long lineId) {
SqlServerApiBusinessService.PlanDetailView plan =
sqlServerApiBusinessService.getPlanByHotCoilId(hotCoilId);
if (plan == null || plan.getFirstRow().isEmpty()) {
return R.ok(null);
}
Map<String, Object> row = plan.getFirstRow();
BigDecimal entryThick = toBigDecimal(row, "ENTRY_THICK", "entry_thick");
BigDecimal exitThick = toBigDecimal(row, "EXIT_THICK", "exit_thick");
BigDecimal entryWidth = toBigDecimal(row, "ENTRY_WIDTH", "entry_width");
BigDecimal exitWidth = toBigDecimal(row, "EXIT_WIDTH", "exit_width");
String grade = toStr(row, "GRADE", "grade");
WmsProcessSpecVersionVo best = specVersionService.matchBestVersion(
entryThick, exitThick, entryWidth, exitWidth, grade, lineId);
return R.ok(best);
}
/**
* 规程同步分页列表。
* 以 L3WMS MySQL为主维度只展示在 wms_coil_pending_action.processed_coil_ids
* 中出现过的钢卷(即生产后处理过的),再按 enter_coil_no = HOT_COILID 从 L2Oracle
* 批量富化计划维度(入口/出口厚宽、钢种等)及上线/下线时间。
*/
@GetMapping("/pageList")
public R<Map<String, Object>> pageList(
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "40") int pageSize,
@RequestParam(required = false) String enterCoilNo,
@RequestParam(required = false) String currentCoilNo,
@RequestParam(required = false) String material,
@RequestParam(required = false) String qualityStatus,
@RequestParam(required = false) String specCode,
@RequestParam(required = false) String syncStatus,
@RequestParam(required = false) Long lineId) {
// ── 1. 预加载规程版本 ──────────────────────────────────────────────────
// 活跃版本:仅用于推荐候选匹配
List<WmsProcessSpecVersionVo> allActive = specVersionService.queryActiveVersionsEnriched(null);
List<WmsProcessSpecVersionVo> globalCandidates = lineId != null
? allActive.stream().filter(v -> lineId.equals(v.getLineId())).collect(Collectors.toList())
: allActive;
// 全部版本(含历史版本):用于展示已绑定规程名称,避免旧版本查不到
Map<Long, WmsProcessSpecVersionVo> allVersionById = specVersionService.queryAllVersionsEnriched().stream()
.collect(Collectors.toMap(WmsProcessSpecVersionVo::getVersionId, v -> v, (a, b) -> a));
// specCode 过滤 → specId 集合(后置内存过滤,从全部版本里搜)
final Set<Long> filterSpecIds;
if (StringUtils.hasText(specCode)) {
final String kw = specCode.trim().toLowerCase();
filterSpecIds = allVersionById.values().stream()
.filter(v -> (v.getSpecCode() != null && v.getSpecCode().toLowerCase().contains(kw))
|| (v.getSpecName() != null && v.getSpecName().toLowerCase().contains(kw)))
.map(WmsProcessSpecVersionVo::getSpecId)
.collect(Collectors.toSet());
} else {
filterSpecIds = null;
}
// ── 2. 预加载产线表 → actionType(int) → Set<lineId> ───────────────────
// 有效产线wms_production_line.action_type IS NOT NULL即配置了操作类型的产线
List<WmsProductionLine> allLines = productionLineMapper.selectList(
Wrappers.<WmsProductionLine>lambdaQuery()
.isNotNull(WmsProductionLine::getActionType));
Map<Integer, Set<Long>> actionTypeToLineIds = new HashMap<>();
for (WmsProductionLine pl : allLines) {
if (!StringUtils.hasText(pl.getActionType())) continue;
for (String part : pl.getActionType().split(",")) {
try {
int at = Integer.parseInt(part.trim());
actionTypeToLineIds.computeIfAbsent(at, k -> new HashSet<>()).add(pl.getLineId());
} catch (NumberFormatException ignore) { /* 跳过非数字 */ }
}
}
// ── 3. 展开已录入action_status=2待操作的 processed_coil_ids → 输出钢卷 ID ──
Set<Integer> validActionTypes = actionTypeToLineIds.keySet();
Set<Long> typedCoilIds = new LinkedHashSet<>();
Map<Long, Integer> allCoilIdToActionType = new HashMap<>();
if (!validActionTypes.isEmpty()) {
List<WmsCoilPendingAction> allPaList =
pendingActionMapper.selectAllProcessedCoilIdsAndActionStatus();
for (WmsCoilPendingAction pa : allPaList) {
if (pa.getActionType() == null || !validActionTypes.contains(pa.getActionType())) continue;
if (!StringUtils.hasText(pa.getProcessedCoilIds())) continue;
for (String idStr : pa.getProcessedCoilIds().split(",")) {
try {
long pid = Long.parseLong(idStr.trim());
typedCoilIds.add(pid);
allCoilIdToActionType.putIfAbsent(pid, pa.getActionType());
} catch (NumberFormatException ignore) { /* 跳过非数字 */ }
}
}
}
final Map<Long, Integer> coilIdToActionType = allCoilIdToActionType;
// ── 4. 计数分页(仅已录入钢卷,按规程绑定状态过滤)────────────────────────
final String effectiveSyncStatus;
if ("synced".equals(syncStatus)) effectiveSyncStatus = "synced";
else if ("unsynced".equals(syncStatus)) effectiveSyncStatus = "unsynced";
else effectiveSyncStatus = null;
if (typedCoilIds.isEmpty()) {
Map<String, Object> emptyResult = new LinkedHashMap<>();
emptyResult.put("rows", Collections.emptyList());
emptyResult.put("total", 0L);
return R.ok(emptyResult);
}
// ── 4a. 整体汇总统计(忽略 syncStatus 过滤,体现全量分布) ─────────────────
Map<String, Long> overallStats = materialCoilService.getOverallSyncStats(
typedCoilIds, enterCoilNo, currentCoilNo, material, qualityStatus, filterSpecIds);
int offset = (pageNum - 1) * pageSize;
long total = materialCoilService.countByProcessedCoilIds(
typedCoilIds, enterCoilNo, currentCoilNo, material, qualityStatus,
effectiveSyncStatus, filterSpecIds);
List<WmsMaterialCoilVo> l3Coils = materialCoilService.queryByProcessedCoilIds(
typedCoilIds, enterCoilNo, currentCoilNo, material, qualityStatus,
effectiveSyncStatus, filterSpecIds, offset, pageSize);
if (l3Coils.isEmpty()) {
Map<String, Object> emptyResult = new LinkedHashMap<>();
emptyResult.put("rows", Collections.emptyList());
emptyResult.put("total", total);
emptyResult.put("overallStats", overallStats);
return R.ok(emptyResult);
}
// ── 5. L2 富化:批量按 enter_coil_no= HOT_COILID查询计划维度 ──────────
List<String> enterCoilNos = new ArrayList<>();
Set<String> seenNos = new HashSet<>();
for (WmsMaterialCoilVo c : l3Coils) {
String primary = primaryEnterCoilNo(c.getEnterCoilNo());
if (primary != null && seenNos.add(primary)) enterCoilNos.add(primary);
}
Map<String, Map<String, Object>> l2DimMap =
sqlServerApiBusinessService.getPlanDimsByHotCoilIds(enterCoilNos);
// ── 6. 上线/下线时间PLTCM_PDO_EXCOIL.EXCOILID = PLTCM_PDI_PLAN.COILID ──
List<String> l2CoilIds = new ArrayList<>();
for (Map<String, Object> dims : l2DimMap.values()) {
String cid = toStr(dims, "COILID", "coilid");
if (StringUtils.hasText(cid)) l2CoilIds.add(cid);
}
Map<String, Map<String, Object>> excoilTimeMap =
sqlServerApiBusinessService.getExcoilTimesByCoilIds(l2CoilIds);
// ── 7. 组装行 ──────────────────────────────────────────────────────────────
List<Map<String, Object>> rows = new ArrayList<>();
for (WmsMaterialCoilVo coil : l3Coils) {
Map<String, Object> row = new LinkedHashMap<>();
String primaryNo = primaryEnterCoilNo(coil.getEnterCoilNo());
// ── L3 基础字段 ──
row.put("wmsCoilId", coil.getCoilId());
row.put("enterCoilNo", primaryNo);
row.put("currentCoilNo", coil.getCurrentCoilNo());
row.put("supplierCoilNo", coil.getSupplierCoilNo());
row.put("netWeight", coil.getNetWeight());
row.put("actualThickness", coil.getActualThickness());
row.put("actualWidth", coil.getActualWidth());
row.put("qualityStatus", coil.getQualityStatus());
row.put("specification", coil.getSpecification());
row.put("material", coil.getMaterial());
// 是否已流转data_type=0
boolean movedOn = Integer.valueOf(0).equals(coil.getDataType());
row.put("movedOn", movedOn);
row.put("dataType", coil.getDataType());
// ── L2 数据有则富化,无则留空(不跳过,避免破坏分页偏移)──
Map<String, Object> l2row = primaryNo != null ? l2DimMap.get(primaryNo) : null;
BigDecimal entryThick = null, exitThick = null, entryWidth = null, exitWidth = null;
String grade = null, l2CoilId = null;
if (l2row != null) {
entryThick = toBigDecimal(l2row, "ENTRY_THICK", "entry_thick");
exitThick = toBigDecimal(l2row, "EXIT_THICK", "exit_thick");
entryWidth = toBigDecimal(l2row, "ENTRY_WIDTH", "entry_width");
exitWidth = toBigDecimal(l2row, "EXIT_WIDTH", "exit_width");
grade = toStr(l2row, "GRADE", "grade");
l2CoilId = toStr(l2row, "COILID", "coilid");
row.put("entryThick", entryThick);
row.put("exitThick", exitThick);
row.put("entryWidth", entryWidth);
row.put("exitWidth", exitWidth);
row.put("grade", grade);
row.put("processCode", toStr(l2row, "PROCESS_CODE", "process_code"));
row.put("l2CoilId", l2CoilId);
row.put("l2Found", true);
}
// 上线/下线时间
Map<String, Object> excoilTimes = StringUtils.hasText(l2CoilId)
? excoilTimeMap.get(l2CoilId) : null;
if (excoilTimes != null) {
row.put("onlineTime", excoilTimes.getOrDefault("START_DATE", excoilTimes.get("start_date")));
row.put("offlineTime", excoilTimes.getOrDefault("END_DATE", excoilTimes.get("end_date")));
}
// ── 规程绑定状态 ──
if (coil.getVersionId() != null) {
WmsProcessSpecVersionVo bound = allVersionById.get(coil.getVersionId());
if (bound != null) {
row.put("specCode", bound.getSpecCode());
row.put("specName", bound.getSpecName());
row.put("versionCode", bound.getVersionCode());
putMatchConds(row, bound);
}
row.put("syncStatus", "synced");
} else {
row.put("syncStatus", "unsynced");
// 按产线限定候选规程lineId=null 的规程不限定产线,始终纳入)
Integer pendingAt = coilIdToActionType.get(coil.getCoilId());
Set<Long> allowedLineIds = pendingAt != null
? actionTypeToLineIds.getOrDefault(pendingAt, Collections.emptySet())
: null;
// 优先用同产线规程;若过滤后为空则兜底到全量活跃版本
List<WmsProcessSpecVersionVo> candidates;
if (allowedLineIds == null || allowedLineIds.isEmpty()) {
candidates = globalCandidates;
} else {
candidates = globalCandidates.stream()
.filter(v -> v.getLineId() == null || allowedLineIds.contains(v.getLineId()))
.collect(Collectors.toList());
if (candidates.isEmpty()) {
candidates = globalCandidates; // 兜底:产线无匹配规程时展示全部
}
}
WmsProcessSpecVersionVo best = null;
int bestScore = -1;
for (WmsProcessSpecVersionVo v : candidates) {
int s = scoreVersion(v, entryThick, exitThick, entryWidth, exitWidth, grade);
if (s > bestScore) { bestScore = s; best = v; }
}
// bestScore >= 0只要存在候选规程就展示推荐0 = 无维度条件匹配但仍有版本可绑)
if (best != null && bestScore >= 0) {
row.put("candidateSpecCode", best.getSpecCode());
row.put("candidateSpecName", best.getSpecName());
row.put("candidateVersionCode", best.getVersionCode());
row.put("candidateVersionId", best.getVersionId());
row.put("candidateSpecId", best.getSpecId());
putMatchConds(row, best);
}
}
rows.add(row);
}
Map<String, Object> result = new LinkedHashMap<>();
result.put("rows", rows);
result.put("total", total);
result.put("overallStats", overallStats);
return R.ok(result);
}
// ── 私有工具方法 ─────────────────────────────────────────────────────────────
/**
* enter_coil_no 字段可能存储了多个逗号分隔的热卷号(如 "26032550,26032550")。
* 取第一个非空值作为主键,用于展示和 L2 关联查询。
*/
private String primaryEnterCoilNo(String raw) {
if (!StringUtils.hasText(raw)) return null;
String first = raw.split(",")[0].trim();
return first.isEmpty() ? null : first;
}
private int scoreVersion(WmsProcessSpecVersionVo v,
BigDecimal entryThick, BigDecimal exitThick,
BigDecimal entryWidth, BigDecimal exitWidth, String grade) {
int score = 0;
if (entryThick != null && v.getMatchEntryThickMin() != null && v.getMatchEntryThickMax() != null
&& entryThick.compareTo(v.getMatchEntryThickMin()) >= 0
&& entryThick.compareTo(v.getMatchEntryThickMax()) <= 0) score++;
if (exitThick != null && v.getMatchExitThickMin() != null && v.getMatchExitThickMax() != null
&& exitThick.compareTo(v.getMatchExitThickMin()) >= 0
&& exitThick.compareTo(v.getMatchExitThickMax()) <= 0) score++;
if (entryWidth != null && v.getMatchEntryWidthMin() != null && v.getMatchEntryWidthMax() != null
&& entryWidth.compareTo(v.getMatchEntryWidthMin()) >= 0
&& entryWidth.compareTo(v.getMatchEntryWidthMax()) <= 0) score++;
if (exitWidth != null && v.getMatchExitWidthMin() != null && v.getMatchExitWidthMax() != null
&& exitWidth.compareTo(v.getMatchExitWidthMin()) >= 0
&& exitWidth.compareTo(v.getMatchExitWidthMax()) <= 0) score++;
if (StringUtils.hasText(grade) && StringUtils.hasText(v.getMatchSteelGrade())
&& grade.toLowerCase().contains(v.getMatchSteelGrade().toLowerCase())) score++;
return score;
}
private void putMatchConds(Map<String, Object> row, WmsProcessSpecVersionVo v) {
row.put("matchEntryThickMin", v.getMatchEntryThickMin());
row.put("matchEntryThickMax", v.getMatchEntryThickMax());
row.put("matchExitThickMin", v.getMatchExitThickMin());
row.put("matchExitThickMax", v.getMatchExitThickMax());
row.put("matchEntryWidthMin", v.getMatchEntryWidthMin());
row.put("matchEntryWidthMax", v.getMatchEntryWidthMax());
row.put("matchExitWidthMin", v.getMatchExitWidthMin());
row.put("matchExitWidthMax", v.getMatchExitWidthMax());
row.put("matchSteelGrade", v.getMatchSteelGrade());
}
/**
* 待录入核查分页列表。
* 数据源wms_production_line 有效产线对应的待操作记录中 action_status != 2尚未完成 typing的条目。
* 额外按入场卷号从 L2Oracle查询计划/实绩维度,供核查人员判断二级是否已有实绩。
*/
@GetMapping("/untypedPageList")
public R<Map<String, Object>> untypedPageList(
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "40") int pageSize,
@RequestParam(required = false) String enterCoilNo,
@RequestParam(required = false) String currentCoilNo,
@RequestParam(required = false) String operatorName) {
// ── 1. 有效产线 actionType ──────────────────────────────────────────────
List<WmsProductionLine> lines = productionLineMapper.selectList(
Wrappers.<WmsProductionLine>lambdaQuery().isNotNull(WmsProductionLine::getActionType));
Set<Integer> validAts = new HashSet<>();
for (WmsProductionLine pl : lines) {
if (!StringUtils.hasText(pl.getActionType())) continue;
for (String part : pl.getActionType().split(",")) {
try { validAts.add(Integer.parseInt(part.trim())); } catch (NumberFormatException ignore) {}
}
}
if (validAts.isEmpty()) {
Map<String, Object> empty = new LinkedHashMap<>();
empty.put("rows", Collections.emptyList());
empty.put("total", 0L);
return R.ok(empty);
}
// ── 2. 分页查询未录入待操作 ────────────────────────────────────────────────
// 条件1action_status IN (0,1) —— 0=待处理/1=进行中2=已完成/3=已取消均排除
// 条件2processed_coil_ids 为空 —— 只有未写入产出卷 ID 的记录才是尚未录入的
QueryWrapper<WmsCoilPendingAction> qw = new QueryWrapper<>();
qw.eq("wcpa.del_flag", 0);
qw.in("wcpa.action_type", validAts);
qw.in("wcpa.action_status", java.util.Arrays.asList(0, 1));
qw.and(w -> w.isNull("wcpa.processed_coil_ids")
.or().eq("wcpa.processed_coil_ids", ""));
if (StringUtils.hasText(enterCoilNo)) qw.like("wmc.enter_coil_no", enterCoilNo);
if (StringUtils.hasText(currentCoilNo)) qw.like("wcpa.current_coil_no", currentCoilNo);
if (StringUtils.hasText(operatorName)) qw.like("wcpa.operator_name", operatorName);
qw.orderByDesc("wcpa.scan_time");
Page<WmsCoilPendingActionVo> voPage =
pendingActionMapper.selectVoPagePlus(Page.of(pageNum, pageSize), qw);
List<WmsCoilPendingActionVo> paList = voPage.getRecords();
if (paList.isEmpty()) {
Map<String, Object> empty = new LinkedHashMap<>();
empty.put("rows", Collections.emptyList());
empty.put("total", voPage.getTotal());
return R.ok(empty);
}
// ── 3. L2 富化 ─────────────────────────────────────────────────────────
List<String> nos = new ArrayList<>();
Set<String> seen = new HashSet<>();
for (WmsCoilPendingActionVo pa : paList) {
String primary = primaryEnterCoilNo(pa.getEnterCoilNo());
if (primary != null && seen.add(primary)) nos.add(primary);
}
Map<String, Map<String, Object>> l2DimMap = nos.isEmpty()
? Collections.emptyMap()
: sqlServerApiBusinessService.getPlanDimsByHotCoilIds(nos);
// ── 4. 组装行 ──────────────────────────────────────────────────────────
List<Map<String, Object>> rows = new ArrayList<>();
for (WmsCoilPendingActionVo pa : paList) {
String primaryNo = primaryEnterCoilNo(pa.getEnterCoilNo());
Map<String, Object> l2row = primaryNo != null ? l2DimMap.get(primaryNo) : null;
Map<String, Object> row = new LinkedHashMap<>();
row.put("actionId", pa.getActionId());
row.put("coilId", pa.getCoilId());
row.put("actionType", pa.getActionType());
row.put("actionStatus", pa.getActionStatus());
row.put("scanTime", pa.getScanTime());
row.put("createTime", pa.getCreateTime());
row.put("operatorName", pa.getOperatorName());
row.put("warehouseName", pa.getWarehouseName());
row.put("enterCoilNo", primaryNo);
row.put("currentCoilNo", pa.getCurrentCoilNo());
row.put("supplierCoilNo", pa.getSupplierCoilNo());
row.put("material", pa.getMaterial());
row.put("specification", pa.getSpecification());
row.put("itemName", pa.getItemName());
if (l2row != null) {
row.put("entryThick", toBigDecimal(l2row, "ENTRY_THICK", "entry_thick"));
row.put("exitThick", toBigDecimal(l2row, "EXIT_THICK", "exit_thick"));
row.put("entryWidth", toBigDecimal(l2row, "ENTRY_WIDTH", "entry_width"));
row.put("exitWidth", toBigDecimal(l2row, "EXIT_WIDTH", "exit_width"));
row.put("grade", toStr(l2row, "GRADE", "grade"));
row.put("processCode", toStr(l2row, "PROCESS_CODE", "process_code"));
row.put("l2Found", true);
} else {
row.put("l2Found", false);
}
rows.add(row);
}
Map<String, Object> result = new LinkedHashMap<>();
result.put("rows", rows);
result.put("total", voPage.getTotal());
return R.ok(result);
}
/**
* 批量同步规程绑定。
* 请求体:{ "bindings": [{ "coilId": 123, "specId": 456, "versionId": 789 }, ...] }
* 前端已完成匹配计算,直接写入指定的 specId/versionId不重新跑匹配算法。
*/
@PostMapping("/syncSpec")
@SuppressWarnings("unchecked")
public R<Void> syncSpec(@RequestBody Map<String, Object> body) {
List<Map<String, Object>> bindings = (List<Map<String, Object>>) body.get("bindings");
if (bindings == null || bindings.isEmpty()) {
return R.fail("bindings 不能为空");
}
for (Map<String, Object> b : bindings) {
try {
Long coilId = toLong(b, "coilId");
Long specId = toLong(b, "specId");
Long versionId = toLong(b, "versionId");
if (coilId == 0L || specId == 0L || versionId == 0L) continue;
WmsMaterialCoilBo bo = new WmsMaterialCoilBo();
bo.setCoilId(coilId);
bo.setSpecId(specId);
bo.setVersionId(versionId);
materialCoilService.updateSimple(bo);
} catch (Exception e) {
log.warn("规程同步失败 binding={}", b, e);
}
}
return R.ok();
}
private BigDecimal toBigDecimal(Map<String, Object> row, String upperKey, String lowerKey) {
Object val = row.getOrDefault(upperKey, row.get(lowerKey));
if (val == null) return null;
try { return new BigDecimal(val.toString()); } catch (NumberFormatException e) { return null; }
}
private String toStr(Map<String, Object> row, String upperKey, String lowerKey) {
Object val = row.getOrDefault(upperKey, row.get(lowerKey));
return val == null ? null : val.toString().trim();
}
private long toLong(Map<String, Object> row, String key) {
if (row == null) return 0L;
Object v = row.get(key);
if (v == null) return 0L;
try { return Long.parseLong(v.toString()); } catch (NumberFormatException e) { return 0L; }
}
}

View File

@@ -98,6 +98,14 @@ spring:
url: jdbc:mysql://140.143.206.120:3306/cgldb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: klp
password: KeLunPu123@
# 双机架数据源
double-rack:
lazy: true
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://140.143.206.120:13306/double-rack?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
username: klp
password: KeLunPu@123
# Oracle 数据源
acid-l2:
lazy: true
@@ -167,7 +175,7 @@ redisson:
# 客户端名称
clientName: ${klp.name}
# 最小空闲连接数
connectionMinimumIdleSize: 8
connectionMinimumIdleSize: 4
# 连接池大小
connectionPoolSize: 32
# 连接空闲超时,单位:毫秒

View File

@@ -103,6 +103,15 @@ spring:
password: root
hikari:
connectionTestQuery: SELECT 1 FROM DUAL
# 双机架数据源
double-rack:
lazy: true
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://140.143.206.120:13306/double-rack?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
username: klp
password: KeLunPu@123
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
@@ -117,7 +126,7 @@ spring:
# password: root
hikari:
# 最大连接池数量
maxPoolSize: 20
maxPoolSize: 100
# 最小空闲线程数量
minIdle: 10
# 配置获取连接等待超时的时间
@@ -163,7 +172,7 @@ redisson:
# 最小空闲连接数
connectionMinimumIdleSize: 4
# 连接池大小
connectionPoolSize: 64
connectionPoolSize: 128
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 100000
# 命令等待超时,单位:毫秒

View File

@@ -76,6 +76,16 @@ public class ApsPlanDetailController extends BaseController {
return toAjax(iApsPlanDetailService.insertByBo(bo));
}
/**
* 批量新增排产单明细
*/
@Log(title = "排产单明细", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/batch")
public R<Void> batchAdd(@Validated(AddGroup.class) @RequestBody List<ApsPlanDetailBo> boList) {
return toAjax(iApsPlanDetailService.insertBatchByBo(boList));
}
/**
* 修改排产单明细
*/

View File

@@ -226,5 +226,9 @@ public class ApsPlanDetailBo extends BaseEntity {
*/
private String remark;
/**
* 排产日期(字符串格式,例如 '2025-12-29')
*/
private String detailDate;
}

View File

@@ -52,6 +52,11 @@ public class ApsPlanSheetBo extends BaseEntity {
*/
private String planType;
/**
* 排产文件
*/
private String apsUrl;
/**
* 排产人
*/

View File

@@ -184,6 +184,10 @@ public class ApsPlanDetail extends BaseEntity {
* 备注
*/
private String remark;
/**
* 排产日期(字符串格式,例如 '2025-12-29')
*/
private String detailDate;
/**
* 删除标记(0正常 1删除)
*/

View File

@@ -49,6 +49,10 @@ public class ApsPlanSheet extends BaseEntity {
* 排产类型
*/
private String planType;
/**
* 排产文件
*/
private String apsUrl;
/**
* 排产人
*/

View File

@@ -261,6 +261,12 @@ public class ApsPlanDetailVo {
@ExcelProperty(value = "备注")
private String remark;
/**
* 排产日期(字符串格式,例如 '2025-12-29')
*/
@ExcelProperty(value = "排产日期")
private String detailDate;
/**
* 技术附件
*/

View File

@@ -60,6 +60,12 @@ public class ApsPlanSheetVo {
@ExcelProperty(value = "排产类型")
private String planType;
/**
* 排产文件
*/
@ExcelProperty(value = "排产文件")
private String apsUrl;
/**
* 排产人
*/

View File

@@ -43,6 +43,11 @@ public interface IApsPlanDetailService {
*/
Boolean insertByBo(ApsPlanDetailBo bo);
/**
* 批量新增排产单明细
*/
Boolean insertBatchByBo(List<ApsPlanDetailBo> boList);
/**
* 修改排产单明细
*/

View File

@@ -101,6 +101,7 @@ public class ApsPlanDetailServiceImpl implements IApsPlanDetailService {
qw.eq(StringUtils.isNotBlank(bo.getSampleReq()), "d.sample_req", bo.getSampleReq());
qw.eq(bo.getStartTime() != null, "d.start_time", bo.getStartTime());
qw.eq(bo.getEndTime() != null, "d.end_time", bo.getEndTime());
qw.eq(StringUtils.isNotBlank(bo.getDetailDate()), "d.detail_date", bo.getDetailDate());
//根据创建时间倒叙
qw.orderByDesc("d.create_time");
return qw;
@@ -168,6 +169,7 @@ public class ApsPlanDetailServiceImpl implements IApsPlanDetailService {
lqw.eq(StringUtils.isNotBlank(bo.getSampleReq()), ApsPlanDetail::getSampleReq, bo.getSampleReq());
lqw.eq(bo.getStartTime() != null, ApsPlanDetail::getStartTime, bo.getStartTime());
lqw.eq(bo.getEndTime() != null, ApsPlanDetail::getEndTime, bo.getEndTime());
lqw.eq(StringUtils.isNotBlank(bo.getDetailDate()), ApsPlanDetail::getDetailDate, bo.getDetailDate());
return lqw;
}
@@ -185,6 +187,16 @@ public class ApsPlanDetailServiceImpl implements IApsPlanDetailService {
return flag;
}
/**
* 批量新增排产单明细
*/
@Override
public Boolean insertBatchByBo(List<ApsPlanDetailBo> boList) {
List<ApsPlanDetail> list = BeanUtil.copyToList(boList, ApsPlanDetail.class);
list.forEach(this::validEntityBeforeSave);
return baseMapper.insertBatch(list);
}
/**
* 修改排产单明细
*/

View File

@@ -44,6 +44,7 @@
<result property="startTime" column="start_time"/>
<result property="endTime" column="end_time"/>
<result property="remark" column="remark"/>
<result property="detailDate" column="detail_date"/>
<result property="delFlag" column="del_flag"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>

View File

@@ -11,6 +11,7 @@
<result property="lineName" column="line_name"/>
<result property="planCode" column="plan_code"/>
<result property="planType" column="plan_type"/>
<result property="apsUrl" column="aps_url"/>
<result property="scheduler" column="scheduler"/>
<result property="remark" column="remark"/>
<result property="delFlag" column="del_flag"/>
@@ -27,6 +28,7 @@
s.line_name AS lineName,
s.plan_code AS planCode,
s.plan_type AS planType,
s.aps_url AS apsUrl,
s.scheduler AS scheduler,
s.remark AS masterRemark,
d.remark AS detailRemark,

View File

@@ -26,9 +26,15 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Excel相关处理
@@ -149,6 +155,33 @@ public class ExcelUtil {
builder.doWrite(list);
}
/**
* 导出excel仅导出指定列
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param includeColumnFieldNames 需要导出的字段名集合Java字段名非Excel列名
* @param response 响应体
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz,
Set<String> includeColumnFieldNames,
HttpServletResponse response) {
try {
resetResponse(sheetName, response);
ServletOutputStream os = response.getOutputStream();
EasyExcel.write(os, clazz)
.autoCloseStream(false)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerConverter(new ExcelBigNumberConvert())
.includeColumnFieldNames(includeColumnFieldNames)
.sheet(sheetName)
.doWrite(list);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 单表多数据模板导出 模板格式为 {.属性}
*
@@ -325,4 +358,67 @@ public class ExcelUtil {
return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx";
}
/**
* 导出excel按指定顺序的列导出使用动态表头
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param orderedFields 按导出顺序排列的Java字段名列表
* @param fieldLabelMap Java字段名 -> Excel列头中文名 映射
* @param response 响应体
*/
public static <T> void exportExcelOrdered(List<T> list, String sheetName,
List<String> orderedFields,
Map<String, String> fieldLabelMap,
HttpServletResponse response) {
if (orderedFields == null || orderedFields.isEmpty()) {
throw new IllegalArgumentException("导出列不能为空");
}
// 构建动态表头
List<List<String>> heads = orderedFields.stream()
.map(f -> Collections.singletonList(fieldLabelMap.getOrDefault(f, f)))
.collect(Collectors.toList());
// 构建数据行
List<List<Object>> data = new ArrayList<>(list.size());
if (!list.isEmpty()) {
Map<String, Field> fieldCache = new HashMap<>();
Class<?> clazz = list.get(0).getClass();
for (T vo : list) {
List<Object> row = new ArrayList<>(orderedFields.size());
for (String fieldName : orderedFields) {
Field field = fieldCache.computeIfAbsent(fieldName, k -> {
try {
Field f = clazz.getDeclaredField(k);
f.setAccessible(true);
return f;
} catch (NoSuchFieldException e) {
return null;
}
});
try {
row.add(field != null ? field.get(vo) : null);
} catch (IllegalAccessException e) {
row.add(null);
}
}
data.add(row);
}
}
try {
resetResponse(sheetName, response);
ServletOutputStream os = response.getOutputStream();
EasyExcel.write(os)
.head(heads)
.autoCloseStream(false)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerConverter(new ExcelBigNumberConvert())
.sheet(sheetName)
.doWrite(data);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常", e);
}
}
}

20
klp-cost/pom.xml Normal file
View File

@@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.klp</groupId>
<artifactId>klp-oa</artifactId>
<version>0.8.3</version>
</parent>
<artifactId>klp-cost</artifactId>
<name>Archetype - klp-cost</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>com.klp</groupId>
<artifactId>klp-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,99 @@
package com.klp.cost.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.cost.domain.vo.CostItemVo;
import com.klp.cost.domain.bo.CostItemBo;
import com.klp.cost.service.ICostItemService;
import com.klp.common.core.page.TableDataInfo;
/**
* 成本项目配置
*
* @author klp
* @date 2026-05-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cost/item")
public class CostItemController extends BaseController {
private final ICostItemService iCostItemService;
/**
* 查询成本项目配置列表
*/
@GetMapping("/list")
public TableDataInfo<CostItemVo> list(CostItemBo bo, PageQuery pageQuery) {
return iCostItemService.queryPageList(bo, pageQuery);
}
/**
* 导出成本项目配置列表
*/
@Log(title = "成本项目配置", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(CostItemBo bo, HttpServletResponse response) {
List<CostItemVo> list = iCostItemService.queryList(bo);
ExcelUtil.exportExcel(list, "成本项目配置", CostItemVo.class, response);
}
/**
* 获取成本项目配置详细信息
*
* @param itemId 主键
*/
@GetMapping("/{itemId}")
public R<CostItemVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long itemId) {
return R.ok(iCostItemService.queryById(itemId));
}
/**
* 新增成本项目配置
*/
@Log(title = "成本项目配置", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CostItemBo bo) {
return toAjax(iCostItemService.insertByBo(bo));
}
/**
* 修改成本项目配置
*/
@Log(title = "成本项目配置", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CostItemBo bo) {
return toAjax(iCostItemService.updateByBo(bo));
}
/**
* 删除成本项目配置
*
* @param itemIds 主键串
*/
@Log(title = "成本项目配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{itemIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] itemIds) {
return toAjax(iCostItemService.deleteWithValidByIds(Arrays.asList(itemIds), true));
}
}

View File

@@ -0,0 +1,100 @@
package com.klp.cost.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.cost.domain.vo.CostPriceVo;
import com.klp.cost.domain.bo.CostPriceBo;
import com.klp.cost.service.ICostPriceService;
import com.klp.common.core.page.TableDataInfo;
/**
* 成本单价历史
*
* @author klp
* @date 2026-05-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cost/price")
public class CostPriceController extends BaseController {
private final ICostPriceService iCostPriceService;
/**
* 查询成本单价历史列表
*/
@GetMapping("/list")
public TableDataInfo<CostPriceVo> list(CostPriceBo bo, PageQuery pageQuery) {
return iCostPriceService.queryPageList(bo, pageQuery);
}
/**
* 导出成本单价历史列表
*/
@Log(title = "成本单价历史", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(CostPriceBo bo, HttpServletResponse response) {
List<CostPriceVo> list = iCostPriceService.queryList(bo);
ExcelUtil.exportExcel(list, "成本单价历史", CostPriceVo.class, response);
}
/**
* 获取成本单价历史详细信息
*
* @param priceId 主键
*/
@GetMapping("/{priceId}")
public R<CostPriceVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long priceId) {
return R.ok(iCostPriceService.queryById(priceId));
}
/**
* 新增成本单价历史
*/
@Log(title = "成本单价历史", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CostPriceBo bo) {
return toAjax(iCostPriceService.insertByBo(bo));
}
/**
* 修改成本单价历史
*/
@Log(title = "成本单价历史", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CostPriceBo bo) {
return toAjax(iCostPriceService.updateByBo(bo));
}
/**
* 删除成本单价历史
*
* @param priceIds 主键串
*/
@Log(title = "成本单价历史", businessType = BusinessType.DELETE)
@DeleteMapping("/{priceIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] priceIds) {
return toAjax(iCostPriceService.deleteWithValidByIds(Arrays.asList(priceIds), true));
}
}

View File

@@ -0,0 +1,109 @@
package com.klp.cost.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.cost.domain.vo.CostProdDetailVo;
import com.klp.cost.domain.bo.CostProdDetailBo;
import com.klp.cost.service.ICostProdDetailService;
import com.klp.common.core.page.TableDataInfo;
/**
* 生产成本明细
*
* @author klp
* @date 2026-05-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cost/prodDetail")
public class CostProdDetailController extends BaseController {
private final ICostProdDetailService iCostProdDetailService;
/**
* 查询生产成本明细列表
*/
@GetMapping("/list")
public TableDataInfo<CostProdDetailVo> list(CostProdDetailBo bo, PageQuery pageQuery) {
return iCostProdDetailService.queryPageList(bo, pageQuery);
}
/**
* 导出生产成本明细列表
*/
@Log(title = "生产成本明细", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(CostProdDetailBo bo, HttpServletResponse response) {
List<CostProdDetailVo> list = iCostProdDetailService.queryList(bo);
ExcelUtil.exportExcel(list, "生产成本明细", CostProdDetailVo.class, response);
}
/**
* 获取生产成本明细详细信息
*
* @param detailId 主键
*/
@GetMapping("/{detailId}")
public R<CostProdDetailVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long detailId) {
return R.ok(iCostProdDetailService.queryById(detailId));
}
/**
* 新增生产成本明细
*/
@Log(title = "生产成本明细", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody CostProdDetailBo bo) {
return R.ok(iCostProdDetailService.insertByBo(bo));
}
/**
* 批量保存生产成本明细(先删除再插入)
*/
@Log(title = "生产成本明细", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/batch")
public R<Void> batchSave(@RequestBody CostProdDetailBo bo) {
return toAjax(iCostProdDetailService.batchSaveWithDelete(bo));
}
/**
* 修改生产成本明细
*/
@Log(title = "生产成本明细", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CostProdDetailBo bo) {
return toAjax(iCostProdDetailService.updateByBo(bo));
}
/**
* 删除生产成本明细
*
* @param detailIds 主键串
*/
@Log(title = "生产成本明细", businessType = BusinessType.DELETE)
@DeleteMapping("/{detailIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] detailIds) {
return toAjax(iCostProdDetailService.deleteWithValidByIds(Arrays.asList(detailIds), true));
}
}

View File

@@ -0,0 +1,99 @@
package com.klp.cost.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.cost.domain.vo.CostProdMetricVo;
import com.klp.cost.domain.bo.CostProdMetricBo;
import com.klp.cost.service.ICostProdMetricService;
import com.klp.common.core.page.TableDataInfo;
/**
* 生产指标明细
*
* @author klp
* @date 2026-05-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cost/prodMetric")
public class CostProdMetricController extends BaseController {
private final ICostProdMetricService iCostProdMetricService;
/**
* 查询生产指标明细列表
*/
@GetMapping("/list")
public TableDataInfo<CostProdMetricVo> list(CostProdMetricBo bo, PageQuery pageQuery) {
return iCostProdMetricService.queryPageList(bo, pageQuery);
}
/**
* 导出生产指标明细列表
*/
@Log(title = "生产指标明细", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(CostProdMetricBo bo, HttpServletResponse response) {
List<CostProdMetricVo> list = iCostProdMetricService.queryList(bo);
ExcelUtil.exportExcel(list, "生产指标明细", CostProdMetricVo.class, response);
}
/**
* 获取生产指标明细详细信息
*
* @param metricId 主键
*/
@GetMapping("/{metricId}")
public R<CostProdMetricVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long metricId) {
return R.ok(iCostProdMetricService.queryById(metricId));
}
/**
* 新增生产指标明细
*/
@Log(title = "生产指标明细", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CostProdMetricBo bo) {
return toAjax(iCostProdMetricService.insertByBo(bo));
}
/**
* 修改生产指标明细
*/
@Log(title = "生产指标明细", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CostProdMetricBo bo) {
return toAjax(iCostProdMetricService.updateByBo(bo));
}
/**
* 删除生产指标明细
*
* @param metricIds 主键串
*/
@Log(title = "生产指标明细", businessType = BusinessType.DELETE)
@DeleteMapping("/{metricIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] metricIds) {
return toAjax(iCostProdMetricService.deleteWithValidByIds(Arrays.asList(metricIds), true));
}
}

View File

@@ -0,0 +1,111 @@
package com.klp.cost.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.cost.domain.vo.CostProdReportVo;
import com.klp.cost.domain.bo.CostProdReportBo;
import com.klp.cost.service.ICostProdReportService;
import com.klp.common.core.page.TableDataInfo;
/**
* 生产月报
*
* @author klp
* @date 2026-05-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cost/prodReport")
public class CostProdReportController extends BaseController {
private final ICostProdReportService iCostProdReportService;
/**
* 查询生产月报列表
*/
@GetMapping("/list")
public TableDataInfo<CostProdReportVo> list(CostProdReportBo bo, PageQuery pageQuery) {
return iCostProdReportService.queryPageList(bo, pageQuery);
}
/**
* 导出生产月报列表
*/
@Log(title = "生产月报", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(CostProdReportBo bo, HttpServletResponse response) {
List<CostProdReportVo> list = iCostProdReportService.queryList(bo);
ExcelUtil.exportExcel(list, "生产月报", CostProdReportVo.class, response);
}
/**
* 获取生产月报详细信息
*
* @param reportId 主键
*/
@GetMapping("/{reportId}")
public R<CostProdReportVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long reportId) {
return R.ok(iCostProdReportService.queryById(reportId));
}
/**
* 新增生产月报
*/
@Log(title = "生产月报", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CostProdReportBo bo) {
return toAjax(iCostProdReportService.insertByBo(bo));
}
/**
* 修改生产月报
*/
@Log(title = "生产月报", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CostProdReportBo bo) {
return toAjax(iCostProdReportService.updateByBo(bo));
}
/**
* 删除生产月报
*
* @param reportIds 主键串
*/
@Log(title = "生产月报", businessType = BusinessType.DELETE)
@DeleteMapping("/{reportIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] reportIds) {
return toAjax(iCostProdReportService.deleteWithValidByIds(Arrays.asList(reportIds), true));
}
/**
* 复制生产月报
* 明细列原样保留指标列重新插入并更新config中的id引用
*/
@Log(title = "生产月报", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/copy/{sourceId}")
public R<CostProdReportVo> copy(@NotNull(message = "源报表ID不能为空") @PathVariable Long sourceId,
@RequestBody CostProdReportBo bo) {
return R.ok(iCostProdReportService.copyReport(sourceId, bo));
}
}

View File

@@ -0,0 +1,57 @@
package com.klp.cost.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 成本项目配置对象 cost_item
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("cost_item")
public class CostItem extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "item_id")
private Long itemId;
/**
* 成本项目编码
*/
private String itemCode;
/**
* 成本项目名称
*/
private String itemName;
/**
* 成本分类 原料/能耗/辅料/设备/人工
*/
private String category;
/**
* 计量单位
*/
private String unit;
/**
* 备注
*/
private String remark;
/**
* 查询条件JSON格式
*/
private String queryCondition;
/**
* 删除标识 0=正常 2=删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,55 @@
package com.klp.cost.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 成本单价历史对象 cost_price
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("cost_price")
public class CostPrice extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "price_id")
private Long priceId;
/**
* 成本项目ID
*/
private Long itemId;
/**
* 单价
*/
private BigDecimal price;
/**
* 生效日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date effectiveDate;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0=正常 2=删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,71 @@
package com.klp.cost.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 生产成本明细对象 cost_prod_detail
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("cost_prod_detail")
public class CostProdDetail extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "detail_id")
private Long detailId;
/**
* 生产月报ID
*/
private Long reportId;
/**
* 班次 1=甲班 2=乙班
*/
private String shift;
/**
* 日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date detailDate;
/**
* 成本项目ID
*/
private Long itemId;
/**
* 消耗用量
*/
private BigDecimal quantity;
/**
* 单价
*/
private BigDecimal unitPrice;
/**
* 总金额
*/
private BigDecimal amount;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0=正常 2=删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,62 @@
package com.klp.cost.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
/**
* 生产指标明细对象 cost_prod_metric
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("cost_prod_metric")
public class CostProdMetric extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "metric_id")
private Long metricId;
/**
* 生产日报ID
*/
private Long reportId;
/**
* 指标编码
*/
private String metricCode;
/**
* 指标名称
*/
private String metricName;
/**
* 指标计算公式output_weight/input_weight*100
*/
private String metricFormula;
/**
* 单价
*/
private BigDecimal metricValue;
/**
* 是否使用单价 0=否 1=是
*/
private Integer usePrice;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0=正常 2=删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,67 @@
package com.klp.cost.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 生产月报对象 cost_prod_report
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("cost_prod_report")
public class CostProdReport extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "report_id")
private Long reportId;
/**
* 报表标题
*/
private String reportTitle;
/**
* 报表日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date reportDate;
/**
* 产线类型 acid=酸轧 galvanized=镀锌
*/
private String lineType;
/**
* 投入量 单位:吨
*/
private BigDecimal inputWeight;
/**
* 产出量 单位:吨
*/
private BigDecimal outputWeight;
/**
* 备注
*/
private String remark;
/**
* 列配置JSON
*/
private String colConfig;
/**
* 删除标识 0=正常 2=删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,56 @@
package com.klp.cost.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
/**
* 成本项目配置业务对象 cost_item
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CostItemBo extends BaseEntity {
/**
* 主键ID
*/
private Long itemId;
/**
* 成本项目编码
*/
private String itemCode;
/**
* 成本项目名称
*/
private String itemName;
/**
* 成本分类 原料/能耗/辅料/设备/人工
*/
private String category;
/**
* 计量单位
*/
private String unit;
/**
* 备注
*/
private String remark;
/**
* 查询条件JSON格式
*/
private String queryCondition;
}

View File

@@ -0,0 +1,52 @@
package com.klp.cost.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 成本单价历史业务对象 cost_price
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CostPriceBo extends BaseEntity {
/**
* 主键ID
*/
private Long priceId;
/**
* 成本项目ID
*/
private Long itemId;
/**
* 单价
*/
private BigDecimal price;
/**
* 生效日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date effectiveDate;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,83 @@
package com.klp.cost.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 生产成本明细业务对象 cost_prod_detail
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CostProdDetailBo extends BaseEntity {
/**
* 主键ID
*/
private Long detailId;
/**
* 生产月报ID
*/
private Long reportId;
/**
* 班次 1=甲班 2=乙班
*/
private String shift;
/**
* 日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date detailDate;
/**
* 成本项目ID
*/
private Long itemId;
/**
* 消耗用量
*/
private BigDecimal quantity;
/**
* 单价
*/
private BigDecimal unitPrice;
/**
* 总金额
*/
private BigDecimal amount;
/**
* 备注
*/
private String remark;
/**
* 要删除的主键ID集合
*/
private List<Long> detailIds;
/**
* 要批量插入的数据集合
*/
private List<CostProdDetailBo> prodDetailList;
}

View File

@@ -0,0 +1,62 @@
package com.klp.cost.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.math.BigDecimal;
/**
* 生产指标明细业务对象 cost_prod_metric
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CostProdMetricBo extends BaseEntity {
/**
* 主键ID
*/
private Long metricId;
/**
* 生产日报ID
*/
private Long reportId;
/**
* 指标编码
*/
private String metricCode;
/**
* 指标名称
*/
private String metricName;
/**
* 指标计算公式output_weight/input_weight*100
*/
private String metricFormula;
/**
* 单价
*/
private BigDecimal metricValue;
/**
* 是否使用单价 0=否 1=是
*/
private Integer usePrice;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,66 @@
package com.klp.cost.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 生产月报业务对象 cost_prod_report
*
* @author klp
* @date 2026-05-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CostProdReportBo extends BaseEntity {
/**
* 主键ID
*/
private Long reportId;
/**
* 报表标题
*/
private String reportTitle;
/**
* 报表日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date reportDate;
/**
* 产线类型 acid=酸轧 galvanized=镀锌
*/
private String lineType;
/**
* 投入量 单位:吨
*/
private BigDecimal inputWeight;
/**
* 产出量 单位:吨
*/
private BigDecimal outputWeight;
/**
* 备注
*/
private String remark;
/**
* 列配置JSON
*/
private String colConfig;
}

View File

@@ -0,0 +1,65 @@
package com.klp.cost.domain.vo;
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;
/**
* 成本项目配置视图对象 cost_item
*
* @author klp
* @date 2026-05-25
*/
@Data
@ExcelIgnoreUnannotated
public class CostItemVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long itemId;
/**
* 成本项目编码
*/
@ExcelProperty(value = "成本项目编码")
private String itemCode;
/**
* 成本项目名称
*/
@ExcelProperty(value = "成本项目名称")
private String itemName;
/**
* 成本分类 原料/能耗/辅料/设备/人工
*/
@ExcelProperty(value = "成本分类 原料/能耗/辅料/设备/人工")
private String category;
/**
* 计量单位
*/
@ExcelProperty(value = "计量单位")
private String unit;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 查询条件JSON格式
*/
@ExcelProperty(value = "查询条件JSON格式")
private String queryCondition;
}

View File

@@ -0,0 +1,56 @@
package com.klp.cost.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;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
/**
* 成本单价历史视图对象 cost_price
*
* @author klp
* @date 2026-05-25
*/
@Data
@ExcelIgnoreUnannotated
public class CostPriceVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long priceId;
/**
* 成本项目ID
*/
@ExcelProperty(value = "成本项目ID")
private Long itemId;
/**
* 单价
*/
@ExcelProperty(value = "单价")
private BigDecimal price;
/**
* 生效日期
*/
@ExcelProperty(value = "生效日期")
private Date effectiveDate;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,80 @@
package com.klp.cost.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;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
/**
* 生产成本明细视图对象 cost_prod_detail
*
* @author klp
* @date 2026-05-25
*/
@Data
@ExcelIgnoreUnannotated
public class CostProdDetailVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long detailId;
/**
* 生产月报ID
*/
@ExcelProperty(value = "生产月报ID")
private Long reportId;
/**
* 班次 1=甲班 2=乙班
*/
@ExcelProperty(value = "班次 1=甲班 2=乙班")
private String shift;
/**
* 日期
*/
@ExcelProperty(value = "日期")
private Date detailDate;
/**
* 成本项目ID
*/
@ExcelProperty(value = "成本项目ID")
private Long itemId;
/**
* 消耗用量
*/
@ExcelProperty(value = "消耗用量")
private BigDecimal quantity;
/**
* 单价
*/
@ExcelProperty(value = "单价")
private BigDecimal unitPrice;
/**
* 总金额
*/
@ExcelProperty(value = "总金额")
private BigDecimal amount;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,73 @@
package com.klp.cost.domain.vo;
import java.math.BigDecimal;
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;
/**
* 生产指标明细视图对象 cost_prod_metric
*
* @author klp
* @date 2026-05-25
*/
@Data
@ExcelIgnoreUnannotated
public class CostProdMetricVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long metricId;
/**
* 生产日报ID
*/
@ExcelProperty(value = "生产日报ID")
private Long reportId;
/**
* 指标编码
*/
@ExcelProperty(value = "指标编码")
private String metricCode;
/**
* 指标名称
*/
@ExcelProperty(value = "指标名称")
private String metricName;
/**
* 指标计算公式output_weight/input_weight*100
*/
@ExcelProperty(value = "指标计算公式", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "如=output_weight/input_weight*100")
private String metricFormula;
/**
* 单价
*/
@ExcelProperty(value = "单价")
private BigDecimal metricValue;
/**
* 是否使用单价 0=否 1=是
*/
@ExcelProperty(value = "是否使用单价")
private Integer usePrice;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,72 @@
package com.klp.cost.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;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
/**
* 生产月报视图对象 cost_prod_report
*
* @author klp
* @date 2026-05-25
*/
@Data
@ExcelIgnoreUnannotated
public class CostProdReportVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long reportId;
/**
* 报表标题
*/
@ExcelProperty(value = "报表标题")
private String reportTitle;
/**
* 报表日期
*/
@ExcelProperty(value = "报表日期")
private Date reportDate;
/**
* 产线类型 acid=酸轧 galvanized=镀锌
*/
@ExcelProperty(value = "产线类型 acid=酸轧 galvanized=镀锌")
private String lineType;
/**
* 投入量 单位:吨
*/
@ExcelProperty(value = "投入量 单位:吨")
private BigDecimal inputWeight;
/**
* 产出量 单位:吨
*/
@ExcelProperty(value = "产出量 单位:吨")
private BigDecimal outputWeight;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 列配置JSON
*/
private String colConfig;
}

View File

@@ -0,0 +1,15 @@
package com.klp.cost.mapper;
import com.klp.cost.domain.CostItem;
import com.klp.cost.domain.vo.CostItemVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 成本项目配置Mapper接口
*
* @author klp
* @date 2026-05-25
*/
public interface CostItemMapper extends BaseMapperPlus<CostItemMapper, CostItem, CostItemVo> {
}

View File

@@ -0,0 +1,15 @@
package com.klp.cost.mapper;
import com.klp.cost.domain.CostPrice;
import com.klp.cost.domain.vo.CostPriceVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 成本单价历史Mapper接口
*
* @author klp
* @date 2026-05-25
*/
public interface CostPriceMapper extends BaseMapperPlus<CostPriceMapper, CostPrice, CostPriceVo> {
}

View File

@@ -0,0 +1,15 @@
package com.klp.cost.mapper;
import com.klp.cost.domain.CostProdDetail;
import com.klp.cost.domain.vo.CostProdDetailVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 生产成本明细Mapper接口
*
* @author klp
* @date 2026-05-25
*/
public interface CostProdDetailMapper extends BaseMapperPlus<CostProdDetailMapper, CostProdDetail, CostProdDetailVo> {
}

View File

@@ -0,0 +1,15 @@
package com.klp.cost.mapper;
import com.klp.cost.domain.CostProdMetric;
import com.klp.cost.domain.vo.CostProdMetricVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 生产指标明细Mapper接口
*
* @author klp
* @date 2026-05-25
*/
public interface CostProdMetricMapper extends BaseMapperPlus<CostProdMetricMapper, CostProdMetric, CostProdMetricVo> {
}

View File

@@ -0,0 +1,15 @@
package com.klp.cost.mapper;
import com.klp.cost.domain.CostProdReport;
import com.klp.cost.domain.vo.CostProdReportVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 生产月报Mapper接口
*
* @author klp
* @date 2026-05-25
*/
public interface CostProdReportMapper extends BaseMapperPlus<CostProdReportMapper, CostProdReport, CostProdReportVo> {
}

View File

@@ -0,0 +1,49 @@
package com.klp.cost.service;
import com.klp.cost.domain.CostItem;
import com.klp.cost.domain.vo.CostItemVo;
import com.klp.cost.domain.bo.CostItemBo;
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-05-25
*/
public interface ICostItemService {
/**
* 查询成本项目配置
*/
CostItemVo queryById(Long itemId);
/**
* 查询成本项目配置列表
*/
TableDataInfo<CostItemVo> queryPageList(CostItemBo bo, PageQuery pageQuery);
/**
* 查询成本项目配置列表
*/
List<CostItemVo> queryList(CostItemBo bo);
/**
* 新增成本项目配置
*/
Boolean insertByBo(CostItemBo bo);
/**
* 修改成本项目配置
*/
Boolean updateByBo(CostItemBo bo);
/**
* 校验并批量删除成本项目配置信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,49 @@
package com.klp.cost.service;
import com.klp.cost.domain.CostPrice;
import com.klp.cost.domain.vo.CostPriceVo;
import com.klp.cost.domain.bo.CostPriceBo;
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-05-25
*/
public interface ICostPriceService {
/**
* 查询成本单价历史
*/
CostPriceVo queryById(Long priceId);
/**
* 查询成本单价历史列表
*/
TableDataInfo<CostPriceVo> queryPageList(CostPriceBo bo, PageQuery pageQuery);
/**
* 查询成本单价历史列表
*/
List<CostPriceVo> queryList(CostPriceBo bo);
/**
* 新增成本单价历史
*/
Boolean insertByBo(CostPriceBo bo);
/**
* 修改成本单价历史
*/
Boolean updateByBo(CostPriceBo bo);
/**
* 校验并批量删除成本单价历史信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,54 @@
package com.klp.cost.service;
import com.klp.cost.domain.CostProdDetail;
import com.klp.cost.domain.vo.CostProdDetailVo;
import com.klp.cost.domain.bo.CostProdDetailBo;
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-05-25
*/
public interface ICostProdDetailService {
/**
* 查询生产成本明细
*/
CostProdDetailVo queryById(Long detailId);
/**
* 查询生产成本明细列表
*/
TableDataInfo<CostProdDetailVo> queryPageList(CostProdDetailBo bo, PageQuery pageQuery);
/**
* 查询生产成本明细列表
*/
List<CostProdDetailVo> queryList(CostProdDetailBo bo);
/**
* 新增生产成本明细
*/
Long insertByBo(CostProdDetailBo bo);
/**
* 修改生产成本明细
*/
Boolean updateByBo(CostProdDetailBo bo);
/**
* 校验并批量删除生产成本明细信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 批量保存(先删除再插入)
*/
Boolean batchSaveWithDelete(CostProdDetailBo bo);
}

View File

@@ -0,0 +1,49 @@
package com.klp.cost.service;
import com.klp.cost.domain.CostProdMetric;
import com.klp.cost.domain.vo.CostProdMetricVo;
import com.klp.cost.domain.bo.CostProdMetricBo;
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-05-25
*/
public interface ICostProdMetricService {
/**
* 查询生产指标明细
*/
CostProdMetricVo queryById(Long metricId);
/**
* 查询生产指标明细列表
*/
TableDataInfo<CostProdMetricVo> queryPageList(CostProdMetricBo bo, PageQuery pageQuery);
/**
* 查询生产指标明细列表
*/
List<CostProdMetricVo> queryList(CostProdMetricBo bo);
/**
* 新增生产指标明细
*/
Boolean insertByBo(CostProdMetricBo bo);
/**
* 修改生产指标明细
*/
Boolean updateByBo(CostProdMetricBo bo);
/**
* 校验并批量删除生产指标明细信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,54 @@
package com.klp.cost.service;
import com.klp.cost.domain.CostProdReport;
import com.klp.cost.domain.vo.CostProdReportVo;
import com.klp.cost.domain.bo.CostProdReportBo;
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-05-25
*/
public interface ICostProdReportService {
/**
* 查询生产月报
*/
CostProdReportVo queryById(Long reportId);
/**
* 查询生产月报列表
*/
TableDataInfo<CostProdReportVo> queryPageList(CostProdReportBo bo, PageQuery pageQuery);
/**
* 查询生产月报列表
*/
List<CostProdReportVo> queryList(CostProdReportBo bo);
/**
* 新增生产月报
*/
Boolean insertByBo(CostProdReportBo bo);
/**
* 修改生产月报
*/
Boolean updateByBo(CostProdReportBo bo);
/**
* 校验并批量删除生产月报信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 复制生产月报明细列原样保留指标列重新插入并更新config中的id引用
*/
CostProdReportVo copyReport(Long sourceId, CostProdReportBo bo);
}

View File

@@ -0,0 +1,113 @@
package com.klp.cost.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.cost.domain.bo.CostItemBo;
import com.klp.cost.domain.vo.CostItemVo;
import com.klp.cost.domain.CostItem;
import com.klp.cost.mapper.CostItemMapper;
import com.klp.cost.service.ICostItemService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 成本项目配置Service业务层处理
*
* @author klp
* @date 2026-05-25
*/
@RequiredArgsConstructor
@Service
public class CostItemServiceImpl implements ICostItemService {
private final CostItemMapper baseMapper;
/**
* 查询成本项目配置
*/
@Override
public CostItemVo queryById(Long itemId){
return baseMapper.selectVoById(itemId);
}
/**
* 查询成本项目配置列表
*/
@Override
public TableDataInfo<CostItemVo> queryPageList(CostItemBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<CostItem> lqw = buildQueryWrapper(bo);
Page<CostItemVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询成本项目配置列表
*/
@Override
public List<CostItemVo> queryList(CostItemBo bo) {
LambdaQueryWrapper<CostItem> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<CostItem> buildQueryWrapper(CostItemBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CostItem> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getItemCode()), CostItem::getItemCode, bo.getItemCode());
lqw.like(StringUtils.isNotBlank(bo.getItemName()), CostItem::getItemName, bo.getItemName());
lqw.eq(StringUtils.isNotBlank(bo.getCategory()), CostItem::getCategory, bo.getCategory());
lqw.eq(StringUtils.isNotBlank(bo.getUnit()), CostItem::getUnit, bo.getUnit());
lqw.eq(StringUtils.isNotBlank(bo.getQueryCondition()), CostItem::getQueryCondition, bo.getQueryCondition());
return lqw;
}
/**
* 新增成本项目配置
*/
@Override
public Boolean insertByBo(CostItemBo bo) {
CostItem add = BeanUtil.toBean(bo, CostItem.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setItemId(add.getItemId());
}
return flag;
}
/**
* 修改成本项目配置
*/
@Override
public Boolean updateByBo(CostItemBo bo) {
CostItem update = BeanUtil.toBean(bo, CostItem.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(CostItem entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除成本项目配置
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,110 @@
package com.klp.cost.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 lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.cost.domain.bo.CostPriceBo;
import com.klp.cost.domain.vo.CostPriceVo;
import com.klp.cost.domain.CostPrice;
import com.klp.cost.mapper.CostPriceMapper;
import com.klp.cost.service.ICostPriceService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 成本单价历史Service业务层处理
*
* @author klp
* @date 2026-05-25
*/
@RequiredArgsConstructor
@Service
public class CostPriceServiceImpl implements ICostPriceService {
private final CostPriceMapper baseMapper;
/**
* 查询成本单价历史
*/
@Override
public CostPriceVo queryById(Long priceId){
return baseMapper.selectVoById(priceId);
}
/**
* 查询成本单价历史列表
*/
@Override
public TableDataInfo<CostPriceVo> queryPageList(CostPriceBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<CostPrice> lqw = buildQueryWrapper(bo);
Page<CostPriceVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询成本单价历史列表
*/
@Override
public List<CostPriceVo> queryList(CostPriceBo bo) {
LambdaQueryWrapper<CostPrice> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<CostPrice> buildQueryWrapper(CostPriceBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CostPrice> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getItemId() != null, CostPrice::getItemId, bo.getItemId());
lqw.eq(bo.getPrice() != null, CostPrice::getPrice, bo.getPrice());
lqw.eq(bo.getEffectiveDate() != null, CostPrice::getEffectiveDate, bo.getEffectiveDate());
return lqw;
}
/**
* 新增成本单价历史
*/
@Override
public Boolean insertByBo(CostPriceBo bo) {
CostPrice add = BeanUtil.toBean(bo, CostPrice.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPriceId(add.getPriceId());
}
return flag;
}
/**
* 修改成本单价历史
*/
@Override
public Boolean updateByBo(CostPriceBo bo) {
CostPrice update = BeanUtil.toBean(bo, CostPrice.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(CostPrice entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除成本单价历史
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,136 @@
package com.klp.cost.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;
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 org.springframework.transaction.annotation.Transactional;
import com.klp.cost.domain.bo.CostProdDetailBo;
import com.klp.cost.domain.vo.CostProdDetailVo;
import com.klp.cost.domain.CostProdDetail;
import com.klp.cost.mapper.CostProdDetailMapper;
import com.klp.cost.service.ICostProdDetailService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* 生产成本明细Service业务层处理
*
* @author klp
* @date 2026-05-25
*/
@RequiredArgsConstructor
@Service
public class CostProdDetailServiceImpl implements ICostProdDetailService {
private final CostProdDetailMapper baseMapper;
/**
* 查询生产成本明细
*/
@Override
public CostProdDetailVo queryById(Long detailId){
return baseMapper.selectVoById(detailId);
}
/**
* 查询生产成本明细列表
*/
@Override
public TableDataInfo<CostProdDetailVo> queryPageList(CostProdDetailBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<CostProdDetail> lqw = buildQueryWrapper(bo);
Page<CostProdDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询生产成本明细列表
*/
@Override
public List<CostProdDetailVo> queryList(CostProdDetailBo bo) {
LambdaQueryWrapper<CostProdDetail> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<CostProdDetail> buildQueryWrapper(CostProdDetailBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CostProdDetail> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getReportId() != null, CostProdDetail::getReportId, bo.getReportId());
lqw.eq(StringUtils.isNotBlank(bo.getShift()), CostProdDetail::getShift, bo.getShift());
lqw.eq(bo.getDetailDate() != null, CostProdDetail::getDetailDate, bo.getDetailDate());
lqw.eq(bo.getItemId() != null, CostProdDetail::getItemId, bo.getItemId());
lqw.eq(bo.getQuantity() != null, CostProdDetail::getQuantity, bo.getQuantity());
lqw.eq(bo.getUnitPrice() != null, CostProdDetail::getUnitPrice, bo.getUnitPrice());
lqw.eq(bo.getAmount() != null, CostProdDetail::getAmount, bo.getAmount());
return lqw;
}
/**
* 新增生产成本明细
*/
@Override
public Long insertByBo(CostProdDetailBo bo) {
CostProdDetail add = BeanUtil.toBean(bo, CostProdDetail.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setDetailId(add.getDetailId());
}
return add.getDetailId();
}
/**
* 修改生产成本明细
*/
@Override
public Boolean updateByBo(CostProdDetailBo bo) {
CostProdDetail update = BeanUtil.toBean(bo, CostProdDetail.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(CostProdDetail entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除生产成本明细
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
/**
* 批量保存(先删除再插入)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean batchSaveWithDelete(CostProdDetailBo bo) {
if (CollUtil.isNotEmpty(bo.getProdDetailList())) {
if (CollUtil.isNotEmpty(bo.getDetailIds())) {
baseMapper.deleteBatchIds(bo.getDetailIds());
}
List<CostProdDetail> list = bo.getProdDetailList().stream()
.map(item -> BeanUtil.toBean(item, CostProdDetail.class))
.collect(Collectors.toList());
return baseMapper.insertBatch(list);
}
return false;
}
}

View File

@@ -0,0 +1,114 @@
package com.klp.cost.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.cost.domain.bo.CostProdMetricBo;
import com.klp.cost.domain.vo.CostProdMetricVo;
import com.klp.cost.domain.CostProdMetric;
import com.klp.cost.mapper.CostProdMetricMapper;
import com.klp.cost.service.ICostProdMetricService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 生产指标明细Service业务层处理
*
* @author klp
* @date 2026-05-25
*/
@RequiredArgsConstructor
@Service
public class CostProdMetricServiceImpl implements ICostProdMetricService {
private final CostProdMetricMapper baseMapper;
/**
* 查询生产指标明细
*/
@Override
public CostProdMetricVo queryById(Long metricId){
return baseMapper.selectVoById(metricId);
}
/**
* 查询生产指标明细列表
*/
@Override
public TableDataInfo<CostProdMetricVo> queryPageList(CostProdMetricBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<CostProdMetric> lqw = buildQueryWrapper(bo);
Page<CostProdMetricVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询生产指标明细列表
*/
@Override
public List<CostProdMetricVo> queryList(CostProdMetricBo bo) {
LambdaQueryWrapper<CostProdMetric> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<CostProdMetric> buildQueryWrapper(CostProdMetricBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CostProdMetric> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getReportId() != null, CostProdMetric::getReportId, bo.getReportId());
lqw.eq(StringUtils.isNotBlank(bo.getMetricCode()), CostProdMetric::getMetricCode, bo.getMetricCode());
lqw.like(StringUtils.isNotBlank(bo.getMetricName()), CostProdMetric::getMetricName, bo.getMetricName());
lqw.eq(StringUtils.isNotBlank(bo.getMetricFormula()), CostProdMetric::getMetricFormula, bo.getMetricFormula());
lqw.eq(bo.getMetricValue() != null, CostProdMetric::getMetricValue, bo.getMetricValue());
lqw.eq(bo.getUsePrice() != null, CostProdMetric::getUsePrice, bo.getUsePrice());
return lqw;
}
/**
* 新增生产指标明细
*/
@Override
public Boolean insertByBo(CostProdMetricBo bo) {
CostProdMetric add = BeanUtil.toBean(bo, CostProdMetric.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setMetricId(add.getMetricId());
}
return flag;
}
/**
* 修改生产指标明细
*/
@Override
public Boolean updateByBo(CostProdMetricBo bo) {
CostProdMetric update = BeanUtil.toBean(bo, CostProdMetric.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(CostProdMetric entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除生产指标明细
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,173 @@
package com.klp.cost.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
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.cost.domain.bo.CostProdReportBo;
import com.klp.cost.domain.vo.CostProdReportVo;
import com.klp.cost.domain.CostProdReport;
import com.klp.cost.domain.CostProdMetric;
import com.klp.cost.mapper.CostProdReportMapper;
import com.klp.cost.mapper.CostProdMetricMapper;
import com.klp.cost.service.ICostProdReportService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 生产月报Service业务层处理
*
* @author klp
* @date 2026-05-25
*/
@RequiredArgsConstructor
@Service
public class CostProdReportServiceImpl implements ICostProdReportService {
private final CostProdReportMapper baseMapper;
private final CostProdMetricMapper metricMapper;
/**
* 查询生产月报
*/
@Override
public CostProdReportVo queryById(Long reportId){
return baseMapper.selectVoById(reportId);
}
/**
* 查询生产月报列表
*/
@Override
public TableDataInfo<CostProdReportVo> queryPageList(CostProdReportBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<CostProdReport> lqw = buildQueryWrapper(bo);
Page<CostProdReportVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询生产月报列表
*/
@Override
public List<CostProdReportVo> queryList(CostProdReportBo bo) {
LambdaQueryWrapper<CostProdReport> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<CostProdReport> buildQueryWrapper(CostProdReportBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CostProdReport> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getReportTitle()), CostProdReport::getReportTitle, bo.getReportTitle());
lqw.eq(StringUtils.isNotBlank(bo.getLineType()), CostProdReport::getLineType, bo.getLineType());
lqw.eq(bo.getInputWeight() != null, CostProdReport::getInputWeight, bo.getInputWeight());
lqw.eq(bo.getOutputWeight() != null, CostProdReport::getOutputWeight, bo.getOutputWeight());
lqw.apply(bo.getReportDate() != null, "DATE_FORMAT(report_date, '%Y-%m') = {0}", bo.getReportDate());
return lqw;
}
/**
* 新增生产月报
*/
@Override
public Boolean insertByBo(CostProdReportBo bo) {
CostProdReport add = BeanUtil.toBean(bo, CostProdReport.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setReportId(add.getReportId());
}
return flag;
}
/**
* 修改生产月报
*/
@Override
public Boolean updateByBo(CostProdReportBo bo) {
CostProdReport update = BeanUtil.toBean(bo, CostProdReport.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(CostProdReport entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除生产月报
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
/**
* 复制生产月报
* 明细列原样保留itemId不变指标列重新插入并更新config中的id引用
*/
@Override
public CostProdReportVo copyReport(Long sourceId, CostProdReportBo bo) {
CostProdReport source = baseMapper.selectById(sourceId);
if (source == null) {
throw new RuntimeException("源报表不存在");
}
// 创建新报表先插入以获取ID
CostProdReport newRp = new CostProdReport();
BeanUtil.copyProperties(source, newRp, "reportId", "colConfig");
newRp.setReportTitle(bo.getReportTitle() != null ? bo.getReportTitle() : source.getReportTitle() + "-副本");
if (bo.getReportDate() != null) newRp.setReportDate(bo.getReportDate());
if (bo.getLineType() != null) newRp.setLineType(bo.getLineType());
if (bo.getInputWeight() != null) newRp.setInputWeight(bo.getInputWeight());
if (bo.getOutputWeight() != null) newRp.setOutputWeight(bo.getOutputWeight());
if (bo.getRemark() != null) newRp.setRemark(bo.getRemark());
baseMapper.insert(newRp);
Long newRid = newRp.getReportId();
// 处理colConfig为每个指标列重新插入metric记录更新id引用
String colConfig = source.getColConfig();
if (StringUtils.isNotBlank(colConfig)) {
JSONObject cfg = JSONUtil.parseObj(colConfig);
JSONArray columns = cfg.getJSONArray("columns");
if (columns != null && columns.size() > 0) {
for (int i = 0; i < columns.size(); i++) {
JSONObject col = columns.getJSONObject(i);
if ("m".equals(col.getStr("t"))) {
String idStr = col.getStr("id");
Long oldMetricId = idStr != null ? Long.parseLong(idStr) : null;
if (oldMetricId != null) {
CostProdMetric srcMetric = metricMapper.selectById(oldMetricId);
if (srcMetric != null) {
CostProdMetric newMetric = new CostProdMetric();
BeanUtil.copyProperties(srcMetric, newMetric, "metricId", "reportId");
newMetric.setReportId(newRid);
metricMapper.insert(newMetric);
col.set("id", String.valueOf(newMetric.getMetricId()));
}
}
}
}
newRp.setColConfig(cfg.toString());
}
baseMapper.updateById(newRp);
}
return baseMapper.selectVoById(newRid);
}
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.cost.mapper.CostItemMapper">
<resultMap type="com.klp.cost.domain.CostItem" id="CostItemResult">
<result property="itemId" column="item_id"/>
<result property="itemCode" column="item_code"/>
<result property="itemName" column="item_name"/>
<result property="category" column="category"/>
<result property="unit" column="unit"/>
<result property="remark" column="remark"/>
<result property="queryCondition" column="query_condition"/>
<result property="delFlag" column="del_flag"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.cost.mapper.CostPriceMapper">
<resultMap type="com.klp.cost.domain.CostPrice" id="CostPriceResult">
<result property="priceId" column="price_id"/>
<result property="itemId" column="item_id"/>
<result property="price" column="price"/>
<result property="effectiveDate" column="effective_date"/>
<result property="remark" column="remark"/>
<result property="delFlag" column="del_flag"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.cost.mapper.CostProdDetailMapper">
<resultMap type="com.klp.cost.domain.CostProdDetail" id="CostProdDetailResult">
<result property="detailId" column="detail_id"/>
<result property="reportId" column="report_id"/>
<result property="shift" column="shift"/>
<result property="detailDate" column="detail_date"/>
<result property="itemId" column="item_id"/>
<result property="quantity" column="quantity"/>
<result property="unitPrice" column="unit_price"/>
<result property="amount" column="amount"/>
<result property="remark" column="remark"/>
<result property="delFlag" column="del_flag"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.cost.mapper.CostProdMetricMapper">
<resultMap type="com.klp.cost.domain.CostProdMetric" id="CostProdMetricResult">
<result property="metricId" column="metric_id"/>
<result property="reportId" column="report_id"/>
<result property="metricCode" column="metric_code"/>
<result property="metricName" column="metric_name"/>
<result property="metricFormula" column="metric_formula"/>
<result property="metricValue" column="metric_value"/>
<result property="usePrice" column="use_price"/>
<result property="remark" column="remark"/>
<result property="delFlag" column="del_flag"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.cost.mapper.CostProdReportMapper">
<resultMap type="com.klp.cost.domain.CostProdReport" id="CostProdReportResult">
<result property="reportId" column="report_id"/>
<result property="reportTitle" column="report_title"/>
<result property="reportDate" column="report_date"/>
<result property="lineType" column="line_type"/>
<result property="inputWeight" column="input_weight"/>
<result property="outputWeight" column="output_weight"/>
<result property="remark" column="remark"/>
<result property="colConfig" column="col_config"/>
<result property="delFlag" column="del_flag"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>

View File

@@ -85,6 +85,15 @@ public class CrmSalesReportController extends BaseController {
return R.ok(stats);
}
/**
* 查询省份统计数据
*/
@GetMapping("/provinceStats")
public R<List<CrmSalesReportVo.ProvinceStat>> getProvinceStats(CrmSalesReportBo bo) {
List<CrmSalesReportVo.ProvinceStat> stats = iCrmSalesReportService.queryProvinceStats(bo);
return R.ok(stats);
}
/**
* 导出销售报表订单明细
*/

View File

@@ -1,8 +1,10 @@
package com.klp.crm.domain.vo;
import java.math.BigDecimal;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
@@ -173,6 +175,65 @@ public class CrmOrderItemVo {
@ExcelProperty(value = "用途")
private String purpose;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 创建人
*/
private String createBy;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 更新人
*/
private String updateBy;
/**
* 删除标志
*/
private Long delFlag;
/**
* 合同号(联表查询直接映射)
*/
@ExcelProperty(value = "合同号")
private String contractCode;
/**
* 供方(联表查询直接映射)
*/
@ExcelProperty(value = "供方")
private String supplier;
/**
* 需方(联表查询直接映射)
*/
@ExcelProperty(value = "需方")
private String customer;
/**
* 签订时间(联表查询直接映射)
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@ExcelProperty(value = "签订时间")
private Date signTime;
/**
* 交货日期(联表查询直接映射)
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@ExcelProperty(value = "交货日期")
private Date deliveryDate;
/**
* 订单信息
*/

View File

@@ -290,4 +290,35 @@ public class CrmSalesReportVo {
@ExcelProperty(value = "销售金额")
private BigDecimal salesAmount;
}
/**
* 省份统计内部类
*/
@Data
public static class ProvinceStat {
/**
* 省份
*/
@ExcelProperty(value = "省份")
private String province;
/**
* 客户数量
*/
@ExcelProperty(value = "客户数量")
private Integer customerCount;
/**
* 订单数量
*/
@ExcelProperty(value = "订单数量")
private Integer orderCount;
/**
* 销售金额
*/
@ExcelProperty(value = "销售金额")
private BigDecimal salesAmount;
}
}

View File

@@ -12,4 +12,9 @@ import com.klp.common.core.mapper.BaseMapperPlus;
*/
public interface CrmCustomerMapper extends BaseMapperPlus<CrmCustomerMapper, CrmCustomer, CrmCustomerVo> {
/**
* 查询当前最大的customer_code用于自动生成新编码
*/
String selectMaxCustomerCode();
}

View File

@@ -1,8 +1,10 @@
package com.klp.crm.mapper;
import com.klp.crm.domain.CrmOrderItem;
import com.klp.crm.domain.bo.CrmOrderItemBo;
import com.klp.crm.domain.vo.CrmOrderItemVo;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -22,4 +24,14 @@ public interface CrmOrderItemMapper extends BaseMapperPlus<CrmOrderItemMapper, C
* @return 订单明细列表
*/
List<CrmOrderItem> selectOrderItemsByOrderIds(@Param("orderIds") List<Long> orderIds);
/**
* 联表查询订单明细(支持排序和分页)
* 排序规则deliveryDate DESC -> orderId ASC -> createTime DESC
*
* @param page 分页对象
* @param bo 查询条件
* @return 分页结果
*/
Page<CrmOrderItemVo> selectVoListWithOrder(Page<CrmOrderItemVo> page, @Param("bo") CrmOrderItemBo bo);
}

View File

@@ -54,4 +54,12 @@ public interface CrmSalesReportMapper {
* @return 行业统计列表
*/
List<CrmSalesReportVo.IndustryStat> selectIndustryStats(@Param("bo") CrmSalesReportBo bo);
/**
* 查询省份统计数据
*
* @param bo 查询条件
* @return 省份统计列表
*/
List<CrmSalesReportVo.ProvinceStat> selectProvinceStats(@Param("bo") CrmSalesReportBo bo);
}

View File

@@ -72,4 +72,12 @@ public interface ICrmSalesReportService {
* @return 行业统计列表
*/
List<CrmSalesReportVo.IndustryStat> queryIndustryStats(CrmSalesReportBo bo);
/**
* 查询省份统计数据
*
* @param bo 查询条件
* @return 省份统计列表
*/
List<CrmSalesReportVo.ProvinceStat> queryProvinceStats(CrmSalesReportBo bo);
}

View File

@@ -91,6 +91,25 @@ public class CrmCustomerServiceImpl implements ICrmCustomerService {
@Override
public Boolean insertByBo(CrmCustomerBo bo) {
CrmCustomer add = BeanUtil.toBean(bo, CrmCustomer.class);
// 自动生成customer_code查询最大编码并加1
if (StringUtils.isBlank(add.getCustomerCode())) {
String maxCode = baseMapper.selectMaxCustomerCode();
if (StringUtils.isBlank(maxCode)) {
add.setCustomerCode("00001");
} else {
// 提取末尾数字后缀并递增,支持纯数字("00001")和带前缀("KH00001")两种格式
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("^(.*?)(\\d+)$");
java.util.regex.Matcher matcher = pattern.matcher(maxCode);
if (matcher.matches()) {
String prefix = matcher.group(1);
String numStr = matcher.group(2);
long num = Long.parseLong(numStr) + 1;
add.setCustomerCode(prefix + String.format("%0" + numStr.length() + "d", num));
} else {
add.setCustomerCode(maxCode + "1");
}
}
}
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {

View File

@@ -69,23 +69,31 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService {
/**
* 查询正式订单明细列表
* 实现逻辑SQL联表查询 → 数据库层排序交货日期倒序→订单ID升序→创建时间倒序→ 物理分页
* 排序跨页生效,同一合同明细连续排列,避免内存排序大数据量问题
*/
@Override
public TableDataInfo<CrmOrderItemVo> queryPageList(CrmOrderItemBo bo, PageQuery pageQuery) {
List<Long> orderIdScope = resolveOrderIdScope(bo);
if (orderIdScope != null && orderIdScope.isEmpty()) {
Page<CrmOrderItemVo> emptyPage = new Page<>(ObjectUtil.defaultIfNull(pageQuery.getPageNum(), 1),
ObjectUtil.defaultIfNull(pageQuery.getPageSize(), 10), 0);
emptyPage.setRecords(Collections.emptyList());
return TableDataInfo.build(emptyPage);
}
LambdaQueryWrapper<CrmOrderItem> lqw = buildQueryWrapper(bo);
if (orderIdScope != null) {
lqw.in(CrmOrderItem::getOrderId, orderIdScope);
}
Page<CrmOrderItemVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
fillOrderInfoOnItems(result.getRecords());
return TableDataInfo.build(result);
// 使用MyBatis-Plus分页插件SQL层完成联表查询、排序和分页
Page<CrmOrderItemVo> page = new Page<>(
ObjectUtil.defaultIfNull(pageQuery.getPageNum(), 1),
ObjectUtil.defaultIfNull(pageQuery.getPageSize(), 10)
);
// 联表查询在SQL层完成排序避免内存排序
Page<CrmOrderItemVo> resultPage = baseMapper.selectVoListWithOrder(page, bo);
return TableDataInfo.build(resultPage);
}
/**
* 比较两个日期null 值排在末尾
* @param desc true=倒序false=升序
*/
private int compareDate(Date a, Date b, boolean desc) {
if (a == null && b == null) return 0;
if (a == null) return 1; // null 排在后面
if (b == null) return -1;
int cmp = a.compareTo(b);
return desc ? -cmp : cmp;
}
/**

View File

@@ -250,11 +250,9 @@ public class CrmOrderServiceImpl implements ICrmOrderService {
qw.eq("co.del_flag", 0);
//排序规则:
// 1. 置顶优先 (is_top=1 排在前面)
// 2. 状态为1(已生效)的排在前
// 3. 创建时间倒序
// 2. 合同号倒序KLPY+年月日+序号,降序最新在前
qw.orderByDesc("co.is_top")
.orderByDesc("CASE WHEN co.status = 1 THEN 1 ELSE 0 END")
.orderByDesc("co.create_time");
.orderByDesc("co.contract_code");
return qw;
}

View File

@@ -136,4 +136,12 @@ public class CrmSalesReportServiceImpl implements ICrmSalesReportService {
public List<CrmSalesReportVo.IndustryStat> queryIndustryStats(CrmSalesReportBo bo) {
return baseMapper.selectIndustryStats(bo);
}
/**
* 查询省份统计数据
*/
@Override
public List<CrmSalesReportVo.ProvinceStat> queryProvinceStats(CrmSalesReportBo bo) {
return baseMapper.selectProvinceStats(bo);
}
}

View File

@@ -23,5 +23,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="delFlag" column="del_flag"/>
</resultMap>
<select id="selectMaxCustomerCode" resultType="String">
SELECT customer_code FROM crm_customer WHERE del_flag = 0 ORDER BY LENGTH(customer_code) DESC, customer_code DESC LIMIT 1
</select>
</mapper>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.crm.mapper.CrmOrderItemMapper">
<resultMap type="com.klp.crm.domain.CrmOrderItem" id="CrmOrderItemResult">
@@ -36,6 +36,46 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
<!-- 联表查询结果映射 -->
<resultMap type="com.klp.crm.domain.vo.CrmOrderItemVo" id="CrmOrderItemVoResult">
<result property="itemId" column="item_id"/>
<result property="orderId" column="order_id"/>
<result property="productType" column="product_type"/>
<result property="rawMaterialSpec" column="raw_material_spec"/>
<result property="productNum" column="product_num"/>
<result property="specialRequire" column="special_require"/>
<result property="itemAmount" column="item_amount"/>
<result property="remark" column="remark"/>
<result property="finishedProductSpec" column="finished_product_spec"/>
<result property="material" column="material"/>
<result property="grade" column="grade"/>
<result property="weight" column="weight"/>
<result property="widthTolerance" column="width_tolerance"/>
<result property="thicknessTolerance" column="thickness_tolerance"/>
<result property="contractPrice" column="contract_price"/>
<result property="customizer" column="customizer"/>
<result property="shipper" column="shipper"/>
<result property="productionBatch" column="production_batch"/>
<result property="surfaceTreatment" column="surface_treatment"/>
<result property="surfaceQuality" column="surface_quality"/>
<result property="edgeCuttingReq" column="edge_cutting_req"/>
<result property="packagingReq" column="packaging_req"/>
<result property="width" column="width"/>
<result property="thickness" column="thickness"/>
<result property="purpose" column="purpose"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<!-- 合同信息字段 -->
<result property="contractCode" column="contract_code"/>
<result property="supplier" column="supplier"/>
<result property="customer" column="customer"/>
<result property="signTime" column="sign_time"/>
<result property="deliveryDate" column="delivery_date"/>
</resultMap>
<!-- 根据订单ID列表查询订单明细 -->
<select id="selectOrderItemsByOrderIds" resultMap="CrmOrderItemResult">
SELECT
@@ -78,5 +118,132 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY item_id ASC
</select>
<!-- 联表查询订单明细(支持排序和分页) -->
<select id="selectVoListWithOrder" resultMap="CrmOrderItemVoResult">
SELECT
i.item_id,
i.order_id,
i.product_type,
i.raw_material_spec,
i.product_num,
i.special_require,
i.item_amount,
i.remark,
i.finished_product_spec,
i.material,
i.grade,
i.weight,
i.width_tolerance,
i.thickness_tolerance,
i.contract_price,
i.customizer,
i.shipper,
i.production_batch,
i.surface_treatment,
i.surface_quality,
i.edge_cutting_req,
i.packaging_req,
i.width,
i.thickness,
i.purpose,
i.create_by,
i.create_time,
i.update_by,
i.update_time,
i.del_flag,
o.contract_code,
o.supplier,
o.customer,
o.sign_time,
o.delivery_date
FROM crm_order_item i
LEFT JOIN crm_order o ON i.order_id = o.order_id AND o.del_flag = 0
<where>
i.del_flag = 0
<if test="bo.itemId != null">
AND i.item_id = #{bo.itemId}
</if>
<if test="bo.orderId != null">
AND i.order_id = #{bo.orderId}
</if>
<if test="bo.productType != null and bo.productType != ''">
AND i.product_type = #{bo.productType}
</if>
<if test="bo.rawMaterialSpec != null and bo.rawMaterialSpec != ''">
AND i.raw_material_spec = #{bo.rawMaterialSpec}
</if>
<if test="bo.productNum != null">
AND i.product_num = #{bo.productNum}
</if>
<if test="bo.specialRequire != null and bo.specialRequire != ''">
AND i.special_require = #{bo.specialRequire}
</if>
<if test="bo.finishedProductSpec != null and bo.finishedProductSpec != ''">
AND i.finished_product_spec = #{bo.finishedProductSpec}
</if>
<if test="bo.material != null and bo.material != ''">
AND i.material LIKE CONCAT('%', #{bo.material}, '%')
</if>
<if test="bo.grade != null and bo.grade != ''">
AND i.grade = #{bo.grade}
</if>
<if test="bo.weight != null">
AND i.weight = #{bo.weight}
</if>
<if test="bo.contractPrice != null">
AND i.contract_price = #{bo.contractPrice}
</if>
<if test="bo.customizer != null and bo.customizer != ''">
AND i.customizer = #{bo.customizer}
</if>
<if test="bo.shipper != null and bo.shipper != ''">
AND i.shipper = #{bo.shipper}
</if>
<if test="bo.productionBatch != null and bo.productionBatch != ''">
AND i.production_batch = #{bo.productionBatch}
</if>
<if test="bo.surfaceTreatment != null and bo.surfaceTreatment != ''">
AND i.surface_treatment = #{bo.surfaceTreatment}
</if>
<if test="bo.surfaceQuality != null and bo.surfaceQuality != ''">
AND i.surface_quality = #{bo.surfaceQuality}
</if>
<if test="bo.edgeCuttingReq != null and bo.edgeCuttingReq != ''">
AND i.edge_cutting_req = #{bo.edgeCuttingReq}
</if>
<if test="bo.packagingReq != null and bo.packagingReq != ''">
AND i.packaging_req = #{bo.packagingReq}
</if>
<if test="bo.width != null and bo.width != ''">
AND i.width = #{bo.width}
</if>
<if test="bo.thickness != null and bo.thickness != ''">
AND i.thickness = #{bo.thickness}
</if>
<if test="bo.purpose != null and bo.purpose != ''">
AND i.purpose = #{bo.purpose}
</if>
<!-- 合同表筛选条件 -->
<if test="bo.contractCode != null and bo.contractCode != ''">
AND o.contract_code LIKE CONCAT('%', #{bo.contractCode}, '%')
</if>
<if test="bo.customer != null and bo.customer != ''">
AND o.customer LIKE CONCAT('%', #{bo.customer}, '%')
</if>
<if test="bo.signDateStart != null">
AND o.sign_time &gt;= #{bo.signDateStart}
</if>
<if test="bo.signDateEnd != null">
AND o.sign_time &lt; DATE_ADD(#{bo.signDateEnd}, INTERVAL 1 DAY)
</if>
<if test="bo.deliveryDateStart != null">
AND o.delivery_date &gt;= #{bo.deliveryDateStart}
</if>
<if test="bo.deliveryDateEnd != null">
AND o.delivery_date &lt; DATE_ADD(#{bo.deliveryDateEnd}, INTERVAL 1 DAY)
</if>
</where>
ORDER BY o.delivery_date DESC, i.order_id ASC, i.create_time DESC
</select>
</mapper>

View File

@@ -268,4 +268,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY salesAmount DESC
</select>
<!-- 查询省份统计数据 -->
<select id="selectProvinceStats" resultType="com.klp.crm.domain.vo.CrmSalesReportVo$ProvinceStat">
SELECT
COALESCE(c.province, '其他') as province,
COUNT(DISTINCT c.customer_id) as customerCount,
COUNT(o.order_id) as orderCount,
COALESCE(SUM(o.order_amount), 0) as salesAmount
FROM crm_order o
LEFT JOIN crm_customer c ON o.customer_id = c.customer_id
<include refid="selectCondition"/>
GROUP BY c.province
ORDER BY salesAmount DESC
</select>
</mapper>

View File

@@ -0,0 +1,99 @@
package com.klp.mes.eqp.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.mes.eqp.domain.vo.EqpEquipmentChecklistVo;
import com.klp.mes.eqp.domain.bo.EqpEquipmentChecklistBo;
import com.klp.mes.eqp.service.IEqpEquipmentChecklistService;
import com.klp.common.core.page.TableDataInfo;
/**
* 设备检验清单
*
* @author klp
* @date 2026-05-21
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eqp/equipmentChecklist")
public class EqpEquipmentChecklistController extends BaseController {
private final IEqpEquipmentChecklistService iEqpEquipmentChecklistService;
/**
* 查询设备检验清单列表
*/
@GetMapping("/list")
public TableDataInfo<EqpEquipmentChecklistVo> list(EqpEquipmentChecklistBo bo, PageQuery pageQuery) {
return iEqpEquipmentChecklistService.queryPageList(bo, pageQuery);
}
/**
* 导出设备检验清单列表
*/
@Log(title = "设备检验清单", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(EqpEquipmentChecklistBo bo, HttpServletResponse response) {
List<EqpEquipmentChecklistVo> list = iEqpEquipmentChecklistService.queryList(bo);
ExcelUtil.exportExcel(list, "设备检验清单", EqpEquipmentChecklistVo.class, response);
}
/**
* 获取设备检验清单详细信息
*
* @param checkId 主键
*/
@GetMapping("/{checkId}")
public R<EqpEquipmentChecklistVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long checkId) {
return R.ok(iEqpEquipmentChecklistService.queryById(checkId));
}
/**
* 新增设备检验清单
*/
@Log(title = "设备检验清单", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody EqpEquipmentChecklistBo bo) {
return toAjax(iEqpEquipmentChecklistService.insertByBo(bo));
}
/**
* 修改设备检验清单
*/
@Log(title = "设备检验清单", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody EqpEquipmentChecklistBo bo) {
return toAjax(iEqpEquipmentChecklistService.updateByBo(bo));
}
/**
* 删除设备检验清单
*
* @param checkIds 主键串
*/
@Log(title = "设备检验清单", businessType = BusinessType.DELETE)
@DeleteMapping("/{checkIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] checkIds) {
return toAjax(iEqpEquipmentChecklistService.deleteWithValidByIds(Arrays.asList(checkIds), true));
}
}

View File

@@ -0,0 +1,99 @@
package com.klp.mes.eqp.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.mes.eqp.domain.vo.EqpEquipmentInspectionApprovalVo;
import com.klp.mes.eqp.domain.bo.EqpEquipmentInspectionApprovalBo;
import com.klp.mes.eqp.service.IEqpEquipmentInspectionApprovalService;
import com.klp.common.core.page.TableDataInfo;
/**
* 设备巡检审批(按产线+时间范围审批)
*
* @author klp
* @date 2026-05-29
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eqp/equipmentInspectionApproval")
public class EqpEquipmentInspectionApprovalController extends BaseController {
private final IEqpEquipmentInspectionApprovalService iEqpEquipmentInspectionApprovalService;
/**
* 查询设备巡检审批(按产线+时间范围审批)列表
*/
@GetMapping("/list")
public TableDataInfo<EqpEquipmentInspectionApprovalVo> list(EqpEquipmentInspectionApprovalBo bo, PageQuery pageQuery) {
return iEqpEquipmentInspectionApprovalService.queryPageList(bo, pageQuery);
}
/**
* 导出设备巡检审批(按产线+时间范围审批)列表
*/
@Log(title = "设备巡检审批(按产线+时间范围审批)", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(EqpEquipmentInspectionApprovalBo bo, HttpServletResponse response) {
List<EqpEquipmentInspectionApprovalVo> list = iEqpEquipmentInspectionApprovalService.queryList(bo);
ExcelUtil.exportExcel(list, "设备巡检审批(按产线+时间范围审批)", EqpEquipmentInspectionApprovalVo.class, response);
}
/**
* 获取设备巡检审批(按产线+时间范围审批)详细信息
*
* @param approvalId 主键
*/
@GetMapping("/{approvalId}")
public R<EqpEquipmentInspectionApprovalVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long approvalId) {
return R.ok(iEqpEquipmentInspectionApprovalService.queryById(approvalId));
}
/**
* 新增设备巡检审批(按产线+时间范围审批)
*/
@Log(title = "设备巡检审批(按产线+时间范围审批)", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody EqpEquipmentInspectionApprovalBo bo) {
return toAjax(iEqpEquipmentInspectionApprovalService.insertByBo(bo));
}
/**
* 修改设备巡检审批(按产线+时间范围审批)
*/
@Log(title = "设备巡检审批(按产线+时间范围审批)", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody EqpEquipmentInspectionApprovalBo bo) {
return toAjax(iEqpEquipmentInspectionApprovalService.updateByBo(bo));
}
/**
* 删除设备巡检审批(按产线+时间范围审批)
*
* @param approvalIds 主键串
*/
@Log(title = "设备巡检审批(按产线+时间范围审批)", businessType = BusinessType.DELETE)
@DeleteMapping("/{approvalIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] approvalIds) {
return toAjax(iEqpEquipmentInspectionApprovalService.deleteWithValidByIds(Arrays.asList(approvalIds), true));
}
}

View File

@@ -0,0 +1,99 @@
package com.klp.mes.eqp.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.mes.eqp.domain.vo.EqpEquipmentInspectionRecordVo;
import com.klp.mes.eqp.domain.bo.EqpEquipmentInspectionRecordBo;
import com.klp.mes.eqp.service.IEqpEquipmentInspectionRecordService;
import com.klp.common.core.page.TableDataInfo;
/**
* 设备巡检记录
*
* @author klp
* @date 2026-05-21
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eqp/equipmentInspectionRecord")
public class EqpEquipmentInspectionRecordController extends BaseController {
private final IEqpEquipmentInspectionRecordService iEqpEquipmentInspectionRecordService;
/**
* 查询设备巡检记录列表
*/
@GetMapping("/list")
public TableDataInfo<EqpEquipmentInspectionRecordVo> list(EqpEquipmentInspectionRecordBo bo, PageQuery pageQuery) {
return iEqpEquipmentInspectionRecordService.queryPageList(bo, pageQuery);
}
/**
* 导出设备巡检记录列表
*/
@Log(title = "设备巡检记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(EqpEquipmentInspectionRecordBo bo, HttpServletResponse response) {
List<EqpEquipmentInspectionRecordVo> list = iEqpEquipmentInspectionRecordService.queryList(bo);
ExcelUtil.exportExcel(list, "设备巡检记录", EqpEquipmentInspectionRecordVo.class, response);
}
/**
* 获取设备巡检记录详细信息
*
* @param recordId 主键
*/
@GetMapping("/{recordId}")
public R<EqpEquipmentInspectionRecordVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long recordId) {
return R.ok(iEqpEquipmentInspectionRecordService.queryById(recordId));
}
/**
* 新增设备巡检记录
*/
@Log(title = "设备巡检记录", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody EqpEquipmentInspectionRecordBo bo) {
return toAjax(iEqpEquipmentInspectionRecordService.insertByBo(bo));
}
/**
* 修改设备巡检记录
*/
@Log(title = "设备巡检记录", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody EqpEquipmentInspectionRecordBo bo) {
return toAjax(iEqpEquipmentInspectionRecordService.updateByBo(bo));
}
/**
* 删除设备巡检记录
*
* @param recordIds 主键串
*/
@Log(title = "设备巡检记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{recordIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] recordIds) {
return toAjax(iEqpEquipmentInspectionRecordService.deleteWithValidByIds(Arrays.asList(recordIds), true));
}
}

View File

@@ -0,0 +1,109 @@
package com.klp.mes.eqp.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.mes.eqp.domain.vo.EqpEquipmentPartVo;
import com.klp.mes.eqp.domain.bo.EqpEquipmentPartBo;
import com.klp.mes.eqp.service.IEqpEquipmentPartService;
import com.klp.common.core.page.TableDataInfo;
/**
* 检验部位
*
* @author klp
* @date 2026-05-21
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eqp/equipmentPart")
public class EqpEquipmentPartController extends BaseController {
private final IEqpEquipmentPartService iEqpEquipmentPartService;
/**
* 查询检验部位列表
*/
@GetMapping("/list")
public TableDataInfo<EqpEquipmentPartVo> list(EqpEquipmentPartBo bo, PageQuery pageQuery) {
return iEqpEquipmentPartService.queryPageList(bo, pageQuery);
}
/**
* 导出检验部位列表
*/
@Log(title = "检验部位", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(EqpEquipmentPartBo bo, HttpServletResponse response) {
List<EqpEquipmentPartVo> list = iEqpEquipmentPartService.queryList(bo);
ExcelUtil.exportExcel(list, "检验部位", EqpEquipmentPartVo.class, response);
}
/**
* 获取检验部位详细信息
*
* @param partId 主键
*/
@GetMapping("/{partId}")
public R<EqpEquipmentPartVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long partId) {
return R.ok(iEqpEquipmentPartService.queryById(partId));
}
/**
* 新增检验部位
*/
@Log(title = "检验部位", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody EqpEquipmentPartBo bo) {
return toAjax(iEqpEquipmentPartService.insertByBo(bo));
}
/**
* 修改检验部位
*/
@Log(title = "检验部位", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody EqpEquipmentPartBo bo) {
return toAjax(iEqpEquipmentPartService.updateByBo(bo));
}
/**
* 删除检验部位
*
* @param partIds 主键串
*/
@Log(title = "检验部位", businessType = BusinessType.DELETE)
@DeleteMapping("/{partIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] partIds) {
return toAjax(iEqpEquipmentPartService.deleteWithValidByIds(Arrays.asList(partIds), true));
}
/**
* 批量新增检验部位及检验清单
*/
@Log(title = "检验部位", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/batch")
public R<Void> addBatch(@RequestBody EqpEquipmentPartBo bo) {
return toAjax(iEqpEquipmentPartService.insertBatchByBo(bo));
}
}

View File

@@ -0,0 +1,65 @@
package com.klp.mes.eqp.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 设备检验清单对象 eqp_equipment_checklist
*
* @author klp
* @date 2026-05-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eqp_equipment_checklist")
public class EqpEquipmentChecklist extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 检验清单ID
*/
@TableId(value = "check_id")
private Long checkId;
/**
* 检验编号
*/
private String checkNo;
/**
* 检验部位表
*/
private Long partId;
/**
* 设备部件名称
*/
private String partName;
/**
* 检验内容
*/
private String checkContent;
/**
* 设备状态 运行/停止
*/
private String equipmentState;
/**
* 检验标准
*/
private String checkStandard;
/**
* 责任人
*/
private String responsiblePerson;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,75 @@
package com.klp.mes.eqp.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;
/**
* 设备巡检审批(按产线+时间范围审批)对象 eqp_equipment_inspection_approval
*
* @author klp
* @date 2026-05-29
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eqp_equipment_inspection_approval")
public class EqpEquipmentInspectionApproval extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 审批ID 主键
*/
@TableId(value = "approval_id")
private Long approvalId;
/**
* 产线ID对应你刚改的bigint类型
*/
private Long productionLine;
/**
* 巡检开始时间
*/
private Date insStartTime;
/**
* 巡检结束时间
*/
private Date insEndTime;
/**
* 申请人
*/
private String applyUser;
/**
* 申请时间
*/
private Date applyTime;
/**
* 审批状态 1=待审批 2=已通过 3=已驳回 4=已撤销
*/
private Integer approvalStatus;
/**
* 审批人
*/
private String approvalUser;
/**
* 审批时间
*/
private Date approvalTime;
/**
* 审批意见
*/
private String approvalOpinion;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,67 @@
package com.klp.mes.eqp.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;
/**
* 设备巡检记录对象 eqp_equipment_inspection_record
*
* @author klp
* @date 2026-05-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eqp_equipment_inspection_record")
public class EqpEquipmentInspectionRecord extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 巡检记录ID
*/
@TableId(value = "record_id")
private Long recordId;
/**
* 检验清单ID
*/
private Long checkId;
/**
* 班次 1白班 2夜班
*/
private Integer shift;
/**
* 巡检时间
*/
private Date inspectTime;
/**
* 运行状态 1正常 2故障
*/
private Integer runStatus;
/**
* 巡检人
*/
private String inspector;
/**
* 异常描述
*/
private String abnormalDesc;
/**
* 备注
*/
private String remark;
/**
* 巡检照片URL多个用英文逗号分隔
*/
private String photo;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,54 @@
package com.klp.mes.eqp.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 检验部位对象 eqp_equipment_part
*
* @author klp
* @date 2026-05-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eqp_equipment_part")
public class EqpEquipmentPart extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 巡检记录ID
*/
@TableId(value = "part_id")
private Long partId;
/**
* 巡检部位
*/
private String inspectPart;
/**
* 产线
*/
private Long productionLine;
/**
* 产线段
*/
private String lineSection;
/**
* 备注
*/
private String remark;
/**
* 负责人
*/
private String responsiblePerson;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,69 @@
package com.klp.mes.eqp.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.util.List;
/**
* 设备检验清单业务对象 eqp_equipment_checklist
*
* @author klp
* @date 2026-05-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class EqpEquipmentChecklistBo extends BaseEntity {
/**
* 检验清单ID
*/
private Long checkId;
/**
* 检验编号
*/
private String checkNo;
/**
* 检验部位表
*/
private Long partId;
/**
* 设备部件名称
*/
private String partName;
/**
* 检验内容
*/
private String checkContent;
/**
* 设备状态 运行/停止
*/
private String equipmentState;
/**
* 检验标准
*/
private String checkStandard;
/**
* 责任人
*/
private String responsiblePerson;
/**
* 备注
*/
private String remark;
private List<Long> partIds;
}

View File

@@ -0,0 +1,78 @@
package com.klp.mes.eqp.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;
/**
* 设备巡检审批(按产线+时间范围审批)业务对象 eqp_equipment_inspection_approval
*
* @author klp
* @date 2026-05-29
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class EqpEquipmentInspectionApprovalBo extends BaseEntity {
/**
* 审批ID 主键
*/
private Long approvalId;
/**
* 产线ID对应你刚改的bigint类型
*/
private Long productionLine;
/**
* 巡检开始时间
*/
private Date insStartTime;
/**
* 巡检结束时间
*/
private Date insEndTime;
/**
* 申请人
*/
private String applyUser;
/**
* 申请时间
*/
private Date applyTime;
/**
* 审批状态 1=待审批 2=已通过 3=已驳回 4=已撤销
*/
private Integer approvalStatus;
/**
* 审批人
*/
private String approvalUser;
/**
* 审批时间
*/
private Date approvalTime;
/**
* 审批意见
*/
private String approvalOpinion;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,88 @@
package com.klp.mes.eqp.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;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 设备巡检记录业务对象 eqp_equipment_inspection_record
*
* @author klp
* @date 2026-05-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class EqpEquipmentInspectionRecordBo extends BaseEntity {
/**
* 巡检记录ID
*/
private Long recordId;
/**
* 检验清单ID
*/
private Long checkId;
/**
* 班次 1白班 2夜班
*/
private Integer shift;
/**
* 巡检时间
*/
private Date inspectTime;
/**
* 运行状态 1正常 2故障
*/
private Integer runStatus;
/**
* 巡检人
*/
private String inspector;
/**
* 异常描述
*/
private String abnormalDesc;
/**
* 备注
*/
private String remark;
/**
* 巡检照片URL多个用英文逗号分隔
*/
private String photo;
/**
* 产线
*/
private Long productionLine;
/**
* 巡检时间开始
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startInspectTime;
/**
* 巡检时间结束
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endInspectTime;
}

View File

@@ -0,0 +1,57 @@
package com.klp.mes.eqp.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.util.List;
/**
* 检验部位业务对象 eqp_equipment_part
*
* @author klp
* @date 2026-05-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class EqpEquipmentPartBo extends BaseEntity {
/**
* 巡检记录ID
*/
private Long partId;
/**
* 巡检部位
*/
private String inspectPart;
/**
* 产线
*/
private Long productionLine;
/**
* 产线段
*/
private String lineSection;
/**
* 负责人
*/
private String responsiblePerson;
/**
* 备注
*/
private String remark;
/**
* 检验清单列表
*/
private List<EqpEquipmentChecklistBo> checklistList;
}

View File

@@ -0,0 +1,77 @@
package com.klp.mes.eqp.domain.vo;
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;
/**
* 设备检验清单视图对象 eqp_equipment_checklist
*
* @author klp
* @date 2026-05-21
*/
@Data
@ExcelIgnoreUnannotated
public class EqpEquipmentChecklistVo {
private static final long serialVersionUID = 1L;
/**
* 检验清单ID
*/
@ExcelProperty(value = "检验清单ID")
private Long checkId;
/**
* 检验编号
*/
@ExcelProperty(value = "检验编号")
private String checkNo;
/**
* 检验部位表
*/
@ExcelProperty(value = "检验部位表")
private Long partId;
/**
* 设备部件名称
*/
@ExcelProperty(value = "设备部件名称")
private String partName;
/**
* 检验内容
*/
@ExcelProperty(value = "检验内容")
private String checkContent;
/**
* 设备状态 运行/停止
*/
@ExcelProperty(value = "设备状态 运行/停止")
private String equipmentState;
/**
* 检验标准
*/
@ExcelProperty(value = "检验标准")
private String checkStandard;
/**
* 责任人
*/
@ExcelProperty(value = "责任人")
private String responsiblePerson;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,92 @@
package com.klp.mes.eqp.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;
/**
* 设备巡检审批(按产线+时间范围审批)视图对象 eqp_equipment_inspection_approval
*
* @author klp
* @date 2026-05-29
*/
@Data
@ExcelIgnoreUnannotated
public class EqpEquipmentInspectionApprovalVo {
private static final long serialVersionUID = 1L;
/**
* 审批ID 主键
*/
@ExcelProperty(value = "审批ID 主键")
private Long approvalId;
/**
* 产线ID对应你刚改的bigint类型
*/
@ExcelProperty(value = "产线ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "对=应你刚改的bigint类型")
private Long productionLine;
/**
* 巡检开始时间
*/
@ExcelProperty(value = "巡检开始时间")
private Date insStartTime;
/**
* 巡检结束时间
*/
@ExcelProperty(value = "巡检结束时间")
private Date insEndTime;
/**
* 申请人
*/
@ExcelProperty(value = "申请人")
private String applyUser;
/**
* 申请时间
*/
@ExcelProperty(value = "申请时间")
private Date applyTime;
/**
* 审批状态 1=待审批 2=已通过 3=已驳回 4=已撤销
*/
@ExcelProperty(value = "审批状态 1=待审批 2=已通过 3=已驳回 4=已撤销")
private Integer approvalStatus;
/**
* 审批人
*/
@ExcelProperty(value = "审批人")
private String approvalUser;
/**
* 审批时间
*/
@ExcelProperty(value = "审批时间")
private Date approvalTime;
/**
* 审批意见
*/
@ExcelProperty(value = "审批意见")
private String approvalOpinion;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,98 @@
package com.klp.mes.eqp.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;
/**
* 设备巡检记录视图对象 eqp_equipment_inspection_record
*
* @author klp
* @date 2026-05-21
*/
@Data
@ExcelIgnoreUnannotated
public class EqpEquipmentInspectionRecordVo {
private static final long serialVersionUID = 1L;
/**
* 巡检记录ID
*/
@ExcelProperty(value = "巡检记录ID")
private Long recordId;
/**
* 检验清单ID
*/
@ExcelProperty(value = "检验清单ID")
private Long checkId;
/**
* 班次 1白班 2夜班
*/
@ExcelProperty(value = "班次 1白班 2夜班")
private Integer shift;
/**
* 巡检时间
*/
@ExcelProperty(value = "巡检时间")
private Date inspectTime;
/**
* 运行状态 1正常 2故障
*/
@ExcelProperty(value = "运行状态 1正常 2故障")
private Integer runStatus;
/**
* 巡检人
*/
@ExcelProperty(value = "巡检人")
private String inspector;
/**
* 异常描述
*/
@ExcelProperty(value = "异常描述")
private String abnormalDesc;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 巡检照片URL多个用英文逗号分隔
*/
private String photo;
/**
* 检验内容
*/
private String checkContent;
/**
* 检验标准
*/
private String checkStandard;
/**
* 巡检部位
*/
private String inspectPart;
/**
* 产线
*/
private String productionLine;
}

View File

@@ -0,0 +1,65 @@
package com.klp.mes.eqp.domain.vo;
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;
import java.util.List;
/**
* 检验部位视图对象 eqp_equipment_part
*
* @author klp
* @date 2026-05-21
*/
@Data
@ExcelIgnoreUnannotated
public class EqpEquipmentPartVo {
private static final long serialVersionUID = 1L;
/**
* 巡检记录ID
*/
@ExcelProperty(value = "巡检记录ID")
private Long partId;
/**
* 巡检部位
*/
@ExcelProperty(value = "巡检部位")
private String inspectPart;
/**
* 产线
*/
@ExcelProperty(value = "产线")
private Long productionLine;
/**
* 产线段
*/
@ExcelProperty(value = "产线段")
private String lineSection;
/**
* 负责人
*/
@ExcelProperty(value = "负责人")
private String responsiblePerson;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 检验清单列表
*/
private List<EqpEquipmentChecklistVo> checklistList;
}

View File

@@ -0,0 +1,15 @@
package com.klp.mes.eqp.mapper;
import com.klp.mes.eqp.domain.EqpEquipmentChecklist;
import com.klp.mes.eqp.domain.vo.EqpEquipmentChecklistVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 设备检验清单Mapper接口
*
* @author klp
* @date 2026-05-21
*/
public interface EqpEquipmentChecklistMapper extends BaseMapperPlus<EqpEquipmentChecklistMapper, EqpEquipmentChecklist, EqpEquipmentChecklistVo> {
}

View File

@@ -0,0 +1,15 @@
package com.klp.mes.eqp.mapper;
import com.klp.mes.eqp.domain.EqpEquipmentInspectionApproval;
import com.klp.mes.eqp.domain.vo.EqpEquipmentInspectionApprovalVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 设备巡检审批(按产线+时间范围审批Mapper接口
*
* @author klp
* @date 2026-05-29
*/
public interface EqpEquipmentInspectionApprovalMapper extends BaseMapperPlus<EqpEquipmentInspectionApprovalMapper, EqpEquipmentInspectionApproval, EqpEquipmentInspectionApprovalVo> {
}

View File

@@ -0,0 +1,19 @@
package com.klp.mes.eqp.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.mes.eqp.domain.EqpEquipmentInspectionRecord;
import com.klp.mes.eqp.domain.vo.EqpEquipmentInspectionRecordVo;
import com.klp.common.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
/**
* 设备巡检记录Mapper接口
*
* @author klp
* @date 2026-05-21
*/
public interface EqpEquipmentInspectionRecordMapper extends BaseMapperPlus<EqpEquipmentInspectionRecordMapper, EqpEquipmentInspectionRecord, EqpEquipmentInspectionRecordVo> {
Page<EqpEquipmentInspectionRecordVo> selectVoPagePlus(Page<Object> build, @Param("ew") QueryWrapper<EqpEquipmentInspectionRecord> lqw);
}

View File

@@ -0,0 +1,15 @@
package com.klp.mes.eqp.mapper;
import com.klp.mes.eqp.domain.EqpEquipmentPart;
import com.klp.mes.eqp.domain.vo.EqpEquipmentPartVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 检验部位Mapper接口
*
* @author klp
* @date 2026-05-21
*/
public interface EqpEquipmentPartMapper extends BaseMapperPlus<EqpEquipmentPartMapper, EqpEquipmentPart, EqpEquipmentPartVo> {
}

View File

@@ -0,0 +1,49 @@
package com.klp.mes.eqp.service;
import com.klp.mes.eqp.domain.EqpEquipmentChecklist;
import com.klp.mes.eqp.domain.vo.EqpEquipmentChecklistVo;
import com.klp.mes.eqp.domain.bo.EqpEquipmentChecklistBo;
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-05-21
*/
public interface IEqpEquipmentChecklistService {
/**
* 查询设备检验清单
*/
EqpEquipmentChecklistVo queryById(Long checkId);
/**
* 查询设备检验清单列表
*/
TableDataInfo<EqpEquipmentChecklistVo> queryPageList(EqpEquipmentChecklistBo bo, PageQuery pageQuery);
/**
* 查询设备检验清单列表
*/
List<EqpEquipmentChecklistVo> queryList(EqpEquipmentChecklistBo bo);
/**
* 新增设备检验清单
*/
Boolean insertByBo(EqpEquipmentChecklistBo bo);
/**
* 修改设备检验清单
*/
Boolean updateByBo(EqpEquipmentChecklistBo bo);
/**
* 校验并批量删除设备检验清单信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

Some files were not shown because too many files have changed in this diff Show More