feat: 新增质量评审流程全量功能
- 新增质量评审相关的实体、Mapper、Service、Controller接口与实现 - 新增前端页面与API接口,支持评审单增删改查、提交送审、审批驳回、改判执行 - 新增数据库初始化脚本与字典数据 - 修复vue.config热加载监视系统文件导致的EBUSY错误 - 清理HRM模块API导出注释
This commit is contained in:
153
docs/sql_quality_review_install.sql
Normal file
153
docs/sql_quality_review_install.sql
Normal file
@@ -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';
|
||||
@@ -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='质量评审审批日志';
|
||||
@@ -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<QcQualityReviewVo> 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<QcQualityReviewVo> list = iQcQualityReviewService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "质量评审单", QcQualityReviewVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取质量评审单详细信息
|
||||
*/
|
||||
@GetMapping("/{reviewId}")
|
||||
public R<QcQualityReviewVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long reviewId) {
|
||||
return R.ok(iQcQualityReviewService.queryById(reviewId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增质量评审单
|
||||
*/
|
||||
@Log(title = "质量评审单", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody QcQualityReviewBo bo) {
|
||||
return toAjax(iQcQualityReviewService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改质量评审单
|
||||
*/
|
||||
@Log(title = "质量评审单", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody QcQualityReviewBo bo) {
|
||||
return toAjax(iQcQualityReviewService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除质量评审单
|
||||
*/
|
||||
@Log(title = "质量评审单", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{reviewIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] reviewIds) {
|
||||
return toAjax(iQcQualityReviewService.deleteWithValidByIds(Arrays.asList(reviewIds), true));
|
||||
}
|
||||
|
||||
// ==================== 业务操作 ====================
|
||||
|
||||
/**
|
||||
* 提交送审
|
||||
*/
|
||||
@Log(title = "质量评审单", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/submit/{reviewId}")
|
||||
public R<Void> submit(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long reviewId) {
|
||||
return toAjax(iQcQualityReviewService.submit(reviewId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批通过
|
||||
*/
|
||||
@Log(title = "质量评审单", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/approve")
|
||||
public R<Void> approve(@Validated @RequestBody QcQualityReviewApproveBo bo) {
|
||||
return toAjax(iQcQualityReviewService.approve(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 驳回
|
||||
*/
|
||||
@Log(title = "质量评审单", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/reject/{reviewId}")
|
||||
public R<Void> 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<Void> execute(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long reviewId) {
|
||||
return toAjax(iQcQualityReviewService.execute(reviewId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询钢卷明细列表
|
||||
*/
|
||||
@GetMapping("/coilList/{reviewId}")
|
||||
public R<List<QcQualityReviewCoilVo>> coilList(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long reviewId) {
|
||||
return R.ok(iQcQualityReviewService.queryCoilListByReviewId(reviewId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询审批日志列表
|
||||
*/
|
||||
@GetMapping("/logList/{reviewId}")
|
||||
public R<List<QcQualityReviewLogVo>> logList(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long reviewId) {
|
||||
return R.ok(iQcQualityReviewService.queryLogListByReviewId(reviewId));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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<CoilRegradeBo> coilRegradeList;
|
||||
|
||||
@Data
|
||||
public static class CoilRegradeBo {
|
||||
/** 明细ID */
|
||||
@NotNull(message = "钢卷明细ID不能为空")
|
||||
private Long detailId;
|
||||
|
||||
/** 改判后质量状态 */
|
||||
@NotBlank(message = "改判后质量状态不能为空")
|
||||
private String regradeQuality;
|
||||
}
|
||||
}
|
||||
@@ -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<QcQualityReviewCoilBo> coilList;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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<QcQualityReviewCoilVo> coilList;
|
||||
|
||||
/** 审批日志列表 */
|
||||
private List<QcQualityReviewLogVo> logList;
|
||||
|
||||
}
|
||||
@@ -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<QcQualityReviewCoil> {
|
||||
|
||||
/**
|
||||
* 根据评审单ID查询钢卷明细列表
|
||||
*/
|
||||
List<QcQualityReviewCoilVo> selectVoListByReviewId(Long reviewId);
|
||||
|
||||
}
|
||||
@@ -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<QcQualityReviewLog> {
|
||||
|
||||
/**
|
||||
* 根据评审单ID查询审批日志列表
|
||||
*/
|
||||
List<QcQualityReviewLogVo> selectVoListByReviewId(Long reviewId);
|
||||
|
||||
}
|
||||
@@ -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<QcQualityReview> {
|
||||
|
||||
/**
|
||||
* 分页查询评审单列表(含状态字典值)
|
||||
*/
|
||||
Page<QcQualityReviewVo> selectVoPage(IPage<?> page, @Param("vo") QcQualityReviewVo vo);
|
||||
|
||||
/**
|
||||
* 查询评审单详情
|
||||
*/
|
||||
QcQualityReviewVo selectVoById(@Param("reviewId") Long reviewId);
|
||||
|
||||
/**
|
||||
* 查询评审单列表
|
||||
*/
|
||||
List<QcQualityReviewVo> selectVoList(@Param("vo") QcQualityReviewVo vo);
|
||||
|
||||
}
|
||||
@@ -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<QcQualityReviewVo> queryPageList(QcQualityReviewBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询评审单列表
|
||||
*/
|
||||
List<QcQualityReviewVo> queryList(QcQualityReviewBo bo);
|
||||
|
||||
/**
|
||||
* 创建评审单
|
||||
*/
|
||||
Boolean insertByBo(QcQualityReviewBo bo);
|
||||
|
||||
/**
|
||||
* 修改评审单
|
||||
*/
|
||||
Boolean updateByBo(QcQualityReviewBo bo);
|
||||
|
||||
/**
|
||||
* 批量删除评审单
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> 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<QcQualityReviewCoilVo> queryCoilListByReviewId(Long reviewId);
|
||||
|
||||
/**
|
||||
* 查询审批日志列表
|
||||
*/
|
||||
List<QcQualityReviewLogVo> queryLogListByReviewId(Long reviewId);
|
||||
|
||||
}
|
||||
@@ -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<QcQualityReviewVo> queryPageList(QcQualityReviewBo bo, PageQuery pageQuery) {
|
||||
QcQualityReviewVo queryVo = new QcQualityReviewVo();
|
||||
BeanUtil.copyProperties(bo, queryVo);
|
||||
Page<QcQualityReviewVo> result = baseMapper.selectVoPage(pageQuery.build(), queryVo);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询评审单列表
|
||||
*/
|
||||
@Override
|
||||
public List<QcQualityReviewVo> 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.<QcQualityReviewCoil>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<Long> 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.<QcQualityReviewCoil>lambdaQuery()
|
||||
.in(QcQualityReviewCoil::getReviewId, ids));
|
||||
// 删除审批日志
|
||||
logMapper.delete(Wrappers.<QcQualityReviewLog>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.<QcQualityReviewCoil>lambdaQuery()
|
||||
.eq(QcQualityReviewCoil::getReviewId, reviewId)
|
||||
.eq(QcQualityReviewCoil::getDelFlag, 0));
|
||||
if (coilCount == null || coilCount == 0) {
|
||||
throw new RuntimeException("请至少添加一个钢卷");
|
||||
}
|
||||
|
||||
// 更新流程状态为待审批,清除驳回原因
|
||||
baseMapper.update(null, Wrappers.<QcQualityReview>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.<QcQualityReview>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.<QcQualityReviewCoil>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.<QcQualityReview>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<QcQualityReviewCoil> coilList = coilMapper.selectList(
|
||||
Wrappers.<QcQualityReviewCoil>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.<WmsMaterialCoil>lambdaUpdate()
|
||||
.eq(WmsMaterialCoil::getCoilId, coil.getCoilId())
|
||||
.set(WmsMaterialCoil::getQualityStatus, coil.getRegradeQuality()));
|
||||
}
|
||||
|
||||
// 3. 更新明细执行状态
|
||||
coilMapper.update(null, Wrappers.<QcQualityReviewCoil>lambdaUpdate()
|
||||
.eq(QcQualityReviewCoil::getDetailId, coil.getDetailId())
|
||||
.set(QcQualityReviewCoil::getExecuteStatus, 1L)
|
||||
.set(QcQualityReviewCoil::getExecuteTime, now));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== 查询方法 ====================
|
||||
|
||||
@Override
|
||||
public List<QcQualityReviewCoilVo> queryCoilListByReviewId(Long reviewId) {
|
||||
return coilMapper.selectVoListByReviewId(reviewId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QcQualityReviewLogVo> queryLogListByReviewId(Long reviewId) {
|
||||
return logMapper.selectVoListByReviewId(reviewId);
|
||||
}
|
||||
|
||||
// ==================== 私有方法 ====================
|
||||
|
||||
/**
|
||||
* 保存钢卷明细列表
|
||||
*/
|
||||
private void saveCoilList(Long reviewId, List<QcQualityReviewCoilBo> 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.<QcQualityReview>lambdaQuery()
|
||||
.likeRight(QcQualityReview::getReviewNo, "QR-" + dateStr));
|
||||
return "QR-" + dateStr + "-" + String.format("%04d", count + 1);
|
||||
}
|
||||
|
||||
private void validEntityBeforeSave(QcQualityReview entity) {
|
||||
// TODO 数据校验
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.klp.mes.qc.mapper.QcQualityReviewCoilMapper">
|
||||
|
||||
<resultMap type="com.klp.mes.qc.domain.vo.QcQualityReviewCoilVo" id="QcQualityReviewCoilVo">
|
||||
<id property="detailId" column="detail_id"/>
|
||||
<result property="reviewId" column="review_id"/>
|
||||
<result property="groupSeq" column="group_seq"/>
|
||||
<result property="groupRemark" column="group_remark"/>
|
||||
<result property="coilId" column="coil_id"/>
|
||||
<result property="currentCoilNo" column="current_coil_no"/>
|
||||
<result property="supplierCoilNo" column="supplier_coil_no"/>
|
||||
<result property="spec" column="spec"/>
|
||||
<result property="netWeight" column="net_weight"/>
|
||||
<result property="defectDesc" column="defect_desc"/>
|
||||
<result property="beforeQuality" column="before_quality"/>
|
||||
<result property="regradeQuality" column="regrade_quality"/>
|
||||
<result property="executeStatus" column="execute_status"/>
|
||||
<result property="executeTime" column="execute_time"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectVoListByReviewId" resultMap="QcQualityReviewCoilVo">
|
||||
SELECT * FROM qc_quality_review_coil
|
||||
WHERE review_id = #{reviewId} AND del_flag = 0
|
||||
ORDER BY group_seq ASC, detail_id ASC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.klp.mes.qc.mapper.QcQualityReviewLogMapper">
|
||||
|
||||
<resultMap type="com.klp.mes.qc.domain.vo.QcQualityReviewLogVo" id="QcQualityReviewLogVo">
|
||||
<id property="logId" column="log_id"/>
|
||||
<result property="reviewId" column="review_id"/>
|
||||
<result property="action" column="action"/>
|
||||
<result property="operator" column="operator"/>
|
||||
<result property="opinion" column="opinion"/>
|
||||
<result property="operateTime" column="operate_time"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectVoListByReviewId" resultMap="QcQualityReviewLogVo">
|
||||
SELECT * FROM qc_quality_review_log
|
||||
WHERE review_id = #{reviewId}
|
||||
ORDER BY operate_time ASC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.klp.mes.qc.mapper.QcQualityReviewMapper">
|
||||
|
||||
<resultMap type="com.klp.mes.qc.domain.vo.QcQualityReviewVo" id="QcQualityReviewVo">
|
||||
<id property="reviewId" column="review_id"/>
|
||||
<result property="reviewNo" column="review_no"/>
|
||||
<result property="productName" column="product_name"/>
|
||||
<result property="transmitDept" column="transmit_dept"/>
|
||||
<result property="transmitUser" column="transmit_user"/>
|
||||
<result property="transmitDate" column="transmit_date"/>
|
||||
<result property="prodDateRange" column="prod_date_range"/>
|
||||
<result property="flowStatus" column="flow_status"/>
|
||||
<result property="deptOpinion" column="dept_opinion"/>
|
||||
<result property="deptSign" column="dept_sign"/>
|
||||
<result property="deptSignDate" column="dept_sign_date"/>
|
||||
<result property="leaderOpinion" column="leader_opinion"/>
|
||||
<result property="leaderSign" column="leader_sign"/>
|
||||
<result property="leaderSignDate" column="leader_sign_date"/>
|
||||
<result property="rejectReason" column="reject_reason"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="delFlag" column="del_flag"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectVoPage" resultMap="QcQualityReviewVo">
|
||||
SELECT * FROM qc_quality_review
|
||||
<where>
|
||||
del_flag = 0
|
||||
<if test="vo.reviewNo != null and vo.reviewNo != ''">
|
||||
AND review_no LIKE CONCAT('%', #{vo.reviewNo}, '%')
|
||||
</if>
|
||||
<if test="vo.productName != null and vo.productName != ''">
|
||||
AND product_name LIKE CONCAT('%', #{vo.productName}, '%')
|
||||
</if>
|
||||
<if test="vo.flowStatus != null">
|
||||
AND flow_status = #{vo.flowStatus}
|
||||
</if>
|
||||
<if test="vo.transmitUser != null and vo.transmitUser != ''">
|
||||
AND transmit_user LIKE CONCAT('%', #{vo.transmitUser}, '%')
|
||||
</if>
|
||||
<if test="vo.params != null and vo.params.beginTime != null and vo.params.beginTime != ''">
|
||||
AND create_time >= #{vo.params.beginTime}
|
||||
</if>
|
||||
<if test="vo.params != null and vo.params.endTime != null and vo.params.endTime != ''">
|
||||
AND create_time <= #{vo.params.endTime}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="selectVoById" resultMap="QcQualityReviewVo">
|
||||
SELECT * FROM qc_quality_review WHERE review_id = #{reviewId} AND del_flag = 0
|
||||
</select>
|
||||
|
||||
<select id="selectVoList" resultMap="QcQualityReviewVo">
|
||||
SELECT * FROM qc_quality_review
|
||||
<where>
|
||||
del_flag = 0
|
||||
<if test="vo.reviewNo != null and vo.reviewNo != ''">
|
||||
AND review_no LIKE CONCAT('%', #{vo.reviewNo}, '%')
|
||||
</if>
|
||||
<if test="vo.flowStatus != null">
|
||||
AND flow_status = #{vo.flowStatus}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,4 +1,3 @@
|
||||
// 导出所有 HRM 模块 API
|
||||
export * from './employee'
|
||||
export * from './org'
|
||||
export * from './certContract'
|
||||
|
||||
94
klp-ui/src/api/mes/qc/qualityReview.js
Normal file
94
klp-ui/src/api/mes/qc/qualityReview.js
Normal file
@@ -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'
|
||||
})
|
||||
}
|
||||
815
klp-ui/src/views/mes/qc/qualityReview/index.vue
Normal file
815
klp-ui/src/views/mes/qc/qualityReview/index.vue
Normal file
@@ -0,0 +1,815 @@
|
||||
<template>
|
||||
<div class="app-container quality-review-container">
|
||||
<div class="left-panel">
|
||||
<div class="panel-header">
|
||||
<div class="header-title">
|
||||
<i class="el-icon-document-checked"></i>
|
||||
<span>质量评审单</span>
|
||||
<el-button size="mini" type="text" icon="el-icon-refresh" @click="getList" style="margin-left:4px;" title="刷新列表"></el-button>
|
||||
</div>
|
||||
<el-select v-model="queryParams.flowStatus" placeholder="全部状态" clearable size="mini" @change="handleQuery" class="header-filter">
|
||||
<el-option v-for="item in dict.type.quality_review_status" :key="item.value" :label="item.label" :value="parseInt(item.value)" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="search-row">
|
||||
<el-input v-model="queryParams.reviewNo" placeholder="搜索评审单编号..." clearable prefix-icon="el-icon-search" size="small" @keyup.enter.native="handleQuery" @clear="handleQuery" />
|
||||
<el-button type="primary" size="small" @click="handleAdd" v-hasPermi="['qc:qualityReview:add']">
|
||||
<i class="el-icon-plus"></i>
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-loading="loading" class="list-body">
|
||||
<div v-for="item in dataList" :key="item.reviewId" class="list-item"
|
||||
:class="{ active: currentRow && currentRow.reviewId === item.reviewId }" @click="handleRowClick(item)">
|
||||
<div class="item-main">
|
||||
<span class="item-title">{{ item.reviewNo }}</span>
|
||||
<span class="item-sub">{{ item.transmitUser }} · {{ item.productName }}</span>
|
||||
</div>
|
||||
<div class="item-meta">
|
||||
<el-tag v-if="item.flowStatus === 1" type="info" size="mini">待提交</el-tag>
|
||||
<el-tag v-else-if="item.flowStatus === 2" type="warning" size="mini">待审批</el-tag>
|
||||
<el-tag v-else-if="item.flowStatus === 3" type="success" size="mini">已通过</el-tag>
|
||||
<el-tag v-else-if="item.flowStatus === 4" type="danger" size="mini">已驳回</el-tag>
|
||||
</div>
|
||||
<div class="item-actions">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click.stop="handleUpdate(item)" v-hasPermi="['qc:qualityReview:edit']"></el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click.stop="handleDelete(item)" v-hasPermi="['qc:qualityReview:delete']"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="dataList.length === 0 && !loading" class="list-empty">
|
||||
<i class="el-icon-folder-opened"></i>
|
||||
<span>暂无质量评审单</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-footer">
|
||||
<pagination :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧详情 -->
|
||||
<div class="right-panel">
|
||||
<div v-if="!currentRow" class="empty-tip">
|
||||
<i class="el-icon-info"></i>
|
||||
<span>请在左侧列表中选择一条评审单查看详情</span>
|
||||
</div>
|
||||
<div v-else v-loading="detailLoading" class="detail-content">
|
||||
|
||||
<!-- ===== 顶部操作栏 ===== -->
|
||||
<div class="detail-header">
|
||||
<div class="detail-header-left">
|
||||
<span class="detail-title">{{ currentRow.reviewNo }}</span>
|
||||
<el-tag v-if="currentRow.flowStatus === 1" type="info" size="small">待提交</el-tag>
|
||||
<el-tag v-else-if="currentRow.flowStatus === 2" type="warning" size="small">待审批</el-tag>
|
||||
<el-tag v-else-if="currentRow.flowStatus === 3" type="success" size="small">已通过</el-tag>
|
||||
<el-tag v-else-if="currentRow.flowStatus === 4" type="danger" size="small">已驳回</el-tag>
|
||||
</div>
|
||||
<div class="detail-header-actions">
|
||||
<!-- 待提交:提交送审 -->
|
||||
<el-button v-if="currentRow.flowStatus === 1" size="mini" type="primary" plain icon="el-icon-s-promotion"
|
||||
@click="handleSubmit" v-hasPermi="['qc:qualityReview:submit']">提交送审</el-button>
|
||||
<!-- 待审批:审批/驳回 -->
|
||||
<el-button v-if="currentRow.flowStatus === 2" size="mini" type="success" plain icon="el-icon-check"
|
||||
@click="handleApprove" v-hasPermi="['qc:qualityReview:approve']">审批通过</el-button>
|
||||
<el-button v-if="currentRow.flowStatus === 2" size="mini" type="danger" plain icon="el-icon-close"
|
||||
@click="handleReject" v-hasPermi="['qc:qualityReview:approve']">驳回</el-button>
|
||||
<!-- 已通过:执行改判 -->
|
||||
<el-button v-if="currentRow.flowStatus === 3" size="mini" type="warning" plain icon="el-icon-setting"
|
||||
@click="handleExecute" v-hasPermi="['qc:qualityReview:execute']">执行改判</el-button>
|
||||
<!-- 已驳回:重新提交 -->
|
||||
<el-button v-if="currentRow.flowStatus === 4" size="mini" type="primary" plain icon="el-icon-s-promotion"
|
||||
@click="handleReSubmit" v-hasPermi="['qc:qualityReview:submit']">重新提交</el-button>
|
||||
<!-- 通用 -->
|
||||
<el-button size="mini" type="text" icon="el-icon-refresh" @click="handleRefreshDetail">刷新</el-button>
|
||||
<el-button v-if="currentRow.flowStatus === 1 || currentRow.flowStatus === 4" size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(currentRow)">编辑</el-button>
|
||||
<el-button v-if="currentRow.flowStatus === 1 || currentRow.flowStatus === 4" size="mini" type="text" icon="el-icon-delete" @click="handleDelete(currentRow)">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 基本信息 ===== -->
|
||||
<el-card class="detail-section" shadow="never">
|
||||
<div slot="header"><span><i class="el-icon-info"></i> 基本信息</span></div>
|
||||
<el-form :model="currentRow" label-width="100px" size="small" class="basic-form">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="评审单编号">{{ currentRow.reviewNo }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="产品名称">{{ currentRow.productName }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="传递部门">{{ currentRow.transmitDept }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="传递人">{{ currentRow.transmitUser }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="传递日期">{{ currentRow.transmitDate }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="生产日期">{{ currentRow.prodDateRange }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- ===== 钢卷明细表(详情只读) ===== -->
|
||||
<el-card class="detail-section" shadow="never">
|
||||
<div slot="header">
|
||||
<span><i class="el-icon-s-management"></i> 问题钢卷明细</span>
|
||||
</div>
|
||||
<el-table :data="coilList" border style="width: 100%" size="small" max-height="400">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="currentCoilNo" label="产品卷号" min-width="140" />
|
||||
<el-table-column prop="supplierCoilNo" label="原料卷号" min-width="140" />
|
||||
<el-table-column prop="spec" label="规格(mm)" width="110" />
|
||||
<el-table-column prop="netWeight" label="卷重(t)" width="90" align="right" />
|
||||
<el-table-column prop="defectDesc" label="缺陷描述" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="beforeQuality" label="改判前" width="80" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag size="mini" type="danger">{{ scope.row.beforeQuality }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="regradeQuality" label="改判后" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.regradeQuality" size="mini" type="warning">{{ scope.row.regradeQuality }}</el-tag>
|
||||
<span v-else class="text-muted">待指定</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- ===== 品质部评审意见 ===== -->
|
||||
<el-card class="detail-section" shadow="never">
|
||||
<div slot="header"><span><i class="el-icon-edit-outline"></i> 品质部评审意见</span></div>
|
||||
<div v-if="editing" class="section-editor">
|
||||
<el-input type="textarea" :rows="3" v-model="editForm.deptOpinion" placeholder="请填写品质部评审意见..." />
|
||||
<div style="margin-top:8px; display:flex; gap:8px;">
|
||||
<el-input v-model="editForm.deptSign" placeholder="签字人" style="width:160px;" size="small" />
|
||||
<el-date-picker v-model="editForm.deptSignDate" type="date" placeholder="签字日期" size="small" />
|
||||
</div>
|
||||
<el-button size="small" type="primary" @click="saveOpinion" style="margin-top:8px;">保存意见</el-button>
|
||||
</div>
|
||||
<div v-else class="section-display">
|
||||
<div class="opinion-text">{{ currentRow.deptOpinion || '暂未填写' }}</div>
|
||||
<div class="opinion-footer" v-if="currentRow.deptOpinion">
|
||||
<span>签字:{{ currentRow.deptSign || '-' }}</span>
|
||||
<span>日期:{{ currentRow.deptSignDate || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ===== 领导审批意见 ===== -->
|
||||
<el-card class="detail-section" shadow="never">
|
||||
<div slot="header"><span><i class="el-icon-s-check"></i> 领导审批意见</span></div>
|
||||
<!-- flowStatus=2时显示审批表单,权限由后端API控制,前端不做限制 -->
|
||||
<div v-if="currentRow.flowStatus === 2" class="section-editor">
|
||||
<!-- 审批通过模式 -->
|
||||
<el-radio-group v-model="approveAction" style="margin-bottom:12px;">
|
||||
<el-radio-button label="approve">通过</el-radio-button>
|
||||
<el-radio-button label="reject">驳回</el-radio-button>
|
||||
</el-radio-group>
|
||||
|
||||
<template v-if="approveAction === 'approve'">
|
||||
<el-input type="textarea" :rows="3" v-model="approveForm.leaderOpinion" placeholder="请输入领导审批意见..." />
|
||||
<div style="margin:8px 0;">
|
||||
<el-input v-model="approveForm.leaderSign" placeholder="签字人" style="width:160px;" size="small" />
|
||||
</div>
|
||||
<div class="approve-coil-section">
|
||||
<div class="approve-coil-title">请为每个钢卷指定改判后质量状态:</div>
|
||||
<div v-for="coil in coilList" :key="coil.detailId" class="approve-coil-row">
|
||||
<span class="approve-coil-label">{{ coil.currentCoilNo }}({{ coil.spec }})</span>
|
||||
<el-select v-model="approveCoilMap[coil.detailId]" placeholder="请选择改判后状态" size="small" style="width:180px;">
|
||||
<el-option v-for="item in regradeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<el-button size="small" type="success" @click="doApprove">确认通过</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-input type="textarea" :rows="3" v-model="rejectReason" placeholder="请输入驳回原因..." />
|
||||
<el-button size="small" type="danger" @click="doReject" style="margin-top:8px;">确认驳回</el-button>
|
||||
</template>
|
||||
</div>
|
||||
<div v-else class="section-display">
|
||||
<div class="opinion-text">{{ currentRow.leaderOpinion || '暂无审批意见' }}</div>
|
||||
<div class="opinion-footer" v-if="currentRow.leaderOpinion">
|
||||
<span>签字:{{ currentRow.leaderSign || '-' }}</span>
|
||||
<span>日期:{{ currentRow.leaderSignDate || '-' }}</span>
|
||||
</div>
|
||||
<div v-if="currentRow.flowStatus === 4 && currentRow.rejectReason" class="reject-reason">
|
||||
<el-alert :title="'驳回原因:' + currentRow.rejectReason" type="error" show-icon :closable="false" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- ===== 审批日志 ===== -->
|
||||
<el-card class="detail-section" shadow="never">
|
||||
<div slot="header"><span><i class="el-icon-time"></i> 审批记录</span></div>
|
||||
<div v-if="logList.length === 0" class="text-muted" style="padding:12px;">暂无审批记录</div>
|
||||
<el-timeline v-else>
|
||||
<el-timeline-item v-for="log in logList" :key="log.logId"
|
||||
:timestamp="log.createTime"
|
||||
:type="log.action === 'submit' ? 'primary' : (log.action === 'approve' ? 'success' : 'danger')"
|
||||
:icon="log.action === 'submit' ? 'el-icon-s-promotion' : (log.action === 'approve' ? 'el-icon-check' : 'el-icon-close')">
|
||||
<div>
|
||||
<strong>{{ log.action === 'submit' ? '提交送审' : (log.action === 'approve' ? '审批通过' : '驳回') }}</strong>
|
||||
<span v-if="log.operator"> — {{ log.operator }}</span>
|
||||
</div>
|
||||
<div v-if="log.opinion" class="timeline-opinion">{{ log.opinion }}</div>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</el-card>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="900px" :close-on-click-modal="false" append-to-body>
|
||||
<el-form ref="form" :model="editForm" :rules="rules" label-width="100px" size="small">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="产品名称" prop="productName">
|
||||
<el-input v-model="editForm.productName" placeholder="如:镀锌产品" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="传递部门" prop="transmitDept">
|
||||
<el-input v-model="editForm.transmitDept" placeholder="品质部" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="传递人" prop="transmitUser">
|
||||
<el-input v-model="editForm.transmitUser" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="传递日期" prop="transmitDate">
|
||||
<el-date-picker v-model="editForm.transmitDate" type="date" placeholder="选择日期" style="width:100%;" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="生产日期" prop="prodDateRange">
|
||||
<el-input v-model="editForm.prodDateRange" placeholder="如:14-15" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- ===== 钢卷选择 ===== -->
|
||||
<div class="dialog-section">
|
||||
<div class="dialog-section-header">
|
||||
<span>问题钢卷</span>
|
||||
<el-button size="mini" type="primary" plain icon="el-icon-plus" @click="showCoilSelector = true">选择O级钢卷</el-button>
|
||||
</div>
|
||||
<el-table :data="editForm.coilList" border style="width:100%" size="small" max-height="250">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="currentCoilNo" label="产品卷号" min-width="130" />
|
||||
<el-table-column prop="supplierCoilNo" label="原料卷号" min-width="130" />
|
||||
<el-table-column prop="spec" label="规格(mm)" width="100" />
|
||||
<el-table-column prop="netWeight" label="卷重(t)" width="80" align="right" />
|
||||
<el-table-column prop="defectDesc" label="缺陷描述" min-width="160">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.defectDesc" size="mini" placeholder="输入缺陷描述" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="60" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="editForm.coilList.splice(scope.$index, 1)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="editForm.coilList.length === 0" class="dialog-table-empty">请点击上方按钮选择O级钢卷</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 钢卷选择器(嵌套在弹窗内) ===== -->
|
||||
<CoilSelector
|
||||
:visible.sync="showCoilSelector"
|
||||
:multiple="true"
|
||||
:filters="{ qualityStatusCsv: 'O', status: 0 }"
|
||||
@confirm="onDialogCoilConfirm" />
|
||||
|
||||
<el-divider />
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="品质部意见" prop="deptOpinion">
|
||||
<el-input type="textarea" :rows="3" v-model="editForm.deptOpinion" placeholder="请填写品质部评审意见" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="签字人">
|
||||
<el-input v-model="editForm.deptSign" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="签字日期">
|
||||
<el-date-picker v-model="editForm.deptSignDate" type="date" placeholder="选择日期" style="width:100%;" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveForm">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listQualityReview, getQualityReview, addQualityReview, updateQualityReview, delQualityReview,
|
||||
submitQualityReview, approveQualityReview, rejectQualityReview, executeQualityReview,
|
||||
listQualityReviewCoil, listQualityReviewLog } from '@/api/mes/qc/qualityReview'
|
||||
import CoilSelector from '@/components/CoilSelector'
|
||||
|
||||
export default {
|
||||
name: 'QualityReview',
|
||||
components: { CoilSelector },
|
||||
dicts: ['quality_review_status', 'regrade_quality_type'],
|
||||
data() {
|
||||
return {
|
||||
// 列表
|
||||
loading: false,
|
||||
dataList: [],
|
||||
total: 0,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
reviewNo: undefined,
|
||||
flowStatus: undefined
|
||||
},
|
||||
currentRow: null,
|
||||
|
||||
// 详情
|
||||
detailLoading: false,
|
||||
coilList: [],
|
||||
logList: [],
|
||||
|
||||
// 钢卷选择
|
||||
showCoilSelector: false,
|
||||
|
||||
// 编辑弹窗
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
editing: false,
|
||||
editForm: {
|
||||
reviewId: undefined,
|
||||
productName: '',
|
||||
transmitDept: '品质部',
|
||||
transmitUser: '',
|
||||
transmitDate: undefined,
|
||||
prodDateRange: '',
|
||||
deptOpinion: '',
|
||||
deptSign: '',
|
||||
deptSignDate: undefined,
|
||||
coilList: []
|
||||
},
|
||||
rules: {
|
||||
productName: [{ required: true, message: '请输入产品名称', trigger: 'blur' }]
|
||||
},
|
||||
|
||||
// 改判状态选项(硬编码后备,优先使用字典)
|
||||
regradeOptions: [
|
||||
{ label: '协议销售', value: 'protocol_sale' },
|
||||
{ label: '转分剪', value: 'to_slitting' },
|
||||
{ label: '降级', value: 'downgrade' },
|
||||
{ label: '返修', value: 'rework' },
|
||||
{ label: '报废', value: 'scrap' }
|
||||
],
|
||||
// 审批
|
||||
approveAction: 'approve',
|
||||
approveForm: {
|
||||
reviewId: undefined,
|
||||
leaderOpinion: '',
|
||||
leaderSign: ''
|
||||
},
|
||||
approveCoilMap: {},
|
||||
rejectReason: ''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// ===== 列表 =====
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
getList() {
|
||||
this.loading = true
|
||||
listQualityReview(this.queryParams).then(res => {
|
||||
this.dataList = res.rows || []
|
||||
this.total = res.total || 0
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleRowClick(row) {
|
||||
this.currentRow = row
|
||||
this.loadDetail(row.reviewId)
|
||||
},
|
||||
|
||||
// ===== 详情 =====
|
||||
loadDetail(reviewId) {
|
||||
this.detailLoading = true
|
||||
getQualityReview(reviewId).then(res => {
|
||||
const data = res.data
|
||||
this.currentRow = data
|
||||
this.coilList = data.coilList || []
|
||||
this.logList = data.logList || []
|
||||
// 初始化审批表单数据(先构建完整对象再赋值,解决Vue2响应式问题)
|
||||
const map = {}
|
||||
this.coilList.forEach(c => {
|
||||
map[c.detailId] = c.regradeQuality || ''
|
||||
})
|
||||
this.approveCoilMap = map
|
||||
this.approveForm.reviewId = reviewId
|
||||
this.approveForm.leaderOpinion = ''
|
||||
this.approveForm.leaderSign = ''
|
||||
this.rejectReason = ''
|
||||
this.detailLoading = false
|
||||
}).catch(() => { this.detailLoading = false })
|
||||
},
|
||||
handleRefreshDetail() {
|
||||
if (this.currentRow) {
|
||||
this.loadDetail(this.currentRow.reviewId)
|
||||
this.getList()
|
||||
}
|
||||
},
|
||||
|
||||
// ===== 新增/编辑 =====
|
||||
handleAdd() {
|
||||
this.dialogTitle = '新建质量评审单'
|
||||
this.editForm = {
|
||||
reviewId: undefined,
|
||||
productName: '',
|
||||
transmitDept: '品质部',
|
||||
transmitUser: '',
|
||||
transmitDate: undefined,
|
||||
prodDateRange: '',
|
||||
deptOpinion: '',
|
||||
deptSign: '',
|
||||
deptSignDate: undefined,
|
||||
coilList: []
|
||||
}
|
||||
this.editing = true
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleUpdate(row) {
|
||||
this.dialogTitle = '编辑质量评审单'
|
||||
this.editForm = {
|
||||
reviewId: row.reviewId,
|
||||
productName: row.productName,
|
||||
transmitDept: row.transmitDept,
|
||||
transmitUser: row.transmitUser,
|
||||
transmitDate: row.transmitDate,
|
||||
prodDateRange: row.prodDateRange,
|
||||
deptOpinion: row.deptOpinion,
|
||||
deptSign: row.deptSign,
|
||||
deptSignDate: row.deptSignDate,
|
||||
coilList: this.coilList.map(c => ({ ...c }))
|
||||
}
|
||||
this.editing = true
|
||||
this.dialogVisible = true
|
||||
},
|
||||
saveForm() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (!valid) return
|
||||
const data = { ...this.editForm, coilList: this.editForm.coilList || [] }
|
||||
if (this.editForm.reviewId) {
|
||||
updateQualityReview(data).then(() => {
|
||||
this.$modal.msgSuccess('修改成功')
|
||||
this.dialogVisible = false
|
||||
this.handleRefreshDetail()
|
||||
})
|
||||
} else {
|
||||
addQualityReview(data).then(() => {
|
||||
this.$modal.msgSuccess('创建成功')
|
||||
this.dialogVisible = false
|
||||
this.getList()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// ===== 钢卷选择(弹窗内) =====
|
||||
onDialogCoilConfirm(selected) {
|
||||
if (!selected || selected.length === 0) return
|
||||
const startIdx = this.editForm.coilList.length || 0
|
||||
const newCoils = selected.map((coil, idx) => ({
|
||||
coilId: coil.coilId,
|
||||
currentCoilNo: coil.currentCoilNo,
|
||||
supplierCoilNo: coil.supplierCoilNo || coil.enterCoilNo,
|
||||
spec: coil.spec,
|
||||
netWeight: coil.netWeight,
|
||||
defectDesc: '',
|
||||
groupSeq: startIdx + idx + 1,
|
||||
beforeQuality: coil.qualityStatus || 'O'
|
||||
}))
|
||||
this.editForm.coilList = [...(this.editForm.coilList || []), ...newCoils]
|
||||
},
|
||||
handleRemoveCoil(index) {
|
||||
this.coilList.splice(index, 1)
|
||||
},
|
||||
|
||||
// ===== 提交送审 =====
|
||||
handleSubmit() {
|
||||
this.$confirm('确认提交送审?', '提示', { type: 'warning' }).then(() => {
|
||||
submitQualityReview(this.currentRow.reviewId).then(() => {
|
||||
this.$modal.msgSuccess('送审成功')
|
||||
this.handleRefreshDetail()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
handleReSubmit() {
|
||||
this.$confirm('确认重新提交?提交后将进入待审批状态。', '提示', { type: 'warning' }).then(() => {
|
||||
submitQualityReview(this.currentRow.reviewId).then(() => {
|
||||
this.$modal.msgSuccess('送审成功')
|
||||
this.handleRefreshDetail()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ===== 审批 =====
|
||||
handleApprove() {
|
||||
this.approveAction = 'approve'
|
||||
this.approveForm = {
|
||||
reviewId: this.currentRow.reviewId,
|
||||
leaderOpinion: '',
|
||||
leaderSign: ''
|
||||
}
|
||||
// 先构建完整对象再赋值
|
||||
const map = {}
|
||||
this.coilList.forEach(c => {
|
||||
map[c.detailId] = c.regradeQuality || ''
|
||||
})
|
||||
this.approveCoilMap = map
|
||||
},
|
||||
doApprove() {
|
||||
if (!this.approveForm.leaderOpinion) {
|
||||
this.$modal.msgError('请输入审批意见')
|
||||
return
|
||||
}
|
||||
const coilRegradeList = this.coilList.map(c => ({
|
||||
detailId: c.detailId,
|
||||
regradeQuality: this.approveCoilMap[c.detailId]
|
||||
}))
|
||||
const invalid = coilRegradeList.some(r => !r.regradeQuality)
|
||||
if (invalid) {
|
||||
this.$modal.msgError('请为每个钢卷指定改判后质量状态')
|
||||
return
|
||||
}
|
||||
this.$confirm('确认审批通过?', '提示', { type: 'success' }).then(() => {
|
||||
approveQualityReview({
|
||||
reviewId: this.currentRow.reviewId,
|
||||
leaderOpinion: this.approveForm.leaderOpinion,
|
||||
leaderSign: this.approveForm.leaderSign,
|
||||
coilRegradeList
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess('审批通过')
|
||||
this.handleRefreshDetail()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
handleReject() {
|
||||
this.approveAction = 'reject'
|
||||
this.rejectReason = ''
|
||||
},
|
||||
doReject() {
|
||||
if (!this.rejectReason) {
|
||||
this.$modal.msgError('请输入驳回原因')
|
||||
return
|
||||
}
|
||||
this.$confirm('确认驳回该评审单?', '提示', { type: 'warning' }).then(() => {
|
||||
rejectQualityReview(this.currentRow.reviewId, this.rejectReason).then(() => {
|
||||
this.$modal.msgSuccess('已驳回')
|
||||
this.handleRefreshDetail()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ===== 执行改判 =====
|
||||
handleExecute() {
|
||||
this.$confirm('确认执行改判?执行后钢卷质量状态将被更新。', '提示', { type: 'warning' }).then(() => {
|
||||
executeQualityReview(this.currentRow.reviewId).then(() => {
|
||||
this.$modal.msgSuccess('改判执行成功')
|
||||
this.handleRefreshDetail()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ===== 删除 =====
|
||||
handleDelete(row) {
|
||||
this.$confirm('确认删除评审单【' + (row.reviewNo || row.reviewId) + '】?', '提示', { type: 'warning' }).then(() => {
|
||||
delQualityReview(row.reviewId).then(() => {
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
if (this.currentRow && this.currentRow.reviewId === row.reviewId) {
|
||||
this.currentRow = null
|
||||
this.coilList = []
|
||||
this.logList = []
|
||||
}
|
||||
this.getList()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ===== 辅助 =====
|
||||
hasPermi(permi) {
|
||||
return this.$store.getters.permissions && this.$store.getters.permissions.includes(permi)
|
||||
},
|
||||
saveOpinion() {
|
||||
if (!this.currentRow) return
|
||||
updateQualityReview({
|
||||
reviewId: this.currentRow.reviewId,
|
||||
deptOpinion: this.editForm.deptOpinion,
|
||||
deptSign: this.editForm.deptSign,
|
||||
deptSignDate: this.editForm.deptSignDate
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess('保存成功')
|
||||
this.handleRefreshDetail()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.quality-review-container {
|
||||
display: flex;
|
||||
height: calc(100vh - 84px);
|
||||
gap: 12px;
|
||||
padding: 0;
|
||||
|
||||
.left-panel {
|
||||
width: 320px;
|
||||
min-width: 320px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #e4e7ed;
|
||||
|
||||
.panel-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 12px 0;
|
||||
|
||||
.header-title {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.header-filter { width: 130px; }
|
||||
}
|
||||
.search-row {
|
||||
display: flex;
|
||||
padding: 8px 12px;
|
||||
gap: 6px;
|
||||
.el-input { flex: 1; }
|
||||
}
|
||||
.list-body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0 8px;
|
||||
}
|
||||
.list-item {
|
||||
padding: 10px 12px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
margin: 2px 0;
|
||||
&:hover { background: #f5f7fa; }
|
||||
&.active { background: #ecf5ff; }
|
||||
.item-main {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.item-title { font-weight: 500; font-size: 13px; }
|
||||
.item-sub { font-size: 12px; color: #909399; }
|
||||
}
|
||||
.item-meta { margin-top: 4px; }
|
||||
.item-actions {
|
||||
margin-top: 4px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.list-empty {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
color: #c0c4cc;
|
||||
i { font-size: 36px; display: block; margin-bottom: 8px; }
|
||||
}
|
||||
.list-footer { padding: 8px; }
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #e4e7ed;
|
||||
overflow-y: auto;
|
||||
padding: 16px;
|
||||
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
padding: 80px 0;
|
||||
color: #c0c4cc;
|
||||
i { font-size: 48px; display: block; margin-bottom: 12px; }
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
margin-bottom: 12px;
|
||||
.detail-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
.detail-title { font-size: 16px; font-weight: 600; }
|
||||
}
|
||||
.detail-header-actions { display: flex; gap: 4px; flex-wrap: wrap; }
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 12px;
|
||||
.basic-form .el-form-item { margin-bottom: 0; }
|
||||
}
|
||||
|
||||
.section-editor {
|
||||
.approve-coil-section {
|
||||
background: #fafafa;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
margin: 8px 0;
|
||||
.approve-coil-title { font-weight: 500; margin-bottom: 8px; }
|
||||
.approve-coil-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 6px;
|
||||
.approve-coil-label { min-width: 200px; font-size: 13px; }
|
||||
}
|
||||
}
|
||||
}
|
||||
.section-display {
|
||||
.opinion-text {
|
||||
background: #fafafa;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
line-height: 1.6;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.opinion-footer {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
}
|
||||
.reject-reason { margin-top: 12px; }
|
||||
}
|
||||
.dialog-section {
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
margin-bottom: 16px;
|
||||
.dialog-section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
.dialog-table-empty {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
color: #c0c4cc;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.text-muted { color: #c0c4cc; }
|
||||
.timeline-opinion {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
margin-top: 4px;
|
||||
background: #f5f7fa;
|
||||
padding: 6px 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
220
klp-ui/src/views/mes/qc/qualityReview/todo.vue
Normal file
220
klp-ui/src/views/mes/qc/qualityReview/todo.vue
Normal file
@@ -0,0 +1,220 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="todo-header">
|
||||
<h3><i class="el-icon-s-promotion"></i> 待审批质量评审单</h3>
|
||||
</div>
|
||||
<el-table :data="todoList" v-loading="loading" border stripe @row-click="handleRowClick" style="cursor:pointer;">
|
||||
<el-table-column label="评审单编号" prop="reviewNo" width="180" />
|
||||
<el-table-column label="产品名称" prop="productName" width="160" />
|
||||
<el-table-column label="传递人" prop="transmitUser" width="100" />
|
||||
<el-table-column label="传递日期" prop="transmitDate" width="120" />
|
||||
<el-table-column label="生产日期" prop="prodDateRange" width="120" />
|
||||
<el-table-column label="品质部意见" prop="deptOpinion" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="创建时间" prop="createTime" width="160" />
|
||||
<el-table-column label="操作" width="200" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="success" plain @click.stop="handleQuickApprove(scope.row)">通过</el-button>
|
||||
<el-button size="mini" type="danger" plain @click.stop="handleQuickReject(scope.row)">驳回</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
|
||||
<!-- 快速审批弹窗 -->
|
||||
<el-dialog title="审批质量评审单" :visible.sync="approveDialog.visible" width="700px" :close-on-click-modal="false" append-to-body>
|
||||
<div v-if="approveDialog.review">
|
||||
<div class="approve-info">
|
||||
<el-descriptions :column="2" size="small" border>
|
||||
<el-descriptions-item label="评审单编号">{{ approveDialog.review.reviewNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="产品名称">{{ approveDialog.review.productName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="传递人">{{ approveDialog.review.transmitUser }}</el-descriptions-item>
|
||||
<el-descriptions-item label="传递日期">{{ approveDialog.review.transmitDate }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div class="approve-opinion-box">
|
||||
<label>品质部意见:</label>
|
||||
<div class="opinion-content">{{ approveDialog.review.deptOpinion }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-divider />
|
||||
|
||||
<el-radio-group v-model="approveAction" style="margin-bottom:12px;">
|
||||
<el-radio-button label="approve">通过</el-radio-button>
|
||||
<el-radio-button label="reject">驳回</el-radio-button>
|
||||
</el-radio-group>
|
||||
|
||||
<template v-if="approveAction === 'approve'">
|
||||
<el-input type="textarea" :rows="3" v-model="approveForm.leaderOpinion" placeholder="请输入领导审批意见..." style="margin-bottom:12px;" />
|
||||
<el-input v-model="approveForm.leaderSign" placeholder="签字人" style="width:160px; margin-bottom:12px;" size="small" />
|
||||
<div class="coil-regrade-section">
|
||||
<div class="coil-regrade-title">请为以下钢卷指定改判后质量状态:</div>
|
||||
<el-table :data="approveCoilList" size="small" border max-height="300">
|
||||
<el-table-column prop="currentCoilNo" label="产品卷号" width="140" />
|
||||
<el-table-column prop="spec" label="规格" width="100" />
|
||||
<el-table-column prop="beforeQuality" label="当前等级" width="80">
|
||||
<template slot-scope="s"><el-tag size="mini" type="danger">{{ s.row.beforeQuality }}</el-tag></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="改判后状态" width="160">
|
||||
<template slot-scope="s">
|
||||
<el-select v-model="approveCoilMap[s.row.detailId]" placeholder="请选择" size="small">
|
||||
<el-option v-for="item in regradeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div style="margin-top:12px;">
|
||||
<el-button type="success" @click="doApprove" :loading="approveLoading">确认通过</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-input type="textarea" :rows="3" v-model="rejectReason" placeholder="请输入驳回原因..." />
|
||||
<el-button type="danger" @click="doReject" :loading="approveLoading" style="margin-top:12px;">确认驳回</el-button>
|
||||
</template>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listQualityReview, approveQualityReview, rejectQualityReview, getQualityReview } from '@/api/mes/qc/qualityReview'
|
||||
|
||||
export default {
|
||||
name: 'QualityReviewTodo',
|
||||
dicts: ['quality_review_status', 'regrade_quality_type'],
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
todoList: [],
|
||||
total: 0,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
flowStatus: 2
|
||||
},
|
||||
regradeOptions: [
|
||||
{ label: '协议销售', value: 'protocol_sale' },
|
||||
{ label: '转分剪', value: 'to_slitting' },
|
||||
{ label: '降级', value: 'downgrade' },
|
||||
{ label: '返修', value: 'rework' },
|
||||
{ label: '报废', value: 'scrap' }
|
||||
],
|
||||
approveDialog: {
|
||||
visible: false,
|
||||
review: null
|
||||
},
|
||||
approveAction: 'approve',
|
||||
approveForm: {
|
||||
reviewId: undefined,
|
||||
leaderOpinion: '',
|
||||
leaderSign: ''
|
||||
},
|
||||
approveCoilList: [],
|
||||
approveCoilMap: {},
|
||||
approveLoading: false,
|
||||
rejectReason: ''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
listQualityReview(this.queryParams).then(res => {
|
||||
this.todoList = res.rows || []
|
||||
this.total = res.total || 0
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleRowClick(row) {
|
||||
this.handleQuickApprove(row)
|
||||
},
|
||||
handleQuickApprove(row) {
|
||||
this.approveAction = 'approve'
|
||||
this.approveDialog.review = row
|
||||
this.approveForm = { reviewId: row.reviewId, leaderOpinion: '', leaderSign: '' }
|
||||
this.rejectReason = ''
|
||||
this.approveDialog.visible = true
|
||||
|
||||
// 加载明细
|
||||
getQualityReview(row.reviewId).then(res => {
|
||||
const data = res.data
|
||||
this.approveCoilList = data.coilList || []
|
||||
const map = {}
|
||||
;(data.coilList || []).forEach(c => {
|
||||
map[c.detailId] = c.regradeQuality || ''
|
||||
})
|
||||
this.approveCoilMap = map
|
||||
})
|
||||
},
|
||||
handleQuickReject(row) {
|
||||
this.$prompt('请输入驳回原因', '驳回评审单', { inputType: 'textarea', inputPattern: /.+/, inputErrorMessage: '驳回原因不能为空' }).then(({ value }) => {
|
||||
rejectQualityReview(row.reviewId, value).then(() => {
|
||||
this.$modal.msgSuccess('已驳回')
|
||||
this.getList()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
doApprove() {
|
||||
if (!this.approveForm.leaderOpinion) {
|
||||
this.$modal.msgError('请输入审批意见')
|
||||
return
|
||||
}
|
||||
const coilRegradeList = this.approveCoilList.map(c => ({
|
||||
detailId: c.detailId,
|
||||
regradeQuality: this.approveCoilMap[c.detailId]
|
||||
}))
|
||||
if (coilRegradeList.some(r => !r.regradeQuality)) {
|
||||
this.$modal.msgError('请为每个钢卷指定改判后质量状态')
|
||||
return
|
||||
}
|
||||
this.approveLoading = true
|
||||
approveQualityReview({
|
||||
reviewId: this.approveDialog.review.reviewId,
|
||||
leaderOpinion: this.approveForm.leaderOpinion,
|
||||
leaderSign: this.approveForm.leaderSign,
|
||||
coilRegradeList
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess('审批通过')
|
||||
this.approveDialog.visible = false
|
||||
this.approveLoading = false
|
||||
this.getList()
|
||||
}).catch(() => { this.approveLoading = false })
|
||||
},
|
||||
doReject() {
|
||||
if (!this.rejectReason) {
|
||||
this.$modal.msgError('请输入驳回原因')
|
||||
return
|
||||
}
|
||||
this.approveLoading = true
|
||||
rejectQualityReview(this.approveDialog.review.reviewId, this.rejectReason).then(() => {
|
||||
this.$modal.msgSuccess('已驳回')
|
||||
this.approveDialog.visible = false
|
||||
this.approveLoading = false
|
||||
this.getList()
|
||||
}).catch(() => { this.approveLoading = false })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.todo-header h3 { margin: 0 0 16px; i { margin-right: 6px; } }
|
||||
.approve-info { margin-bottom: 8px; }
|
||||
.approve-opinion-box {
|
||||
margin-top: 12px;
|
||||
label { font-weight: 600; display: block; margin-bottom: 6px; }
|
||||
.opinion-content {
|
||||
background: #f5f7fa;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
line-height: 1.6;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
.coil-regrade-section {
|
||||
margin-top: 12px;
|
||||
.coil-regrade-title { font-weight: 500; margin-bottom: 8px; }
|
||||
}
|
||||
</style>
|
||||
@@ -86,6 +86,10 @@ module.exports = {
|
||||
'@': resolve('src')
|
||||
}
|
||||
},
|
||||
// 解决 chokidar 监视系统文件 (pagefile.sys) 导致的 EBUSY 错误
|
||||
watchOptions: {
|
||||
ignored: ['node_modules', '\.git', /pagefile\.sys$/, /swapfile\.sys$/]
|
||||
},
|
||||
plugins: [
|
||||
// http://doc.klp.vip/klp-vue/other/faq.html#使用gzip解压缩静态文件
|
||||
new CompressionPlugin({
|
||||
|
||||
Reference in New Issue
Block a user