diff --git a/docs/sql_quality_review_install.sql b/docs/sql_quality_review_install.sql new file mode 100644 index 000000000..8e9eb8ed9 --- /dev/null +++ b/docs/sql_quality_review_install.sql @@ -0,0 +1,153 @@ +-- ============================================================= +-- 质量评审流程 - 安装脚本 +-- 用法: mysql -h 140.143.206.120 -P 13306 -u klp -p 数据库名 --default-character-set=utf8mb4 < 本文件 +-- ============================================================= +SET NAMES utf8mb4; + +-- ========== 1. 彻底清理所有质量评审相关数据 ========== +-- 删除角色-菜单关联 +DELETE FROM sys_role_menu WHERE menu_id IN (SELECT menu_id FROM sys_menu WHERE perms LIKE '%qualityReview%'); +DELETE FROM sys_role_menu WHERE menu_id IN (SELECT menu_id FROM sys_menu WHERE menu_name = '质量评审' OR menu_name = '质量评审待审批'); +-- 删除菜单本身 +DELETE FROM sys_menu WHERE perms LIKE '%qualityReview%'; +DELETE FROM sys_menu WHERE menu_name = '质量评审'; +DELETE FROM sys_menu WHERE menu_name = '质量评审待审批'; +-- 删除字典 +DELETE FROM sys_dict_data WHERE dict_type = 'quality_review_status'; +DELETE FROM sys_dict_data WHERE dict_type = 'regrade_quality_type'; +DELETE FROM sys_dict_type WHERE dict_type = 'quality_review_status'; +DELETE FROM sys_dict_type WHERE dict_type = 'regrade_quality_type'; +-- 删表 +DROP TABLE IF EXISTS qc_quality_review_log; +DROP TABLE IF EXISTS qc_quality_review_coil; +DROP TABLE IF EXISTS qc_quality_review; + +-- ========== 2. 建表 ========== +CREATE TABLE IF NOT EXISTS `qc_quality_review` ( + `review_id` bigint NOT NULL AUTO_INCREMENT COMMENT '评审单主键', + `review_no` varchar(50) NOT NULL COMMENT '评审单编号', + `product_name` varchar(100) DEFAULT NULL COMMENT '产品名称', + `transmit_dept` varchar(50) DEFAULT NULL COMMENT '传递部门', + `transmit_user` varchar(50) DEFAULT NULL COMMENT '传递人', + `transmit_date` date DEFAULT NULL COMMENT '传递日期', + `prod_date_range` varchar(50) DEFAULT NULL COMMENT '生产日期范围', + `flow_status` tinyint(1) DEFAULT '1' COMMENT '流程状态: 1=待提交 2=待审批 3=已通过 4=已驳回', + `dept_opinion` text COMMENT '品质部评审意见', + `dept_sign` varchar(50) DEFAULT NULL COMMENT '品质部签字人', + `dept_sign_date` date DEFAULT NULL COMMENT '品质部签字日期', + `leader_opinion` text COMMENT '领导审批意见', + `leader_sign` varchar(50) DEFAULT NULL COMMENT '领导签字人', + `leader_sign_date` date DEFAULT NULL COMMENT '领导签字日期', + `reject_reason` varchar(500) DEFAULT NULL COMMENT '驳回原因', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `del_flag` tinyint(1) DEFAULT '0' COMMENT '删除标志', + `create_by` varchar(50) DEFAULT NULL, + `create_time` datetime DEFAULT CURRENT_TIMESTAMP, + `update_by` varchar(50) DEFAULT NULL, + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`review_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='质量评审单'; + +CREATE TABLE IF NOT EXISTS `qc_quality_review_coil` ( + `detail_id` bigint NOT NULL AUTO_INCREMENT COMMENT '明细主键', + `review_id` bigint NOT NULL COMMENT '关联评审单ID', + `group_seq` int DEFAULT NULL COMMENT '序号', + `group_remark` varchar(200) DEFAULT NULL COMMENT '组备注', + `coil_id` bigint DEFAULT NULL COMMENT '钢卷ID', + `current_coil_no` varchar(50) DEFAULT NULL COMMENT '产品卷号', + `supplier_coil_no` varchar(50) DEFAULT NULL COMMENT '原料卷号', + `spec` varchar(50) DEFAULT NULL COMMENT '规格', + `net_weight` decimal(10,3) DEFAULT NULL COMMENT '卷重(t)', + `defect_desc` text COMMENT '缺陷描述', + `before_quality` varchar(20) DEFAULT NULL COMMENT '改判前质量等级', + `regrade_quality` varchar(50) DEFAULT NULL COMMENT '改判后质量状态', + `execute_status` tinyint(1) DEFAULT '0' COMMENT '执行状态: 0=待执行 1=已执行', + `execute_time` datetime DEFAULT NULL COMMENT '执行时间', + `remark` varchar(500) DEFAULT NULL, + `del_flag` tinyint(1) DEFAULT '0', + `create_by` varchar(50) DEFAULT NULL, + `create_time` datetime DEFAULT CURRENT_TIMESTAMP, + `update_by` varchar(50) DEFAULT NULL, + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`detail_id`), + KEY `idx_review_id` (`review_id`), + KEY `idx_coil_id` (`coil_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='质量评审钢卷明细'; + +CREATE TABLE IF NOT EXISTS `qc_quality_review_log` ( + `log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志主键', + `review_id` bigint NOT NULL COMMENT '关联评审单ID', + `action` varchar(20) NOT NULL COMMENT '动作: submit/approve/reject', + `operator` varchar(50) DEFAULT NULL COMMENT '操作人', + `opinion` text COMMENT '审批意见', + `operate_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间', + `create_by` varchar(50) DEFAULT NULL, + `create_time` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`log_id`), + KEY `idx_review_id` (`review_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='质量评审审批日志'; + +-- ========== 3. 字典 ========== +INSERT IGNORE INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, update_by, update_time, remark) +VALUES ('Quality Review Status', 'quality_review_status', '0', 'admin', NOW(), 'admin', NOW(), ''); +INSERT IGNORE INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, update_by, update_time, remark) +VALUES ('Regrade Quality Type', 'regrade_quality_type', '0', 'admin', NOW(), 'admin', NOW(), ''); + +INSERT IGNORE INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) VALUES (1, '待提交', '1', 'quality_review_status', '', 'info', 'Y', '0', 'admin', NOW()); +INSERT IGNORE INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) VALUES (2, '待审批', '2', 'quality_review_status', '', 'warning', 'Y', '0', 'admin', NOW()); +INSERT IGNORE INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) VALUES (3, '已通过', '3', 'quality_review_status', '', 'success', 'Y', '0', 'admin', NOW()); +INSERT IGNORE INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) VALUES (4, '已驳回', '4', 'quality_review_status', '', 'danger', 'Y', '0', 'admin', NOW()); + +INSERT IGNORE INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) VALUES (1, '协议销售', 'protocol_sale', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW()); +INSERT IGNORE INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) VALUES (2, '转分剪', 'to_slitting', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW()); +INSERT IGNORE INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) VALUES (3, '降级', 'downgrade', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW()); +INSERT IGNORE INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) VALUES (4, '返修', 'rework', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW()); +INSERT IGNORE INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) VALUES (5, '报废', 'scrap', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW()); + +-- ========== 4. 创建菜单 ========== +-- 父菜单: 质量模块 (path=quality, menu_id=2068954238598967297) +SET @parent_id = 2068954238598967297; +SET @max_order = (SELECT COALESCE(MAX(order_num), 0) FROM sys_menu WHERE parent_id = @parent_id); +SET @max_id = (SELECT COALESCE(MAX(menu_id), 0) FROM sys_menu); + +SET @id1 = @max_id + 1; +SET @id2 = @max_id + 2; +SET @id3 = @max_id + 3; +SET @id4 = @max_id + 4; +SET @id5 = @max_id + 5; +SET @id6 = @max_id + 6; +SET @id7 = @max_id + 7; +SET @id8 = @max_id + 8; + +-- 质量评审菜单 (type=C 菜单) +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time) +VALUES (@id1, '质量评审', @parent_id, @max_order + 1, 'qualityReview', 'mes/qc/qualityReview/index', 1, 0, 'C', '0', '0', 'qc:qualityReview:list', 'guide', 'admin', NOW()); + +-- 质量评审待审批 (type=C 隐藏) +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time) +VALUES (@id2, '质量评审待审批', @parent_id, @max_order + 2, 'qualityReviewTodo', 'mes/qc/qualityReview/todo', 1, 0, 'C', '1', '0', 'qc:qualityReview:approve', 'checkbox', 'admin', NOW()); + +-- 按钮权限 (type=F) +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, menu_type, visible, status, perms, create_by, create_time) +VALUES (@id3, '质量评审新增', @id1, 1, 'F', '0', '0', 'qc:qualityReview:add', 'admin', NOW()); +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, menu_type, visible, status, perms, create_by, create_time) +VALUES (@id4, '质量评审修改', @id1, 2, 'F', '0', '0', 'qc:qualityReview:edit', 'admin', NOW()); +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, menu_type, visible, status, perms, create_by, create_time) +VALUES (@id5, '质量评审删除', @id1, 3, 'F', '0', '0', 'qc:qualityReview:delete', 'admin', NOW()); +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, menu_type, visible, status, perms, create_by, create_time) +VALUES (@id6, '质量评审提交送审', @id1, 4, 'F', '0', '0', 'qc:qualityReview:submit', 'admin', NOW()); +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, menu_type, visible, status, perms, create_by, create_time) +VALUES (@id7, '质量评审审批', @id1, 5, 'F', '0', '0', 'qc:qualityReview:approve', 'admin', NOW()); +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, menu_type, visible, status, perms, create_by, create_time) +VALUES (@id8, '质量评审执行改判', @id1, 6, 'F', '0', '0', 'qc:qualityReview:execute', 'admin', NOW()); + +-- ========== 5. 授权 admin 角色 ========== +INSERT IGNORE INTO sys_role_menu (role_id, menu_id) VALUES +(1, @parent_id), (1, @id1), (1, @id2), +(1, @id3), (1, @id4), (1, @id5), +(1, @id6), (1, @id7), (1, @id8); + +-- ========== 6. 验证 ========== +SELECT CONCAT('Tables: ', COUNT(*)) AS result FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME LIKE 'qc_quality_review%'; +SELECT CONCAT('Dict: ', dict_type) AS result FROM sys_dict_type WHERE dict_type = 'quality_review_status'; +SELECT CONCAT('Menu: ', menu_name, ' -> parent_id=', parent_id) AS result FROM sys_menu WHERE perms = 'qc:qualityReview:list'; diff --git a/klp-admin/src/main/java/com/klp/web/controller/system/SysFileController.java b/klp-admin/src/main/java/com/klp/web/controller/system/SysFileController.java new file mode 100644 index 000000000..d2c287236 --- /dev/null +++ b/klp-admin/src/main/java/com/klp/web/controller/system/SysFileController.java @@ -0,0 +1,108 @@ +package com.klp.web.controller.system; + +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.system.domain.vo.SysFileVo; +import com.klp.system.domain.bo.SysFileBo; +import com.klp.system.service.ISysFileService; +import com.klp.common.core.page.TableDataInfo; + +/** + * 文件主信息 + * + * @author klp + * @date 2026-06-30 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/file") +public class SysFileController extends BaseController { + + private final ISysFileService iSysFileService; + + /** + * 查询文件主信息列表 + */ + @GetMapping("/list") + public TableDataInfo list(SysFileBo bo, PageQuery pageQuery) { + return iSysFileService.queryPageList(bo, pageQuery); + } + + /** + * 导出文件主信息列表 + */ + @Log(title = "文件主信息", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(SysFileBo bo, HttpServletResponse response) { + List list = iSysFileService.queryList(bo); + ExcelUtil.exportExcel(list, "文件主信息", SysFileVo.class, response); + } + + /** + * 获取文件主信息详细信息 + * + * @param fileId 主键 + */ + @GetMapping("/{fileId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long fileId) { + return R.ok(iSysFileService.queryById(fileId)); + } + + /** + * 新增文件主信息 + */ + @Log(title = "文件主信息", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody SysFileBo bo) { + iSysFileService.insertByBo(bo); + return R.ok(bo.getFileId()); + } + + /** + * 修改文件主信息 + */ + @Log(title = "文件主信息", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody SysFileBo bo) { + return toAjax(iSysFileService.updateByBo(bo)); + } + + /** + * 删除文件主信息 + * + * @param fileIds 主键串 + */ + @Log(title = "文件主信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{fileIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] fileIds) { + return toAjax(iSysFileService.deleteWithValidByIds(Arrays.asList(fileIds), true)); + } + + /** + * 查询与我相关的文件(私有文件且当前用户在可见用户列表中) + */ + @GetMapping("/relatedToMe") + public TableDataInfo relatedToMe(SysFileBo bo, PageQuery pageQuery) { + return iSysFileService.queryPageListRelatedToMe(bo, pageQuery); + } +} diff --git a/klp-admin/src/main/java/com/klp/web/controller/system/SysFileVisibleUserController.java b/klp-admin/src/main/java/com/klp/web/controller/system/SysFileVisibleUserController.java new file mode 100644 index 000000000..470dd9155 --- /dev/null +++ b/klp-admin/src/main/java/com/klp/web/controller/system/SysFileVisibleUserController.java @@ -0,0 +1,99 @@ +package com.klp.web.controller.system; + +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.system.domain.vo.SysFileVisibleUserVo; +import com.klp.system.domain.bo.SysFileVisibleUserBo; +import com.klp.system.service.ISysFileVisibleUserService; +import com.klp.common.core.page.TableDataInfo; + +/** + * 私有文件可见用户多对多关联 + * + * @author klp + * @date 2026-06-30 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/fileVisibleUser") +public class SysFileVisibleUserController extends BaseController { + + private final ISysFileVisibleUserService iSysFileVisibleUserService; + + /** + * 查询私有文件可见用户多对多关联列表 + */ + @GetMapping("/list") + public TableDataInfo list(SysFileVisibleUserBo bo, PageQuery pageQuery) { + return iSysFileVisibleUserService.queryPageList(bo, pageQuery); + } + + /** + * 导出私有文件可见用户多对多关联列表 + */ + @Log(title = "私有文件可见用户多对多关联", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(SysFileVisibleUserBo bo, HttpServletResponse response) { + List list = iSysFileVisibleUserService.queryList(bo); + ExcelUtil.exportExcel(list, "私有文件可见用户多对多关联", SysFileVisibleUserVo.class, response); + } + + /** + * 获取私有文件可见用户多对多关联详细信息 + * + * @param visibleId 主键 + */ + @GetMapping("/{visibleId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long visibleId) { + return R.ok(iSysFileVisibleUserService.queryById(visibleId)); + } + + /** + * 新增私有文件可见用户多对多关联 + */ + @Log(title = "私有文件可见用户多对多关联", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody SysFileVisibleUserBo bo) { + return toAjax(iSysFileVisibleUserService.insertByBo(bo)); + } + + /** + * 修改私有文件可见用户多对多关联 + */ + @Log(title = "私有文件可见用户多对多关联", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody SysFileVisibleUserBo bo) { + return toAjax(iSysFileVisibleUserService.updateByBo(bo)); + } + + /** + * 删除私有文件可见用户多对多关联 + * + * @param visibleIds 主键串 + */ + @Log(title = "私有文件可见用户多对多关联", businessType = BusinessType.DELETE) + @DeleteMapping("/{visibleIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] visibleIds) { + return toAjax(iSysFileVisibleUserService.deleteWithValidByIds(Arrays.asList(visibleIds), true)); + } +} diff --git a/klp-admin/src/main/resources/db/migration/V15__qc_quality_review.sql b/klp-admin/src/main/resources/db/migration/V15__qc_quality_review.sql new file mode 100644 index 000000000..d6c5931b3 --- /dev/null +++ b/klp-admin/src/main/resources/db/migration/V15__qc_quality_review.sql @@ -0,0 +1,105 @@ +-- ------------------------------------------------------------ +-- 质量评审流程 - 异常产品评审审批单 +-- V15__qc_quality_review.sql +-- ------------------------------------------------------------ + +-- 1. 字典类型 +INSERT INTO `sys_dict_type` VALUES (NULL, '质量评审状态', 'quality_review_status', '0', 'admin', NOW(), '', NULL, '质量评审单流程状态'); +INSERT INTO `sys_dict_type` VALUES (NULL, '改判后质量状态', 'regrade_quality_type', '0', 'admin', NOW(), '', NULL, '领导审批时指定的改判结果'); + +-- 2. 字典数据 - 质量评审状态 +INSERT INTO `sys_dict_data` VALUES (NULL, 1, '待提交', '1', 'quality_review_status', '', 'info', 'Y', '0', 'admin', NOW(), '', NULL, ''); +INSERT INTO `sys_dict_data` VALUES (NULL, 2, '待审批', '2', 'quality_review_status', '', 'warning', 'Y', '0', 'admin', NOW(), '', NULL, ''); +INSERT INTO `sys_dict_data` VALUES (NULL, 3, '已通过', '3', 'quality_review_status', '', 'success', 'Y', '0', 'admin', NOW(), '', NULL, ''); +INSERT INTO `sys_dict_data` VALUES (NULL, 4, '已驳回', '4', 'quality_review_status', '', 'danger', 'Y', '0', 'admin', NOW(), '', NULL, ''); + +-- 3. 字典数据 - 改判后质量状态 +INSERT INTO `sys_dict_data` VALUES (NULL, 1, '协议销售', 'protocol_sale', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW(), '', NULL, ''); +INSERT INTO `sys_dict_data` VALUES (NULL, 2, '转分剪', 'to_slitting', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW(), '', NULL, ''); +INSERT INTO `sys_dict_data` VALUES (NULL, 3, '降级', 'downgrade', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW(), '', NULL, ''); +INSERT INTO `sys_dict_data` VALUES (NULL, 4, '返修', 'rework', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW(), '', NULL, ''); +INSERT INTO `sys_dict_data` VALUES (NULL, 5, '报废', 'scrap', 'regrade_quality_type', '', '', 'Y', '0', 'admin', NOW(), '', NULL, ''); + +-- 4. 质量评审主表 +CREATE TABLE `qc_quality_review` ( + `review_id` bigint NOT NULL AUTO_INCREMENT COMMENT '评审单主键', + `review_no` varchar(50) NOT NULL COMMENT '评审单编号(QR-2026-XXXX)', + `product_name` varchar(100) DEFAULT NULL COMMENT '产品名称', + `transmit_dept` varchar(50) DEFAULT '品质部' COMMENT '传递部门', + `transmit_user` varchar(50) DEFAULT NULL COMMENT '传递人', + `transmit_date` date DEFAULT NULL COMMENT '传递日期', + `prod_date_range` varchar(50) DEFAULT NULL COMMENT '生产日期范围', + + -- 流程状态 + `flow_status` tinyint(1) DEFAULT '1' COMMENT '流程状态:1=待提交 2=待审批 3=已通过 4=已驳回', + + -- 品质部评审 + `dept_opinion` text COMMENT '品质部评审意见', + `dept_sign` varchar(50) DEFAULT NULL COMMENT '品质部签字人', + `dept_sign_date` date DEFAULT NULL COMMENT '品质部签字日期', + + -- 领导审批 + `leader_opinion` text COMMENT '领导审批意见', + `leader_sign` varchar(50) DEFAULT NULL COMMENT '领导签字人', + `leader_sign_date` date DEFAULT NULL COMMENT '领导签字日期', + `reject_reason` varchar(500) DEFAULT NULL COMMENT '驳回原因', + + -- 公共基础字段 + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `del_flag` tinyint(1) DEFAULT '0' COMMENT '删除标志(0=正常,1=已删除)', + `create_by` varchar(50) DEFAULT '' COMMENT '创建人', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` varchar(50) DEFAULT '' COMMENT '更新人', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`review_id`) USING BTREE, + UNIQUE KEY `uk_review_no` (`review_no`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='质量评审单'; + +-- 5. 质量评审钢卷明细表 +CREATE TABLE `qc_quality_review_coil` ( + `detail_id` bigint NOT NULL AUTO_INCREMENT COMMENT '明细主键', + `review_id` bigint NOT NULL COMMENT '关联评审单ID', + + -- 钢卷分组信息 + `group_seq` int DEFAULT NULL COMMENT '序号(1,2,3...)', + `group_remark` varchar(200) DEFAULT NULL COMMENT '组备注(如"含3个钢卷")', + + -- 钢卷信息 + `coil_id` bigint DEFAULT NULL COMMENT '钢卷ID(关联wms_material_coil)', + `current_coil_no` varchar(50) DEFAULT NULL COMMENT '产品卷号', + `supplier_coil_no` varchar(50) DEFAULT NULL COMMENT '原料卷号', + `spec` varchar(50) DEFAULT NULL COMMENT '规格(如1.35×1250)', + `net_weight` decimal(10,3) DEFAULT NULL COMMENT '卷重(t)', + + -- 缺陷与改判 + `defect_desc` text COMMENT '缺陷描述', + `before_quality` varchar(20) DEFAULT NULL COMMENT '改判前质量等级(系统自动带出)', + `regrade_quality` varchar(50) DEFAULT NULL COMMENT '改判后质量状态(字典:regrade_quality_type)', + `execute_status` tinyint(1) DEFAULT '0' COMMENT '执行状态:0=待执行 1=已执行', + `execute_time` datetime DEFAULT NULL COMMENT '执行时间', + + -- 公共基础字段 + `remark` varchar(500) DEFAULT NULL, + `del_flag` tinyint(1) DEFAULT '0', + `create_by` varchar(50) DEFAULT '', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP, + `update_by` varchar(50) DEFAULT '', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`detail_id`) USING BTREE, + KEY `idx_review_id` (`review_id`) USING BTREE, + KEY `idx_coil_id` (`coil_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='质量评审钢卷明细'; + +-- 6. 质量评审审批日志表 +CREATE TABLE `qc_quality_review_log` ( + `log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志主键', + `review_id` bigint NOT NULL COMMENT '关联评审单ID', + `action` varchar(20) NOT NULL COMMENT '动作:submit=提交 approve=通过 reject=驳回', + `operator` varchar(50) DEFAULT NULL COMMENT '操作人', + `opinion` text COMMENT '审批意见', + `operate_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间', + `create_by` varchar(50) DEFAULT '', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`log_id`) USING BTREE, + KEY `idx_review_id` (`review_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='质量评审审批日志'; diff --git a/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderItemController.java b/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderItemController.java index 69e43426c..e18d2f75b 100644 --- a/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderItemController.java +++ b/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderItemController.java @@ -105,11 +105,12 @@ public class CrmOrderItemController extends BaseController { @PathVariable Long contractId) { return R.ok(iCrmOrderItemService.queryFinanceAndObjectionByContractId(contractId)); } - // 根据订单id查询发货单据中的配卷。 + // 根据订单id查询发货单据中的配卷(分页)。 @GetMapping("/coils/order/{orderId}") - public R> getCoilsByOrderId(@NotNull(message = "订单ID不能为空") - @PathVariable Long orderId) { - return R.ok(iCrmOrderItemService.queryCoilsByOrderId(orderId)); + public TableDataInfo getCoilsByOrderId(@NotNull(message = "订单ID不能为空") + @PathVariable Long orderId, + PageQuery pageQuery) { + return iCrmOrderItemService.queryCoilsByOrderId(orderId, pageQuery); } // 根据合同id查询发货单据中的配卷。 @@ -132,4 +133,39 @@ public class CrmOrderItemController extends BaseController { @PathVariable String customerId) { return R.ok(iCrmOrderItemService.queryCoilsByCustomerId(customerId)); } + + // 根据销售员查询生产成果(钢卷列表),分页 + @GetMapping("/coils/bySalesman") + public TableDataInfo getCoilsBySalesman(@RequestParam String salesman, + PageQuery pageQuery) { + return iCrmOrderItemService.queryCoilsBySalesman(salesman, pageQuery); + } + + // 根据合同ID查询生产成果(钢卷列表),分页 + @GetMapping("/coils/byContract/{contractId}") + public TableDataInfo getCoilsByContractIdPaginated(@NotNull(message = "合同ID不能为空") + @PathVariable Long contractId, + PageQuery pageQuery) { + return iCrmOrderItemService.queryCoilsByContractIdPaginated(contractId, pageQuery); + } + + // 根据订单ID统计配卷汇总 + @GetMapping("/coils/order/{orderId}/statistics") + public R> getCoilsByOrderIdStatistics(@NotNull(message = "订单ID不能为空") + @PathVariable Long orderId) { + return R.ok(iCrmOrderItemService.queryCoilsByOrderIdStatistics(orderId)); + } + + // 根据销售员统计生产成果汇总 + @GetMapping("/coils/bySalesman/statistics") + public R> getCoilsBySalesmanStatistics(@RequestParam String salesman) { + return R.ok(iCrmOrderItemService.queryCoilsBySalesmanStatistics(salesman)); + } + + // 根据合同ID统计生产成果汇总 + @GetMapping("/coils/byContract/{contractId}/statistics") + public R> getCoilsByContractIdStatistics(@NotNull(message = "合同ID不能为空") + @PathVariable Long contractId) { + return R.ok(iCrmOrderItemService.queryCoilsByContractIdStatistics(contractId)); + } } diff --git a/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderItemService.java b/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderItemService.java index ae9a299c7..29d312fb1 100644 --- a/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderItemService.java +++ b/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderItemService.java @@ -57,9 +57,9 @@ public interface ICrmOrderItemService { CrmContractOrderFinanceVo queryFinanceAndObjectionByContractId(Long contractId); /** - * 根据订单ID查询发货单配卷 + * 根据订单ID查询发货单配卷(分页) */ - List queryCoilsByOrderId(Long orderId); + TableDataInfo queryCoilsByOrderId(Long orderId, PageQuery pageQuery); /** * 根据合同ID查询发货单配卷 @@ -75,4 +75,29 @@ public interface ICrmOrderItemService { * 根据客户ID查询发货单配卷 */ List queryCoilsByCustomerId(String customerId); + + /** + * 根据销售员查询生产成果(钢卷列表)分页 + */ + TableDataInfo queryCoilsBySalesman(String salesman, PageQuery pageQuery); + + /** + * 根据合同ID查询生产成果(钢卷列表)分页 + */ + TableDataInfo queryCoilsByContractIdPaginated(Long contractId, PageQuery pageQuery); + + /** + * 根据订单ID统计配卷汇总数据(数量、毛重、净重) + */ + java.util.Map queryCoilsByOrderIdStatistics(Long orderId); + + /** + * 根据销售员统计生产成果汇总数据(数量、毛重、净重) + */ + java.util.Map queryCoilsBySalesmanStatistics(String salesman); + + /** + * 根据合同ID统计生产成果汇总数据(数量、毛重、净重) + */ + java.util.Map queryCoilsByContractIdStatistics(Long contractId); } diff --git a/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderItemServiceImpl.java b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderItemServiceImpl.java index 7d7510549..fc5a2fa9a 100644 --- a/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderItemServiceImpl.java +++ b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderItemServiceImpl.java @@ -35,6 +35,8 @@ import com.klp.crm.service.ICrmOrderItemService; import com.klp.mapper.WmsReceivableMapper; import com.klp.mapper.WmsDeliveryWaybillMapper; import com.klp.mapper.WmsDeliveryWaybillDetailMapper; +import com.klp.mapper.WmsCoilContractRelMapper; +import com.klp.domain.WmsCoilContractRel; import com.klp.service.IWmsMaterialCoilService; import java.util.*; @@ -57,6 +59,7 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { private final WmsReceivableMapper wmsReceivableMapper; private final WmsDeliveryWaybillMapper wmsDeliveryWaybillMapper; private final WmsDeliveryWaybillDetailMapper wmsDeliveryWaybillDetailMapper; + private final WmsCoilContractRelMapper coilContractRelMapper; private final IWmsMaterialCoilService iWmsMaterialCoilService; /** @@ -287,16 +290,19 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { return result; } - @Override - public List queryCoilsByOrderId(Long orderId) { + // ==================== 线圈ID解析辅助方法 ==================== + + /** + * 根据订单ID解析关联的线圈ID串(通过发货单→发货单明细) + * @return 逗号分隔的coilId字符串,无数据返回null + */ + private String resolveCoilIdsByOrderId(Long orderId) { LambdaQueryWrapper waybillWrapper = new LambdaQueryWrapper<>(); waybillWrapper.eq(WmsDeliveryWaybill::getOrderId, orderId); List waybills = wmsDeliveryWaybillMapper.selectList(waybillWrapper); - if (waybills == null || waybills.isEmpty()) { - return Collections.emptyList(); + return null; } - List waybillIds = waybills.stream() .map(WmsDeliveryWaybill::getWaybillId) .collect(Collectors.toList()); @@ -304,31 +310,155 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { LambdaQueryWrapper detailWrapper = new LambdaQueryWrapper<>(); detailWrapper.in(WmsDeliveryWaybillDetail::getWaybillId, waybillIds); List details = wmsDeliveryWaybillDetailMapper.selectList(detailWrapper); - if (details == null || details.isEmpty()) { - return Collections.emptyList(); + return null; } - - String coilIds = details.stream() + return details.stream() .map(WmsDeliveryWaybillDetail::getCoilId) .map(String::valueOf) .collect(Collectors.joining(",")); + } + /** + * 根据销售员解析关联的线圈ID串(通过crm_order→wms_coil_contract_rel) + * @return 逗号分隔的coilId字符串,无数据返回null + */ + private String resolveCoilIdsBySalesman(String salesman) { + LambdaQueryWrapper orderWrapper = new LambdaQueryWrapper<>(); + orderWrapper.eq(CrmOrder::getSalesman, salesman); + orderWrapper.eq(CrmOrder::getDelFlag, 0); + List orders = crmOrderMapper.selectList(orderWrapper); + if (orders == null || orders.isEmpty()) { + return null; + } + List orderIds = orders.stream() + .map(CrmOrder::getOrderId) + .collect(Collectors.toList()); + + LambdaQueryWrapper relWrapper = new LambdaQueryWrapper<>(); + relWrapper.in(WmsCoilContractRel::getContractId, orderIds); + relWrapper.eq(WmsCoilContractRel::getDelFlag, 0); + List rels = coilContractRelMapper.selectList(relWrapper); + if (rels == null || rels.isEmpty()) { + return null; + } + return rels.stream() + .map(WmsCoilContractRel::getCoilId) + .distinct() + .map(String::valueOf) + .collect(Collectors.joining(",")); + } + + /** + * 根据合同ID解析关联的线圈ID串(通过crm_order→wms_coil_contract_rel) + * @return 逗号分隔的coilId字符串,无数据返回null + */ + private String resolveCoilIdsByContractId(Long contractId) { + LambdaQueryWrapper orderWrapper = new LambdaQueryWrapper<>(); + orderWrapper.eq(CrmOrder::getContractId, contractId); + orderWrapper.eq(CrmOrder::getDelFlag, 0); + List orders = crmOrderMapper.selectList(orderWrapper); + if (orders == null || orders.isEmpty()) { + return null; + } + List orderIds = orders.stream() + .map(CrmOrder::getOrderId) + .collect(Collectors.toList()); + + LambdaQueryWrapper relWrapper = new LambdaQueryWrapper<>(); + relWrapper.in(WmsCoilContractRel::getContractId, orderIds); + relWrapper.eq(WmsCoilContractRel::getDelFlag, 0); + List rels = coilContractRelMapper.selectList(relWrapper); + if (rels == null || rels.isEmpty()) { + return null; + } + return rels.stream() + .map(WmsCoilContractRel::getCoilId) + .distinct() + .map(String::valueOf) + .collect(Collectors.joining(",")); + } + + // ==================== 分页列表查询 ==================== + + @Override + public TableDataInfo queryCoilsByOrderId(Long orderId, PageQuery pageQuery) { + String coilIds = resolveCoilIdsByOrderId(orderId); + if (coilIds == null) { + return new TableDataInfo<>(); + } WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo(); coilBo.setCoilIds(coilIds); - return iWmsMaterialCoilService.queryList(coilBo); + return iWmsMaterialCoilService.queryPageList(coilBo, pageQuery); } + @Override + public TableDataInfo queryCoilsBySalesman(String salesman, PageQuery pageQuery) { + String coilIds = resolveCoilIdsBySalesman(salesman); + if (coilIds == null) { + return new TableDataInfo<>(); + } + WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo(); + coilBo.setCoilIds(coilIds); + return iWmsMaterialCoilService.queryPageList(coilBo, pageQuery); + } + + @Override + public TableDataInfo queryCoilsByContractIdPaginated(Long contractId, PageQuery pageQuery) { + String coilIds = resolveCoilIdsByContractId(contractId); + if (coilIds == null) { + return new TableDataInfo<>(); + } + WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo(); + coilBo.setCoilIds(coilIds); + return iWmsMaterialCoilService.queryPageList(coilBo, pageQuery); + } + + // ==================== 统计汇总查询 ==================== + + @Override + public Map queryCoilsByOrderIdStatistics(Long orderId) { + String coilIds = resolveCoilIdsByOrderId(orderId); + if (coilIds == null) { + return emptyStatistics(); + } + WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo(); + coilBo.setCoilIds(coilIds); + return iWmsMaterialCoilService.getStatistics(coilBo); + } + + @Override + public Map queryCoilsBySalesmanStatistics(String salesman) { + String coilIds = resolveCoilIdsBySalesman(salesman); + if (coilIds == null) { + return emptyStatistics(); + } + WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo(); + coilBo.setCoilIds(coilIds); + return iWmsMaterialCoilService.getStatistics(coilBo); + } + + @Override + public Map queryCoilsByContractIdStatistics(Long contractId) { + String coilIds = resolveCoilIdsByContractId(contractId); + if (coilIds == null) { + return emptyStatistics(); + } + WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo(); + coilBo.setCoilIds(coilIds); + return iWmsMaterialCoilService.getStatistics(coilBo); + } + + // ==================== 已有方法(非分页) ==================== + @Override public List queryCoilsByContractId(Long contractId) { LambdaQueryWrapper orderWrapper = new LambdaQueryWrapper<>(); orderWrapper.eq(CrmOrder::getContractId, contractId); List orders = crmOrderMapper.selectList(orderWrapper); - if (orders == null || orders.isEmpty()) { return Collections.emptyList(); } - List orderIds = orders.stream() .map(CrmOrder::getOrderId) .collect(Collectors.toList()); @@ -336,11 +466,9 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { LambdaQueryWrapper waybillWrapper = new LambdaQueryWrapper<>(); waybillWrapper.in(WmsDeliveryWaybill::getOrderId, orderIds); List waybills = wmsDeliveryWaybillMapper.selectList(waybillWrapper); - if (waybills == null || waybills.isEmpty()) { return Collections.emptyList(); } - List waybillIds = waybills.stream() .map(WmsDeliveryWaybill::getWaybillId) .collect(Collectors.toList()); @@ -348,11 +476,9 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { LambdaQueryWrapper detailWrapper = new LambdaQueryWrapper<>(); detailWrapper.in(WmsDeliveryWaybillDetail::getWaybillId, waybillIds); List details = wmsDeliveryWaybillDetailMapper.selectList(detailWrapper); - if (details == null || details.isEmpty()) { return Collections.emptyList(); } - String coilIds = details.stream() .map(WmsDeliveryWaybillDetail::getCoilId) .map(String::valueOf) @@ -370,11 +496,9 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { LambdaQueryWrapper orderWrapper = new LambdaQueryWrapper<>(); orderWrapper.eq(CrmOrder::getCustomerId, customerId); List orders = crmOrderMapper.selectList(orderWrapper); - if (orders == null || orders.isEmpty()) { return result; } - List orderIds = orders.stream() .map(CrmOrder::getOrderId) .collect(Collectors.toList()); @@ -402,11 +526,9 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { LambdaQueryWrapper orderWrapper = new LambdaQueryWrapper<>(); orderWrapper.eq(CrmOrder::getCustomerId, customerId); List orders = crmOrderMapper.selectList(orderWrapper); - if (orders == null || orders.isEmpty()) { return Collections.emptyList(); } - List orderIds = orders.stream() .map(CrmOrder::getOrderId) .collect(Collectors.toList()); @@ -414,11 +536,9 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { LambdaQueryWrapper waybillWrapper = new LambdaQueryWrapper<>(); waybillWrapper.in(WmsDeliveryWaybill::getOrderId, orderIds); List waybills = wmsDeliveryWaybillMapper.selectList(waybillWrapper); - if (waybills == null || waybills.isEmpty()) { return Collections.emptyList(); } - List waybillIds = waybills.stream() .map(WmsDeliveryWaybill::getWaybillId) .collect(Collectors.toList()); @@ -426,11 +546,9 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { LambdaQueryWrapper detailWrapper = new LambdaQueryWrapper<>(); detailWrapper.in(WmsDeliveryWaybillDetail::getWaybillId, waybillIds); List details = wmsDeliveryWaybillDetailMapper.selectList(detailWrapper); - if (details == null || details.isEmpty()) { return Collections.emptyList(); } - String coilIds = details.stream() .map(WmsDeliveryWaybillDetail::getCoilId) .map(String::valueOf) @@ -440,4 +558,12 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService { coilBo.setCoilIds(coilIds); return iWmsMaterialCoilService.queryList(coilBo); } + + private Map emptyStatistics() { + Map empty = new HashMap<>(); + empty.put("total_count", java.math.BigDecimal.ZERO); + empty.put("total_gross_weight", java.math.BigDecimal.ZERO); + empty.put("total_net_weight", java.math.BigDecimal.ZERO); + return empty; + } } diff --git a/klp-flow/src/main/java/com/klp/flow/domain/SchProdScheduleItem.java b/klp-flow/src/main/java/com/klp/flow/domain/SchProdScheduleItem.java index f888ece07..ef0cf17e2 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/SchProdScheduleItem.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/SchProdScheduleItem.java @@ -131,6 +131,10 @@ public class SchProdScheduleItem extends BaseEntity { * 排产明细关联主表ID(逗号分隔,未合并存单值,合并后存多个) */ private String scheduleDetailIds; + /** + * 工序类型 + */ + private String actionType; /** * 规格 例:1.0X1250 */ diff --git a/klp-flow/src/main/java/com/klp/flow/domain/bo/SchProdScheduleItemBo.java b/klp-flow/src/main/java/com/klp/flow/domain/bo/SchProdScheduleItemBo.java index c2fbd5f3f..64a8d0799 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/bo/SchProdScheduleItemBo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/bo/SchProdScheduleItemBo.java @@ -158,6 +158,11 @@ public class SchProdScheduleItemBo extends BaseEntity { */ private String scheduleDetailIds; + /** + * 工序类型 + */ + private String actionType; + /** * 规格 例:1.0X1250 */ diff --git a/klp-flow/src/main/java/com/klp/flow/domain/vo/SchProdScheduleItemVo.java b/klp-flow/src/main/java/com/klp/flow/domain/vo/SchProdScheduleItemVo.java index 6adfeb3a5..1dc7f0001 100644 --- a/klp-flow/src/main/java/com/klp/flow/domain/vo/SchProdScheduleItemVo.java +++ b/klp-flow/src/main/java/com/klp/flow/domain/vo/SchProdScheduleItemVo.java @@ -189,6 +189,12 @@ public class SchProdScheduleItemVo { @ExcelProperty(value = "排产明细关联主表ID") private String scheduleDetailIds; + /** + * 工序类型 + */ + @ExcelProperty(value = "工序类型") + private String actionType; + /** * 规格 例:1.0X1250 */ diff --git a/klp-flow/src/main/java/com/klp/flow/service/impl/SchProdScheduleItemServiceImpl.java b/klp-flow/src/main/java/com/klp/flow/service/impl/SchProdScheduleItemServiceImpl.java index dee39cfb3..1254fffeb 100644 --- a/klp-flow/src/main/java/com/klp/flow/service/impl/SchProdScheduleItemServiceImpl.java +++ b/klp-flow/src/main/java/com/klp/flow/service/impl/SchProdScheduleItemServiceImpl.java @@ -108,6 +108,8 @@ public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemServi lqw.eq(bo.getScheduleWeight() != null, SchProdScheduleItem::getScheduleWeight, bo.getScheduleWeight()); lqw.eq(StringUtils.isNotBlank(bo.getProductItem()), SchProdScheduleItem::getProductItem, bo.getProductItem()); lqw.eq(StringUtils.isNotBlank(bo.getRowRemark()), SchProdScheduleItem::getRowRemark, bo.getRowRemark()); + // actionType + lqw.eq(StringUtils.isNotBlank(bo.getActionType()), SchProdScheduleItem::getActionType, bo.getActionType()); return lqw; } diff --git a/klp-mes/src/main/java/com/klp/mes/qc/controller/QcQualityReviewController.java b/klp-mes/src/main/java/com/klp/mes/qc/controller/QcQualityReviewController.java new file mode 100644 index 000000000..ef41a2813 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/controller/QcQualityReviewController.java @@ -0,0 +1,159 @@ +package com.klp.mes.qc.controller; + +import com.klp.common.annotation.Log; +import com.klp.common.annotation.RepeatSubmit; +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.page.TableDataInfo; +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.qc.domain.bo.QcQualityReviewApproveBo; +import com.klp.mes.qc.domain.bo.QcQualityReviewBo; +import com.klp.mes.qc.domain.vo.QcQualityReviewCoilVo; +import com.klp.mes.qc.domain.vo.QcQualityReviewLogVo; +import com.klp.mes.qc.domain.vo.QcQualityReviewVo; +import com.klp.mes.qc.service.IQcQualityReviewService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; + +/** + * 质量评审单Controller + * + * @author klp + * @date 2026-06-30 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/qc/qualityReview") +public class QcQualityReviewController extends BaseController { + + private final IQcQualityReviewService iQcQualityReviewService; + + /** + * 查询质量评审单列表 + */ + @GetMapping("/list") + public TableDataInfo list(QcQualityReviewBo bo, PageQuery pageQuery) { + return iQcQualityReviewService.queryPageList(bo, pageQuery); + } + + /** + * 导出质量评审单列表 + */ + @Log(title = "质量评审单", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(QcQualityReviewBo bo, HttpServletResponse response) { + List list = iQcQualityReviewService.queryList(bo); + ExcelUtil.exportExcel(list, "质量评审单", QcQualityReviewVo.class, response); + } + + /** + * 获取质量评审单详细信息 + */ + @GetMapping("/{reviewId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long reviewId) { + return R.ok(iQcQualityReviewService.queryById(reviewId)); + } + + /** + * 新增质量评审单 + */ + @Log(title = "质量评审单", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody QcQualityReviewBo bo) { + return toAjax(iQcQualityReviewService.insertByBo(bo)); + } + + /** + * 修改质量评审单 + */ + @Log(title = "质量评审单", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody QcQualityReviewBo bo) { + return toAjax(iQcQualityReviewService.updateByBo(bo)); + } + + /** + * 删除质量评审单 + */ + @Log(title = "质量评审单", businessType = BusinessType.DELETE) + @DeleteMapping("/{reviewIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] reviewIds) { + return toAjax(iQcQualityReviewService.deleteWithValidByIds(Arrays.asList(reviewIds), true)); + } + + // ==================== 业务操作 ==================== + + /** + * 提交送审 + */ + @Log(title = "质量评审单", businessType = BusinessType.UPDATE) + @PostMapping("/submit/{reviewId}") + public R submit(@NotNull(message = "主键不能为空") + @PathVariable Long reviewId) { + return toAjax(iQcQualityReviewService.submit(reviewId)); + } + + /** + * 审批通过 + */ + @Log(title = "质量评审单", businessType = BusinessType.UPDATE) + @PostMapping("/approve") + public R approve(@Validated @RequestBody QcQualityReviewApproveBo bo) { + return toAjax(iQcQualityReviewService.approve(bo)); + } + + /** + * 驳回 + */ + @Log(title = "质量评审单", businessType = BusinessType.UPDATE) + @PostMapping("/reject/{reviewId}") + public R reject(@NotNull(message = "主键不能为空") + @PathVariable Long reviewId, + @RequestParam String reason) { + return toAjax(iQcQualityReviewService.reject(reviewId, reason)); + } + + /** + * 执行改判 + */ + @Log(title = "质量评审单", businessType = BusinessType.UPDATE) + @PostMapping("/execute/{reviewId}") + public R execute(@NotNull(message = "主键不能为空") + @PathVariable Long reviewId) { + return toAjax(iQcQualityReviewService.execute(reviewId)); + } + + /** + * 查询钢卷明细列表 + */ + @GetMapping("/coilList/{reviewId}") + public R> coilList(@NotNull(message = "主键不能为空") + @PathVariable Long reviewId) { + return R.ok(iQcQualityReviewService.queryCoilListByReviewId(reviewId)); + } + + /** + * 查询审批日志列表 + */ + @GetMapping("/logList/{reviewId}") + public R> logList(@NotNull(message = "主键不能为空") + @PathVariable Long reviewId) { + return R.ok(iQcQualityReviewService.queryLogListByReviewId(reviewId)); + } +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/domain/QcQualityReview.java b/klp-mes/src/main/java/com/klp/mes/qc/domain/QcQualityReview.java new file mode 100644 index 000000000..da386f74f --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/domain/QcQualityReview.java @@ -0,0 +1,76 @@ +package com.klp.mes.qc.domain; + +import com.baomidou.mybatisplus.annotation.*; +import com.klp.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 质量评审单对象 qc_quality_review + * + * @author klp + * @date 2026-06-30 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("qc_quality_review") +public class QcQualityReview extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** 评审单主键 */ + @TableId(value = "review_id") + private Long reviewId; + + /** 评审单编号 */ + private String reviewNo; + + /** 产品名称 */ + private String productName; + + /** 传递部门 */ + private String transmitDept; + + /** 传递人 */ + private String transmitUser; + + /** 传递日期 */ + private Date transmitDate; + + /** 生产日期范围 */ + private String prodDateRange; + + /** 流程状态:1=待提交 2=待审批 3=已通过 4=已驳回 */ + private Long flowStatus; + + /** 品质部评审意见 */ + private String deptOpinion; + + /** 品质部签字人 */ + private String deptSign; + + /** 品质部签字日期 */ + private Date deptSignDate; + + /** 领导审批意见 */ + private String leaderOpinion; + + /** 领导签字人 */ + private String leaderSign; + + /** 领导签字日期 */ + private Date leaderSignDate; + + /** 驳回原因 */ + private String rejectReason; + + /** 备注 */ + private String remark; + + /** 删除标志(0=正常,1=已删除) */ + @TableLogic + private Integer delFlag; + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/domain/QcQualityReviewCoil.java b/klp-mes/src/main/java/com/klp/mes/qc/domain/QcQualityReviewCoil.java new file mode 100644 index 000000000..cf8f3a68c --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/domain/QcQualityReviewCoil.java @@ -0,0 +1,74 @@ +package com.klp.mes.qc.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; + +/** + * 质量评审钢卷明细对象 qc_quality_review_coil + * + * @author klp + * @date 2026-06-30 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("qc_quality_review_coil") +public class QcQualityReviewCoil extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** 明细主键 */ + @TableId(value = "detail_id") + private Long detailId; + + /** 关联评审单ID */ + private Long reviewId; + + /** 序号 */ + private Integer groupSeq; + + /** 组备注 */ + private String groupRemark; + + /** 钢卷ID */ + private Long coilId; + + /** 产品卷号 */ + private String currentCoilNo; + + /** 原料卷号 */ + private String supplierCoilNo; + + /** 规格 */ + private String spec; + + /** 卷重(t) */ + private BigDecimal netWeight; + + /** 缺陷描述 */ + private String defectDesc; + + /** 改判前质量等级 */ + private String beforeQuality; + + /** 改判后质量状态(字典:regrade_quality_type) */ + private String regradeQuality; + + /** 执行状态:0=待执行 1=已执行 */ + private Long executeStatus; + + /** 执行时间 */ + private Date executeTime; + + /** 备注 */ + private String remark; + + /** 删除标志(0=正常,1=已删除) */ + @TableLogic + private Integer delFlag; + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/domain/QcQualityReviewLog.java b/klp-mes/src/main/java/com/klp/mes/qc/domain/QcQualityReviewLog.java new file mode 100644 index 000000000..5cacdde9a --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/domain/QcQualityReviewLog.java @@ -0,0 +1,45 @@ +package com.klp.mes.qc.domain; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.util.Date; + +/** + * 质量评审审批日志对象 qc_quality_review_log + * + * @author klp + * @date 2026-06-30 + */ +@Data +@TableName("qc_quality_review_log") +public class QcQualityReviewLog { + + private static final long serialVersionUID = 1L; + + /** 日志主键 */ + @TableId(value = "log_id") + private Long logId; + + /** 关联评审单ID */ + private Long reviewId; + + /** 动作:submit=提交 approve=通过 reject=驳回 */ + private String action; + + /** 操作人 */ + private String operator; + + /** 审批意见 */ + private String opinion; + + /** 操作时间 */ + private Date operateTime; + + /** 创建人 */ + private String createBy; + + /** 创建时间 */ + private Date createTime; + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/domain/bo/QcQualityReviewApproveBo.java b/klp-mes/src/main/java/com/klp/mes/qc/domain/bo/QcQualityReviewApproveBo.java new file mode 100644 index 000000000..832fbe36e --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/domain/bo/QcQualityReviewApproveBo.java @@ -0,0 +1,41 @@ +package com.klp.mes.qc.domain.bo; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 质量评审审批参数(领导审批时使用) + * + * @author klp + * @date 2026-06-30 + */ +@Data +public class QcQualityReviewApproveBo { + + /** 评审单ID */ + @NotNull(message = "评审单ID不能为空") + private Long reviewId; + + /** 领导审批意见 */ + private String leaderOpinion; + + /** 领导签字人 */ + private String leaderSign; + + /** 各钢卷的改判状态 */ + private List coilRegradeList; + + @Data + public static class CoilRegradeBo { + /** 明细ID */ + @NotNull(message = "钢卷明细ID不能为空") + private Long detailId; + + /** 改判后质量状态 */ + @NotBlank(message = "改判后质量状态不能为空") + private String regradeQuality; + } +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/domain/bo/QcQualityReviewBo.java b/klp-mes/src/main/java/com/klp/mes/qc/domain/bo/QcQualityReviewBo.java new file mode 100644 index 000000000..ee8d9de63 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/domain/bo/QcQualityReviewBo.java @@ -0,0 +1,85 @@ +package com.klp.mes.qc.domain.bo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.klp.common.core.domain.BaseEntity; +import com.klp.common.core.validate.AddGroup; +import com.klp.common.core.validate.EditGroup; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.List; + +/** + * 质量评审单业务对象 qc_quality_review + * + * @author klp + * @date 2026-06-30 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class QcQualityReviewBo extends BaseEntity { + + /** 评审单主键 */ + @NotNull(message = "主键不能为空", groups = {EditGroup.class}) + private Long reviewId; + + /** 评审单编号 */ + private String reviewNo; + + /** 产品名称 */ + @NotBlank(message = "产品名称不能为空", groups = {AddGroup.class}) + private String productName; + + /** 传递部门 */ + private String transmitDept; + + /** 传递人 */ + private String transmitUser; + + /** 传递日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date transmitDate; + + /** 生产日期范围 */ + private String prodDateRange; + + /** 流程状态 */ + private Long flowStatus; + + /** 品质部评审意见 */ + private String deptOpinion; + + /** 品质部签字人 */ + private String deptSign; + + /** 品质部签字日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date deptSignDate; + + /** 领导审批意见 */ + private String leaderOpinion; + + /** 领导签字人 */ + private String leaderSign; + + /** 领导签字日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date leaderSignDate; + + /** 驳回原因 */ + private String rejectReason; + + /** 备注 */ + private String remark; + + /** 钢卷明细列表 */ + private List coilList; + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/domain/bo/QcQualityReviewCoilBo.java b/klp-mes/src/main/java/com/klp/mes/qc/domain/bo/QcQualityReviewCoilBo.java new file mode 100644 index 000000000..a9c304d05 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/domain/bo/QcQualityReviewCoilBo.java @@ -0,0 +1,67 @@ +package com.klp.mes.qc.domain.bo; + +import com.klp.common.core.domain.BaseEntity; +import com.klp.common.core.validate.AddGroup; +import com.klp.common.core.validate.EditGroup; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + * 质量评审钢卷明细业务对象 qc_quality_review_coil + * + * @author klp + * @date 2026-06-30 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class QcQualityReviewCoilBo extends BaseEntity { + + /** 明细主键 */ + @NotNull(message = "主键不能为空", groups = {EditGroup.class}) + private Long detailId; + + /** 关联评审单ID */ + private Long reviewId; + + /** 序号 */ + private Integer groupSeq; + + /** 组备注 */ + private String groupRemark; + + /** 钢卷ID */ + @NotNull(message = "钢卷不能为空", groups = {AddGroup.class}) + private Long coilId; + + /** 产品卷号 */ + private String currentCoilNo; + + /** 原料卷号 */ + private String supplierCoilNo; + + /** 规格 */ + private String spec; + + /** 卷重(t) */ + private BigDecimal netWeight; + + /** 缺陷描述 */ + private String defectDesc; + + /** 改判前质量等级 */ + private String beforeQuality; + + /** 改判后质量状态 */ + private String regradeQuality; + + /** 执行状态 */ + private Long executeStatus; + + /** 备注 */ + private String remark; + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/domain/vo/QcQualityReviewCoilVo.java b/klp-mes/src/main/java/com/klp/mes/qc/domain/vo/QcQualityReviewCoilVo.java new file mode 100644 index 000000000..21e203f75 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/domain/vo/QcQualityReviewCoilVo.java @@ -0,0 +1,72 @@ +package com.klp.mes.qc.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.klp.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 质量评审钢卷明细视图对象 qc_quality_review_coil + * + * @author klp + * @date 2026-06-30 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class QcQualityReviewCoilVo extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** 明细主键 */ + private Long detailId; + + /** 关联评审单ID */ + private Long reviewId; + + /** 序号 */ + private Integer groupSeq; + + /** 组备注 */ + private String groupRemark; + + /** 钢卷ID */ + private Long coilId; + + /** 产品卷号 */ + private String currentCoilNo; + + /** 原料卷号 */ + private String supplierCoilNo; + + /** 规格 */ + private String spec; + + /** 卷重(t) */ + private BigDecimal netWeight; + + /** 缺陷描述 */ + private String defectDesc; + + /** 改判前质量等级 */ + private String beforeQuality; + + /** 改判后质量状态 */ + private String regradeQuality; + + /** 执行状态 */ + private Long executeStatus; + + /** 执行时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date executeTime; + + /** 备注 */ + private String remark; + + /** 删除标志 */ + private Integer delFlag; + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/domain/vo/QcQualityReviewLogVo.java b/klp-mes/src/main/java/com/klp/mes/qc/domain/vo/QcQualityReviewLogVo.java new file mode 100644 index 000000000..2a510dfac --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/domain/vo/QcQualityReviewLogVo.java @@ -0,0 +1,40 @@ +package com.klp.mes.qc.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + +/** + * 质量评审审批日志视图对象 + * + * @author klp + * @date 2026-06-30 + */ +@Data +public class QcQualityReviewLogVo { + + /** 日志主键 */ + private Long logId; + + /** 关联评审单ID */ + private Long reviewId; + + /** 动作:submit=提交 approve=通过 reject=驳回 */ + private String action; + + /** 操作人 */ + private String operator; + + /** 审批意见 */ + private String opinion; + + /** 操作时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date operateTime; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/domain/vo/QcQualityReviewVo.java b/klp-mes/src/main/java/com/klp/mes/qc/domain/vo/QcQualityReviewVo.java new file mode 100644 index 000000000..1930bc248 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/domain/vo/QcQualityReviewVo.java @@ -0,0 +1,83 @@ +package com.klp.mes.qc.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.klp.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import java.util.List; + +/** + * 质量评审单视图对象 qc_quality_review + * + * @author klp + * @date 2026-06-30 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class QcQualityReviewVo extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** 评审单主键 */ + private Long reviewId; + + /** 评审单编号 */ + private String reviewNo; + + /** 产品名称 */ + private String productName; + + /** 传递部门 */ + private String transmitDept; + + /** 传递人 */ + private String transmitUser; + + /** 传递日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + private Date transmitDate; + + /** 生产日期范围 */ + private String prodDateRange; + + /** 流程状态 */ + private Long flowStatus; + + /** 品质部评审意见 */ + private String deptOpinion; + + /** 品质部签字人 */ + private String deptSign; + + /** 品质部签字日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + private Date deptSignDate; + + /** 领导审批意见 */ + private String leaderOpinion; + + /** 领导签字人 */ + private String leaderSign; + + /** 领导签字日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + private Date leaderSignDate; + + /** 驳回原因 */ + private String rejectReason; + + /** 备注 */ + private String remark; + + /** 删除标志 */ + private Integer delFlag; + + /** 钢卷明细列表 */ + private List coilList; + + /** 审批日志列表 */ + private List logList; + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/mapper/QcQualityReviewCoilMapper.java b/klp-mes/src/main/java/com/klp/mes/qc/mapper/QcQualityReviewCoilMapper.java new file mode 100644 index 000000000..7379eb337 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/mapper/QcQualityReviewCoilMapper.java @@ -0,0 +1,22 @@ +package com.klp.mes.qc.mapper; + +import com.klp.mes.qc.domain.QcQualityReviewCoil; +import com.klp.mes.qc.domain.vo.QcQualityReviewCoilVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import java.util.List; + +/** + * 质量评审钢卷明细Mapper接口 + * + * @author klp + * @date 2026-06-30 + */ +public interface QcQualityReviewCoilMapper extends BaseMapper { + + /** + * 根据评审单ID查询钢卷明细列表 + */ + List selectVoListByReviewId(Long reviewId); + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/mapper/QcQualityReviewLogMapper.java b/klp-mes/src/main/java/com/klp/mes/qc/mapper/QcQualityReviewLogMapper.java new file mode 100644 index 000000000..7fa432069 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/mapper/QcQualityReviewLogMapper.java @@ -0,0 +1,22 @@ +package com.klp.mes.qc.mapper; + +import com.klp.mes.qc.domain.QcQualityReviewLog; +import com.klp.mes.qc.domain.vo.QcQualityReviewLogVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import java.util.List; + +/** + * 质量评审审批日志Mapper接口 + * + * @author klp + * @date 2026-06-30 + */ +public interface QcQualityReviewLogMapper extends BaseMapper { + + /** + * 根据评审单ID查询审批日志列表 + */ + List selectVoListByReviewId(Long reviewId); + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/mapper/QcQualityReviewMapper.java b/klp-mes/src/main/java/com/klp/mes/qc/mapper/QcQualityReviewMapper.java new file mode 100644 index 000000000..87bd77530 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/mapper/QcQualityReviewMapper.java @@ -0,0 +1,35 @@ +package com.klp.mes.qc.mapper; + +import com.klp.mes.qc.domain.QcQualityReview; +import com.klp.mes.qc.domain.vo.QcQualityReviewVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 质量评审单Mapper接口 + * + * @author klp + * @date 2026-06-30 + */ +public interface QcQualityReviewMapper extends BaseMapper { + + /** + * 分页查询评审单列表(含状态字典值) + */ + Page selectVoPage(IPage page, @Param("vo") QcQualityReviewVo vo); + + /** + * 查询评审单详情 + */ + QcQualityReviewVo selectVoById(@Param("reviewId") Long reviewId); + + /** + * 查询评审单列表 + */ + List selectVoList(@Param("vo") QcQualityReviewVo vo); + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/service/IQcQualityReviewService.java b/klp-mes/src/main/java/com/klp/mes/qc/service/IQcQualityReviewService.java new file mode 100644 index 000000000..695348139 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/service/IQcQualityReviewService.java @@ -0,0 +1,82 @@ +package com.klp.mes.qc.service; + +import com.klp.common.core.domain.PageQuery; +import com.klp.common.core.page.TableDataInfo; +import com.klp.mes.qc.domain.bo.QcQualityReviewApproveBo; +import com.klp.mes.qc.domain.bo.QcQualityReviewBo; +import com.klp.mes.qc.domain.vo.QcQualityReviewVo; +import com.klp.mes.qc.domain.vo.QcQualityReviewCoilVo; +import com.klp.mes.qc.domain.vo.QcQualityReviewLogVo; + +import java.util.Collection; +import java.util.List; + +/** + * 质量评审单Service接口 + * + * @author klp + * @date 2026-06-30 + */ +public interface IQcQualityReviewService { + + /** + * 查询评审单详情 + */ + QcQualityReviewVo queryById(Long reviewId); + + /** + * 分页查询评审单列表 + */ + TableDataInfo queryPageList(QcQualityReviewBo bo, PageQuery pageQuery); + + /** + * 查询评审单列表 + */ + List queryList(QcQualityReviewBo bo); + + /** + * 创建评审单 + */ + Boolean insertByBo(QcQualityReviewBo bo); + + /** + * 修改评审单 + */ + Boolean updateByBo(QcQualityReviewBo bo); + + /** + * 批量删除评审单 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 提交送审(flowStatus: 1→2) + */ + Boolean submit(Long reviewId); + + /** + * 审批通过(flowStatus: 2→3) + */ + Boolean approve(QcQualityReviewApproveBo bo); + + /** + * 驳回(flowStatus: 2→4) + */ + Boolean reject(Long reviewId, String reason); + + /** + * 执行改判(写改判记录 + 更新钢卷状态) + */ + Boolean execute(Long reviewId); + + /** + * 查询钢卷明细列表 + */ + List queryCoilListByReviewId(Long reviewId); + + /** + * 查询审批日志列表 + */ + List queryLogListByReviewId(Long reviewId); + +} diff --git a/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java b/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java new file mode 100644 index 000000000..460b9cb61 --- /dev/null +++ b/klp-mes/src/main/java/com/klp/mes/qc/service/impl/QcQualityReviewServiceImpl.java @@ -0,0 +1,389 @@ +package com.klp.mes.qc.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.klp.common.core.domain.PageQuery; +import com.klp.common.core.page.TableDataInfo; +import com.klp.common.utils.StringUtils; +import com.klp.domain.WmsCoilQualityRejudge; +import com.klp.domain.WmsMaterialCoil; +import com.klp.mapper.WmsCoilQualityRejudgeMapper; +import com.klp.mapper.WmsMaterialCoilMapper; +import com.klp.mes.qc.domain.QcQualityReview; +import com.klp.mes.qc.domain.QcQualityReviewCoil; +import com.klp.mes.qc.domain.QcQualityReviewLog; +import com.klp.mes.qc.domain.bo.QcQualityReviewApproveBo; +import com.klp.mes.qc.domain.bo.QcQualityReviewBo; +import com.klp.mes.qc.domain.bo.QcQualityReviewCoilBo; +import com.klp.mes.qc.domain.vo.QcQualityReviewCoilVo; +import com.klp.mes.qc.domain.vo.QcQualityReviewLogVo; +import com.klp.mes.qc.domain.vo.QcQualityReviewVo; +import com.klp.mes.qc.mapper.QcQualityReviewCoilMapper; +import com.klp.mes.qc.mapper.QcQualityReviewLogMapper; +import com.klp.mes.qc.mapper.QcQualityReviewMapper; +import com.klp.mes.qc.service.IQcQualityReviewService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 质量评审单Service业务层处理 + * + * @author klp + * @date 2026-06-30 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class QcQualityReviewServiceImpl implements IQcQualityReviewService { + + private final QcQualityReviewMapper baseMapper; + private final QcQualityReviewCoilMapper coilMapper; + private final QcQualityReviewLogMapper logMapper; + private final WmsMaterialCoilMapper wmsMaterialCoilMapper; + private final WmsCoilQualityRejudgeMapper wmsCoilQualityRejudgeMapper; + + /** + * 查询评审单详情(含钢卷明细和审批日志) + */ + @Override + public QcQualityReviewVo queryById(Long reviewId) { + QcQualityReviewVo vo = baseMapper.selectVoById(reviewId); + if (vo != null) { + vo.setCoilList(coilMapper.selectVoListByReviewId(reviewId)); + vo.setLogList(logMapper.selectVoListByReviewId(reviewId)); + } + return vo; + } + + /** + * 分页查询评审单列表 + */ + @Override + public TableDataInfo queryPageList(QcQualityReviewBo bo, PageQuery pageQuery) { + QcQualityReviewVo queryVo = new QcQualityReviewVo(); + BeanUtil.copyProperties(bo, queryVo); + Page result = baseMapper.selectVoPage(pageQuery.build(), queryVo); + return TableDataInfo.build(result); + } + + /** + * 查询评审单列表 + */ + @Override + public List queryList(QcQualityReviewBo bo) { + QcQualityReviewVo queryVo = new QcQualityReviewVo(); + BeanUtil.copyProperties(bo, queryVo); + return baseMapper.selectVoList(queryVo); + } + + /** + * 创建评审单(草稿状态) + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insertByBo(QcQualityReviewBo bo) { + // 1. 保存主表 + QcQualityReview add = BeanUtil.toBean(bo, QcQualityReview.class); + // 设置默认值 + add.setFlowStatus(1L); // 1=待提交 + add.setReviewNo(generateReviewNo()); + if (StringUtils.isBlank(add.getTransmitDept())) { + add.setTransmitDept("品质部"); + } + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setReviewId(add.getReviewId()); + // 2. 保存钢卷明细 + if (CollUtil.isNotEmpty(bo.getCoilList())) { + saveCoilList(add.getReviewId(), bo.getCoilList()); + } + } + return flag; + } + + /** + * 修改评审单(仅草稿状态可修改) + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateByBo(QcQualityReviewBo bo) { + QcQualityReview update = BeanUtil.toBean(bo, QcQualityReview.class); + validEntityBeforeSave(update); + boolean flag = baseMapper.updateById(update) > 0; + if (flag) { + // 先删除原有明细,再重新插入 + coilMapper.delete(Wrappers.lambdaQuery() + .eq(QcQualityReviewCoil::getReviewId, bo.getReviewId())); + if (CollUtil.isNotEmpty(bo.getCoilList())) { + saveCoilList(bo.getReviewId(), bo.getCoilList()); + } + } + return flag; + } + + /** + * 批量删除评审单 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if (isValid) { + // 校验:只能删除待提交状态的 + for (Long id : ids) { + QcQualityReview review = baseMapper.selectById(id); + if (review != null && !Long.valueOf(1L).equals(review.getFlowStatus())) { + throw new RuntimeException("评审单【" + review.getReviewNo() + "】不是待提交状态,无法删除"); + } + } + } + // 级联删除钢卷明细 + coilMapper.delete(Wrappers.lambdaQuery() + .in(QcQualityReviewCoil::getReviewId, ids)); + // 删除审批日志 + logMapper.delete(Wrappers.lambdaQuery() + .in(QcQualityReviewLog::getReviewId, ids)); + // 删除主表 + return baseMapper.deleteBatchIds(ids) > 0; + } + + // ==================== 业务操作 ==================== + + /** + * 提交送审(允许待提交→待审批,已驳回→待审批) + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean submit(Long reviewId) { + QcQualityReview review = baseMapper.selectById(reviewId); + if (review == null) { + throw new RuntimeException("评审单不存在"); + } + Long status = review.getFlowStatus(); + if (!Long.valueOf(1L).equals(status) && !Long.valueOf(4L).equals(status)) { + throw new RuntimeException("当前状态不允许送审"); + } + // 校验:必须有品质部意见 + if (StringUtils.isBlank(review.getDeptOpinion())) { + throw new RuntimeException("请先填写品质部评审意见"); + } + // 校验:至少有一个钢卷 + Long coilCount = coilMapper.selectCount( + Wrappers.lambdaQuery() + .eq(QcQualityReviewCoil::getReviewId, reviewId) + .eq(QcQualityReviewCoil::getDelFlag, 0)); + if (coilCount == null || coilCount == 0) { + throw new RuntimeException("请至少添加一个钢卷"); + } + + // 更新流程状态为待审批,清除驳回原因 + baseMapper.update(null, Wrappers.lambdaUpdate() + .eq(QcQualityReview::getReviewId, reviewId) + .set(QcQualityReview::getFlowStatus, 2L) + .set(QcQualityReview::getRejectReason, null)); + + // 记录审批日志 + addLog(reviewId, "submit", "提交送审", null); + return true; + } + + /** + * 审批通过 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean approve(QcQualityReviewApproveBo bo) { + QcQualityReview review = baseMapper.selectById(bo.getReviewId()); + if (review == null) { + throw new RuntimeException("评审单不存在"); + } + if (!Long.valueOf(2L).equals(review.getFlowStatus())) { + throw new RuntimeException("只有待审批状态的评审单才能审批"); + } + if (CollUtil.isEmpty(bo.getCoilRegradeList())) { + throw new RuntimeException("请为每个钢卷指定改判后质量状态"); + } + + // 1. 更新主表流程状态 + baseMapper.update(null, Wrappers.lambdaUpdate() + .eq(QcQualityReview::getReviewId, bo.getReviewId()) + .set(QcQualityReview::getFlowStatus, 3L) + .set(QcQualityReview::getLeaderOpinion, bo.getLeaderOpinion()) + .set(QcQualityReview::getLeaderSign, bo.getLeaderSign()) + .set(QcQualityReview::getLeaderSignDate, new java.sql.Date(System.currentTimeMillis()))); + + // 2. 更新每个钢卷的改判状态 + for (QcQualityReviewApproveBo.CoilRegradeBo regrade : bo.getCoilRegradeList()) { + coilMapper.update(null, Wrappers.lambdaUpdate() + .eq(QcQualityReviewCoil::getDetailId, regrade.getDetailId()) + .set(QcQualityReviewCoil::getRegradeQuality, regrade.getRegradeQuality())); + } + + // 3. 记录审批日志 + addLog(bo.getReviewId(), "approve", bo.getLeaderOpinion(), bo.getLeaderSign()); + return true; + } + + /** + * 驳回 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean reject(Long reviewId, String reason) { + QcQualityReview review = baseMapper.selectById(reviewId); + if (review == null) { + throw new RuntimeException("评审单不存在"); + } + if (!Long.valueOf(2L).equals(review.getFlowStatus())) { + throw new RuntimeException("只有待审批状态的评审单才能驳回"); + } + if (StringUtils.isBlank(reason)) { + throw new RuntimeException("请填写驳回原因"); + } + + // 更新流程状态为已驳回 + baseMapper.update(null, Wrappers.lambdaUpdate() + .eq(QcQualityReview::getReviewId, reviewId) + .set(QcQualityReview::getFlowStatus, 4L) + .set(QcQualityReview::getRejectReason, reason)); + + // 记录审批日志 + addLog(reviewId, "reject", reason, null); + return true; + } + + /** + * 执行改判 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean execute(Long reviewId) { + QcQualityReview review = baseMapper.selectById(reviewId); + if (review == null) { + throw new RuntimeException("评审单不存在"); + } + if (!Long.valueOf(3L).equals(review.getFlowStatus())) { + throw new RuntimeException("只有已通过的评审单才能执行改判"); + } + + // 查询待执行的钢卷明细 + List coilList = coilMapper.selectList( + Wrappers.lambdaQuery() + .eq(QcQualityReviewCoil::getReviewId, reviewId) + .eq(QcQualityReviewCoil::getDelFlag, 0) + .eq(QcQualityReviewCoil::getExecuteStatus, 0)); + + if (CollUtil.isEmpty(coilList)) { + throw new RuntimeException("没有待执行的钢卷"); + } + + Date now = new Date(); + for (QcQualityReviewCoil coil : coilList) { + // 1. 写入 wms_coil_quality_rejudge 改判记录 + WmsCoilQualityRejudge rejudge = new WmsCoilQualityRejudge(); + rejudge.setCoilId(coil.getCoilId()); + rejudge.setBeforeQuality(coil.getBeforeQuality()); + rejudge.setAfterQuality(coil.getRegradeQuality()); + rejudge.setRejudgeReason("异常产品评审改判,评审单号:" + review.getReviewNo()); + wmsCoilQualityRejudgeMapper.insert(rejudge); + + // 2. 更新钢卷的 qualityStatus 为改判后的值 + if (coil.getCoilId() != null && StringUtils.isNotBlank(coil.getRegradeQuality())) { + wmsMaterialCoilMapper.update(null, Wrappers.lambdaUpdate() + .eq(WmsMaterialCoil::getCoilId, coil.getCoilId()) + .set(WmsMaterialCoil::getQualityStatus, coil.getRegradeQuality())); + } + + // 3. 更新明细执行状态 + coilMapper.update(null, Wrappers.lambdaUpdate() + .eq(QcQualityReviewCoil::getDetailId, coil.getDetailId()) + .set(QcQualityReviewCoil::getExecuteStatus, 1L) + .set(QcQualityReviewCoil::getExecuteTime, now)); + } + + return true; + } + + // ==================== 查询方法 ==================== + + @Override + public List queryCoilListByReviewId(Long reviewId) { + return coilMapper.selectVoListByReviewId(reviewId); + } + + @Override + public List queryLogListByReviewId(Long reviewId) { + return logMapper.selectVoListByReviewId(reviewId); + } + + // ==================== 私有方法 ==================== + + /** + * 保存钢卷明细列表 + */ + private void saveCoilList(Long reviewId, List coilBoList) { + int seq = 1; + for (QcQualityReviewCoilBo coilBo : coilBoList) { + QcQualityReviewCoil coil = BeanUtil.toBean(coilBo, QcQualityReviewCoil.class); + coil.setReviewId(reviewId); + coil.setExecuteStatus(0L); + if (coil.getGroupSeq() == null) { + coil.setGroupSeq(seq); + } + // 若未传改判前质量等级,从钢卷表获取 + if (StringUtils.isBlank(coil.getBeforeQuality()) && coil.getCoilId() != null) { + WmsMaterialCoil wmsCoil = wmsMaterialCoilMapper.selectById(coil.getCoilId()); + if (wmsCoil != null) { + coil.setBeforeQuality(wmsCoil.getQualityStatus()); + if (StringUtils.isBlank(coil.getCurrentCoilNo())) { + coil.setCurrentCoilNo(wmsCoil.getCurrentCoilNo()); + } + if (StringUtils.isBlank(coil.getSupplierCoilNo())) { + coil.setSupplierCoilNo(wmsCoil.getSupplierCoilNo()); + } + if (coil.getNetWeight() == null) { + coil.setNetWeight(wmsCoil.getNetWeight()); + } + } + } + coilMapper.insert(coil); + seq++; + } + } + + /** + * 添加审批日志 + */ + private void addLog(Long reviewId, String action, String opinion, String operator) { + QcQualityReviewLog log = new QcQualityReviewLog(); + log.setReviewId(reviewId); + log.setAction(action); + log.setOpinion(opinion); + log.setOperator(operator); + log.setOperateTime(new Date()); + logMapper.insert(log); + } + + /** + * 生成评审单编号: QR-20260630-0001 + */ + private String generateReviewNo() { + String dateStr = DateUtil.format(new Date(), "yyyyMMdd"); + Long count = baseMapper.selectCount(Wrappers.lambdaQuery() + .likeRight(QcQualityReview::getReviewNo, "QR-" + dateStr)); + return "QR-" + dateStr + "-" + String.format("%04d", count + 1); + } + + private void validEntityBeforeSave(QcQualityReview entity) { + // TODO 数据校验 + } +} diff --git a/klp-mes/src/main/resources/mapper/qc/QcQualityReviewCoilMapper.xml b/klp-mes/src/main/resources/mapper/qc/QcQualityReviewCoilMapper.xml new file mode 100644 index 000000000..b22759e1b --- /dev/null +++ b/klp-mes/src/main/resources/mapper/qc/QcQualityReviewCoilMapper.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/klp-mes/src/main/resources/mapper/qc/QcQualityReviewLogMapper.xml b/klp-mes/src/main/resources/mapper/qc/QcQualityReviewLogMapper.xml new file mode 100644 index 000000000..e78c65040 --- /dev/null +++ b/klp-mes/src/main/resources/mapper/qc/QcQualityReviewLogMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/klp-mes/src/main/resources/mapper/qc/QcQualityReviewMapper.xml b/klp-mes/src/main/resources/mapper/qc/QcQualityReviewMapper.xml new file mode 100644 index 000000000..3ed4a68df --- /dev/null +++ b/klp-mes/src/main/resources/mapper/qc/QcQualityReviewMapper.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/klp-system/src/main/java/com/klp/system/domain/SysFile.java b/klp-system/src/main/java/com/klp/system/domain/SysFile.java new file mode 100644 index 000000000..708877aec --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/domain/SysFile.java @@ -0,0 +1,69 @@ +package com.klp.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import com.klp.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + + +/** + * 文件主信息对象 sys_file + * + * @author klp + * @date 2026-06-30 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sys_file") +public class SysFile extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * 主键ID + */ + @TableId(value = "file_id") + private Long fileId; + /** + * 文件原始名称 + */ + private String fileName; + /** + * 文件存储路径/对象存储地址 + */ + private String filePath; + /** + * 文件大小(字节) + */ + private Long fileSize; + /** + * 文件后缀 pdf/xlsx/docx + */ + private String suffix; + /** + * 绑定订单编号 + */ + private String orderNo; + /** + * 所属部门 + */ + private String dept; + /** + * 文件类型字典值(制度文件/财务文件等,字典维护) + */ + private String fileType; + /** + * 可见范围类型 1公开 2私有 + */ + private Long scopeType; + /** + * 备注 + */ + private String remark; + /** + * 删除标识 0正常 2删除 + */ + @TableLogic + private Long delFlag; + +} diff --git a/klp-system/src/main/java/com/klp/system/domain/SysFileVisibleUser.java b/klp-system/src/main/java/com/klp/system/domain/SysFileVisibleUser.java new file mode 100644 index 000000000..7e83916b7 --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/domain/SysFileVisibleUser.java @@ -0,0 +1,45 @@ +package com.klp.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import com.klp.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + + +/** + * 私有文件可见用户多对多关联对象 sys_file_visible_user + * + * @author klp + * @date 2026-06-30 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sys_file_visible_user") +public class SysFileVisibleUser extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * 主键ID + */ + @TableId(value = "visible_id") + private Long visibleId; + /** + * 文件ID 关联sys_file.file_id + */ + private Long fileId; + /** + * 用户ID 关联sys_user.user_id + */ + private Long userId; + /** + * 备注 + */ + private String remark; + /** + * 删除标识 0正常 2删除 + */ + @TableLogic + private Long delFlag; + +} diff --git a/klp-system/src/main/java/com/klp/system/domain/bo/SysFileBo.java b/klp-system/src/main/java/com/klp/system/domain/bo/SysFileBo.java new file mode 100644 index 000000000..4d84f2d1e --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/domain/bo/SysFileBo.java @@ -0,0 +1,71 @@ +package com.klp.system.domain.bo; + +import com.klp.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; +import javax.validation.constraints.*; + + +/** + * 文件主信息业务对象 sys_file + * + * @author klp + * @date 2026-06-30 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class SysFileBo extends BaseEntity { + + /** + * 主键ID + */ + private Long fileId; + + /** + * 文件原始名称 + */ + private String fileName; + + /** + * 文件存储路径/对象存储地址 + */ + private String filePath; + + /** + * 文件大小(字节) + */ + private Long fileSize; + + /** + * 文件后缀 pdf/xlsx/docx + */ + private String suffix; + + /** + * 绑定订单编号 + */ + private String orderNo; + + /** + * 所属部门 + */ + private String dept; + + /** + * 文件类型字典值(制度文件/财务文件等,字典维护) + */ + private String fileType; + + /** + * 可见范围类型 1公开 2私有 + */ + private Long scopeType; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/klp-system/src/main/java/com/klp/system/domain/bo/SysFileVisibleUserBo.java b/klp-system/src/main/java/com/klp/system/domain/bo/SysFileVisibleUserBo.java new file mode 100644 index 000000000..b17d7d981 --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/domain/bo/SysFileVisibleUserBo.java @@ -0,0 +1,41 @@ +package com.klp.system.domain.bo; + +import com.klp.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; +import javax.validation.constraints.*; + + +/** + * 私有文件可见用户多对多关联业务对象 sys_file_visible_user + * + * @author klp + * @date 2026-06-30 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class SysFileVisibleUserBo extends BaseEntity { + + /** + * 主键ID + */ + private Long visibleId; + + /** + * 文件ID 关联sys_file.file_id + */ + private Long fileId; + + /** + * 用户ID 关联sys_user.user_id + */ + private Long userId; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/klp-system/src/main/java/com/klp/system/domain/vo/SysFileVisibleUserVo.java b/klp-system/src/main/java/com/klp/system/domain/vo/SysFileVisibleUserVo.java new file mode 100644 index 000000000..588ed4c45 --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/domain/vo/SysFileVisibleUserVo.java @@ -0,0 +1,47 @@ +package com.klp.system.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; + + +/** + * 私有文件可见用户多对多关联视图对象 sys_file_visible_user + * + * @author klp + * @date 2026-06-30 + */ +@Data +@ExcelIgnoreUnannotated +public class SysFileVisibleUserVo { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ExcelProperty(value = "主键ID") + private Long visibleId; + + /** + * 文件ID 关联sys_file.file_id + */ + @ExcelProperty(value = "文件ID 关联sys_file.file_id") + private Long fileId; + + /** + * 用户ID 关联sys_user.user_id + */ + @ExcelProperty(value = "用户ID 关联sys_user.user_id") + private Long userId; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + +} diff --git a/klp-system/src/main/java/com/klp/system/domain/vo/SysFileVo.java b/klp-system/src/main/java/com/klp/system/domain/vo/SysFileVo.java new file mode 100644 index 000000000..a9075d43c --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/domain/vo/SysFileVo.java @@ -0,0 +1,84 @@ +package com.klp.system.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 com.klp.common.core.domain.BaseEntity; +import lombok.Data; + + +/** + * 文件主信息视图对象 sys_file + * + * @author klp + * @date 2026-06-30 + */ +@Data +@ExcelIgnoreUnannotated +public class SysFileVo extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ExcelProperty(value = "主键ID") + private Long fileId; + + /** + * 文件原始名称 + */ + @ExcelProperty(value = "文件原始名称") + private String fileName; + + /** + * 文件存储路径/对象存储地址 + */ + @ExcelProperty(value = "文件存储路径/对象存储地址") + private String filePath; + + /** + * 文件大小(字节) + */ + @ExcelProperty(value = "文件大小(字节)") + private Long fileSize; + + /** + * 文件后缀 pdf/xlsx/docx + */ + @ExcelProperty(value = "文件后缀 pdf/xlsx/docx") + private String suffix; + + /** + * 绑定订单编号 + */ + @ExcelProperty(value = "绑定订单编号") + private String orderNo; + + /** + * 所属部门 + */ + @ExcelProperty(value = "所属部门") + private String dept; + + /** + * 文件类型字典值(制度文件/财务文件等,字典维护) + */ + @ExcelProperty(value = "文件类型字典值(制度文件/财务文件等,字典维护)") + private String fileType; + + /** + * 可见范围类型 1公开 2私有 + */ + @ExcelProperty(value = "可见范围类型 1公开 2私有") + private Long scopeType; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + +} diff --git a/klp-system/src/main/java/com/klp/system/mapper/SysFileMapper.java b/klp-system/src/main/java/com/klp/system/mapper/SysFileMapper.java new file mode 100644 index 000000000..782d95d8b --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/mapper/SysFileMapper.java @@ -0,0 +1,15 @@ +package com.klp.system.mapper; + +import com.klp.system.domain.SysFile; +import com.klp.system.domain.vo.SysFileVo; +import com.klp.common.core.mapper.BaseMapperPlus; + +/** + * 文件主信息Mapper接口 + * + * @author klp + * @date 2026-06-30 + */ +public interface SysFileMapper extends BaseMapperPlus { + +} diff --git a/klp-system/src/main/java/com/klp/system/mapper/SysFileVisibleUserMapper.java b/klp-system/src/main/java/com/klp/system/mapper/SysFileVisibleUserMapper.java new file mode 100644 index 000000000..617dd1c14 --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/mapper/SysFileVisibleUserMapper.java @@ -0,0 +1,15 @@ +package com.klp.system.mapper; + +import com.klp.system.domain.SysFileVisibleUser; +import com.klp.system.domain.vo.SysFileVisibleUserVo; +import com.klp.common.core.mapper.BaseMapperPlus; + +/** + * 私有文件可见用户多对多关联Mapper接口 + * + * @author klp + * @date 2026-06-30 + */ +public interface SysFileVisibleUserMapper extends BaseMapperPlus { + +} diff --git a/klp-system/src/main/java/com/klp/system/service/ISysFileService.java b/klp-system/src/main/java/com/klp/system/service/ISysFileService.java new file mode 100644 index 000000000..1cd0a32da --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/service/ISysFileService.java @@ -0,0 +1,54 @@ +package com.klp.system.service; + +import com.klp.system.domain.SysFile; +import com.klp.system.domain.vo.SysFileVo; +import com.klp.system.domain.bo.SysFileBo; +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-06-30 + */ +public interface ISysFileService { + + /** + * 查询文件主信息 + */ + SysFileVo queryById(Long fileId); + + /** + * 查询文件主信息列表 + */ + TableDataInfo queryPageList(SysFileBo bo, PageQuery pageQuery); + + /** + * 查询文件主信息列表 + */ + List queryList(SysFileBo bo); + + /** + * 新增文件主信息 + */ + Boolean insertByBo(SysFileBo bo); + + /** + * 修改文件主信息 + */ + Boolean updateByBo(SysFileBo bo); + + /** + * 校验并批量删除文件主信息信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 查询与我相关的文件(私有文件且当前用户在可见用户列表中) + */ + TableDataInfo queryPageListRelatedToMe(SysFileBo bo, PageQuery pageQuery); +} diff --git a/klp-system/src/main/java/com/klp/system/service/ISysFileVisibleUserService.java b/klp-system/src/main/java/com/klp/system/service/ISysFileVisibleUserService.java new file mode 100644 index 000000000..2b77658d6 --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/service/ISysFileVisibleUserService.java @@ -0,0 +1,49 @@ +package com.klp.system.service; + +import com.klp.system.domain.SysFileVisibleUser; +import com.klp.system.domain.vo.SysFileVisibleUserVo; +import com.klp.system.domain.bo.SysFileVisibleUserBo; +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-06-30 + */ +public interface ISysFileVisibleUserService { + + /** + * 查询私有文件可见用户多对多关联 + */ + SysFileVisibleUserVo queryById(Long visibleId); + + /** + * 查询私有文件可见用户多对多关联列表 + */ + TableDataInfo queryPageList(SysFileVisibleUserBo bo, PageQuery pageQuery); + + /** + * 查询私有文件可见用户多对多关联列表 + */ + List queryList(SysFileVisibleUserBo bo); + + /** + * 新增私有文件可见用户多对多关联 + */ + Boolean insertByBo(SysFileVisibleUserBo bo); + + /** + * 修改私有文件可见用户多对多关联 + */ + Boolean updateByBo(SysFileVisibleUserBo bo); + + /** + * 校验并批量删除私有文件可见用户多对多关联信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/klp-system/src/main/java/com/klp/system/service/impl/SysFileServiceImpl.java b/klp-system/src/main/java/com/klp/system/service/impl/SysFileServiceImpl.java new file mode 100644 index 000000000..b06095d64 --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/service/impl/SysFileServiceImpl.java @@ -0,0 +1,144 @@ +package com.klp.system.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.helper.LoginHelper; +import com.klp.common.utils.StringUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import com.klp.system.domain.bo.SysFileBo; +import com.klp.system.domain.vo.SysFileVo; +import com.klp.system.domain.SysFile; +import com.klp.system.domain.SysFileVisibleUser; +import com.klp.system.mapper.SysFileMapper; +import com.klp.system.mapper.SysFileVisibleUserMapper; +import com.klp.system.service.ISysFileService; + +import java.util.List; +import java.util.Map; +import java.util.Collection; +import java.util.stream.Collectors; + +/** + * 文件主信息Service业务层处理 + * + * @author klp + * @date 2026-06-30 + */ +@RequiredArgsConstructor +@Service +public class SysFileServiceImpl implements ISysFileService { + + private final SysFileMapper baseMapper; + private final SysFileVisibleUserMapper visibleUserMapper; + + /** + * 查询文件主信息 + */ + @Override + public SysFileVo queryById(Long fileId){ + return baseMapper.selectVoById(fileId); + } + + /** + * 查询文件主信息列表 + */ + @Override + public TableDataInfo queryPageList(SysFileBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询文件主信息列表 + */ + @Override + public List queryList(SysFileBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysFileBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getFileName()), SysFile::getFileName, bo.getFileName()); + lqw.eq(StringUtils.isNotBlank(bo.getFilePath()), SysFile::getFilePath, bo.getFilePath()); + lqw.eq(bo.getFileSize() != null, SysFile::getFileSize, bo.getFileSize()); + lqw.eq(StringUtils.isNotBlank(bo.getSuffix()), SysFile::getSuffix, bo.getSuffix()); + lqw.eq(StringUtils.isNotBlank(bo.getOrderNo()), SysFile::getOrderNo, bo.getOrderNo()); + lqw.eq(StringUtils.isNotBlank(bo.getDept()), SysFile::getDept, bo.getDept()); + lqw.eq(StringUtils.isNotBlank(bo.getFileType()), SysFile::getFileType, bo.getFileType()); + lqw.eq(bo.getScopeType() != null, SysFile::getScopeType, bo.getScopeType()); + lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), SysFile::getCreateBy, bo.getCreateBy()); + return lqw; + } + + /** + * 新增文件主信息 + */ + @Override + public Boolean insertByBo(SysFileBo bo) { + SysFile add = BeanUtil.toBean(bo, SysFile.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setFileId(add.getFileId()); + } + return flag; + } + + /** + * 修改文件主信息 + */ + @Override + public Boolean updateByBo(SysFileBo bo) { + SysFile update = BeanUtil.toBean(bo, SysFile.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 查询与我相关的文件(私有文件且当前用户在可见用户列表中) + */ + @Override + public TableDataInfo queryPageListRelatedToMe(SysFileBo bo, PageQuery pageQuery) { + Long currentUserId = LoginHelper.getUserId(); + // 查询当前用户可见的私有文件ID列表 + LambdaQueryWrapper vuLqw = Wrappers.lambdaQuery(); + vuLqw.eq(SysFileVisibleUser::getUserId, currentUserId); + List visibleList = visibleUserMapper.selectList(vuLqw); + List fileIds = visibleList.stream().map(SysFileVisibleUser::getFileId).distinct().collect(Collectors.toList()); + + if (fileIds.isEmpty()) { + return TableDataInfo.build(new Page<>()); + } + + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + lqw.in(SysFile::getFileId, fileIds); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(SysFile entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除文件主信息 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } +} diff --git a/klp-system/src/main/java/com/klp/system/service/impl/SysFileVisibleUserServiceImpl.java b/klp-system/src/main/java/com/klp/system/service/impl/SysFileVisibleUserServiceImpl.java new file mode 100644 index 000000000..3559be2af --- /dev/null +++ b/klp-system/src/main/java/com/klp/system/service/impl/SysFileVisibleUserServiceImpl.java @@ -0,0 +1,109 @@ +package com.klp.system.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.system.domain.bo.SysFileVisibleUserBo; +import com.klp.system.domain.vo.SysFileVisibleUserVo; +import com.klp.system.domain.SysFileVisibleUser; +import com.klp.system.mapper.SysFileVisibleUserMapper; +import com.klp.system.service.ISysFileVisibleUserService; + +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 私有文件可见用户多对多关联Service业务层处理 + * + * @author klp + * @date 2026-06-30 + */ +@RequiredArgsConstructor +@Service +public class SysFileVisibleUserServiceImpl implements ISysFileVisibleUserService { + + private final SysFileVisibleUserMapper baseMapper; + + /** + * 查询私有文件可见用户多对多关联 + */ + @Override + public SysFileVisibleUserVo queryById(Long visibleId){ + return baseMapper.selectVoById(visibleId); + } + + /** + * 查询私有文件可见用户多对多关联列表 + */ + @Override + public TableDataInfo queryPageList(SysFileVisibleUserBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询私有文件可见用户多对多关联列表 + */ + @Override + public List queryList(SysFileVisibleUserBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysFileVisibleUserBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(bo.getFileId() != null, SysFileVisibleUser::getFileId, bo.getFileId()); + lqw.eq(bo.getUserId() != null, SysFileVisibleUser::getUserId, bo.getUserId()); + return lqw; + } + + /** + * 新增私有文件可见用户多对多关联 + */ + @Override + public Boolean insertByBo(SysFileVisibleUserBo bo) { + SysFileVisibleUser add = BeanUtil.toBean(bo, SysFileVisibleUser.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setVisibleId(add.getVisibleId()); + } + return flag; + } + + /** + * 修改私有文件可见用户多对多关联 + */ + @Override + public Boolean updateByBo(SysFileVisibleUserBo bo) { + SysFileVisibleUser update = BeanUtil.toBean(bo, SysFileVisibleUser.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(SysFileVisibleUser entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除私有文件可见用户多对多关联 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } +} diff --git a/klp-system/src/main/resources/mapper/system/SysFileMapper.xml b/klp-system/src/main/resources/mapper/system/SysFileMapper.xml new file mode 100644 index 000000000..809b1c040 --- /dev/null +++ b/klp-system/src/main/resources/mapper/system/SysFileMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/klp-system/src/main/resources/mapper/system/SysFileVisibleUserMapper.xml b/klp-system/src/main/resources/mapper/system/SysFileVisibleUserMapper.xml new file mode 100644 index 000000000..747ac9be1 --- /dev/null +++ b/klp-system/src/main/resources/mapper/system/SysFileVisibleUserMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/klp-ui/src/api/aps/materialCoil.js b/klp-ui/src/api/aps/materialCoil.js new file mode 100644 index 000000000..68330647d --- /dev/null +++ b/klp-ui/src/api/aps/materialCoil.js @@ -0,0 +1,10 @@ +import request from '@/utils/request' + +// 查询钢卷物料列表 +export function listMaterialCoil(query) { + return request({ + url: '/wms/materialCoil/list', + method: 'get', + params: query + }) +} diff --git a/klp-ui/src/api/crm/coil.js b/klp-ui/src/api/crm/coil.js new file mode 100644 index 000000000..2763424c6 --- /dev/null +++ b/klp-ui/src/api/crm/coil.js @@ -0,0 +1,83 @@ +import request from '@/utils/request' + +// ==================== 配卷列表查询 ==================== + +// 指定客户的发货配卷列表 +export function listDeliveryCoilsByCustomer(customerId) { + return request({ + url: '/crm/orderItem/coils/customer/' + customerId, + method: 'get' + }) +} + +// 指定合同的发货配卷列表(分页) +export function listDeliveryCoilsByOrder(orderId, query) { + return request({ + url: `/crm/orderItem/coils/order/${orderId}`, + method: 'get', + params: query + }) +} + +// 指定销售员的发货配卷列表(分页) +export function listDeliveryCoilsByPrincipal(query) { + return request({ + url: '/wms/deliveryWaybillDetail/coilListByPrincipal', + method: 'get', + params: query + }) +} + +// 指定销售员的生产成果列表(分页) +export function listProductCoilsBySalesman(query) { + return request({ + url: '/crm/orderItem/coils/bySalesman', + method: 'get', + params: query + }) +} + +// 指定合同的生产成果列表(分页) +export function listProductCoilsByContract(contractId, query) { + return request({ + url: `/crm/orderItem/coils/byContract/${contractId}`, + method: 'get', + params: query + }) +} + +// ==================== 配卷统计汇总 ==================== + +// 根据订单ID统计发货配卷汇总 +export function getDeliveryCoilsStatisticsByOrder(orderId) { + return request({ + url: `/crm/orderItem/coils/order/${orderId}/statistics`, + method: 'get' + }) +} + +// 根据销售员统计生产成果汇总 +export function getProductCoilsStatisticsBySalesman(salesman) { + return request({ + url: '/crm/orderItem/coils/bySalesman/statistics', + method: 'get', + params: { salesman } + }) +} + +// 根据合同ID统计生产成果汇总 +export function getProductCoilsStatisticsByContract(contractId) { + return request({ + url: `/crm/orderItem/coils/byContract/${contractId}/statistics`, + method: 'get' + }) +} + +// 根据负责人统计发货配卷汇总 +export function getDeliveryCoilsStatisticsByPrincipal(principal) { + return request({ + url: '/wms/deliveryWaybillDetail/coilListByPrincipal/statistics', + method: 'get', + params: { principal } + }) +} diff --git a/klp-ui/src/api/crm/order.js b/klp-ui/src/api/crm/order.js index 5e80b519a..6f151bae5 100644 --- a/klp-ui/src/api/crm/order.js +++ b/klp-ui/src/api/crm/order.js @@ -44,12 +44,13 @@ export function delOrder(orderId) { } /** - * 查询该订单下的所有配卷 + * 查询该订单下的配卷(分页) */ -export function listOrderPackaging(orderId) { +export function listOrderPackaging(orderId, query) { return request({ url: `/crm/orderItem/coils/order/${orderId}`, method: 'get', + params: query }) } diff --git a/klp-ui/src/api/hrm/index.js b/klp-ui/src/api/hrm/index.js index f45bf7542..582a0c769 100644 --- a/klp-ui/src/api/hrm/index.js +++ b/klp-ui/src/api/hrm/index.js @@ -1,4 +1,3 @@ -// 导出所有 HRM 模块 API export * from './employee' export * from './org' export * from './certContract' diff --git a/klp-ui/src/api/mes/qc/qualityReview.js b/klp-ui/src/api/mes/qc/qualityReview.js new file mode 100644 index 000000000..8f7667686 --- /dev/null +++ b/klp-ui/src/api/mes/qc/qualityReview.js @@ -0,0 +1,94 @@ +import request from '@/utils/request' + +// 查询质量评审单列表 +export function listQualityReview(query) { + return request({ + url: '/qc/qualityReview/list', + method: 'get', + params: query + }) +} + +// 查询质量评审单详细 +export function getQualityReview(reviewId) { + return request({ + url: '/qc/qualityReview/' + reviewId, + method: 'get' + }) +} + +// 新增质量评审单 +export function addQualityReview(data) { + return request({ + url: '/qc/qualityReview', + method: 'post', + data: data + }) +} + +// 修改质量评审单 +export function updateQualityReview(data) { + return request({ + url: '/qc/qualityReview', + method: 'put', + data: data + }) +} + +// 删除质量评审单 +export function delQualityReview(reviewIds) { + return request({ + url: '/qc/qualityReview/' + reviewIds, + method: 'delete' + }) +} + +// 提交送审 +export function submitQualityReview(reviewId) { + return request({ + url: '/qc/qualityReview/submit/' + reviewId, + method: 'post' + }) +} + +// 审批通过 +export function approveQualityReview(data) { + return request({ + url: '/qc/qualityReview/approve', + method: 'post', + data: data + }) +} + +// 驳回 +export function rejectQualityReview(reviewId, reason) { + return request({ + url: '/qc/qualityReview/reject/' + reviewId, + method: 'post', + params: { reason } + }) +} + +// 执行改判 +export function executeQualityReview(reviewId) { + return request({ + url: '/qc/qualityReview/execute/' + reviewId, + method: 'post' + }) +} + +// 查询钢卷明细 +export function listQualityReviewCoil(reviewId) { + return request({ + url: '/qc/qualityReview/coilList/' + reviewId, + method: 'get' + }) +} + +// 查询审批日志 +export function listQualityReviewLog(reviewId) { + return request({ + url: '/qc/qualityReview/logList/' + reviewId, + method: 'get' + }) +} diff --git a/klp-ui/src/api/system/file.js b/klp-ui/src/api/system/file.js new file mode 100644 index 000000000..c184ddda3 --- /dev/null +++ b/klp-ui/src/api/system/file.js @@ -0,0 +1,99 @@ +import request from '@/utils/request' + +// 查询文件列表 +export function listFile(query) { + return request({ + url: '/system/file/list', + method: 'get', + params: query + }) +} + +// 查询文件详细 +export function getFile(fileId) { + return request({ + url: '/system/file/' + fileId, + method: 'get' + }) +} + +// 新增文件 +export function addFile(data) { + return request({ + url: '/system/file', + method: 'post', + data: data + }) +} + +// 修改文件 +export function updateFile(data) { + return request({ + url: '/system/file', + method: 'put', + data: data + }) +} + +// 删除文件 +export function delFile(fileIds) { + return request({ + url: '/system/file/' + fileIds, + method: 'delete' + }) +} + +// 导出文件列表 +export function exportFile(query) { + return request({ + url: '/system/file/export', + method: 'post', + params: query + }) +} + +// 查询与我相关的文件 +export function listRelatedToMe(query) { + return request({ + url: '/system/file/relatedToMe', + method: 'get', + params: query + }) +} + +// ============ 文件可见用户关联 ============ + +// 查询可见用户列表 +export function listVisibleUser(query) { + return request({ + url: '/system/fileVisibleUser/list', + method: 'get', + params: query + }) +} + +// 新增可见用户关联 +export function addVisibleUser(data) { + return request({ + url: '/system/fileVisibleUser', + method: 'post', + data: data + }) +} + +// 删除可见用户关联 +export function delVisibleUser(visibleIds) { + return request({ + url: '/system/fileVisibleUser/' + visibleIds, + method: 'delete' + }) +} + +// 按文件ID查询可见用户列表 +export function listVisibleUserByFileId(fileId) { + return request({ + url: '/system/fileVisibleUser/list', + method: 'get', + params: { fileId: fileId } + }) +} diff --git a/klp-ui/src/api/wms/contractCoilStatistics.js b/klp-ui/src/api/wms/contractCoilStatistics.js new file mode 100644 index 000000000..ee0e97c09 --- /dev/null +++ b/klp-ui/src/api/wms/contractCoilStatistics.js @@ -0,0 +1,10 @@ +import request from '@/utils/request' + +// 查询合同挂接情况统计 +export function getContractCoilStatistics(query) { + return request({ + url: '/wms/coilContractRel/statistics', + method: 'get', + params: query + }) +} diff --git a/klp-ui/src/api/wms/deliveryWaybillDetail.js b/klp-ui/src/api/wms/deliveryWaybillDetail.js index a951d8695..f90b521b0 100644 --- a/klp-ui/src/api/wms/deliveryWaybillDetail.js +++ b/klp-ui/src/api/wms/deliveryWaybillDetail.js @@ -69,13 +69,11 @@ export function getBoundCoilStatisticsList(query) { }) } -// 按销售员查询订单明细的卷 -export function listDeliveryWaybillDetailBySaleman(principal) { +// 按销售员查询订单明细的卷(分页) +export function listDeliveryWaybillDetailBySaleman(query) { return request({ url: '/wms/deliveryWaybillDetail/coilListByPrincipal', method: 'get', - params: { - principal: principal - } + params: query }) } \ No newline at end of file diff --git a/klp-ui/src/layout/components/Sidebar/SidebarItem.vue b/klp-ui/src/layout/components/Sidebar/SidebarItem.vue index 60d39e8b9..d69c49331 100644 --- a/klp-ui/src/layout/components/Sidebar/SidebarItem.vue +++ b/klp-ui/src/layout/components/Sidebar/SidebarItem.vue @@ -91,20 +91,14 @@ export default { return this.findFirstLeaf(this.item, this.basePath) }, menuStyle() { - console.log('[SidebarItem] 完整 item 对象:', JSON.parse(JSON.stringify(this.item))) - console.log('[SidebarItem] item.meta:', this.item.meta) - console.log('[SidebarItem] item.meta?.style 原始值:', this.item.meta && this.item.meta.style) if (this.item.meta && this.item.meta.style) { try { const parsed = JSON.parse(this.item.meta.style) - console.log('[SidebarItem] ✅ menuStyle 解析成功:', parsed) return parsed } catch (e) { - console.warn('[SidebarItem] ❌ JSON.parse 失败:', e) return {} } } - console.log('[SidebarItem] ⚠️ item.meta.style 为空,返回 {}') return {} } }, diff --git a/klp-ui/src/store/modules/permission.js b/klp-ui/src/store/modules/permission.js index 512229fbc..17129d557 100644 --- a/klp-ui/src/store/modules/permission.js +++ b/klp-ui/src/store/modules/permission.js @@ -49,13 +49,10 @@ const permission = { arr.forEach(item => { const title = (item.meta && item.meta.title) || item.name || '' const styleVal = item.meta && item.meta.style - console.log('[permission] depth=' + depth, title, 'meta.style=', styleVal) if (item.children) logMetaStyle(item.children, depth + 1) }) } - console.log('[permission] === getRouters 原始数据 ===') logMetaStyle(res.data) - console.log('[permission] === getRouters 数据结束 ===') const sdata = JSON.parse(JSON.stringify(res.data)) const rdata = JSON.parse(JSON.stringify(res.data)) const sidebarRoutes = filterAsyncRouter(sdata) diff --git a/klp-ui/src/utils/meta.js b/klp-ui/src/utils/meta.js new file mode 100644 index 000000000..5bcc8e65d --- /dev/null +++ b/klp-ui/src/utils/meta.js @@ -0,0 +1,34 @@ +// lockValue: 锁值,用于防止并发操作,不同的lockValue对应不同的锁 +// 1:分步加工 2. 退火 3. 酸轧 4. 酸轧分条 4. 合卷 +export const PROCESSES = [ + { name: '酸连轧工序', actionType: 11, api: 'pendingAction', lockValue: 3 }, + { name: '酸轧分条工序', actionType: 120, api: 'pendingAction', lockValue: 4 }, + { name: '酸轧合卷', actionType: 201, api: 'pendingAction', lockValue: 5 }, + { name: '镀锌合卷', actionType: 202, api: 'pendingAction', lockValue: 5 }, + { name: '脱脂合卷', actionType: 203, api: 'pendingAction', lockValue: 5 }, + { name: '拉矫平整合卷', actionType: 204, api: 'pendingAction', lockValue: 5 }, + { name: '双机架合卷', actionType: 205, api: 'pendingAction', lockValue: 5 }, + { name: '镀铬合卷', actionType: 206, api: 'pendingAction', lockValue: 5 }, + { name: '镀锌工序', actionType: 501, api: 'specialSplit', lockValue: 1 }, + { name: '脱脂工序', actionType: 502, api: 'specialSplit', lockValue: 1 }, + { name: '拉矫平整工序', actionType: 503, api: 'specialSplit', lockValue: 1 }, + { name: '双机架工序', actionType: 504, api: 'specialSplit', lockValue: 1 }, + { name: '镀铬工序', actionType: 505, api: 'specialSplit', lockValue: 1 }, + { name: '纵剪分条工序', actionType: 506, api: 'specialSplit', lockValue: 1 }, + { name: '酸轧修复工序', actionType: 520, api: 'specialSplit', lockValue: 1 }, + { name: '镀锌修复工序', actionType: 521, api: 'specialSplit', lockValue: 1 }, + { name: '脱脂修复工序', actionType: 522, api: 'specialSplit', lockValue: 1 }, + { name: '拉矫修复工序', actionType: 523, api: 'specialSplit', lockValue: 1 }, + { name: '双机架修复工序', actionType: 524, api: 'specialSplit', lockValue: 1 }, + { name: '镀铬修复工序', actionType: 525, api: 'specialSplit', lockValue: 1 }, +] + +export const PRODUCTION_LINES = [ + { name: '镀锌线', id: 1, processes: '501,202,521', hasPendingAction: true }, + { name: '酸轧线', id: 2, processes: '11,120,201,520', hasPendingAction: true }, + { name: '脱脂线', id: 3, processes: '203,502,522', hasPendingAction: true }, + { name: '镀铬线', id: 4, processes: '206,505,525', hasPendingAction: true }, + { name: '双机架', id: 5, processes: '205,504,524', hasPendingAction: true }, + { name: '退火线', id: 6, processes: '600', hasPendingAction: false }, + { name: '拉矫线', id: 7, processes: '204,503,523', hasPendingAction: true }, +] \ No newline at end of file diff --git a/klp-ui/src/views/crm/components/CoilTable.vue b/klp-ui/src/views/crm/components/CoilTable.vue index 495ad9619..3739463ab 100644 --- a/klp-ui/src/views/crm/components/CoilTable.vue +++ b/klp-ui/src/views/crm/components/CoilTable.vue @@ -2,9 +2,25 @@
+
+
+ 上一页 + + / {{ totalPages }} 页 + 下一页 +
- 总卷数:{{ totalCoils }} - 总净重:{{ totalNetWeight }} kg + + +
@@ -100,6 +116,16 @@ export default { showSelection: { type: Boolean, default: false + }, + // 分页配置 { total, currentPage, pageSize },不为 null 时启用分页 + pagination: { + type: Object, + default: null + }, + // 全部统计数据 { totalCoils, totalNetWeight },由外部传入 + totalStatistics: { + type: Object, + default: null } }, components: { @@ -110,20 +136,26 @@ export default { CoilNo }, computed: { - // 计算总卷数 - totalCoils() { + // 计算本页卷数 + currentPageCoils() { return this.data.length; }, - // 计算总净重 - totalNetWeight() { + // 计算本页净重 + currentPageNetWeight() { return this.data.reduce((sum, item) => { return sum + (Number(item.netWeight) || 0); }, 0).toFixed(2); + }, + // 总页数 + totalPages() { + if (!this.pagination) return 1; + return Math.max(1, Math.ceil(this.pagination.total / this.pagination.pageSize)); } }, data() { return { selectedRows: [], + inputPage: 1, floatLayerConfig: { columns: [ { label: '入场卷号', prop: 'enterCoilNo' }, @@ -161,6 +193,17 @@ export default { } } }, + watch: { + pagination: { + handler(val) { + if (val) { + this.inputPage = val.currentPage; + } + }, + immediate: true, + deep: true + } + }, methods: { handleSelectionChange(selection) { this.selectedRows = selection; @@ -214,6 +257,29 @@ export default { this.trace.loading = false; }); }, + /** 跳转到指定页 */ + goPage(page) { + const p = Math.max(1, Math.min(page, this.totalPages)); + if (p === this.pagination.currentPage) return; + this.inputPage = p; + const newPagination = { ...this.pagination, currentPage: p }; + this.$emit('update:pagination', newPagination); + this.$emit('page-change', { currentPage: p, pageSize: this.pagination.pageSize }); + }, + /** 输入框页码变更 */ + handlePageInputChange() { + const page = Number(this.inputPage); + if (!page || page < 1) { + this.inputPage = this.pagination.currentPage; + return; + } + const p = Math.min(page, this.totalPages); + if (p === this.pagination.currentPage) { + this.inputPage = p; + return; + } + this.goPage(p); + }, } } \ No newline at end of file diff --git a/klp-ui/src/views/crm/components/OrderObjection.vue b/klp-ui/src/views/crm/components/OrderObjection.vue index 869153a81..fd02ad0bf 100644 --- a/klp-ui/src/views/crm/components/OrderObjection.vue +++ b/klp-ui/src/views/crm/components/OrderObjection.vue @@ -371,8 +371,8 @@ export default { // 获取订单已发货的钢卷 getShippedCoils() { if (this.orderId) { - listOrderPackaging(this.orderId).then(response => { - this.shippedCoils = response.data || []; + listOrderPackaging(this.orderId, { pageNum: 1, pageSize: 10000 }).then(response => { + this.shippedCoils = response.rows || []; }).catch(() => { this.shippedCoils = []; }); diff --git a/klp-ui/src/views/crm/contract/components/ContractTabs.vue b/klp-ui/src/views/crm/contract/components/ContractTabs.vue index 05fd8ee43..973c9d71b 100644 --- a/klp-ui/src/views/crm/contract/components/ContractTabs.vue +++ b/klp-ui/src/views/crm/contract/components/ContractTabs.vue @@ -2,12 +2,6 @@
-
@@ -22,10 +16,12 @@
-
+
- + \ No newline at end of file diff --git a/klp-ui/src/views/crm/contract/index.vue b/klp-ui/src/views/crm/contract/index.vue index cab3c1a2d..4981333c6 100644 --- a/klp-ui/src/views/crm/contract/index.vue +++ b/klp-ui/src/views/crm/contract/index.vue @@ -26,9 +26,9 @@
- +
@@ -229,7 +229,7 @@ + + diff --git a/klp-ui/src/views/mes/qc/qualityReview/todo.vue b/klp-ui/src/views/mes/qc/qualityReview/todo.vue new file mode 100644 index 000000000..25bae2859 --- /dev/null +++ b/klp-ui/src/views/mes/qc/qualityReview/todo.vue @@ -0,0 +1,220 @@ + + + + + diff --git a/klp-ui/src/views/system/file/all.vue b/klp-ui/src/views/system/file/all.vue new file mode 100644 index 000000000..757154ac4 --- /dev/null +++ b/klp-ui/src/views/system/file/all.vue @@ -0,0 +1,727 @@ + + + + + diff --git a/klp-ui/src/views/system/file/index.vue b/klp-ui/src/views/system/file/index.vue new file mode 100644 index 000000000..cd40b66d1 --- /dev/null +++ b/klp-ui/src/views/system/file/index.vue @@ -0,0 +1,734 @@ + + + + + diff --git a/klp-ui/src/views/wms/anneal/plan/ctrl.vue b/klp-ui/src/views/wms/anneal/plan/ctrl.vue index 05a718992..dc343566e 100644 --- a/klp-ui/src/views/wms/anneal/plan/ctrl.vue +++ b/klp-ui/src/views/wms/anneal/plan/ctrl.vue @@ -316,6 +316,8 @@ export default { status: 0, dataType: 1, exclusiveStatus: 0, + // 只查询退火原料库的卷 + warehouseId: '1988150648993148929' }, statusForm: { planId: undefined, diff --git a/klp-ui/src/views/wms/anneal/plan/index.vue b/klp-ui/src/views/wms/anneal/plan/index.vue index d9932dead..1dfd9ede5 100644 --- a/klp-ui/src/views/wms/anneal/plan/index.vue +++ b/klp-ui/src/views/wms/anneal/plan/index.vue @@ -258,6 +258,8 @@ export default { status: 0, dataType: 1, exclusiveStatus: 0, + // 只查询退火原料库的卷 + warehouseId: '1988150648993148929' }, statusForm: { planId: undefined, diff --git a/klp-ui/src/views/wms/coil/panels/LabelRender/DuGeTag.vue b/klp-ui/src/views/wms/coil/panels/LabelRender/DuGeTag.vue index 6fd6716d4..ce4428253 100644 --- a/klp-ui/src/views/wms/coil/panels/LabelRender/DuGeTag.vue +++ b/klp-ui/src/views/wms/coil/panels/LabelRender/DuGeTag.vue @@ -66,7 +66,7 @@
产品等级
-
{{ content.qualityStatus || '' }}
+
{{ qualityStatusDisplay }}
@@ -181,6 +181,13 @@ export default { materialWithManufacturer() { return this.content.material }, + qualityStatusDisplay() { + const status = (this.content.qualityStatus || '').trim() + if (['A', 'A+', 'A-', 'B', 'B+', 'B-'].includes(status)) { + return '合格品' + } + return status + }, orderUnitDisplay() { return (this.content.orderUnit || '').replace(/有限公司/g, '') }, diff --git a/klp-ui/src/views/wms/coil/panels/LabelRender/GalvanizedTag.vue b/klp-ui/src/views/wms/coil/panels/LabelRender/GalvanizedTag.vue index c3211c698..ac1d1cc1e 100644 --- a/klp-ui/src/views/wms/coil/panels/LabelRender/GalvanizedTag.vue +++ b/klp-ui/src/views/wms/coil/panels/LabelRender/GalvanizedTag.vue @@ -66,7 +66,7 @@
质量状态
-
{{ content.qualityStatus || '' }}
+
{{ qualityStatusDisplay }}
@@ -182,6 +182,13 @@ export default { materialWithManufacturer() { return this.content.material }, + qualityStatusDisplay() { + const status = (this.content.qualityStatus || '').trim() + if (['A', 'A+', 'A-', 'B', 'B+', 'B-'].includes(status)) { + return '合格品' + } + return status + }, orderUnitDisplay() { return (this.content.orderUnit || '').replace(/有限公司/g, '') }, diff --git a/klp-ui/src/views/wms/coil/panels/LabelRender/OuterTagPreview.vue b/klp-ui/src/views/wms/coil/panels/LabelRender/OuterTagPreview.vue index f93651794..41c576c98 100644 --- a/klp-ui/src/views/wms/coil/panels/LabelRender/OuterTagPreview.vue +++ b/klp-ui/src/views/wms/coil/panels/LabelRender/OuterTagPreview.vue @@ -65,7 +65,7 @@
质量要求
-
{{ content.qualityStatus || '' }}
+
{{ qualityStatusDisplay }}
@@ -188,6 +188,13 @@ export default { materialWithManufacturer() { return this.content.material }, + qualityStatusDisplay() { + const status = (this.content.qualityStatus || '').trim() + if (['A', 'A+', 'A-', 'B', 'B+', 'B-'].includes(status)) { + return '合格品' + } + return status + }, orderUnitDisplay() { return (this.content.orderUnit || '').replace(/有限公司/g, '') }, diff --git a/klp-ui/src/views/wms/coil/panels/do.vue b/klp-ui/src/views/wms/coil/panels/do.vue index dc0652cde..4446891e6 100644 --- a/klp-ui/src/views/wms/coil/panels/do.vue +++ b/klp-ui/src/views/wms/coil/panels/do.vue @@ -11,7 +11,7 @@ :name="tab.value">

待领物料列表

- + 刷新
@@ -44,12 +44,13 @@ - + @@ -297,15 +299,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
请先选择材料类型
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + 保存合同 +
+
+
+
+
+ +
diff --git a/klp-ui/src/views/wms/contractCoilStatistics/index.vue b/klp-ui/src/views/wms/contractCoilStatistics/index.vue new file mode 100644 index 000000000..99976f573 --- /dev/null +++ b/klp-ui/src/views/wms/contractCoilStatistics/index.vue @@ -0,0 +1,613 @@ + + + + + diff --git a/klp-ui/src/views/wms/post/aps/compare.vue b/klp-ui/src/views/wms/post/aps/compare.vue new file mode 100644 index 000000000..2aad31614 --- /dev/null +++ b/klp-ui/src/views/wms/post/aps/compare.vue @@ -0,0 +1,341 @@ + + + + + diff --git a/klp-ui/src/views/wms/post/aps/schedule.vue b/klp-ui/src/views/wms/post/aps/schedule.vue index 726abd298..50afa27bc 100644 --- a/klp-ui/src/views/wms/post/aps/schedule.vue +++ b/klp-ui/src/views/wms/post/aps/schedule.vue @@ -23,14 +23,14 @@
-
+
待审核产需单明细 共 {{ pendingScheduleList.length }} 个产需单
-
+
@@ -162,7 +162,7 @@
-
+
已排产明细
@@ -191,7 +191,7 @@
-
+
+ + + @@ -35,7 +35,7 @@