diff --git a/.vscode/launch.json b/.vscode/launch.json index c7169495..2c977587 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "mainClass": "org.jeecg.JeecgSystemApplication", "projectName": "jeecg-system-start", "cwd": "${workspaceFolder}/jeecg-boot/jeecg-module-system/jeecg-system-start", - "vmArgs": "-Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8" + "vmArgs": "-Dfile.encoding=UTF-8 -Dspring.main.banner-mode=log -Dspring.banner.charset=UTF-8 -Dlogging.charset.console=GBK" } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 6dcea9b2..ed09f41c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -27,5 +27,12 @@ "jeecg-boot-platform" ], "java.debug.settings.console": "integratedTerminal", - "java.debug.settings.vmArgs": "-Dspring.main.banner-mode=log -Dspring.banner.charset=UTF-8 -Dlogging.charset.console=GBK" + "java.debug.settings.vmArgs": "-Dfile.encoding=UTF-8 -Dspring.main.banner-mode=log -Dspring.banner.charset=UTF-8 -Dlogging.charset.console=GBK", + "terminal.integrated.defaultProfile.windows": "PowerShell", + "terminal.integrated.profiles.windows": { + "PowerShell": { + "source": "PowerShell", + "args": ["-NoExit", "-Command", "chcp 936 | Out-Null"] + } + } } diff --git a/jeecg-boot/db/mes-xsl-equip-inspect-config-menu-permission.sql b/jeecg-boot/db/mes-xsl-equip-inspect-config-menu-permission.sql new file mode 100644 index 00000000..4f2a379b --- /dev/null +++ b/jeecg-boot/db/mes-xsl-equip-inspect-config-menu-permission.sql @@ -0,0 +1,91 @@ +-- MES 设备点检配置(主子表):建表 + 菜单 + 按钮 + 租户 admin 授权 +-- 权限前缀:mes:mes_xsl_equip_inspect_config:* +-- 父菜单:设备管理;类型字典复用 xslmes_im_item_category(须先有点检及保养项目功能) +-- Flyway:V3.9.2_78__mes_xsl_equip_inspect_config.sql +SET NAMES utf8mb4; + +CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_config` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `equipment_ledger_id` varchar(32) NOT NULL COMMENT '设备台账主键 mes_xsl_equipment_ledger.id', + `equipment_name` varchar(500) DEFAULT NULL COMMENT '设备名称冗余', + `equipment_code` varchar(500) DEFAULT NULL COMMENT '设备编号冗余', + `config_type` varchar(500) NOT NULL COMMENT '配置类型(字典xslmes_im_item_category:inspect点检/maintain保养;同设备同类型唯一)', + `tenant_id` int DEFAULT NULL COMMENT '租户', + `sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门', + `create_by` varchar(500) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(500) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` int DEFAULT '0' COMMENT '删除标记(0正常1删除)', + PRIMARY KEY (`id`), + KEY `idx_meic_tenant_equip_type` (`tenant_id`, `equipment_ledger_id`, `config_type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES设备点检配置'; + +CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_config_line` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `config_id` varchar(32) NOT NULL COMMENT '主表主键 mes_xsl_equip_inspect_config.id', + `inspect_maintain_item_id` varchar(32) NOT NULL COMMENT '点检及保养项目主键 mes_xsl_inspect_maintain_item.id', + `item_code` varchar(500) DEFAULT NULL COMMENT '点检项目编号冗余', + `item_name` varchar(500) DEFAULT NULL COMMENT '项目名称冗余', + `item_category` varchar(500) DEFAULT NULL COMMENT '项目类别冗余', + `item_type` varchar(500) DEFAULT NULL COMMENT '项目类型冗余', + `equipment_part_name` varchar(500) DEFAULT NULL COMMENT '设备部位名称冗余', + `equipment_sub_part_name` varchar(500) DEFAULT NULL COMMENT '设备小部位名称冗余', + `inspect_method` varchar(500) DEFAULT NULL COMMENT '点检方式冗余', + `judgment_criteria` varchar(500) DEFAULT NULL COMMENT '判断基准冗余', + `sort_no` int DEFAULT '0' COMMENT '排序号', + `create_by` varchar(500) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(500) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_meicl_config` (`config_id`), + KEY `idx_meicl_item` (`inspect_maintain_item_id`), + UNIQUE KEY `uk_meicl_config_item` (`config_id`, `inspect_maintain_item_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES设备点检配置明细'; + +SET @mes_tenant_id = 1002; + +SET @mes_equip_pid = ( + SELECT `id` FROM `sys_permission` + WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理' + LIMIT 1 +); +SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133'); + +INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`) +VALUES ('1860000000000000148', @mes_equip_pid, '设备点检配置', '/xslmes/mesXslEquipInspectConfig', 'xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfigList', NULL, 1, NULL, '1', 12, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW()) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`), +`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`), +`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`), +`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:control-outlined'; + +UPDATE `sys_permission` SET `icon` = 'ant-design:control-outlined' WHERE `id` = '1860000000000000148' AND `del_flag` = 0; + +INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES +('1860000000000000149', '1860000000000000148', '新增', 2, 'mes:mes_xsl_equip_inspect_config:add', '1', '1', 0, 'admin', NOW()), +('1860000000000000150', '1860000000000000148', '编辑', 2, 'mes:mes_xsl_equip_inspect_config:edit', '1', '1', 0, 'admin', NOW()), +('1860000000000000151', '1860000000000000148', '删除', 2, 'mes:mes_xsl_equip_inspect_config:delete', '1', '1', 0, 'admin', NOW()), +('1860000000000000152', '1860000000000000148', '批量删除', 2, 'mes:mes_xsl_equip_inspect_config:deleteBatch', '1', '1', 0, 'admin', NOW()), +('1860000000000000153', '1860000000000000148', '导出', 2, 'mes:mes_xsl_equip_inspect_config:exportXls', '1', '1', 0, 'admin', NOW()), +('1860000000000000154', '1860000000000000148', '导入', 2, 'mes:mes_xsl_equip_inspect_config:importExcel', '1', '1', 0, 'admin', NOW()) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), +`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`); + +INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1' +FROM `sys_role` r +CROSS JOIN `sys_permission` p +WHERE r.`tenant_id` = @mes_tenant_id + AND r.`role_code` = 'admin' + AND p.`id` IN ( + '1860000000000000148', + '1860000000000000149', '1860000000000000150', '1860000000000000151', '1860000000000000152', + '1860000000000000153', '1860000000000000154' + ) + AND NOT EXISTS ( + SELECT 1 FROM `sys_role_permission` rp + WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id` + ); diff --git a/jeecg-boot/db/mes-xsl-equip-inspect-record-menu-permission.sql b/jeecg-boot/db/mes-xsl-equip-inspect-record-menu-permission.sql new file mode 100644 index 00000000..d288dfb3 --- /dev/null +++ b/jeecg-boot/db/mes-xsl-equip-inspect-record-menu-permission.sql @@ -0,0 +1,138 @@ +-- MES 点检/保养记录(主子表):建表 + 字典 + 菜单 + 按钮 + 租户 admin 授权 +-- 权限前缀:mes:mes_xsl_equip_inspect_record:* +-- 父菜单:设备管理;依赖设备点检配置、设备台账 +-- Flyway:V3.9.2_79__mes_xsl_equip_inspect_record.sql +SET NAMES utf8mb4; + +INSERT INTO `sys_dict`(`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`) +SELECT REPLACE(UUID(), '-', ''), 'MES点检记录结果', 'xslmes_im_inspect_result', '合格/不合格', 0, 'admin', NOW(), 0, 0 +WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_im_inspect_result' AND `del_flag` = 0); + +INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.`id`, '合格', 'pass', '', 1, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_im_inspect_result' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'pass'); + +INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.`id`, '不合格', 'fail', '', 2, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_im_inspect_result' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'fail'); + +INSERT INTO `sys_dict`(`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`) +SELECT REPLACE(UUID(), '-', ''), 'MES点检记录状态', 'xslmes_im_record_status', '待点检/已点检', 0, 'admin', NOW(), 0, 0 +WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_im_record_status' AND `del_flag` = 0); + +INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.`id`, '待点检', 'pending', '', 1, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_im_record_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'pending'); + +INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.`id`, '已点检', 'done', '', 2, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_im_record_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'done'); + +CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_record` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `record_no` varchar(32) NOT NULL COMMENT '记录编号(EC+yyyyMMdd+4位流水,租户内按日递增)', + `plan_no` varchar(500) DEFAULT NULL COMMENT '计划单号', + `plan_id` varchar(32) DEFAULT NULL COMMENT '计划主键(隐藏)', + `equipment_ledger_id` varchar(32) NOT NULL COMMENT '设备台账主键 mes_xsl_equipment_ledger.id', + `equipment_code` varchar(500) DEFAULT NULL COMMENT '设备编码冗余', + `equipment_name` varchar(500) DEFAULT NULL COMMENT '设备名称冗余', + `equip_inspect_config_id` varchar(32) DEFAULT NULL COMMENT '设备点检配置主键 mes_xsl_equip_inspect_config.id', + `record_type` varchar(500) NOT NULL COMMENT '类型(字典xslmes_im_item_category:inspect点检/maintain保养)', + `inspect_date` date DEFAULT NULL COMMENT '点检日期', + `inspector_user_id` varchar(32) DEFAULT NULL COMMENT '点检人用户ID', + `inspector_username` varchar(500) DEFAULT NULL COMMENT '点检人账号', + `inspector_realname` varchar(500) DEFAULT NULL COMMENT '点检人姓名', + `inspect_result` varchar(500) NOT NULL COMMENT '点检结果(字典xslmes_im_inspect_result:pass合格/fail不合格)', + `record_status` varchar(500) NOT NULL COMMENT '状态(字典xslmes_im_record_status:pending待点检/done已点检)', + `handled_flag` varchar(1) DEFAULT NULL COMMENT '是否已处理(字典yn:1是0否,仅不合格记录使用)', + `handler_user_id` varchar(32) DEFAULT NULL COMMENT '处理人用户ID', + `handler_username` varchar(500) DEFAULT NULL COMMENT '处理人账号', + `handler_realname` varchar(500) DEFAULT NULL COMMENT '处理人姓名', + `handle_time` datetime DEFAULT NULL COMMENT '处理时间', + `tenant_id` int DEFAULT NULL COMMENT '租户', + `sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门', + `create_by` varchar(500) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(500) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` int DEFAULT '0' COMMENT '删除标记(0正常1删除)', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_meir_tenant_record_no` (`tenant_id`, `record_no`), + KEY `idx_meir_equip_type` (`equipment_ledger_id`, `record_type`), + KEY `idx_meir_inspect_date` (`inspect_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES点检保养记录'; + +CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_record_line` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `record_id` varchar(32) NOT NULL COMMENT '主表主键 mes_xsl_equip_inspect_record.id', + `equip_inspect_config_line_id` varchar(32) NOT NULL COMMENT '设备点检配置明细主键 mes_xsl_equip_inspect_config_line.id', + `inspect_maintain_item_id` varchar(32) DEFAULT NULL COMMENT '点检及保养项目主键冗余', + `item_code` varchar(500) DEFAULT NULL COMMENT '点检项目编号冗余', + `item_name` varchar(500) DEFAULT NULL COMMENT '项目名称冗余', + `item_category` varchar(500) DEFAULT NULL COMMENT '项目类别冗余', + `item_type` varchar(500) DEFAULT NULL COMMENT '项目类型冗余', + `equipment_part_name` varchar(500) DEFAULT NULL COMMENT '设备部位冗余', + `equipment_sub_part_name` varchar(500) DEFAULT NULL COMMENT '设备小部位冗余', + `inspect_method` varchar(500) DEFAULT NULL COMMENT '点检方式冗余', + `judgment_criteria` varchar(500) DEFAULT NULL COMMENT '判断基准冗余', + `line_inspect_result` varchar(500) DEFAULT NULL COMMENT '明细点检结果(文本)', + `picture_files` varchar(2000) DEFAULT NULL COMMENT '图片(上传路径,逗号分隔)', + `sort_no` int DEFAULT '0' COMMENT '排序号', + `create_by` varchar(500) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(500) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_meirl_record` (`record_id`), + KEY `idx_meirl_config_line` (`equip_inspect_config_line_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES点检保养记录明细'; + +SET @mes_tenant_id = 1002; + +SET @mes_equip_pid = ( + SELECT `id` FROM `sys_permission` + WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理' + LIMIT 1 +); +SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133'); + +INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`) +VALUES ('1860000000000000155', @mes_equip_pid, '点检保养记录', '/xslmes/mesXslEquipInspectRecord', 'xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList', 'MesXslEquipInspectRecordList', 1, NULL, '1', 13, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW()) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`), +`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`), +`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`), +`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:file-done-outlined'; + +UPDATE `sys_permission` SET `icon` = 'ant-design:file-done-outlined' WHERE `id` = '1860000000000000155' AND `del_flag` = 0; + +INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES +('1860000000000000156', '1860000000000000155', '新增', 2, 'mes:mes_xsl_equip_inspect_record:add', '1', '1', 0, 'admin', NOW()), +('1860000000000000157', '1860000000000000155', '编辑', 2, 'mes:mes_xsl_equip_inspect_record:edit', '1', '1', 0, 'admin', NOW()), +('1860000000000000158', '1860000000000000155', '删除', 2, 'mes:mes_xsl_equip_inspect_record:delete', '1', '1', 0, 'admin', NOW()), +('1860000000000000159', '1860000000000000155', '批量删除', 2, 'mes:mes_xsl_equip_inspect_record:deleteBatch', '1', '1', 0, 'admin', NOW()), +('1860000000000000160', '1860000000000000155', '导出', 2, 'mes:mes_xsl_equip_inspect_record:exportXls', '1', '1', 0, 'admin', NOW()), +('1860000000000000161', '1860000000000000155', '导入', 2, 'mes:mes_xsl_equip_inspect_record:importExcel', '1', '1', 0, 'admin', NOW()) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), +`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`); + +INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1' +FROM `sys_role` r +CROSS JOIN `sys_permission` p +WHERE r.`tenant_id` = @mes_tenant_id + AND r.`role_code` = 'admin' + AND p.`id` IN ( + '1860000000000000155', + '1860000000000000156', '1860000000000000157', '1860000000000000158', '1860000000000000159', + '1860000000000000160', '1860000000000000161' + ) + AND NOT EXISTS ( + SELECT 1 FROM `sys_role_permission` rp + WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id` + ); diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/doc/代码修改日志 b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/doc/代码修改日志 new file mode 100644 index 00000000..419402bc --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/doc/代码修改日志 @@ -0,0 +1,105 @@ +-- author:jiangxh---date:20260521--for: 【配合示方】新增配合示方主子表模块 --- +jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_91__mes_xsl_formula_spec.sql +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpec.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpecLine.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaSpecPage.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecMapper.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecLineMapper.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecService.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslFormulaSpecController.java +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpecList.vue +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.api.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue + +-- author:jiangxh---date:20260521--for: 【配合示方】主表新增混合段1-7合计字段 --- +jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_92__mes_xsl_formula_spec_stage_total.sql +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpec.java +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】STEP全为A/Q时对应胶比重清零 --- +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】含胶率按密炼物料小类汇总重量% --- +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue +jeecgboot-vue3/src/views/mes/material/modules/MesMixerMaterialSelectModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】含胶率物料小类可配置设置弹窗 --- +jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_96__mes_xsl_formula_spec_rubber_content_setting.sql +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpecSetting.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaRubberContentSettingVO.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecSettingMapper.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecSettingService.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecSettingServiceImpl.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslFormulaSpecController.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.api.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaRubberContentSettingModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】含胶率设置改用系统MES物料分类字典 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.api.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaRubberContentSettingModal.vue +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecSettingService.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecSettingServiceImpl.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslFormulaSpecController.java + +-- author:cursor---date:20260521--for: 【配合示方】含胶率设置小类下拉对齐密炼物料loadTreeData加载 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaRubberContentSettingModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】含胶率设置改为loadAllData加载MES物料分类全部节点 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaRubberContentSettingModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】含胶率设置弹窗openModal未传data导致不加载分类 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaRubberContentSettingModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】明细新增物料大类/小类展示列(不落库) --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue +jeecgboot-vue3/src/views/mes/material/modules/MesMixerMaterialSelectModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】明细备注列与1-7段列宽适当缩小 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts + +-- author:cursor---date:20260521--for: 【配合示方】基本信息模块改为汇总格状布局 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】基本信息改为显式表格格状布局 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts + +-- author:cursor---date:20260521--for: 【配合示方】汇总与基本信息标题格增加内阴影 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】明细列表新增列显示/隐藏设置 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaLineColumnSetting.vue + +-- author:cursor---date:20260521--for: 【配合示方】明细列表列设置改为保存后生效并修复勾选状态 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaLineColumnSetting.vue + +-- author:cursor---date:20260521--for: 【配合示方】审批进度编制人展示真实姓名 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpec.java +jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java + +-- author:cursor---date:20260521--for: 【配合示方】编辑页A胶TOTAL PHR缺失时按明细补算回显 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue + +-- author:cursor---date:20260521--for: 【配合示方】编辑打开时基本资料闪清修复 --- +jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectConfigController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectConfigController.java new file mode 100644 index 00000000..8d5c1db0 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectConfigController.java @@ -0,0 +1,230 @@ +package org.jeecg.modules.xslmes.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.system.base.controller.JeecgController; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfig; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfigLine; +import org.jeecg.modules.xslmes.entity.MesXslEquipmentLedger; +import org.jeecg.modules.xslmes.entity.MesXslInspectMaintainItem; +import org.jeecg.modules.xslmes.service.IMesXslEquipInspectConfigService; +import org.jeecg.modules.xslmes.service.IMesXslEquipmentLedgerService; +import org.jeecg.modules.xslmes.service.IMesXslInspectMaintainItemService; +import org.jeecg.modules.xslmes.vo.MesXslEquipInspectConfigPage; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +/** + * MES 设备点检配置(主子表) + */ +@Tag(name = "MES设备点检配置") +@RestController +@RequestMapping("/xslmes/mesXslEquipInspectConfig") +@Slf4j +public class MesXslEquipInspectConfigController + extends JeecgController { + + private static final Set CONFIG_TYPE = Set.of("inspect", "maintain"); + + @Autowired + private IMesXslEquipInspectConfigService mesXslEquipInspectConfigService; + + @Autowired + private IMesXslEquipmentLedgerService mesXslEquipmentLedgerService; + + @Autowired + private IMesXslInspectMaintainItemService mesXslInspectMaintainItemService; + + @Operation(summary = "MES设备点检配置-分页列表查询") + @GetMapping(value = "/list") + public Result> queryPageList( + MesXslEquipInspectConfig model, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(model, req.getParameterMap()); + queryWrapper.orderByDesc("create_time"); + Page page = new Page<>(pageNo, pageSize); + IPage pageList = mesXslEquipInspectConfigService.page(page, queryWrapper); + return Result.OK(pageList); + } + + @AutoLog(value = "MES设备点检配置-添加") + @Operation(summary = "MES设备点检配置-添加") + @RequiresPermissions("mes:mes_xsl_equip_inspect_config:add") + @PostMapping(value = "/add") + public Result add(@RequestBody MesXslEquipInspectConfigPage page) { + MesXslEquipInspectConfig main = new MesXslEquipInspectConfig(); + BeanUtils.copyProperties(page, main); + //update-begin---author:jiangxh ---date:20260519 for:【MES】设备点检配置保存校验----------- + String err = validateForSave(main, page.getLineList(), null); + if (err != null) { + return Result.error(err); + } + //update-end---author:jiangxh ---date:20260519 for:【MES】设备点检配置保存校验----------- + mesXslEquipInspectConfigService.saveMain(main, page.getLineList()); + return Result.OK("添加成功!"); + } + + @AutoLog(value = "MES设备点检配置-编辑") + @Operation(summary = "MES设备点检配置-编辑") + @RequiresPermissions("mes:mes_xsl_equip_inspect_config:edit") + @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST}) + public Result edit(@RequestBody MesXslEquipInspectConfigPage page) { + MesXslEquipInspectConfig main = new MesXslEquipInspectConfig(); + BeanUtils.copyProperties(page, main); + //update-begin---author:jiangxh ---date:20260519 for:【MES】设备点检配置保存校验----------- + String err = validateForSave(main, page.getLineList(), main.getId()); + if (err != null) { + return Result.error(err); + } + //update-end---author:jiangxh ---date:20260519 for:【MES】设备点检配置保存校验----------- + mesXslEquipInspectConfigService.updateMain(main, page.getLineList()); + return Result.OK("编辑成功!"); + } + + @AutoLog(value = "MES设备点检配置-删除") + @Operation(summary = "MES设备点检配置-通过id删除") + @RequiresPermissions("mes:mes_xsl_equip_inspect_config:delete") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + mesXslEquipInspectConfigService.delMain(id); + return Result.OK("删除成功!"); + } + + @AutoLog(value = "MES设备点检配置-批量删除") + @Operation(summary = "MES设备点检配置-批量删除") + @RequiresPermissions("mes:mes_xsl_equip_inspect_config:deleteBatch") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + mesXslEquipInspectConfigService.delBatchMain(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + @Operation(summary = "MES设备点检配置-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name = "id", required = true) String id) { + MesXslEquipInspectConfig entity = mesXslEquipInspectConfigService.getById(id); + if (entity == null) { + return Result.error("未找到对应数据"); + } + return Result.OK(entity); + } + + @Operation(summary = "MES设备点检配置-查询明细") + @GetMapping(value = "/queryLineListByConfigId") + public Result> queryLineListByConfigId( + @RequestParam(name = "id", required = true) String id) { + return Result.OK(mesXslEquipInspectConfigService.selectLinesByConfigId(id)); + } + + @RequiresPermissions("mes:mes_xsl_equip_inspect_config:exportXls") + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, MesXslEquipInspectConfig model) { + return super.exportXls(request, model, MesXslEquipInspectConfig.class, "MES设备点检配置"); + } + + @RequiresPermissions("mes:mes_xsl_equip_inspect_config:importExcel") + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, MesXslEquipInspectConfig.class); + } + + //update-begin---author:jiangxh ---date:20260519 for:【MES】设备点检配置:主表唯一、明细项目不重复、从点检保养项目带出----------- + private String validateForSave( + MesXslEquipInspectConfig main, List lineList, String excludeId) { + if (main == null) { + return "参数不能为空"; + } + if (oConvertUtils.isEmpty(main.getEquipmentLedgerId())) { + return "请选择设备台账"; + } + MesXslEquipmentLedger ledger = mesXslEquipmentLedgerService.getById(main.getEquipmentLedgerId()); + if (ledger == null || isDeleted(ledger.getDelFlag())) { + return "设备台账不存在或已删除"; + } + main.setEquipmentName(ledger.getEquipmentName()); + main.setEquipmentCode(ledger.getEquipmentCode()); + + String configType = main.getConfigType(); + if (configType != null) { + configType = configType.trim(); + } + if (oConvertUtils.isEmpty(configType) || !CONFIG_TYPE.contains(configType)) { + return "类型无效,请选择点检或保养"; + } + main.setConfigType(configType); + + if (mesXslEquipInspectConfigService.isConfigDuplicated( + main.getEquipmentLedgerId(), configType, excludeId, main)) { + return "该设备在此类型(点检/保养)下已存在配置,不能重复添加"; + } + + if (lineList == null || lineList.isEmpty()) { + return "请至少添加一条点检项目明细"; + } + + Set itemIds = new HashSet<>(); + int sort = 0; + for (int i = 0; i < lineList.size(); i++) { + MesXslEquipInspectConfigLine line = lineList.get(i); + if (line == null) { + continue; + } + int rowNo = i + 1; + if (oConvertUtils.isEmpty(line.getInspectMaintainItemId())) { + return "第 " + rowNo + " 行未选择点检及保养项目"; + } + String itemId = line.getInspectMaintainItemId().trim(); + if (!itemIds.add(itemId)) { + return "第 " + rowNo + " 行点检项目与前面行重复,同一配置中点检项目不能重复"; + } + MesXslInspectMaintainItem item = mesXslInspectMaintainItemService.getById(itemId); + if (item == null || isDeleted(item.getDelFlag())) { + return "第 " + rowNo + " 行点检及保养项目不存在或已删除"; + } + if (!configType.equals(item.getItemCategory())) { + return "第 " + rowNo + " 行项目类别与配置类型不一致(配置为" + + ("inspect".equals(configType) ? "点检" : "保养") + + ")"; + } + line.setInspectMaintainItemId(itemId); + line.setItemCode(item.getItemCode()); + line.setItemName(item.getItemName()); + line.setItemCategory(item.getItemCategory()); + line.setItemType(item.getItemType()); + line.setEquipmentPartName(item.getEquipmentPartName()); + line.setEquipmentSubPartName(item.getEquipmentSubPartName()); + line.setInspectMethod(item.getInspectMethod()); + line.setJudgmentCriteria(item.getJudgmentCriteria()); + line.setSortNo(sort++); + } + if (itemIds.isEmpty()) { + return "请至少添加一条点检项目明细"; + } + return null; + } + + private static boolean isDeleted(Integer delFlag) { + return delFlag != null && delFlag.equals(CommonConstant.DEL_FLAG_1); + } + //update-end---author:jiangxh ---date:20260519 for:【MES】设备点检配置:主表唯一、明细项目不重复、从点检保养项目带出----------- +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectRecordController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectRecordController.java new file mode 100644 index 00000000..237e9da2 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectRecordController.java @@ -0,0 +1,411 @@ +package org.jeecg.modules.xslmes.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.system.base.controller.JeecgController; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfig; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectRecord; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectRecordLine; +import org.jeecg.modules.xslmes.entity.MesXslEquipmentLedger; +import org.jeecg.modules.xslmes.service.IMesXslEquipInspectConfigService; +import org.jeecg.modules.xslmes.service.IMesXslEquipInspectRecordService; +import org.jeecg.modules.xslmes.service.IMesXslEquipmentLedgerService; +import org.jeecg.modules.xslmes.util.MesXslEquipInspectBizMsg; +import org.jeecg.modules.xslmes.vo.MesXslEquipInspectRecordBatchCreateDTO; +import org.jeecg.modules.xslmes.vo.MesXslEquipInspectRecordBatchCreateResult; +import org.jeecg.modules.xslmes.vo.MesXslEquipInspectRecordHandleDTO; +import org.jeecg.modules.xslmes.vo.MesXslEquipInspectRecordPage; +import org.springframework.beans.BeanUtils; +import org.springframework.util.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +/** + * MES 点检/保养记录(主子表) + */ +@Tag(name = "MES点检保养记录") +@RestController +@RequestMapping("/xslmes/mesXslEquipInspectRecord") +@Slf4j +public class MesXslEquipInspectRecordController + extends JeecgController { + + private static final Set RECORD_TYPE = Set.of("inspect", "maintain"); + private static final Set INSPECT_RESULT = Set.of("pass", "fail"); + private static final Set RECORD_STATUS = Set.of("pending", "done"); + + @Autowired + private IMesXslEquipInspectRecordService mesXslEquipInspectRecordService; + + @Autowired + private IMesXslEquipmentLedgerService mesXslEquipmentLedgerService; + + @Autowired + private IMesXslEquipInspectConfigService mesXslEquipInspectConfigService; + + @Operation(summary = "MES点检保养记录-分页列表查询") + @GetMapping(value = "/list") + public Result> queryPageList( + MesXslEquipInspectRecord model, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(model, req.getParameterMap()); + queryWrapper.orderByDesc("create_time"); + Page page = new Page<>(pageNo, pageSize); + IPage pageList = mesXslEquipInspectRecordService.page(page, queryWrapper); + return Result.OK(pageList); + } + + @AutoLog(value = "MES点检保养记录-添加") + @Operation(summary = "MES点检保养记录-添加") + @RequiresPermissions("mes:mes_xsl_equip_inspect_record:add") + @PostMapping(value = "/add") + public Result add(@RequestBody MesXslEquipInspectRecordPage page) { + MesXslEquipInspectRecord main = new MesXslEquipInspectRecord(); + BeanUtils.copyProperties(page, main); + String err = validateForSave(main, page.getLineList(), null); + if (err != null) { + return Result.error(err); + } + fillRecordNoIfEmpty(main); + fillInspector(main); + mesXslEquipInspectRecordService.saveMain(main, page.getLineList()); + return Result.OK("添加成功!"); + } + + @AutoLog(value = "MES点检保养记录-编辑") + @Operation(summary = "MES点检保养记录-编辑") + @RequiresPermissions("mes:mes_xsl_equip_inspect_record:edit") + @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST}) + public Result edit(@RequestBody MesXslEquipInspectRecordPage page) { + MesXslEquipInspectRecord main = new MesXslEquipInspectRecord(); + BeanUtils.copyProperties(page, main); + //update-begin---author:jiangxh ---date:20260520 for:【MES】仅待点检可录入,保存后变已点检----------- + if (oConvertUtils.isEmpty(main.getId())) { + return Result.error("记录主键不能为空"); + } + MesXslEquipInspectRecord existing = mesXslEquipInspectRecordService.getById(main.getId()); + if (existing == null) { + return Result.error("未找到对应数据"); + } + if ("done".equals(existing.getRecordStatus())) { + return Result.error("已点检记录不可修改,仅可查看"); + } + main.setRecordStatus("done"); + String err = validateForEntry(main, page.getLineList()); + if (err != null) { + return Result.error(err); + } + fillInspector(main); + mesXslEquipInspectRecordService.updateMain(main, page.getLineList()); + return Result.OK("录入成功!"); + //update-end---author:jiangxh ---date:20260520 for:【MES】仅待点检可录入,保存后变已点检----------- + } + + @AutoLog(value = "MES点检保养记录-删除") + @Operation(summary = "MES点检保养记录-通过id删除") + @RequiresPermissions("mes:mes_xsl_equip_inspect_record:delete") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + mesXslEquipInspectRecordService.delMain(id); + return Result.OK("删除成功!"); + } + + @AutoLog(value = "MES点检保养记录-批量删除") + @Operation(summary = "MES点检保养记录-批量删除") + @RequiresPermissions("mes:mes_xsl_equip_inspect_record:deleteBatch") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + mesXslEquipInspectRecordService.delBatchMain(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + @Operation(summary = "MES点检保养记录-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name = "id", required = true) String id) { + MesXslEquipInspectRecord entity = mesXslEquipInspectRecordService.getById(id); + if (entity == null) { + return Result.error("未找到对应数据"); + } + return Result.OK(entity); + } + + @Operation(summary = "MES点检保养记录-查询明细") + @GetMapping(value = "/queryLineListByRecordId") + public Result> queryLineListByRecordId( + @RequestParam(name = "id", required = true) String id) { + return Result.OK(mesXslEquipInspectRecordService.selectLinesByRecordId(id)); + } + + //update-begin---author:jiangxh ---date:20260521 for:【MES】不合格点检记录登记处理人及处理时间----------- + @AutoLog(value = "MES点检保养记录-不合格处理") + @Operation(summary = "MES点检保养记录-不合格处理") + @RequiresPermissions("mes:mes_xsl_equip_inspect_record:edit") + @PostMapping(value = "/handleFail") + public Result handleFail(@RequestBody MesXslEquipInspectRecordHandleDTO dto) { + try { + mesXslEquipInspectRecordService.handleFailRecord(dto); + return Result.OK("处理成功!"); + } catch (IllegalArgumentException ex) { + return Result.error(ex.getMessage()); + } + } + //update-end---author:jiangxh ---date:20260521 for:【MES】不合格点检记录登记处理人及处理时间----------- + + @Operation(summary = "MES点检保养记录-生成记录编号") + @GetMapping(value = "/generateRecordNo") + public Result generateRecordNo() { + MesXslEquipInspectRecord ctx = new MesXslEquipInspectRecord(); + return Result.OK(mesXslEquipInspectRecordService.generateRecordNo(ctx)); + } + + @AutoLog(value = "MES点检保养记录-从设备台账批量生成") + @Operation(summary = "MES点检保养记录-从设备台账批量生成") + @RequiresPermissions("mes:mes_xsl_equip_inspect_record:add") + @PostMapping(value = "/batchCreateFromEquipment") + public Result batchCreateFromEquipment( + @RequestBody MesXslEquipInspectRecordBatchCreateDTO dto) { + if (dto == null || CollectionUtils.isEmpty(dto.getEquipmentLedgerIds())) { + return Result.error("请先选择设备"); + } + String recordType = dto.getRecordType(); + if (recordType != null) { + recordType = recordType.trim(); + } + if (oConvertUtils.isEmpty(recordType) || !RECORD_TYPE.contains(recordType)) { + return Result.error("类型无效,请使用点检或保养"); + } + MesXslEquipInspectRecord inspectorCtx = new MesXslEquipInspectRecord(); + fillInspector(inspectorCtx); + MesXslEquipInspectRecordBatchCreateResult result = + mesXslEquipInspectRecordService.batchCreateFromEquipment( + dto.getEquipmentLedgerIds(), recordType, inspectorCtx); + if (result.getSuccessCount() <= 0 && !result.getFailMessages().isEmpty()) { + return Result.error(String.join(";", result.getFailMessages())); + } + String msg = "成功生成 " + result.getSuccessCount() + " 条记录"; + if (!result.getFailMessages().isEmpty()) { + msg = msg + ";" + String.join(";", result.getFailMessages()); + } + return Result.OK(msg, result); + } + + @Operation(summary = "MES点检保养记录-按设备与类型带出配置明细") + @GetMapping(value = "/loadLinesByEquipment") + public Result> loadLinesByEquipment( + @RequestParam(name = "equipmentLedgerId") String equipmentLedgerId, + @RequestParam(name = "recordType") String recordType) { + String type = recordType != null ? recordType.trim() : ""; + if (oConvertUtils.isEmpty(equipmentLedgerId) || !RECORD_TYPE.contains(type)) { + return Result.error("请选择设备与类型(点检/保养)"); + } + List lines = + mesXslEquipInspectRecordService.buildLinesFromEquipConfig(equipmentLedgerId, type); + if (lines.isEmpty()) { + MesXslEquipmentLedger ledger = mesXslEquipmentLedgerService.getById(equipmentLedgerId); + String equipName = + ledger != null && oConvertUtils.isNotEmpty(ledger.getEquipmentName()) + ? ledger.getEquipmentName() + : (ledger != null ? ledger.getEquipmentCode() : equipmentLedgerId); + return Result.error(MesXslEquipInspectBizMsg.noConfigMessage(equipName, type)); + } + return Result.OK(lines); + } + + @RequiresPermissions("mes:mes_xsl_equip_inspect_record:exportXls") + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, MesXslEquipInspectRecord model) { + return super.exportXls(request, model, MesXslEquipInspectRecord.class, "MES点检保养记录"); + } + + @RequiresPermissions("mes:mes_xsl_equip_inspect_record:importExcel") + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, MesXslEquipInspectRecord.class); + } + + private void fillRecordNoIfEmpty(MesXslEquipInspectRecord main) { + if (oConvertUtils.isEmpty(main.getRecordNo())) { + main.setRecordNo(mesXslEquipInspectRecordService.generateRecordNo(main)); + } + } + + private void fillInspector(MesXslEquipInspectRecord main) { + if (SecurityUtils.getSubject() == null || SecurityUtils.getSubject().getPrincipal() == null) { + return; + } + if (!(SecurityUtils.getSubject().getPrincipal() instanceof LoginUser user)) { + return; + } + main.setInspectorUserId(user.getId()); + main.setInspectorUsername(user.getUsername()); + main.setInspectorRealname(user.getRealname()); + } + + //update-begin---author:jiangxh ---date:20260520 for:【MES】录入点检结果:必填项校验,保存为已点检----------- + private String validateForEntry(MesXslEquipInspectRecord main, List lineList) { + String err = validateForSave(main, lineList, main.getId()); + if (err != null) { + return err; + } + if (main.getInspectDate() == null) { + return "请选择点检日期"; + } + if (oConvertUtils.isEmpty(main.getInspectorUserId()) && oConvertUtils.isEmpty(main.getInspectorRealname())) { + return "点检人不能为空"; + } + String inspectResult = main.getInspectResult(); + if (inspectResult != null) { + inspectResult = inspectResult.trim(); + } + if (oConvertUtils.isEmpty(inspectResult) || !INSPECT_RESULT.contains(inspectResult)) { + return "请选择点检结果(合格/不合格)"; + } + main.setInspectResult(inspectResult); + main.setRecordStatus("done"); + //update-begin---author:jiangxh ---date:20260521 for:【MES】不合格记录默认未处理----------- + if ("fail".equals(inspectResult)) { + main.setHandledFlag("0"); + } else { + main.setHandledFlag(null); + main.setHandlerUserId(null); + main.setHandlerUsername(null); + main.setHandlerRealname(null); + main.setHandleTime(null); + } + //update-end---author:jiangxh ---date:20260521 for:【MES】不合格记录默认未处理----------- + return null; + } + //update-end---author:jiangxh ---date:20260520 for:【MES】录入点检结果:必填项校验,保存为已点检----------- + + //update-begin---author:jiangxh ---date:20260520 for:【MES】点检保养记录保存校验与配置明细关联----------- + private String validateForSave( + MesXslEquipInspectRecord main, List lineList, String excludeId) { + if (main == null) { + return "参数不能为空"; + } + if (oConvertUtils.isEmpty(main.getEquipmentLedgerId())) { + return "请选择设备"; + } + MesXslEquipmentLedger ledger = mesXslEquipmentLedgerService.getById(main.getEquipmentLedgerId()); + if (ledger == null || isDeleted(ledger.getDelFlag())) { + return "设备台账不存在或已删除"; + } + main.setEquipmentName(ledger.getEquipmentName()); + main.setEquipmentCode(ledger.getEquipmentCode()); + + String recordType = main.getRecordType(); + if (recordType != null) { + recordType = recordType.trim(); + } + if (oConvertUtils.isEmpty(recordType) || !RECORD_TYPE.contains(recordType)) { + return "类型无效,请选择点检或保养"; + } + main.setRecordType(recordType); + + if (main.getInspectDate() == null) { + main.setInspectDate(new Date()); + } + + String recordStatus = main.getRecordStatus(); + if (recordStatus != null) { + recordStatus = recordStatus.trim(); + } + if (oConvertUtils.isEmpty(recordStatus) || !RECORD_STATUS.contains(recordStatus)) { + return "请选择状态(待点检/已点检)"; + } + main.setRecordStatus(recordStatus); + + String inspectResult = main.getInspectResult(); + if (inspectResult != null) { + inspectResult = inspectResult.trim(); + } + if ("done".equals(recordStatus)) { + if (oConvertUtils.isEmpty(inspectResult) || !INSPECT_RESULT.contains(inspectResult)) { + return "已点检时请选择点检结果(合格/不合格)"; + } + main.setInspectResult(inspectResult); + } else { + if (oConvertUtils.isNotEmpty(inspectResult) && !INSPECT_RESULT.contains(inspectResult)) { + return "点检结果无效"; + } + main.setInspectResult(oConvertUtils.isEmpty(inspectResult) ? null : inspectResult); + } + + if (oConvertUtils.isEmpty(main.getRecordNo())) { + return "记录编号不能为空"; + } + + com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper cw = + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>(); + cw.eq(MesXslEquipInspectConfig::getEquipmentLedgerId, main.getEquipmentLedgerId()); + cw.eq(MesXslEquipInspectConfig::getConfigType, recordType); + cw.and( + q -> + q.eq(MesXslEquipInspectConfig::getDelFlag, CommonConstant.DEL_FLAG_0) + .or() + .isNull(MesXslEquipInspectConfig::getDelFlag)); + MesXslEquipInspectConfig config = mesXslEquipInspectConfigService.getOne(cw, false); + if (config == null) { + String equipName = + oConvertUtils.isNotEmpty(ledger.getEquipmentName()) + ? ledger.getEquipmentName() + : ledger.getEquipmentCode(); + return MesXslEquipInspectBizMsg.noConfigMessage(equipName, recordType); + } + main.setEquipInspectConfigId(config.getId()); + + if (lineList == null || lineList.isEmpty()) { + return "明细不能为空,请选择设备后自动带出点检项目"; + } + + Set configLineIds = new HashSet<>(); + int sort = 0; + for (int i = 0; i < lineList.size(); i++) { + MesXslEquipInspectRecordLine line = lineList.get(i); + if (line == null) { + continue; + } + int rowNo = i + 1; + if (oConvertUtils.isEmpty(line.getEquipInspectConfigLineId())) { + return "第 " + rowNo + " 行未关联点检配置明细"; + } + String lineId = line.getEquipInspectConfigLineId().trim(); + if (!configLineIds.add(lineId)) { + return "第 " + rowNo + " 行点检配置明细重复"; + } + line.setEquipInspectConfigLineId(lineId); + line.setSortNo(sort++); + } + if (configLineIds.isEmpty()) { + return "明细不能为空"; + } + return null; + } + + private static boolean isDeleted(Integer delFlag) { + return delFlag != null && delFlag.equals(CommonConstant.DEL_FLAG_1); + } + //update-end---author:jiangxh ---date:20260520 for:【MES】点检保养记录保存校验与配置明细关联----------- +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslFormulaSpecController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslFormulaSpecController.java new file mode 100644 index 00000000..0ad744a1 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslFormulaSpecController.java @@ -0,0 +1,208 @@ +package org.jeecg.modules.xslmes.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.common.system.base.controller.JeecgController; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine; +import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecService; +import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecSettingService; +import org.jeecg.modules.xslmes.vo.MesXslFormulaRubberContentSettingVO; +import org.jeecg.modules.xslmes.vo.MesXslFormulaSpecPage; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +/** + * MES 配合示方 + */ +@Tag(name = "MES配合示方") +@RestController +@RequestMapping("/xslmes/mesXslFormulaSpec") +@Slf4j +public class MesXslFormulaSpecController extends JeecgController { + + @Autowired + private IMesXslFormulaSpecService mesXslFormulaSpecService; + + @Autowired + private IMesXslFormulaSpecSettingService mesXslFormulaSpecSettingService; + + @Operation(summary = "MES配合示方-分页列表查询") + @GetMapping(value = "/list") + public Result> queryPageList( + MesXslFormulaSpec model, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + @RequestParam(name = "keyword", required = false) String keyword, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(model, req.getParameterMap()); + if (oConvertUtils.isNotEmpty(keyword)) { + queryWrapper.and( + w -> w.like("spec_code", keyword) + .or() + .like("rubber_code", keyword) + .or() + .like("issue_number", keyword) + .or() + .like("purpose", keyword)); + } + queryWrapper.orderByDesc("update_time").orderByDesc("create_time"); + Page page = new Page<>(pageNo, pageSize); + IPage pageList = mesXslFormulaSpecService.page(page, queryWrapper); + return Result.OK(pageList); + } + + @AutoLog(value = "MES配合示方-添加") + @Operation(summary = "MES配合示方-添加") + @RequiresPermissions("xslmes:mes_xsl_formula_spec:add") + @PostMapping(value = "/add") + public Result add(@RequestBody MesXslFormulaSpecPage page) { + //update-begin---author:jiangxh ---date:20260521 for:【配合示方】主子表保存校验----------- + String err = validateMain(page); + if (err != null) { + return Result.error(err); + } + //update-end---author:jiangxh ---date:20260521 for:【配合示方】主子表保存校验----------- + MesXslFormulaSpec main = new MesXslFormulaSpec(); + BeanUtils.copyProperties(page, main); + mesXslFormulaSpecService.saveMain(main, page.getLineList()); + return Result.OK("添加成功!"); + } + + @AutoLog(value = "MES配合示方-编辑") + @Operation(summary = "MES配合示方-编辑") + @RequiresPermissions("xslmes:mes_xsl_formula_spec:edit") + @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST}) + public Result edit(@RequestBody MesXslFormulaSpecPage page) { + //update-begin---author:jiangxh ---date:20260521 for:【配合示方】主子表保存校验----------- + String err = validateMain(page); + if (err != null) { + return Result.error(err); + } + //update-end---author:jiangxh ---date:20260521 for:【配合示方】主子表保存校验----------- + MesXslFormulaSpec main = new MesXslFormulaSpec(); + BeanUtils.copyProperties(page, main); + mesXslFormulaSpecService.updateMain(main, page.getLineList()); + return Result.OK("编辑成功!"); + } + + @AutoLog(value = "MES配合示方-删除") + @Operation(summary = "MES配合示方-通过id删除") + @RequiresPermissions("xslmes:mes_xsl_formula_spec:delete") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + mesXslFormulaSpecService.delMain(id); + return Result.OK("删除成功!"); + } + + @AutoLog(value = "MES配合示方-批量删除") + @Operation(summary = "MES配合示方-批量删除") + @RequiresPermissions("xslmes:mes_xsl_formula_spec:deleteBatch") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + mesXslFormulaSpecService.delBatchMain(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + @Operation(summary = "MES配合示方-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name = "id", required = true) String id) { + MesXslFormulaSpec entity = mesXslFormulaSpecService.getByIdWithLines(id); + if (entity == null) { + return Result.error("未找到对应数据"); + } + return Result.OK(entity); + } + + @Operation(summary = "MES配合示方-查询明细") + @GetMapping(value = "/queryLineListByMainId") + public Result> queryLineListByMainId(@RequestParam(name = "id", required = true) String id) { + return Result.OK(mesXslFormulaSpecService.selectLinesByMainId(id)); + } + + //update-begin---author:cursor ---date:20260521 for:配合示方胶料代号自动生成----------- + @Operation(summary = "MES配合示方-生成胶料代号") + @GetMapping(value = "/generateRubberCode") + public Result> generateRubberCode( + @RequestParam(name = "rubberMaterialId") String rubberMaterialId, + @RequestParam(name = "category") String category, + @RequestParam(name = "excludeSpecId", required = false) String excludeSpecId) { + try { + String rubberCode = mesXslFormulaSpecService.generateRubberCode(rubberMaterialId, category, excludeSpecId); + return Result.OK(Map.of("rubberCode", rubberCode)); + } catch (IllegalArgumentException ex) { + return Result.error(ex.getMessage()); + } + } + //update-end---author:cursor ---date:20260521 for:配合示方胶料代号自动生成----------- + + //update-begin---author:cursor ---date:20260521 for:【配合示方】含胶率物料小类可配置----------- + @Operation(summary = "MES配合示方-查询含胶率物料小类配置") + @GetMapping(value = "/getRubberContentSetting") + public Result getRubberContentSetting() { + return Result.OK(mesXslFormulaSpecSettingService.getRubberContentSetting()); + } + + @AutoLog(value = "MES配合示方-保存含胶率物料小类配置") + @Operation(summary = "MES配合示方-保存含胶率物料小类配置") + @RequiresPermissions("xslmes:mes_xsl_formula_spec:edit") + @PostMapping(value = "/saveRubberContentSetting") + public Result saveRubberContentSetting(@RequestBody MesXslFormulaRubberContentSettingVO setting) { + mesXslFormulaSpecSettingService.saveRubberContentSetting(setting); + return Result.OK("保存成功"); + } + //update-end---author:cursor ---date:20260521 for:【配合示方】含胶率物料小类可配置----------- + + @RequiresPermissions("xslmes:mes_xsl_formula_spec:exportXls") + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, MesXslFormulaSpec model) { + return super.exportXls(request, model, MesXslFormulaSpec.class, "配合示方"); + } + + @RequiresPermissions("xslmes:mes_xsl_formula_spec:importExcel") + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, MesXslFormulaSpec.class); + } + + //update-begin---author:jiangxh ---date:20260521 for:【配合示方】主子表保存校验----------- + private String validateMain(MesXslFormulaSpecPage page) { + if (oConvertUtils.isEmpty(page.getSpecCode())) { + return "请输入示方编号"; + } + if (oConvertUtils.isEmpty(page.getRubberCode())) { + return "请选择胶料并生成胶料代号"; + } + if (oConvertUtils.isEmpty(page.getRubberMaterialId())) { + return "请选择胶料信息"; + } + if (page.getMixingStages() != null && (page.getMixingStages() < 1 || page.getMixingStages() > 7)) { + return "混合段数必须在1-7之间"; + } + if (page.getLineList() == null || page.getLineList().isEmpty()) { + return "请至少添加一行配合明细"; + } + return null; + } + //update-end---author:jiangxh ---date:20260521 for:【配合示方】主子表保存校验----------- +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectConfig.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectConfig.java new file mode 100644 index 00000000..c834b4ae --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectConfig.java @@ -0,0 +1,65 @@ +package org.jeecg.modules.xslmes.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.jeecg.common.aspect.annotation.Dict; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * MES 设备点检配置主表(表 mes_xsl_equip_inspect_config) + */ +@Data +@TableName("mes_xsl_equip_inspect_config") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@Schema(description = "MES设备点检配置") +public class MesXslEquipInspectConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_ID) + private String id; + + @Schema(description = "设备台账主键 mes_xsl_equipment_ledger.id") + private String equipmentLedgerId; + + @Excel(name = "设备名称", width = 22) + @Schema(description = "设备名称冗余") + private String equipmentName; + + @Excel(name = "设备编号", width = 18) + @Schema(description = "设备编号冗余") + private String equipmentCode; + + @Excel(name = "类型", width = 12, dicCode = "xslmes_im_item_category") + @Dict(dicCode = "xslmes_im_item_category") + @Schema(description = "配置类型(字典xslmes_im_item_category:inspect点检/maintain保养;同设备同类型唯一)") + private String configType; + + private Integer tenantId; + private String sysOrgCode; + private String createBy; + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + private String updateBy; + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + private Integer delFlag; + + @TableField(exist = false) + @Schema(description = "点检项目明细") + private List lineList; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectConfigLine.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectConfigLine.java new file mode 100644 index 00000000..e61bb50b --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectConfigLine.java @@ -0,0 +1,73 @@ +package org.jeecg.modules.xslmes.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.jeecg.common.aspect.annotation.Dict; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * MES 设备点检配置明细(表 mes_xsl_equip_inspect_config_line) + */ +@Data +@TableName("mes_xsl_equip_inspect_config_line") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@Schema(description = "MES设备点检配置明细") +public class MesXslEquipInspectConfigLine implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_ID) + private String id; + + @Schema(description = "主表主键 mes_xsl_equip_inspect_config.id") + private String configId; + + @Schema(description = "点检及保养项目主键 mes_xsl_inspect_maintain_item.id") + private String inspectMaintainItemId; + + @Schema(description = "点检项目编号冗余") + private String itemCode; + + @Schema(description = "项目名称冗余") + private String itemName; + + @Dict(dicCode = "xslmes_im_item_category") + @Schema(description = "项目类别冗余") + private String itemCategory; + + @Dict(dicCode = "xslmes_im_item_type") + @Schema(description = "项目类型冗余") + private String itemType; + + @Schema(description = "设备部位名称冗余") + private String equipmentPartName; + + @Schema(description = "设备小部位名称冗余") + private String equipmentSubPartName; + + @Dict(dicCode = "xslmes_im_inspect_method") + @Schema(description = "点检方式冗余") + private String inspectMethod; + + @Schema(description = "判断基准冗余") + private String judgmentCriteria; + + private Integer sortNo; + private String createBy; + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + private String updateBy; + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectRecord.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectRecord.java new file mode 100644 index 00000000..bb70d20d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectRecord.java @@ -0,0 +1,126 @@ +package org.jeecg.modules.xslmes.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.jeecg.common.aspect.annotation.Dict; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * MES 点检/保养记录主表(表 mes_xsl_equip_inspect_record) + */ +@Data +@TableName("mes_xsl_equip_inspect_record") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@Schema(description = "MES点检保养记录") +public class MesXslEquipInspectRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_ID) + private String id; + + @Excel(name = "记录编号", width = 20) + @Schema(description = "记录编号 EC+yyyyMMdd+4位流水") + private String recordNo; + + @Excel(name = "计划单号", width = 18) + @Schema(description = "计划单号") + private String planNo; + + @Schema(description = "计划主键") + private String planId; + + @Schema(description = "设备台账主键") + private String equipmentLedgerId; + + @Excel(name = "设备编码", width = 16) + @Schema(description = "设备编码冗余") + private String equipmentCode; + + @Excel(name = "设备名称", width = 20) + @Schema(description = "设备名称冗余") + private String equipmentName; + + @Schema(description = "设备点检配置主键") + private String equipInspectConfigId; + + @Excel(name = "类型", width = 10, dicCode = "xslmes_im_item_category") + @Dict(dicCode = "xslmes_im_item_category") + @Schema(description = "点检/保养类型") + private String recordType; + + @Excel(name = "点检日期", width = 12, format = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @Schema(description = "点检日期") + private Date inspectDate; + + @Schema(description = "点检人用户ID") + private String inspectorUserId; + + @Schema(description = "点检人账号") + private String inspectorUsername; + + @Excel(name = "点检人", width = 12) + @Schema(description = "点检人姓名") + private String inspectorRealname; + + @Excel(name = "点检结果", width = 10, dicCode = "xslmes_im_inspect_result") + @Dict(dicCode = "xslmes_im_inspect_result") + @Schema(description = "点检结果 pass/fail") + private String inspectResult; + + @Excel(name = "状态", width = 10, dicCode = "xslmes_im_record_status") + @Dict(dicCode = "xslmes_im_record_status") + @Schema(description = "记录状态 pending/done") + private String recordStatus; + + @Excel(name = "是否已处理", width = 10, dicCode = "yn") + @Dict(dicCode = "yn") + @Schema(description = "是否已处理(字典yn:1是0否,不合格记录使用)") + private String handledFlag; + + @Schema(description = "处理人用户ID") + private String handlerUserId; + + @Schema(description = "处理人账号") + private String handlerUsername; + + @Excel(name = "处理人", width = 12) + @Schema(description = "处理人姓名") + private String handlerRealname; + + @Excel(name = "处理时间", width = 18, format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "处理时间") + private Date handleTime; + + private Integer tenantId; + private String sysOrgCode; + private String createBy; + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + private String updateBy; + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + private Integer delFlag; + + @TableField(exist = false) + @Schema(description = "点检明细") + private List lineList; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectRecordLine.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectRecordLine.java new file mode 100644 index 00000000..88a0e604 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectRecordLine.java @@ -0,0 +1,82 @@ +package org.jeecg.modules.xslmes.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.jeecg.common.aspect.annotation.Dict; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * MES 点检/保养记录明细(表 mes_xsl_equip_inspect_record_line) + */ +@Data +@TableName("mes_xsl_equip_inspect_record_line") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@Schema(description = "MES点检保养记录明细") +public class MesXslEquipInspectRecordLine implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_ID) + private String id; + + @Schema(description = "主表主键") + private String recordId; + + @Schema(description = "设备点检配置明细主键") + private String equipInspectConfigLineId; + + @Schema(description = "点检及保养项目主键冗余") + private String inspectMaintainItemId; + + @Schema(description = "点检项目编号") + private String itemCode; + + @Schema(description = "项目名称") + private String itemName; + + @Dict(dicCode = "xslmes_im_item_category") + @Schema(description = "项目类别") + private String itemCategory; + + @Dict(dicCode = "xslmes_im_item_type") + @Schema(description = "项目类型") + private String itemType; + + @Schema(description = "设备部位") + private String equipmentPartName; + + @Schema(description = "设备小部位") + private String equipmentSubPartName; + + @Dict(dicCode = "xslmes_im_inspect_method") + @Schema(description = "点检方式") + private String inspectMethod; + + @Schema(description = "判断基准") + private String judgmentCriteria; + + @Schema(description = "明细点检结果文本") + private String lineInspectResult; + + @Schema(description = "图片路径,逗号分隔") + private String pictureFiles; + + private Integer sortNo; + private String createBy; + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + private String updateBy; + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpec.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpec.java new file mode 100644 index 00000000..474910f8 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpec.java @@ -0,0 +1,220 @@ +package org.jeecg.modules.xslmes.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.jeecg.common.aspect.annotation.Dict; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * MES 配合示方 + */ +@Data +@TableName("mes_xsl_formula_spec") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@Schema(description = "MES配合示方") +public class MesXslFormulaSpec implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_ID) + private String id; + + @Excel(name = "分类", width = 10, dicCode = "xslmes_formula_spec_category") + @Dict(dicCode = "xslmes_formula_spec_category") + @Schema(description = "分类") + private String category; + + @Excel(name = "示方编号", width = 18) + @Schema(description = "示方编号") + private String specCode; + + @Excel(name = "胶料代号", width = 18) + @Schema(description = "胶料代号") + private String rubberCode; + + @Schema(description = "胶料ID(关联mes_material.id)") + private String rubberMaterialId; + + @Excel(name = "基本配合", width = 15) + @Schema(description = "基本配合") + private String basicFormula; + + @Excel(name = "发行日期", width = 15, format = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @Schema(description = "发行日期") + private Date issueDate; + + @Excel(name = "用途", width = 20) + @Schema(description = "用途") + private String purpose; + + @Excel(name = "发行编号", width = 15) + @Schema(description = "发行编号") + private String issueNumber; + + @Excel(name = "混合段数", width = 10) + @Schema(description = "混合段数") + private Integer mixingStages; + + @Excel(name = "混合机器", width = 15) + @Schema(description = "混合机器") + private String mixingMachine; + + @Schema(description = "发行部门ID") + private String issueDeptId; + + @Excel(name = "发行部门", width = 15) + @Schema(description = "发行部门名称") + private String issueDeptName; + + @Excel(name = "A胶TOTAL PHR", width = 14) + @Schema(description = "A胶TOTAL PHR") + private BigDecimal aRubberTotalPhr; + + @Excel(name = "TOTAL PHR", width = 12) + @Schema(description = "TOTAL PHR") + private BigDecimal totalPhr; + + //update-begin---author:jiangxh ---date:20260521 for:【配合示方】主表新增混合段1-7合计字段----------- + @Excel(name = "混合段1合计", width = 12) + @Schema(description = "混合段1合计") + private BigDecimal stage1Total; + + @Excel(name = "混合段2合计", width = 12) + @Schema(description = "混合段2合计") + private BigDecimal stage2Total; + + @Excel(name = "混合段3合计", width = 12) + @Schema(description = "混合段3合计") + private BigDecimal stage3Total; + + @Excel(name = "混合段4合计", width = 12) + @Schema(description = "混合段4合计") + private BigDecimal stage4Total; + + @Excel(name = "混合段5合计", width = 12) + @Schema(description = "混合段5合计") + private BigDecimal stage5Total; + + @Excel(name = "混合段6合计", width = 12) + @Schema(description = "混合段6合计") + private BigDecimal stage6Total; + + @Excel(name = "混合段7合计", width = 12) + @Schema(description = "混合段7合计") + private BigDecimal stage7Total; + //update-end---author:jiangxh ---date:20260521 for:【配合示方】主表新增混合段1-7合计字段----------- + + @Excel(name = "发行理由", width = 30) + @Schema(description = "发行理由") + private String issueReason; + + @Excel(name = "天然橡胶", width = 12) + @Schema(description = "天然橡胶") + private BigDecimal naturalRubber; + + @Excel(name = "合成橡胶", width = 12) + @Schema(description = "合成橡胶") + private BigDecimal syntheticRubber; + + @Excel(name = "合计", width = 12) + @Schema(description = "合计") + private BigDecimal totalAmount; + + @Excel(name = "重量单价", width = 12) + @Schema(description = "重量单价") + private BigDecimal weightUnitPrice; + + @Excel(name = "体积单价", width = 12) + @Schema(description = "体积单价") + private BigDecimal volumeUnitPrice; + + @Excel(name = "Q胶比重", width = 12) + @Schema(description = "Q胶比重") + @TableField("q_rubber_sg") + private BigDecimal qRubberSg; + + @Excel(name = "A胶比重", width = 12) + @Schema(description = "A胶比重") + @TableField("a_rubber_sg") + private BigDecimal aRubberSg; + + @Excel(name = "人工配料", width = 10, replace = {"是_1", "否_0"}) + @Schema(description = "是否有人工配料(0否 1是)") + private Integer hasManualBatch; + + @Excel(name = "状态", width = 12, dicCode = "xslmes_formula_spec_status") + @Dict(dicCode = "xslmes_formula_spec_status") + @Schema(description = "状态") + private String status; + + @Excel(name = "校对人", width = 12) + @Schema(description = "校对人") + private String proofreadBy; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "校对时间") + private Date proofreadTime; + + @Excel(name = "审核人", width = 12) + @Schema(description = "审核人") + private String auditBy; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "审核时间") + private Date auditTime; + + @Excel(name = "批准人", width = 12) + @Schema(description = "批准人") + private String approveBy; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "批准时间") + private Date approveTime; + + @Excel(name = "创建人", width = 12, dictTable = "sys_user", dicText = "realname", dicCode = "username") + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "username") + private String createBy; + + /** queryById 等非分页接口补充创建人姓名(DictAspect 仅翻译分页列表) */ + @TableField(exist = false) + @Schema(description = "创建人姓名") + private String createBy_dictText; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + private String updateBy; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + @Schema(description = "租户ID") + private Integer tenantId; + + private String sysOrgCode; + private Integer delFlag; + + @TableField(exist = false) + @Schema(description = "配合明细") + private List lineList; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpecLine.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpecLine.java new file mode 100644 index 00000000..fe18d492 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpecLine.java @@ -0,0 +1,105 @@ +package org.jeecg.modules.xslmes.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.jeecg.common.aspect.annotation.Dict; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * MES 配合示方明细 + */ +@Data +@TableName("mes_xsl_formula_spec_line") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@Schema(description = "MES配合示方明细") +public class MesXslFormulaSpecLine implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_ID) + private String id; + + @Schema(description = "配合示方主表ID") + private String formulaSpecId; + + @Schema(description = "行序号") + private Integer sortNo; + + @Schema(description = "PHR") + private BigDecimal phr; + + @Schema(description = "密炼物料ID") + private String mixerMaterialId; + + @Schema(description = "密炼物料编码") + private String mixerMaterialCode; + + @Schema(description = "密炼物料名称") + private String mixerMaterialName; + + @Schema(description = "物料描述") + private String materialDesc; + + @Dict(dicCode = "xslmes_formula_spec_step") + @Schema(description = "STEP") + private String step; + + @Dict(dicCode = "xslmes_formula_spec_weigh_mode") + @Schema(description = "称量方式") + private String weighMode; + + @Schema(description = "重量%") + private BigDecimal weightPercent; + + @Schema(description = "体积") + private BigDecimal volume; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "混合段1") + private BigDecimal stage1; + + @Schema(description = "混合段2") + private BigDecimal stage2; + + @Schema(description = "混合段3") + private BigDecimal stage3; + + @Schema(description = "混合段4") + private BigDecimal stage4; + + @Schema(description = "混合段5") + private BigDecimal stage5; + + @Schema(description = "混合段6") + private BigDecimal stage6; + + @Schema(description = "混合段7") + private BigDecimal stage7; + + @Schema(description = "租户ID") + private Integer tenantId; + + private String createBy; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + private String updateBy; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpecSetting.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpecSetting.java new file mode 100644 index 00000000..9e5b4212 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpecSetting.java @@ -0,0 +1,48 @@ +package org.jeecg.modules.xslmes.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 配合示方模块配置 + */ +@Data +@TableName("mes_xsl_formula_spec_setting") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@Schema(description = "配合示方模块配置") +public class MesXslFormulaSpecSetting implements Serializable { + private static final long serialVersionUID = 1L; + + public static final String DEFAULT_ID = "1993000000000000991"; + + @TableId(type = IdType.ASSIGN_ID) + private String id; + + @Schema(description = "天然橡胶物料小类ID,逗号分隔") + private String naturalMinorCategoryIds; + + @Schema(description = "合成橡胶物料小类ID,逗号分隔") + private String syntheticMinorCategoryIds; + + private String createBy; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + private String updateBy; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectConfigLineMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectConfigLineMapper.java new file mode 100644 index 00000000..ec09cd1c --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectConfigLineMapper.java @@ -0,0 +1,6 @@ +package org.jeecg.modules.xslmes.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfigLine; + +public interface MesXslEquipInspectConfigLineMapper extends BaseMapper {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectConfigMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectConfigMapper.java new file mode 100644 index 00000000..c318ce4d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectConfigMapper.java @@ -0,0 +1,6 @@ +package org.jeecg.modules.xslmes.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfig; + +public interface MesXslEquipInspectConfigMapper extends BaseMapper {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectRecordLineMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectRecordLineMapper.java new file mode 100644 index 00000000..b1ec54ae --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectRecordLineMapper.java @@ -0,0 +1,6 @@ +package org.jeecg.modules.xslmes.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectRecordLine; + +public interface MesXslEquipInspectRecordLineMapper extends BaseMapper {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectRecordMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectRecordMapper.java new file mode 100644 index 00000000..0fafdaa6 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectRecordMapper.java @@ -0,0 +1,6 @@ +package org.jeecg.modules.xslmes.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectRecord; + +public interface MesXslEquipInspectRecordMapper extends BaseMapper {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecLineMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecLineMapper.java new file mode 100644 index 00000000..e3a13a1d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecLineMapper.java @@ -0,0 +1,6 @@ +package org.jeecg.modules.xslmes.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine; + +public interface MesXslFormulaSpecLineMapper extends BaseMapper {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecMapper.java new file mode 100644 index 00000000..bce58808 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecMapper.java @@ -0,0 +1,6 @@ +package org.jeecg.modules.xslmes.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec; + +public interface MesXslFormulaSpecMapper extends BaseMapper {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecSettingMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecSettingMapper.java new file mode 100644 index 00000000..959bf3ba --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecSettingMapper.java @@ -0,0 +1,7 @@ +package org.jeecg.modules.xslmes.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecSetting; + +public interface MesXslFormulaSpecSettingMapper extends BaseMapper { +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/package-info.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/package-info.java index aac6a87a..01d97f06 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/package-info.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/package-info.java @@ -1,5 +1,5 @@ /** * MES XSL 业务模块(Maven 工程名:jeecg-module-xslmes)。 - * 包含:客户管理({@link org.jeecg.modules.xslmes.entity.MesXslCustomer})、工序管理({@link org.jeecg.modules.xslmes.entity.MesXslProcessOperation})、设备类别({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentCategory})、设备类型({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentType})、设备台账({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentLedger})、设备部位({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentPart})、设备小部位({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentSubPart})、点检及保养项目({@link org.jeecg.modules.xslmes.entity.MesXslInspectMaintainItem})、备品件类别({@link org.jeecg.modules.xslmes.entity.MesXslSparePartsCategory})、备品件信息({@link org.jeecg.modules.xslmes.entity.MesXslSparePart})、厂家信息({@link org.jeecg.modules.xslmes.entity.MesXslManufacturer})、停机主类型({@link org.jeecg.modules.xslmes.entity.MesXslDowntimeMainType})、停机类型({@link org.jeecg.modules.xslmes.entity.MesXslDowntimeType})等。 + * 包含:客户管理({@link org.jeecg.modules.xslmes.entity.MesXslCustomer})、工序管理({@link org.jeecg.modules.xslmes.entity.MesXslProcessOperation})、设备类别({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentCategory})、设备类型({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentType})、设备台账({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentLedger})、设备部位({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentPart})、设备小部位({@link org.jeecg.modules.xslmes.entity.MesXslEquipmentSubPart})、点检及保养项目({@link org.jeecg.modules.xslmes.entity.MesXslInspectMaintainItem})、设备点检配置({@link org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfig})、备品件类别({@link org.jeecg.modules.xslmes.entity.MesXslSparePartsCategory})、备品件信息({@link org.jeecg.modules.xslmes.entity.MesXslSparePart})、厂家信息({@link org.jeecg.modules.xslmes.entity.MesXslManufacturer})、停机主类型({@link org.jeecg.modules.xslmes.entity.MesXslDowntimeMainType})、停机类型({@link org.jeecg.modules.xslmes.entity.MesXslDowntimeType})等。 */ package org.jeecg.modules.xslmes; diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectConfigService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectConfigService.java new file mode 100644 index 00000000..a8f96eb2 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectConfigService.java @@ -0,0 +1,23 @@ +package org.jeecg.modules.xslmes.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfig; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfigLine; + +public interface IMesXslEquipInspectConfigService extends IService { + + void saveMain(MesXslEquipInspectConfig main, List lineList); + + void updateMain(MesXslEquipInspectConfig main, List lineList); + + void delMain(String id); + + void delBatchMain(Collection idList); + + List selectLinesByConfigId(String configId); + + boolean isConfigDuplicated(String equipmentLedgerId, String configType, String excludeId, MesXslEquipInspectConfig context); +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectRecordService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectRecordService.java new file mode 100644 index 00000000..ab784160 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectRecordService.java @@ -0,0 +1,34 @@ +package org.jeecg.modules.xslmes.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectRecord; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectRecordLine; +import org.jeecg.modules.xslmes.vo.MesXslEquipInspectRecordBatchCreateResult; +import org.jeecg.modules.xslmes.vo.MesXslEquipInspectRecordHandleDTO; + +public interface IMesXslEquipInspectRecordService extends IService { + + void saveMain(MesXslEquipInspectRecord main, List lineList); + + void updateMain(MesXslEquipInspectRecord main, List lineList); + + void delMain(String id); + + void delBatchMain(Collection idList); + + List selectLinesByRecordId(String recordId); + + String generateRecordNo(MesXslEquipInspectRecord context); + + List buildLinesFromEquipConfig(String equipmentLedgerId, String recordType); + + MesXslEquipInspectRecordBatchCreateResult batchCreateFromEquipment( + List equipmentLedgerIds, String recordType, MesXslEquipInspectRecord inspectorContext); + + //update-begin---author:jiangxh ---date:20260521 for:【MES】不合格点检记录登记处理人及处理时间----------- + void handleFailRecord(MesXslEquipInspectRecordHandleDTO dto); + //update-end---author:jiangxh ---date:20260521 for:【MES】不合格点检记录登记处理人及处理时间----------- +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecService.java new file mode 100644 index 00000000..65f453bc --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecService.java @@ -0,0 +1,28 @@ +package org.jeecg.modules.xslmes.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine; + +public interface IMesXslFormulaSpecService extends IService { + + void saveMain(MesXslFormulaSpec main, List lineList); + + void updateMain(MesXslFormulaSpec main, List lineList); + + void delMain(String id); + + void delBatchMain(Collection idList); + + List selectLinesByMainId(String mainId); + + MesXslFormulaSpec getByIdWithLines(String id); + + /** + * 生成胶料代号:D + 胶料名称 + 分类键值(S/P/T/C) + 版本号(A01-Z01) + */ + String generateRubberCode(String rubberMaterialId, String category, String excludeSpecId); +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecSettingService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecSettingService.java new file mode 100644 index 00000000..07022279 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecSettingService.java @@ -0,0 +1,17 @@ +package org.jeecg.modules.xslmes.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import java.util.Set; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecSetting; +import org.jeecg.modules.xslmes.vo.MesXslFormulaRubberContentSettingVO; + +public interface IMesXslFormulaSpecSettingService extends IService { + + MesXslFormulaRubberContentSettingVO getRubberContentSetting(); + + void saveRubberContentSetting(MesXslFormulaRubberContentSettingVO setting); + + Set getNaturalMinorCategoryIds(); + + Set getSyntheticMinorCategoryIds(); +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectConfigServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectConfigServiceImpl.java new file mode 100644 index 00000000..1f869304 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectConfigServiceImpl.java @@ -0,0 +1,132 @@ +package org.jeecg.modules.xslmes.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.jeecg.common.config.TenantContext; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.util.SpringContextUtils; +import org.jeecg.common.util.TokenUtils; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfig; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfigLine; +import org.jeecg.modules.xslmes.mapper.MesXslEquipInspectConfigLineMapper; +import org.jeecg.modules.xslmes.mapper.MesXslEquipInspectConfigMapper; +import org.jeecg.modules.xslmes.service.IMesXslEquipInspectConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +@Service +public class MesXslEquipInspectConfigServiceImpl + extends ServiceImpl + implements IMesXslEquipInspectConfigService { + + @Autowired + private MesXslEquipInspectConfigLineMapper mesXslEquipInspectConfigLineMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveMain(MesXslEquipInspectConfig main, List lineList) { + this.save(main); + insertLines(main.getId(), lineList); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateMain(MesXslEquipInspectConfig main, List lineList) { + this.updateById(main); + mesXslEquipInspectConfigLineMapper.delete( + new LambdaQueryWrapper() + .eq(MesXslEquipInspectConfigLine::getConfigId, main.getId())); + insertLines(main.getId(), lineList); + } + + private void insertLines(String configId, List lineList) { + if (CollectionUtils.isEmpty(lineList)) { + return; + } + int sort = 0; + for (MesXslEquipInspectConfigLine line : lineList) { + line.setId(null); + line.setConfigId(configId); + line.setSortNo(sort++); + mesXslEquipInspectConfigLineMapper.insert(line); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delMain(String id) { + mesXslEquipInspectConfigLineMapper.delete( + new LambdaQueryWrapper().eq(MesXslEquipInspectConfigLine::getConfigId, id)); + this.removeById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delBatchMain(Collection idList) { + for (Serializable id : idList) { + delMain(id.toString()); + } + } + + @Override + public List selectLinesByConfigId(String configId) { + return mesXslEquipInspectConfigLineMapper.selectList( + new LambdaQueryWrapper() + .eq(MesXslEquipInspectConfigLine::getConfigId, configId) + .orderByAsc(MesXslEquipInspectConfigLine::getSortNo)); + } + + //update-begin---author:jiangxh ---date:20260519 for:【MES】设备点检配置:同设备同类型(点检/保养)仅允许一条主数据----------- + @Override + public boolean isConfigDuplicated( + String equipmentLedgerId, String configType, String excludeId, MesXslEquipInspectConfig context) { + if (oConvertUtils.isEmpty(equipmentLedgerId) || oConvertUtils.isEmpty(configType)) { + return false; + } + Integer tenantId = resolveTenantId(context); + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.eq(MesXslEquipInspectConfig::getEquipmentLedgerId, equipmentLedgerId.trim()); + w.eq(MesXslEquipInspectConfig::getConfigType, configType.trim()); + w.and( + q -> + q.eq(MesXslEquipInspectConfig::getDelFlag, CommonConstant.DEL_FLAG_0) + .or() + .isNull(MesXslEquipInspectConfig::getDelFlag)); + if (oConvertUtils.isNotEmpty(excludeId)) { + w.ne(MesXslEquipInspectConfig::getId, excludeId); + } + if (tenantId != null) { + w.eq(MesXslEquipInspectConfig::getTenantId, tenantId); + } + return this.count(w) > 0; + } + + private static Integer resolveTenantId(MesXslEquipInspectConfig context) { + if (context != null && context.getTenantId() != null) { + return context.getTenantId(); + } + String ts = TenantContext.getTenant(); + if (oConvertUtils.isEmpty(ts)) { + try { + ts = TokenUtils.getTenantIdByRequest(SpringContextUtils.getHttpServletRequest()); + } catch (Exception ignored) { + // ignore + } + } + if (oConvertUtils.isEmpty(ts)) { + return null; + } + try { + return Integer.parseInt(ts); + } catch (NumberFormatException e) { + return null; + } + } + //update-end---author:jiangxh ---date:20260519 for:【MES】设备点检配置:同设备同类型(点检/保养)仅允许一条主数据----------- +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectRecordServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectRecordServiceImpl.java new file mode 100644 index 00000000..c28795de --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectRecordServiceImpl.java @@ -0,0 +1,312 @@ +package org.jeecg.modules.xslmes.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import org.jeecg.common.config.TenantContext; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.util.SpringContextUtils; +import org.jeecg.common.util.TokenUtils; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfig; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfigLine; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectRecord; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectRecordLine; +import org.jeecg.modules.xslmes.mapper.MesXslEquipInspectRecordLineMapper; +import org.jeecg.modules.xslmes.mapper.MesXslEquipInspectRecordMapper; +import org.jeecg.modules.xslmes.service.IMesXslEquipInspectConfigService; +import org.jeecg.modules.xslmes.service.IMesXslEquipInspectRecordService; +import org.jeecg.modules.xslmes.service.IMesXslEquipmentLedgerService; +import org.jeecg.modules.xslmes.entity.MesXslEquipmentLedger; +import org.jeecg.modules.xslmes.util.MesXslEquipInspectBizMsg; +import org.jeecg.modules.xslmes.vo.MesXslEquipInspectRecordBatchCreateResult; +import org.jeecg.modules.xslmes.vo.MesXslEquipInspectRecordHandleDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +@Service +public class MesXslEquipInspectRecordServiceImpl + extends ServiceImpl + implements IMesXslEquipInspectRecordService { + + @Autowired + private MesXslEquipInspectRecordLineMapper mesXslEquipInspectRecordLineMapper; + + @Autowired + private IMesXslEquipInspectConfigService mesXslEquipInspectConfigService; + + @Autowired + private IMesXslEquipmentLedgerService mesXslEquipmentLedgerService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveMain(MesXslEquipInspectRecord main, List lineList) { + this.save(main); + insertLines(main.getId(), lineList); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateMain(MesXslEquipInspectRecord main, List lineList) { + this.updateById(main); + mesXslEquipInspectRecordLineMapper.delete( + new LambdaQueryWrapper() + .eq(MesXslEquipInspectRecordLine::getRecordId, main.getId())); + insertLines(main.getId(), lineList); + } + + private void insertLines(String recordId, List lineList) { + if (CollectionUtils.isEmpty(lineList)) { + return; + } + int sort = 0; + for (MesXslEquipInspectRecordLine line : lineList) { + line.setId(null); + line.setRecordId(recordId); + line.setSortNo(sort++); + mesXslEquipInspectRecordLineMapper.insert(line); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delMain(String id) { + mesXslEquipInspectRecordLineMapper.delete( + new LambdaQueryWrapper().eq(MesXslEquipInspectRecordLine::getRecordId, id)); + this.removeById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delBatchMain(Collection idList) { + for (Serializable id : idList) { + delMain(id.toString()); + } + } + + @Override + public List selectLinesByRecordId(String recordId) { + return mesXslEquipInspectRecordLineMapper.selectList( + new LambdaQueryWrapper() + .eq(MesXslEquipInspectRecordLine::getRecordId, recordId) + .orderByAsc(MesXslEquipInspectRecordLine::getSortNo)); + } + + //update-begin---author:jiangxh ---date:20260520 for:【MES】点检保养记录编号 EC+日期+4位流水----------- + @Override + public String generateRecordNo(MesXslEquipInspectRecord context) { + String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date()); + String prefix = "EC" + dateStr; + Integer tenantId = resolveTenantId(context); + + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.likeRight(MesXslEquipInspectRecord::getRecordNo, prefix); + qw.and( + q -> + q.eq(MesXslEquipInspectRecord::getDelFlag, CommonConstant.DEL_FLAG_0) + .or() + .isNull(MesXslEquipInspectRecord::getDelFlag)); + if (tenantId != null) { + qw.eq(MesXslEquipInspectRecord::getTenantId, tenantId); + } + qw.select(MesXslEquipInspectRecord::getRecordNo); + qw.orderByDesc(MesXslEquipInspectRecord::getRecordNo); + qw.last("LIMIT 1"); + + MesXslEquipInspectRecord last = this.getOne(qw, false); + int nextSeq = 1; + if (last != null && oConvertUtils.isNotEmpty(last.getRecordNo()) && last.getRecordNo().length() >= prefix.length() + 4) { + String suffix = last.getRecordNo().substring(prefix.length()); + try { + nextSeq = Integer.parseInt(suffix) + 1; + } catch (NumberFormatException ignored) { + nextSeq = (int) this.count(qw) + 1; + } + } + return prefix + String.format("%04d", nextSeq); + } + //update-end---author:jiangxh ---date:20260520 for:【MES】点检保养记录编号 EC+日期+4位流水----------- + + //update-begin---author:jiangxh ---date:20260520 for:【MES】点检保养记录从设备点检配置带出明细----------- + @Override + public List buildLinesFromEquipConfig(String equipmentLedgerId, String recordType) { + if (oConvertUtils.isEmpty(equipmentLedgerId) || oConvertUtils.isEmpty(recordType)) { + return List.of(); + } + String type = recordType.trim(); + MesXslEquipInspectConfig config = findEquipInspectConfig(equipmentLedgerId.trim(), type); + if (config == null) { + return List.of(); + } + List configLines = + mesXslEquipInspectConfigService.selectLinesByConfigId(config.getId()); + if (CollectionUtils.isEmpty(configLines)) { + return List.of(); + } + return buildRecordLinesFromConfigLines(configLines); + } + + private MesXslEquipInspectConfig findEquipInspectConfig(String equipmentLedgerId, String configType) { + LambdaQueryWrapper cw = new LambdaQueryWrapper<>(); + cw.eq(MesXslEquipInspectConfig::getEquipmentLedgerId, equipmentLedgerId); + cw.eq(MesXslEquipInspectConfig::getConfigType, configType); + cw.and( + q -> + q.eq(MesXslEquipInspectConfig::getDelFlag, CommonConstant.DEL_FLAG_0) + .or() + .isNull(MesXslEquipInspectConfig::getDelFlag)); + return mesXslEquipInspectConfigService.getOne(cw, false); + } + + private List buildRecordLinesFromConfigLines( + List configLines) { + List result = new ArrayList<>(configLines.size()); + for (MesXslEquipInspectConfigLine cl : configLines) { + MesXslEquipInspectRecordLine line = new MesXslEquipInspectRecordLine(); + line.setEquipInspectConfigLineId(cl.getId()); + line.setInspectMaintainItemId(cl.getInspectMaintainItemId()); + line.setItemCode(cl.getItemCode()); + line.setItemName(cl.getItemName()); + line.setItemCategory(cl.getItemCategory()); + line.setItemType(cl.getItemType()); + line.setEquipmentPartName(cl.getEquipmentPartName()); + line.setEquipmentSubPartName(cl.getEquipmentSubPartName()); + line.setInspectMethod(cl.getInspectMethod()); + line.setJudgmentCriteria(cl.getJudgmentCriteria()); + result.add(line); + } + return result; + } + //update-end---author:jiangxh ---date:20260520 for:【MES】点检保养记录从设备点检配置带出明细----------- + + //update-begin---author:jiangxh ---date:20260520 for:【MES】设备台账多选批量生成点检保养记录(待点检)----------- + @Override + @Transactional(rollbackFor = Exception.class) + public MesXslEquipInspectRecordBatchCreateResult batchCreateFromEquipment( + List equipmentLedgerIds, String recordType, MesXslEquipInspectRecord inspectorContext) { + MesXslEquipInspectRecordBatchCreateResult result = new MesXslEquipInspectRecordBatchCreateResult(); + if (CollectionUtils.isEmpty(equipmentLedgerIds) || oConvertUtils.isEmpty(recordType)) { + result.getFailMessages().add("请选择设备并指定点检或保养类型"); + return result; + } + String type = recordType.trim(); + for (String equipmentLedgerId : equipmentLedgerIds) { + if (oConvertUtils.isEmpty(equipmentLedgerId)) { + continue; + } + String equipId = equipmentLedgerId.trim(); + MesXslEquipmentLedger ledger = mesXslEquipmentLedgerService.getById(equipId); + String equipName = + ledger != null + ? (oConvertUtils.isNotEmpty(ledger.getEquipmentName()) + ? ledger.getEquipmentName() + : ledger.getEquipmentCode()) + : equipId; + if (ledger == null + || (ledger.getDelFlag() != null && ledger.getDelFlag().equals(CommonConstant.DEL_FLAG_1))) { + result.getFailMessages().add("设备【" + equipName + "】不存在或已删除"); + continue; + } + //update-begin---author:jiangxh ---date:20260520 for:【MES】未维护对应类型设备点检配置则不生成记录并提示设备名称----------- + MesXslEquipInspectConfig config = findEquipInspectConfig(equipId, type); + if (config == null) { + result.getFailMessages().add(MesXslEquipInspectBizMsg.noConfigMessage(equipName, type)); + continue; + } + List configLines = + mesXslEquipInspectConfigService.selectLinesByConfigId(config.getId()); + if (CollectionUtils.isEmpty(configLines)) { + result.getFailMessages().add(MesXslEquipInspectBizMsg.noConfigLineMessage(equipName, type)); + continue; + } + List lines = buildRecordLinesFromConfigLines(configLines); + //update-end---author:jiangxh ---date:20260520 for:【MES】未维护对应类型设备点检配置则不生成记录并提示设备名称----------- + + MesXslEquipInspectRecord main = new MesXslEquipInspectRecord(); + main.setEquipmentLedgerId(equipId); + main.setEquipmentCode(ledger.getEquipmentCode()); + main.setEquipmentName(ledger.getEquipmentName()); + main.setEquipInspectConfigId(config.getId()); + main.setRecordType(type); + main.setRecordNo(generateRecordNo(main)); + main.setRecordStatus("pending"); + main.setInspectResult(""); + main.setInspectDate(new Date()); + if (inspectorContext != null) { + main.setInspectorUserId(inspectorContext.getInspectorUserId()); + main.setInspectorUsername(inspectorContext.getInspectorUsername()); + main.setInspectorRealname(inspectorContext.getInspectorRealname()); + } + saveMain(main, lines); + result.setSuccessCount(result.getSuccessCount() + 1); + } + return result; + } + //update-end---author:jiangxh ---date:20260520 for:【MES】设备台账多选批量生成点检保养记录(待点检)----------- + + //update-begin---author:jiangxh ---date:20260521 for:【MES】不合格点检记录登记处理人及处理时间----------- + @Override + @Transactional(rollbackFor = Exception.class) + public void handleFailRecord(MesXslEquipInspectRecordHandleDTO dto) { + if (dto == null || oConvertUtils.isEmpty(dto.getId())) { + throw new IllegalArgumentException("记录主键不能为空"); + } + MesXslEquipInspectRecord existing = this.getById(dto.getId().trim()); + if (existing == null) { + throw new IllegalArgumentException("未找到对应数据"); + } + if (!"fail".equals(existing.getInspectResult())) { + throw new IllegalArgumentException("仅不合格记录可处理"); + } + if (!"done".equals(existing.getRecordStatus())) { + throw new IllegalArgumentException("请先完成点检录入"); + } + if ("1".equals(existing.getHandledFlag())) { + throw new IllegalArgumentException("该记录已处理"); + } + if (oConvertUtils.isEmpty(dto.getHandlerUserId()) + && oConvertUtils.isEmpty(dto.getHandlerUsername()) + && oConvertUtils.isEmpty(dto.getHandlerRealname())) { + throw new IllegalArgumentException("请选择处理人"); + } + Date handleTime = dto.getHandleTime() != null ? dto.getHandleTime() : new Date(); + MesXslEquipInspectRecord patch = new MesXslEquipInspectRecord(); + patch.setId(existing.getId()); + patch.setHandledFlag("1"); + patch.setHandlerUserId(dto.getHandlerUserId()); + patch.setHandlerUsername(dto.getHandlerUsername()); + patch.setHandlerRealname(dto.getHandlerRealname()); + patch.setHandleTime(handleTime); + this.updateById(patch); + } + //update-end---author:jiangxh ---date:20260521 for:【MES】不合格点检记录登记处理人及处理时间----------- + + private static Integer resolveTenantId(MesXslEquipInspectRecord context) { + if (context != null && context.getTenantId() != null) { + return context.getTenantId(); + } + String ts = TenantContext.getTenant(); + if (oConvertUtils.isEmpty(ts)) { + try { + ts = TokenUtils.getTenantIdByRequest(SpringContextUtils.getHttpServletRequest()); + } catch (Exception ignored) { + // ignore + } + } + if (oConvertUtils.isEmpty(ts)) { + return null; + } + try { + return Integer.parseInt(ts); + } catch (NumberFormatException e) { + return null; + } + } +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java new file mode 100644 index 00000000..cdb7d341 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java @@ -0,0 +1,403 @@ +package org.jeecg.modules.xslmes.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.lang3.StringUtils; +import org.jeecg.modules.mes.material.entity.MesMaterial; +import org.jeecg.modules.mes.material.entity.MesMixerMaterial; +import org.jeecg.modules.mes.material.service.IMesMaterialService; +import org.jeecg.modules.mes.material.service.IMesMixerMaterialService; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine; +import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecLineMapper; +import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecMapper; +import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecService; +import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecSettingService; +import org.jeecg.modules.system.entity.SysUser; +import org.jeecg.modules.system.service.ISysUserService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +@Service +public class MesXslFormulaSpecServiceImpl extends ServiceImpl + implements IMesXslFormulaSpecService { + + private static final Set RUBBER_CATEGORY_KEYS = Set.of("S", "P", "T", "C"); + private static final Pattern RUBBER_CODE_VERSION_PATTERN = Pattern.compile("([A-Z])01$"); + + @Resource + private MesXslFormulaSpecLineMapper lineMapper; + + @Resource + private IMesMixerMaterialService mesMixerMaterialService; + + @Resource + private IMesMaterialService mesMaterialService; + + @Resource + private IMesXslFormulaSpecSettingService mesXslFormulaSpecSettingService; + + @Resource + private ISysUserService sysUserService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveMain(MesXslFormulaSpec main, List lineList) { + fillMainDefaults(main); + //update-begin---author:cursor ---date:20260521 for:配合示方新增时服务端生成胶料代号----------- + fillRubberCodeOnCreate(main); + //update-end---author:cursor ---date:20260521 for:配合示方新增时服务端生成胶料代号----------- + this.save(main); + insertLines(main, lineList); + refreshMainSummary(main.getId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateMain(MesXslFormulaSpec main, List lineList) { + fillMainDefaults(main); + this.updateById(main); + lineMapper.delete(new LambdaQueryWrapper().eq(MesXslFormulaSpecLine::getFormulaSpecId, main.getId())); + insertLines(main, lineList); + refreshMainSummary(main.getId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delMain(String id) { + lineMapper.delete(new LambdaQueryWrapper().eq(MesXslFormulaSpecLine::getFormulaSpecId, id)); + this.removeById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delBatchMain(Collection idList) { + if (idList == null || idList.isEmpty()) { + return; + } + for (Serializable id : idList) { + if (id != null) { + delMain(id.toString()); + } + } + } + + @Override + public List selectLinesByMainId(String mainId) { + return lineMapper.selectList( + new LambdaQueryWrapper() + .eq(MesXslFormulaSpecLine::getFormulaSpecId, mainId) + .orderByAsc(MesXslFormulaSpecLine::getSortNo) + .orderByAsc(MesXslFormulaSpecLine::getId)); + } + + @Override + public MesXslFormulaSpec getByIdWithLines(String id) { + MesXslFormulaSpec main = this.getById(id); + if (main == null) { + return null; + } + main.setLineList(selectLinesByMainId(id)); + //update-begin---author:cursor ---date:20260521 for:【配合示方】queryById补充创建人姓名供审批进度展示----------- + fillCreateByDictText(main); + //update-end---author:cursor ---date:20260521 for:【配合示方】queryById补充创建人姓名供审批进度展示----------- + return main; + } + + private void fillCreateByDictText(MesXslFormulaSpec main) { + if (main == null || StringUtils.isBlank(main.getCreateBy())) { + return; + } + SysUser user = sysUserService.getUserByName(main.getCreateBy()); + if (user != null && StringUtils.isNotBlank(user.getRealname())) { + main.setCreateBy_dictText(user.getRealname()); + } + } + + //update-begin---author:cursor ---date:20260521 for:配合示方胶料代号自动生成 D+胶料名称+分类+版本号----------- + @Override + public String generateRubberCode(String rubberMaterialId, String category, String excludeSpecId) { + if (StringUtils.isBlank(rubberMaterialId)) { + throw new IllegalArgumentException("请选择胶料信息"); + } + if (StringUtils.isBlank(category) || !RUBBER_CATEGORY_KEYS.contains(category)) { + throw new IllegalArgumentException("请选择有效的示方分类"); + } + MesMaterial material = mesMaterialService.getById(rubberMaterialId); + if (material == null || StringUtils.isBlank(material.getMaterialName())) { + throw new IllegalArgumentException("所选胶料不存在或未维护胶料名称"); + } + String basePrefix = buildRubberCodePrefix(material.getMaterialName(), category); + Set usedLetters = loadUsedRubberCodeLetters(rubberMaterialId, category, basePrefix, excludeSpecId); + for (char letter = 'A'; letter <= 'Z'; letter++) { + if (!usedLetters.contains(letter)) { + return basePrefix + letter + "01"; + } + } + throw new IllegalArgumentException("该胶料在当前分类下的代号版本已用尽(A01-Z01)"); + } + + private void fillRubberCodeOnCreate(MesXslFormulaSpec main) { + if (StringUtils.isBlank(main.getRubberMaterialId()) || StringUtils.isBlank(main.getCategory())) { + return; + } + main.setRubberCode(generateRubberCode(main.getRubberMaterialId(), main.getCategory(), null)); + main.setSpecCode(main.getRubberCode()); + } + + private String buildRubberCodePrefix(String materialName, String category) { + return "D" + materialName.trim() + category; + } + + private Set loadUsedRubberCodeLetters( + String rubberMaterialId, String category, String basePrefix, String excludeSpecId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .eq(MesXslFormulaSpec::getRubberMaterialId, rubberMaterialId) + .eq(MesXslFormulaSpec::getCategory, category) + .likeRight(MesXslFormulaSpec::getRubberCode, basePrefix); + if (StringUtils.isNotBlank(excludeSpecId)) { + queryWrapper.ne(MesXslFormulaSpec::getId, excludeSpecId); + } + List existingList = this.list(queryWrapper); + Set usedLetters = new HashSet<>(); + for (MesXslFormulaSpec item : existingList) { + if (item == null || StringUtils.isBlank(item.getRubberCode())) { + continue; + } + if (!item.getRubberCode().startsWith(basePrefix) || item.getRubberCode().length() <= basePrefix.length()) { + continue; + } + String suffix = item.getRubberCode().substring(basePrefix.length()); + Matcher matcher = RUBBER_CODE_VERSION_PATTERN.matcher(suffix); + if (matcher.matches()) { + usedLetters.add(matcher.group(1).charAt(0)); + } + } + return usedLetters; + } + //update-end---author:cursor ---date:20260521 for:配合示方胶料代号自动生成 D+胶料名称+分类+版本号----------- + + private void fillMainDefaults(MesXslFormulaSpec main) { + if (StringUtils.isBlank(main.getCategory())) { + //update-begin---author:cursor ---date:20260521 for:配合示方分类字典默认值改为 S----------- + main.setCategory("S"); + //update-end---author:cursor ---date:20260521 for:配合示方分类字典默认值改为 S----------- + } + if (StringUtils.isBlank(main.getStatus())) { + main.setStatus("compile"); + } + if (main.getHasManualBatch() == null) { + main.setHasManualBatch(0); + } + } + + private void insertLines(MesXslFormulaSpec main, List lineList) { + if (CollectionUtils.isEmpty(lineList)) { + return; + } + Date now = new Date(); + int sort = 0; + //update-begin---author:cursor ---date:20260521 for:配合示方明细重量%按PHR/总PHR自动计算----------- + BigDecimal totalPhr = BigDecimal.ZERO; + for (MesXslFormulaSpecLine line : lineList) { + if (line == null || StringUtils.isBlank(line.getMixerMaterialId()) || line.getPhr() == null) { + continue; + } + totalPhr = totalPhr.add(line.getPhr()); + } + if (main.getTotalPhr() == null) { + main.setTotalPhr(totalPhr); + } + BigDecimal weightBase = main.getTotalPhr() != null && main.getTotalPhr().compareTo(BigDecimal.ZERO) > 0 + ? main.getTotalPhr() + : totalPhr; + //update-end---author:cursor ---date:20260521 for:配合示方明细重量%按PHR/总PHR自动计算----------- + boolean hasManual = false; + for (MesXslFormulaSpecLine line : lineList) { + if (line == null || StringUtils.isBlank(line.getMixerMaterialId())) { + continue; + } + line.setId(null); + line.setFormulaSpecId(main.getId()); + line.setSortNo(sort++); + fillMaterialInfo(line); + fillVolumeIfBlank(line); + //update-begin---author:cursor ---date:20260521 for:配合示方明细重量%按PHR/总PHR自动计算----------- + fillWeightPercent(line, weightBase); + //update-end---author:cursor ---date:20260521 for:配合示方明细重量%按PHR/总PHR自动计算----------- + if (line.getCreateTime() == null) { + line.setCreateTime(now); + } + if (line.getUpdateTime() == null) { + line.setUpdateTime(now); + } + if ("manual".equals(line.getWeighMode())) { + hasManual = true; + } + lineMapper.insert(line); + } + if (main.getTotalPhr() == null) { + main.setTotalPhr(totalPhr); + } + if (main.getHasManualBatch() == null || main.getHasManualBatch() == 0) { + main.setHasManualBatch(hasManual ? 1 : 0); + } + } + + private void fillMaterialInfo(MesXslFormulaSpecLine line) { + MesMixerMaterial material = mesMixerMaterialService.getById(line.getMixerMaterialId()); + if (material == null) { + return; + } + line.setMixerMaterialCode(material.getMaterialCode()); + line.setMixerMaterialName(material.getMaterialName()); + if (StringUtils.isBlank(line.getMaterialDesc())) { + line.setMaterialDesc(StringUtils.defaultIfBlank(material.getMaterialDesc(), material.getMaterialName())); + } + } + + private void fillVolumeIfBlank(MesXslFormulaSpecLine line) { + if (line.getVolume() != null || line.getPhr() == null || StringUtils.isBlank(line.getMixerMaterialId())) { + return; + } + MesMixerMaterial material = mesMixerMaterialService.getById(line.getMixerMaterialId()); + if (material == null || material.getSpecificGravity() == null || material.getSpecificGravity().compareTo(BigDecimal.ZERO) <= 0) { + return; + } + line.setVolume(line.getPhr().divide(material.getSpecificGravity(), 6, RoundingMode.HALF_UP)); + } + + private void fillWeightPercent(MesXslFormulaSpecLine line, BigDecimal totalPhr) { + //update-begin---author:cursor ---date:20260521 for:配合示方明细重量%按PHR/总PHR自动计算(可手工覆盖)----------- + if (line.getWeightPercent() != null || line.getPhr() == null || totalPhr == null || totalPhr.compareTo(BigDecimal.ZERO) <= 0) { + return; + } + line.setWeightPercent(line.getPhr().multiply(BigDecimal.valueOf(100)).divide(totalPhr, 4, RoundingMode.HALF_UP)); + //update-end---author:cursor ---date:20260521 for:配合示方明细重量%按PHR/总PHR自动计算(可手工覆盖)----------- + } + + //update-begin---author:cursor ---date:20260521 for:【配合示方】保存后汇总A/Q胶比重写入数据库----------- + /** 根据明细重新汇总主表 TOTAL PHR、A胶TOTAL PHR、比重与人工配料标记 */ + private void refreshMainSummary(String mainId) { + List lines = selectLinesByMainId(mainId); + if (CollectionUtils.isEmpty(lines)) { + return; + } + BigDecimal totalPhr = BigDecimal.ZERO; + BigDecimal aRubberPhr = BigDecimal.ZERO; + BigDecimal aRubberVolume = BigDecimal.ZERO; + BigDecimal qRubberPhr = BigDecimal.ZERO; + BigDecimal qRubberVolume = BigDecimal.ZERO; + BigDecimal naturalRubber = BigDecimal.ZERO; + BigDecimal syntheticRubber = BigDecimal.ZERO; + boolean hasManual = false; + Map materialCache = new HashMap<>(); + Set naturalCategoryIds = mesXslFormulaSpecSettingService.getNaturalMinorCategoryIds(); + Set syntheticCategoryIds = mesXslFormulaSpecSettingService.getSyntheticMinorCategoryIds(); + for (MesXslFormulaSpecLine line : lines) { + if (line == null) { + continue; + } + if (line.getPhr() != null) { + totalPhr = totalPhr.add(line.getPhr()); + if ("A".equals(line.getStep())) { + aRubberPhr = aRubberPhr.add(line.getPhr()); + } else if ("Q".equals(line.getStep())) { + qRubberPhr = qRubberPhr.add(line.getPhr()); + } + } + if ("manual".equals(line.getWeighMode())) { + hasManual = true; + } + BigDecimal volume = resolveLineVolume(line); + if (volume == null) { + continue; + } + if ("A".equals(line.getStep())) { + aRubberVolume = aRubberVolume.add(volume); + } else if ("Q".equals(line.getStep())) { + qRubberVolume = qRubberVolume.add(volume); + } + //update-begin---author:cursor ---date:20260521 for:【配合示方】含胶率按密炼物料小类汇总重量%----------- + if (line.getWeightPercent() != null && StringUtils.isNotBlank(line.getMixerMaterialId())) { + MesMixerMaterial mixerMaterial = materialCache.computeIfAbsent( + line.getMixerMaterialId(), mesMixerMaterialService::getById); + if (mixerMaterial != null && StringUtils.isNotBlank(mixerMaterial.getMinorCategoryId())) { + String minorCategoryId = mixerMaterial.getMinorCategoryId(); + if (!naturalCategoryIds.isEmpty() && naturalCategoryIds.contains(minorCategoryId)) { + naturalRubber = naturalRubber.add(line.getWeightPercent()); + } else if (!syntheticCategoryIds.isEmpty() && syntheticCategoryIds.contains(minorCategoryId)) { + syntheticRubber = syntheticRubber.add(line.getWeightPercent()); + } + } + } + //update-end---author:cursor ---date:20260521 for:【配合示方】含胶率按密炼物料小类汇总重量%----------- + } + //update-begin---author:cursor ---date:20260521 for:【配合示方】STEP全为A/Q时对应胶比重清零并写库----------- + BigDecimal aRubberSg = aRubberVolume.compareTo(BigDecimal.ZERO) > 0 + ? aRubberPhr.divide(aRubberVolume, 6, RoundingMode.HALF_UP) + : null; + BigDecimal qRubberSg = qRubberVolume.compareTo(BigDecimal.ZERO) > 0 + ? qRubberPhr.divide(qRubberVolume, 6, RoundingMode.HALF_UP) + : null; + BigDecimal aRubberTotalPhr = aRubberPhr.compareTo(BigDecimal.ZERO) > 0 ? aRubberPhr : null; + BigDecimal naturalRubberValue = naturalRubber.compareTo(BigDecimal.ZERO) > 0 + ? naturalRubber.setScale(4, RoundingMode.HALF_UP) + : null; + BigDecimal syntheticRubberValue = syntheticRubber.compareTo(BigDecimal.ZERO) > 0 + ? syntheticRubber.setScale(4, RoundingMode.HALF_UP) + : null; + BigDecimal totalAmount = null; + if (naturalRubberValue != null || syntheticRubberValue != null) { + totalAmount = (naturalRubberValue != null ? naturalRubberValue : BigDecimal.ZERO) + .add(syntheticRubberValue != null ? syntheticRubberValue : BigDecimal.ZERO) + .setScale(4, RoundingMode.HALF_UP); + } + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() + .eq(MesXslFormulaSpec::getId, mainId) + .set(MesXslFormulaSpec::getTotalPhr, totalPhr) + .set(MesXslFormulaSpec::getHasManualBatch, hasManual ? 1 : 0) + .set(MesXslFormulaSpec::getARubberTotalPhr, aRubberTotalPhr) + .set(MesXslFormulaSpec::getARubberSg, aRubberSg) + .set(MesXslFormulaSpec::getQRubberSg, qRubberSg) + .set(MesXslFormulaSpec::getNaturalRubber, naturalRubberValue) + .set(MesXslFormulaSpec::getSyntheticRubber, syntheticRubberValue) + .set(MesXslFormulaSpec::getTotalAmount, totalAmount); + this.update(updateWrapper); + //update-end---author:cursor ---date:20260521 for:【配合示方】STEP全为A/Q时对应胶比重清零并写库----------- + } + + /** 优先取明细已保存体积,缺失时按 PHR/物料比重补算 */ + private BigDecimal resolveLineVolume(MesXslFormulaSpecLine line) { + if (line == null) { + return null; + } + if (line.getVolume() != null && line.getVolume().compareTo(BigDecimal.ZERO) > 0) { + return line.getVolume(); + } + if (line.getPhr() == null || StringUtils.isBlank(line.getMixerMaterialId())) { + return null; + } + MesMixerMaterial material = mesMixerMaterialService.getById(line.getMixerMaterialId()); + if (material == null || material.getSpecificGravity() == null || material.getSpecificGravity().compareTo(BigDecimal.ZERO) <= 0) { + return null; + } + return line.getPhr().divide(material.getSpecificGravity(), 6, RoundingMode.HALF_UP); + } + //update-end---author:cursor ---date:20260521 for:【配合示方】保存后汇总A/Q胶比重写入数据库----------- +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecSettingServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecSettingServiceImpl.java new file mode 100644 index 00000000..dbbc0585 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecSettingServiceImpl.java @@ -0,0 +1,104 @@ +package org.jeecg.modules.xslmes.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; +import org.jeecg.modules.system.entity.SysCategory; +import org.jeecg.modules.system.service.ISysCategoryService; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecSetting; +import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecSettingMapper; +import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecSettingService; +import org.jeecg.modules.xslmes.vo.MesXslFormulaRubberContentSettingVO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class MesXslFormulaSpecSettingServiceImpl extends ServiceImpl + implements IMesXslFormulaSpecSettingService { + + private static final String DEFAULT_NATURAL_CATEGORY_CODE = "XSLMES_MATERIAL_RAW_AUX_TRJ"; + private static final String DEFAULT_SYNTHETIC_CATEGORY_CODE = "XSLMES_MATERIAL_RAW_AUX_HCJ"; + + private final ISysCategoryService sysCategoryService; + + public MesXslFormulaSpecSettingServiceImpl(ISysCategoryService sysCategoryService) { + this.sysCategoryService = sysCategoryService; + } + + @Override + public MesXslFormulaRubberContentSettingVO getRubberContentSetting() { + MesXslFormulaSpecSetting setting = loadOrInitSetting(); + MesXslFormulaRubberContentSettingVO vo = new MesXslFormulaRubberContentSettingVO(); + vo.setNaturalMinorCategoryIds(parseIdList(setting.getNaturalMinorCategoryIds())); + vo.setSyntheticMinorCategoryIds(parseIdList(setting.getSyntheticMinorCategoryIds())); + return vo; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveRubberContentSetting(MesXslFormulaRubberContentSettingVO settingVo) { + MesXslFormulaSpecSetting setting = loadOrInitSetting(); + setting.setNaturalMinorCategoryIds(joinIdList(settingVo != null ? settingVo.getNaturalMinorCategoryIds() : null)); + setting.setSyntheticMinorCategoryIds(joinIdList(settingVo != null ? settingVo.getSyntheticMinorCategoryIds() : null)); + setting.setUpdateTime(new Date()); + this.updateById(setting); + } + + @Override + public Set getNaturalMinorCategoryIds() { + return new LinkedHashSet<>(parseIdList(loadOrInitSetting().getNaturalMinorCategoryIds())); + } + + @Override + public Set getSyntheticMinorCategoryIds() { + return new LinkedHashSet<>(parseIdList(loadOrInitSetting().getSyntheticMinorCategoryIds())); + } + + private MesXslFormulaSpecSetting loadOrInitSetting() { + MesXslFormulaSpecSetting setting = this.getById(MesXslFormulaSpecSetting.DEFAULT_ID); + if (setting != null) { + return setting; + } + setting = new MesXslFormulaSpecSetting(); + setting.setId(MesXslFormulaSpecSetting.DEFAULT_ID); + setting.setNaturalMinorCategoryIds(resolveCategoryIdByCode(DEFAULT_NATURAL_CATEGORY_CODE)); + setting.setSyntheticMinorCategoryIds(resolveCategoryIdByCode(DEFAULT_SYNTHETIC_CATEGORY_CODE)); + setting.setCreateTime(new Date()); + this.save(setting); + return setting; + } + + private String resolveCategoryIdByCode(String categoryCode) { + if (StringUtils.isBlank(categoryCode)) { + return null; + } + SysCategory category = sysCategoryService.getOne( + new LambdaQueryWrapper().eq(SysCategory::getCode, categoryCode).last("LIMIT 1")); + return category != null ? category.getId() : null; + } + + private List parseIdList(String raw) { + if (StringUtils.isBlank(raw)) { + return Collections.emptyList(); + } + return Arrays.stream(raw.split(",")) + .map(String::trim) + .filter(StringUtils::isNotBlank) + .distinct() + .collect(Collectors.toList()); + } + + private String joinIdList(List ids) { + if (ids == null || ids.isEmpty()) { + return null; + } + return ids.stream().filter(StringUtils::isNotBlank).map(String::trim).distinct().collect(Collectors.joining(",")); + } +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/util/MesXslEquipInspectBizMsg.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/util/MesXslEquipInspectBizMsg.java new file mode 100644 index 00000000..26fab61b --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/util/MesXslEquipInspectBizMsg.java @@ -0,0 +1,27 @@ +package org.jeecg.modules.xslmes.util; + +import org.jeecg.common.util.oConvertUtils; + +/** + * 设备点检/保养业务提示文案 + */ +public final class MesXslEquipInspectBizMsg { + + private MesXslEquipInspectBizMsg() {} + + public static String recordTypeLabel(String recordType) { + return "inspect".equals(recordType) ? "点检" : "保养"; + } + + /** 未维护该类型设备点检配置(不生成记录) */ + public static String noConfigMessage(String equipmentName, String recordType) { + String name = oConvertUtils.isNotEmpty(equipmentName) ? equipmentName.trim() : "该设备"; + return name + " 未维护" + recordTypeLabel(recordType) + "类型的设备点检配置"; + } + + /** 已有点检配置主表但无明细行 */ + public static String noConfigLineMessage(String equipmentName, String recordType) { + String name = oConvertUtils.isNotEmpty(equipmentName) ? equipmentName.trim() : "该设备"; + return name + " 的" + recordTypeLabel(recordType) + "类型设备点检配置未维护明细项"; + } +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectConfigPage.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectConfigPage.java new file mode 100644 index 00000000..636230ab --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectConfigPage.java @@ -0,0 +1,12 @@ +package org.jeecg.modules.xslmes.vo; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectConfig; + +/** + * 设备点检配置主子保存页 VO,继承主表实体(含 {@link MesXslEquipInspectConfig#lineList} 明细)。 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class MesXslEquipInspectConfigPage extends MesXslEquipInspectConfig {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordBatchCreateDTO.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordBatchCreateDTO.java new file mode 100644 index 00000000..57b95f8c --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordBatchCreateDTO.java @@ -0,0 +1,19 @@ +package org.jeecg.modules.xslmes.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; +import lombok.Data; + +/** + * 从设备台账批量生成点检/保养记录 + */ +@Data +@Schema(description = "批量生成点检保养记录请求") +public class MesXslEquipInspectRecordBatchCreateDTO { + + @Schema(description = "设备台账主键列表") + private List equipmentLedgerIds; + + @Schema(description = "记录类型 inspect点检/maintain保养") + private String recordType; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordBatchCreateResult.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordBatchCreateResult.java new file mode 100644 index 00000000..3f79b4f0 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordBatchCreateResult.java @@ -0,0 +1,20 @@ +package org.jeecg.modules.xslmes.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.ArrayList; +import java.util.List; +import lombok.Data; + +/** + * 批量生成点检/保养记录结果 + */ +@Data +@Schema(description = "批量生成点检保养记录结果") +public class MesXslEquipInspectRecordBatchCreateResult { + + @Schema(description = "成功条数") + private int successCount; + + @Schema(description = "失败说明(按设备)") + private List failMessages = new ArrayList<>(); +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordHandleDTO.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordHandleDTO.java new file mode 100644 index 00000000..70496f62 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordHandleDTO.java @@ -0,0 +1,32 @@ +package org.jeecg.modules.xslmes.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.Date; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 不合格点检记录处理入参 + */ +@Data +@Schema(description = "点检保养记录-不合格处理") +public class MesXslEquipInspectRecordHandleDTO { + + @Schema(description = "记录主键", requiredMode = Schema.RequiredMode.REQUIRED) + private String id; + + @Schema(description = "处理人用户ID") + private String handlerUserId; + + @Schema(description = "处理人账号") + private String handlerUsername; + + @Schema(description = "处理人姓名") + private String handlerRealname; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "处理时间") + private Date handleTime; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordPage.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordPage.java new file mode 100644 index 00000000..505d8665 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordPage.java @@ -0,0 +1,12 @@ +package org.jeecg.modules.xslmes.vo; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.jeecg.modules.xslmes.entity.MesXslEquipInspectRecord; + +/** + * 点检/保养记录主子保存 VO + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class MesXslEquipInspectRecordPage extends MesXslEquipInspectRecord {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaRubberContentSettingVO.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaRubberContentSettingVO.java new file mode 100644 index 00000000..f29aa5af --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaRubberContentSettingVO.java @@ -0,0 +1,22 @@ +package org.jeecg.modules.xslmes.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import lombok.Data; + +/** + * 配合示方含胶率物料小类配置 + */ +@Data +@Schema(description = "配合示方含胶率物料小类配置") +public class MesXslFormulaRubberContentSettingVO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "天然橡胶物料小类ID列表") + private List naturalMinorCategoryIds = new ArrayList<>(); + + @Schema(description = "合成橡胶物料小类ID列表") + private List syntheticMinorCategoryIds = new ArrayList<>(); +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaSpecPage.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaSpecPage.java new file mode 100644 index 00000000..8df86850 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaSpecPage.java @@ -0,0 +1,10 @@ +package org.jeecg.modules.xslmes.vo; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec; + +/** 配合示方主子保存 VO */ +@Data +@EqualsAndHashCode(callSuper = true) +public class MesXslFormulaSpecPage extends MesXslFormulaSpec {} diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/docs/代码修改日志 b/jeecg-boot/jeecg-module-system/jeecg-system-biz/docs/代码修改日志 index 4fe8ec42..f6f13582 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/docs/代码修改日志 +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/docs/代码修改日志 @@ -339,3 +339,82 @@ jeecgboot-vue3/src/views/xslmes/mesXslInspectMaintainItem/MesXslInspectMaintainI jeecgboot-vue3/src/views/xslmes/mesXslInspectMaintainItem/components/MesXslInspectMaintainItemModal.vue jeecgboot-vue3/src/views/xslmes/mesXslInspectMaintainItem/components/MesXslEquipmentTypeFilterSelectModal.vue jeecgboot-vue3/src/views/xslmes/mesXslInspectMaintainItem/components/MesXslEquipmentSubPartFilterSelectModal.vue +-- author:jiangxh---date:20260519--for: 【MES】设备点检配置主子表(设备台账+类型唯一、明细从点检保养项目带出)--- +jeecg-boot/db/mes-xsl-equip-inspect-config-menu-permission.sql +jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_78__mes_xsl_equip_inspect_config.sql +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectConfig.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectConfigLine.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectConfigPage.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectConfigMapper.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectConfigLineMapper.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectConfigService.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectConfigServiceImpl.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectConfigController.java +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfigList.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfig.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfig.api.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipInspectConfigModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerSelectModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslInspectMaintainItemSelectModal.vue +-- author:jiangxh---date:20260519--for: 【MES】修复设备点检配置保存失败(Page VO 与主实体重复 lineList 导致编译错误)--- +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectConfigPage.java +-- author:jiangxh---date:20260519--for: 【MES】设备点检配置明细改为多选点检保养项目、禁用JVxe新增--- +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipInspectConfigModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslInspectMaintainItemSelectModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfig.data.ts +-- author:jiangxh---date:20260520--for: 【MES】点检保养记录主子表(EC编号、设备配置带出明细、字典与菜单)--- +jeecg-boot/db/mes-xsl-equip-inspect-record-menu-permission.sql +jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_79__mes_xsl_equip_inspect_record.sql +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectRecord.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectRecordLine.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordPage.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectRecordMapper.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslEquipInspectRecordLineMapper.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectRecordService.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectRecordServiceImpl.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectRecordController.java +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.api.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordModal.vue +-- author:jiangxh---date:20260520--for: 【MES】点检记录改由设备台账批量生成,去掉记录列表新增与表单选设备--- +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordBatchCreateDTO.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordBatchCreateResult.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectRecordService.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectRecordServiceImpl.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectRecordController.java +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.api.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipmentLedger/MesXslEquipmentLedgerList.vue +-- author:jiangxh---date:20260520--for: 【MES】点检记录录入流程:去导入、待点检录入、保存变已点检--- +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectRecordController.java +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordModal.vue +-- author:jiangxh---date:20260520--for: 【MES】修复点检记录明细图片上传一直转圈(uploadUrl 补全 jeecg-boot 上下文)--- +jeecgboot-vue3/src/api/common/api.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.data.ts +-- author:jiangxh---date:20260520--for: 【MES】修复点检明细图片上传后预览「图片错误」(getFileAccessHttpUrl 补全 context-path)--- +jeecgboot-vue3/src/utils/env/apiBaseUrl.ts +jeecgboot-vue3/src/utils/common/compUtils.ts +jeecgboot-vue3/src/api/common/api.ts +-- author:jiangxh---date:20260520--for: 【MES】设备台账批量点检/保养:未维护对应类型点检配置不生成并提示设备名称--- +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/util/MesXslEquipInspectBizMsg.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectRecordServiceImpl.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectRecordController.java +jeecgboot-vue3/src/views/xslmes/mesXslEquipmentLedger/MesXslEquipmentLedgerList.vue +-- author:jiangxh---date:20260521--for: 【MES】点检保养记录不合格处理:是否已处理/处理人/处理时间字段与处理按钮--- +jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_80__mes_xsl_equip_inspect_record_handle.sql +jeecg-boot/db/mes-xsl-equip-inspect-record-menu-permission.sql +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslEquipInspectRecord.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslEquipInspectRecordHandleDTO.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslEquipInspectRecordService.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslEquipInspectRecordServiceImpl.java +jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslEquipInspectRecordController.java +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.data.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.api.ts +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordModal.vue +jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordHandleModal.vue diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_78__mes_xsl_equip_inspect_config.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_78__mes_xsl_equip_inspect_config.sql new file mode 100644 index 00000000..4217b2f1 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_78__mes_xsl_equip_inspect_config.sql @@ -0,0 +1,88 @@ +-- MES 设备点检配置(主子表):与 jeecg-boot/db/mes-xsl-equip-inspect-config-menu-permission.sql 一致 +SET NAMES utf8mb4; + +CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_config` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `equipment_ledger_id` varchar(32) NOT NULL COMMENT '设备台账主键 mes_xsl_equipment_ledger.id', + `equipment_name` varchar(500) DEFAULT NULL COMMENT '设备名称冗余', + `equipment_code` varchar(500) DEFAULT NULL COMMENT '设备编号冗余', + `config_type` varchar(500) NOT NULL COMMENT '配置类型(字典xslmes_im_item_category:inspect点检/maintain保养;同设备同类型唯一)', + `tenant_id` int DEFAULT NULL COMMENT '租户', + `sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门', + `create_by` varchar(500) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(500) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` int DEFAULT '0' COMMENT '删除标记(0正常1删除)', + PRIMARY KEY (`id`), + KEY `idx_meic_tenant_equip_type` (`tenant_id`, `equipment_ledger_id`, `config_type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES设备点检配置'; + +CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_config_line` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `config_id` varchar(32) NOT NULL COMMENT '主表主键 mes_xsl_equip_inspect_config.id', + `inspect_maintain_item_id` varchar(32) NOT NULL COMMENT '点检及保养项目主键 mes_xsl_inspect_maintain_item.id', + `item_code` varchar(500) DEFAULT NULL COMMENT '点检项目编号冗余', + `item_name` varchar(500) DEFAULT NULL COMMENT '项目名称冗余', + `item_category` varchar(500) DEFAULT NULL COMMENT '项目类别冗余', + `item_type` varchar(500) DEFAULT NULL COMMENT '项目类型冗余', + `equipment_part_name` varchar(500) DEFAULT NULL COMMENT '设备部位名称冗余', + `equipment_sub_part_name` varchar(500) DEFAULT NULL COMMENT '设备小部位名称冗余', + `inspect_method` varchar(500) DEFAULT NULL COMMENT '点检方式冗余', + `judgment_criteria` varchar(500) DEFAULT NULL COMMENT '判断基准冗余', + `sort_no` int DEFAULT '0' COMMENT '排序号', + `create_by` varchar(500) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(500) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_meicl_config` (`config_id`), + KEY `idx_meicl_item` (`inspect_maintain_item_id`), + UNIQUE KEY `uk_meicl_config_item` (`config_id`, `inspect_maintain_item_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES设备点检配置明细'; + +SET @mes_tenant_id = 1002; + +SET @mes_equip_pid = ( + SELECT `id` FROM `sys_permission` + WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理' + LIMIT 1 +); +SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133'); + +INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`) +VALUES ('1860000000000000148', @mes_equip_pid, '设备点检配置', '/xslmes/mesXslEquipInspectConfig', 'xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfigList', NULL, 1, NULL, '1', 12, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW()) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`), +`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`), +`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`), +`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:control-outlined'; + +UPDATE `sys_permission` SET `icon` = 'ant-design:control-outlined' WHERE `id` = '1860000000000000148' AND `del_flag` = 0; + +INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES +('1860000000000000149', '1860000000000000148', '新增', 2, 'mes:mes_xsl_equip_inspect_config:add', '1', '1', 0, 'admin', NOW()), +('1860000000000000150', '1860000000000000148', '编辑', 2, 'mes:mes_xsl_equip_inspect_config:edit', '1', '1', 0, 'admin', NOW()), +('1860000000000000151', '1860000000000000148', '删除', 2, 'mes:mes_xsl_equip_inspect_config:delete', '1', '1', 0, 'admin', NOW()), +('1860000000000000152', '1860000000000000148', '批量删除', 2, 'mes:mes_xsl_equip_inspect_config:deleteBatch', '1', '1', 0, 'admin', NOW()), +('1860000000000000153', '1860000000000000148', '导出', 2, 'mes:mes_xsl_equip_inspect_config:exportXls', '1', '1', 0, 'admin', NOW()), +('1860000000000000154', '1860000000000000148', '导入', 2, 'mes:mes_xsl_equip_inspect_config:importExcel', '1', '1', 0, 'admin', NOW()) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), +`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`); + +INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1' +FROM `sys_role` r +CROSS JOIN `sys_permission` p +WHERE r.`tenant_id` = @mes_tenant_id + AND r.`role_code` = 'admin' + AND p.`id` IN ( + '1860000000000000148', + '1860000000000000149', '1860000000000000150', '1860000000000000151', '1860000000000000152', + '1860000000000000153', '1860000000000000154' + ) + AND NOT EXISTS ( + SELECT 1 FROM `sys_role_permission` rp + WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id` + ); diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_79__mes_xsl_equip_inspect_record.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_79__mes_xsl_equip_inspect_record.sql new file mode 100644 index 00000000..bfa8a829 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_79__mes_xsl_equip_inspect_record.sql @@ -0,0 +1,133 @@ +-- MES 点检/保养记录(主子表):建表 + 字典 + 菜单 + 按钮 + 租户 admin 授权 +-- 权限前缀:mes:mes_xsl_equip_inspect_record:* +-- 父菜单:设备管理;依赖设备点检配置、设备台账 +-- Flyway:V3.9.2_79__mes_xsl_equip_inspect_record.sql +SET NAMES utf8mb4; + +INSERT INTO `sys_dict`(`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`) +SELECT REPLACE(UUID(), '-', ''), 'MES点检记录结果', 'xslmes_im_inspect_result', '合格/不合格', 0, 'admin', NOW(), 0, 0 +WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_im_inspect_result' AND `del_flag` = 0); + +INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.`id`, '合格', 'pass', '', 1, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_im_inspect_result' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'pass'); + +INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.`id`, '不合格', 'fail', '', 2, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_im_inspect_result' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'fail'); + +INSERT INTO `sys_dict`(`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`) +SELECT REPLACE(UUID(), '-', ''), 'MES点检记录状态', 'xslmes_im_record_status', '待点检/已点检', 0, 'admin', NOW(), 0, 0 +WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_im_record_status' AND `del_flag` = 0); + +INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.`id`, '待点检', 'pending', '', 1, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_im_record_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'pending'); + +INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.`id`, '已点检', 'done', '', 2, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_im_record_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'done'); + +CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_record` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `record_no` varchar(32) NOT NULL COMMENT '记录编号(EC+yyyyMMdd+4位流水,租户内按日递增)', + `plan_no` varchar(500) DEFAULT NULL COMMENT '计划单号', + `plan_id` varchar(32) DEFAULT NULL COMMENT '计划主键(隐藏)', + `equipment_ledger_id` varchar(32) NOT NULL COMMENT '设备台账主键 mes_xsl_equipment_ledger.id', + `equipment_code` varchar(500) DEFAULT NULL COMMENT '设备编码冗余', + `equipment_name` varchar(500) DEFAULT NULL COMMENT '设备名称冗余', + `equip_inspect_config_id` varchar(32) DEFAULT NULL COMMENT '设备点检配置主键 mes_xsl_equip_inspect_config.id', + `record_type` varchar(500) NOT NULL COMMENT '类型(字典xslmes_im_item_category:inspect点检/maintain保养)', + `inspect_date` date DEFAULT NULL COMMENT '点检日期', + `inspector_user_id` varchar(32) DEFAULT NULL COMMENT '点检人用户ID', + `inspector_username` varchar(500) DEFAULT NULL COMMENT '点检人账号', + `inspector_realname` varchar(500) DEFAULT NULL COMMENT '点检人姓名', + `inspect_result` varchar(500) NOT NULL COMMENT '点检结果(字典xslmes_im_inspect_result:pass合格/fail不合格)', + `record_status` varchar(500) NOT NULL COMMENT '状态(字典xslmes_im_record_status:pending待点检/done已点检)', + `tenant_id` int DEFAULT NULL COMMENT '租户', + `sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门', + `create_by` varchar(500) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(500) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` int DEFAULT '0' COMMENT '删除标记(0正常1删除)', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_meir_tenant_record_no` (`tenant_id`, `record_no`), + KEY `idx_meir_equip_type` (`equipment_ledger_id`, `record_type`), + KEY `idx_meir_inspect_date` (`inspect_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES点检保养记录'; + +CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_record_line` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `record_id` varchar(32) NOT NULL COMMENT '主表主键 mes_xsl_equip_inspect_record.id', + `equip_inspect_config_line_id` varchar(32) NOT NULL COMMENT '设备点检配置明细主键 mes_xsl_equip_inspect_config_line.id', + `inspect_maintain_item_id` varchar(32) DEFAULT NULL COMMENT '点检及保养项目主键冗余', + `item_code` varchar(500) DEFAULT NULL COMMENT '点检项目编号冗余', + `item_name` varchar(500) DEFAULT NULL COMMENT '项目名称冗余', + `item_category` varchar(500) DEFAULT NULL COMMENT '项目类别冗余', + `item_type` varchar(500) DEFAULT NULL COMMENT '项目类型冗余', + `equipment_part_name` varchar(500) DEFAULT NULL COMMENT '设备部位冗余', + `equipment_sub_part_name` varchar(500) DEFAULT NULL COMMENT '设备小部位冗余', + `inspect_method` varchar(500) DEFAULT NULL COMMENT '点检方式冗余', + `judgment_criteria` varchar(500) DEFAULT NULL COMMENT '判断基准冗余', + `line_inspect_result` varchar(500) DEFAULT NULL COMMENT '明细点检结果(文本)', + `picture_files` varchar(2000) DEFAULT NULL COMMENT '图片(上传路径,逗号分隔)', + `sort_no` int DEFAULT '0' COMMENT '排序号', + `create_by` varchar(500) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(500) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_meirl_record` (`record_id`), + KEY `idx_meirl_config_line` (`equip_inspect_config_line_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES点检保养记录明细'; + +SET @mes_tenant_id = 1002; + +SET @mes_equip_pid = ( + SELECT `id` FROM `sys_permission` + WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理' + LIMIT 1 +); +SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133'); + +INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`) +VALUES ('1860000000000000155', @mes_equip_pid, '点检保养记录', '/xslmes/mesXslEquipInspectRecord', 'xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList', 'MesXslEquipInspectRecordList', 1, NULL, '1', 13, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW()) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`), +`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`), +`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`), +`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:file-done-outlined'; + +UPDATE `sys_permission` SET `icon` = 'ant-design:file-done-outlined' WHERE `id` = '1860000000000000155' AND `del_flag` = 0; + +INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES +('1860000000000000156', '1860000000000000155', '新增', 2, 'mes:mes_xsl_equip_inspect_record:add', '1', '1', 0, 'admin', NOW()), +('1860000000000000157', '1860000000000000155', '编辑', 2, 'mes:mes_xsl_equip_inspect_record:edit', '1', '1', 0, 'admin', NOW()), +('1860000000000000158', '1860000000000000155', '删除', 2, 'mes:mes_xsl_equip_inspect_record:delete', '1', '1', 0, 'admin', NOW()), +('1860000000000000159', '1860000000000000155', '批量删除', 2, 'mes:mes_xsl_equip_inspect_record:deleteBatch', '1', '1', 0, 'admin', NOW()), +('1860000000000000160', '1860000000000000155', '导出', 2, 'mes:mes_xsl_equip_inspect_record:exportXls', '1', '1', 0, 'admin', NOW()), +('1860000000000000161', '1860000000000000155', '导入', 2, 'mes:mes_xsl_equip_inspect_record:importExcel', '1', '1', 0, 'admin', NOW()) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), +`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`); + +INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1' +FROM `sys_role` r +CROSS JOIN `sys_permission` p +WHERE r.`tenant_id` = @mes_tenant_id + AND r.`role_code` = 'admin' + AND p.`id` IN ( + '1860000000000000155', + '1860000000000000156', '1860000000000000157', '1860000000000000158', '1860000000000000159', + '1860000000000000160', '1860000000000000161' + ) + AND NOT EXISTS ( + SELECT 1 FROM `sys_role_permission` rp + WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id` + ); diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_80__mes_xsl_equip_inspect_record_handle.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_80__mes_xsl_equip_inspect_record_handle.sql new file mode 100644 index 00000000..b9ad5030 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_80__mes_xsl_equip_inspect_record_handle.sql @@ -0,0 +1,9 @@ +-- MES 点检保养记录:不合格处理字段(是否已处理/处理人/处理时间) +SET NAMES utf8mb4; + +ALTER TABLE `mes_xsl_equip_inspect_record` + ADD COLUMN `handled_flag` varchar(1) DEFAULT NULL COMMENT '是否已处理(字典yn:1是0否,仅不合格记录使用)' AFTER `record_status`, + ADD COLUMN `handler_user_id` varchar(32) DEFAULT NULL COMMENT '处理人用户ID' AFTER `handled_flag`, + ADD COLUMN `handler_username` varchar(500) DEFAULT NULL COMMENT '处理人账号' AFTER `handler_user_id`, + ADD COLUMN `handler_realname` varchar(500) DEFAULT NULL COMMENT '处理人姓名' AFTER `handler_username`, + ADD COLUMN `handle_time` datetime DEFAULT NULL COMMENT '处理时间' AFTER `handler_realname`; diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_91__mes_xsl_formula_spec.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_91__mes_xsl_formula_spec.sql new file mode 100644 index 00000000..854db700 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_91__mes_xsl_formula_spec.sql @@ -0,0 +1,186 @@ +-- 配合示方:分类/STEP/称量方式/状态字典 + 主/子表 + 菜单(挂 MES技术管理)+ admin 授权 +SET NAMES utf8mb4; + +INSERT IGNORE INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`) +VALUES ('1995000000000000010', '配合示方分类', 'xslmes_formula_spec_category', 'MES配合示方分类', 0, 'admin', NOW(), 0, 1002); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001001', '1995000000000000010', '标准', 'standard', 1, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001002', '1995000000000000010', '临时', 'temporary', 2, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001003', '1995000000000000010', '实验', 'trial', 3, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001004', '1995000000000000010', '消费', 'consumption', 4, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`) +VALUES ('1995000000000000011', '配合示方STEP', 'xslmes_formula_spec_step', 'MES配合示方STEP', 0, 'admin', NOW(), 0, 1002); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001011', '1995000000000000011', 'A', 'A', 1, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001012', '1995000000000000011', 'B', 'B', 2, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001013', '1995000000000000011', 'Q', 'Q', 3, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`) +VALUES ('1995000000000000012', '配合示方称量方式', 'xslmes_formula_spec_weigh_mode', 'MES配合示方自动/人工称量', 0, 'admin', NOW(), 0, 1002); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001021', '1995000000000000012', '自动称量1', 'auto1', 1, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001022', '1995000000000000012', '人工称量', 'manual', 2, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`) +VALUES ('1995000000000000013', '配合示方状态', 'xslmes_formula_spec_status', 'MES配合示方状态', 0, 'admin', NOW(), 0, 1002); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001031', '1995000000000000013', '编制', 'compile', 1, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001032', '1995000000000000013', '校对', 'proofread', 2, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001033', '1995000000000000013', '审核', 'audit', 3, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001034', '1995000000000000013', '批准', 'approve', 4, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001035', '1995000000000000013', '正式发布', 'released', 5, 1, 'admin', NOW()); + +INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`) +VALUES ('1995000000000001036', '1995000000000000013', '作废', 'obsolete', 6, 1, 'admin', NOW()); + +CREATE TABLE IF NOT EXISTS `mes_xsl_formula_spec` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `category` varchar(32) DEFAULT 'standard' COMMENT '分类(字典xslmes_formula_spec_category:standard标准 temporary临时 trial实验 consumption消费)', + `spec_code` varchar(100) DEFAULT NULL COMMENT '示方编号', + `rubber_code` varchar(100) DEFAULT NULL COMMENT '胶料代号', + `basic_formula` varchar(100) DEFAULT NULL COMMENT '基本配合', + `issue_date` date DEFAULT NULL COMMENT '发行日期', + `purpose` varchar(500) DEFAULT NULL COMMENT '用途', + `issue_number` varchar(100) DEFAULT NULL COMMENT '发行编号', + `mixing_stages` int DEFAULT NULL COMMENT '混合段数(1-7)', + `mixing_machine` varchar(200) DEFAULT NULL COMMENT '混合机器', + `issue_dept_id` varchar(32) DEFAULT NULL COMMENT '发行部门ID', + `issue_dept_name` varchar(200) DEFAULT NULL COMMENT '发行部门名称冗余', + `a_rubber_total_phr` decimal(18,4) DEFAULT NULL COMMENT 'A胶TOTAL PHR', + `total_phr` decimal(18,4) DEFAULT NULL COMMENT 'TOTAL PHR', + `issue_reason` text COMMENT '发行理由', + `natural_rubber` decimal(18,4) DEFAULT NULL COMMENT '天然橡胶', + `synthetic_rubber` decimal(18,4) DEFAULT NULL COMMENT '合成橡胶', + `total_amount` decimal(18,4) DEFAULT NULL COMMENT '合计', + `weight_unit_price` decimal(18,4) DEFAULT NULL COMMENT '重量单价', + `volume_unit_price` decimal(18,4) DEFAULT NULL COMMENT '体积单价', + `q_rubber_sg` decimal(18,6) DEFAULT NULL COMMENT 'Q胶比重', + `a_rubber_sg` decimal(18,6) DEFAULT NULL COMMENT 'A胶比重', + `has_manual_batch` int DEFAULT 0 COMMENT '是否有人工配料(0否 1是)', + `status` varchar(32) DEFAULT 'compile' COMMENT '状态(字典xslmes_formula_spec_status)', + `proofread_by` varchar(50) DEFAULT NULL COMMENT '校对人', + `proofread_time` datetime DEFAULT NULL COMMENT '校对时间', + `audit_by` varchar(50) DEFAULT NULL COMMENT '审核人', + `audit_time` datetime DEFAULT NULL COMMENT '审核时间', + `approve_by` varchar(50) DEFAULT NULL COMMENT '批准人', + `approve_time` datetime DEFAULT NULL COMMENT '批准时间', + `tenant_id` int DEFAULT NULL COMMENT '租户ID', + `sys_org_code` varchar(64) DEFAULT NULL COMMENT '所属部门', + `create_by` varchar(50) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(50) DEFAULT NULL COMMENT '修改人', + `update_time` datetime DEFAULT NULL COMMENT '修改时间', + `del_flag` int NOT NULL DEFAULT 0 COMMENT '逻辑删除(0正常 1已删除)', + PRIMARY KEY (`id`), + KEY `idx_mxfs_spec_code` (`spec_code`), + KEY `idx_mxfs_rubber_code` (`rubber_code`), + KEY `idx_mxfs_issue_number` (`issue_number`), + KEY `idx_mxfs_category` (`category`), + KEY `idx_mxfs_status` (`status`), + KEY `idx_mxfs_issue_date` (`issue_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES配合示方'; + +CREATE TABLE IF NOT EXISTS `mes_xsl_formula_spec_line` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `formula_spec_id` varchar(32) NOT NULL COMMENT '配合示方主表ID', + `sort_no` int DEFAULT NULL COMMENT '行序号', + `phr` decimal(18,4) DEFAULT NULL COMMENT 'PHR', + `mixer_material_id` varchar(32) DEFAULT NULL COMMENT '密炼物料ID', + `mixer_material_code` varchar(100) DEFAULT NULL COMMENT '密炼物料编码冗余', + `mixer_material_name` varchar(200) DEFAULT NULL COMMENT '密炼物料名称冗余', + `material_desc` varchar(500) DEFAULT NULL COMMENT '物料描述', + `step` varchar(8) DEFAULT NULL COMMENT 'STEP(字典xslmes_formula_spec_step:A/B/Q)', + `weigh_mode` varchar(32) DEFAULT NULL COMMENT '称量方式(字典xslmes_formula_spec_weigh_mode)', + `weight_percent` decimal(18,4) DEFAULT NULL COMMENT '重量%', + `volume` decimal(18,6) DEFAULT NULL COMMENT '体积', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `stage1` decimal(18,4) DEFAULT NULL COMMENT '混合段1', + `stage2` decimal(18,4) DEFAULT NULL COMMENT '混合段2', + `stage3` decimal(18,4) DEFAULT NULL COMMENT '混合段3', + `stage4` decimal(18,4) DEFAULT NULL COMMENT '混合段4', + `stage5` decimal(18,4) DEFAULT NULL COMMENT '混合段5', + `stage6` decimal(18,4) DEFAULT NULL COMMENT '混合段6', + `stage7` decimal(18,4) DEFAULT NULL COMMENT '混合段7', + `tenant_id` int DEFAULT NULL COMMENT '租户ID', + `create_by` varchar(50) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(50) DEFAULT NULL COMMENT '修改人', + `update_time` datetime DEFAULT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + KEY `idx_mxfsl_formula_spec_id` (`formula_spec_id`), + KEY `idx_mxfsl_mixer_material_id` (`mixer_material_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES配合示方明细'; + +UPDATE `sys_permission` +SET `is_leaf` = 0, `update_time` = NOW() +WHERE `id` = '1900000000000000810' AND `is_leaf` = 1; + +INSERT IGNORE INTO `sys_permission` ( + `id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, + `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, + `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, + `del_flag`, `rule_flag`, `status`, `internal_or_external` +) VALUES ( + '177925970995530', '1900000000000000810', '配合示方', '/xslmes/mesXslFormulaSpec', + 'xslmes/mesXslFormulaSpec/MesXslFormulaSpecList', 1, 'MesXslFormulaSpecList', NULL, + 1, NULL, '0', 1.00, 0, 'ant-design:experiment-outlined', 0, 1, + 0, 0, 'MES配合示方', 'admin', NOW(), 'admin', NOW(), + 0, 0, '1', 0 +); + +INSERT IGNORE INTO `sys_permission` (`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `create_by`, `create_time`) +VALUES ('177925970995531', '177925970995530', '新增', 2, 'xslmes:mes_xsl_formula_spec:add', '1', 1.00, 0, 1, 0, '1', 0, 'admin', NOW()); + +INSERT IGNORE INTO `sys_permission` (`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `create_by`, `create_time`) +VALUES ('177925970995532', '177925970995530', '编辑', 2, 'xslmes:mes_xsl_formula_spec:edit', '1', 2.00, 0, 1, 0, '1', 0, 'admin', NOW()); + +INSERT IGNORE INTO `sys_permission` (`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `create_by`, `create_time`) +VALUES ('177925970995533', '177925970995530', '删除', 2, 'xslmes:mes_xsl_formula_spec:delete', '1', 3.00, 0, 1, 0, '1', 0, 'admin', NOW()); + +INSERT IGNORE INTO `sys_permission` (`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `create_by`, `create_time`) +VALUES ('177925970995534', '177925970995530', '批量删除', 2, 'xslmes:mes_xsl_formula_spec:deleteBatch', '1', 4.00, 0, 1, 0, '1', 0, 'admin', NOW()); + +INSERT IGNORE INTO `sys_permission` (`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `create_by`, `create_time`) +VALUES ('177925970995535', '177925970995530', '导出', 2, 'xslmes:mes_xsl_formula_spec:exportXls', '1', 5.00, 0, 1, 0, '1', 0, 'admin', NOW()); + +INSERT IGNORE INTO `sys_permission` (`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `create_by`, `create_time`) +VALUES ('177925970995536', '177925970995530', '导入', 2, 'xslmes:mes_xsl_formula_spec:importExcel', '1', 6.00, 0, 1, 0, '1', 0, 'admin', NOW()); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, p.id, NULL, NOW(), '127.0.0.1' +FROM `sys_role` r +CROSS JOIN `sys_permission` p +WHERE r.`role_code` = 'admin' + AND p.`id` IN ( + '177925970995530', '177925970995531', '177925970995532', + '177925970995533', '177925970995534', '177925970995535', '177925970995536' + ) + AND NOT EXISTS ( + SELECT 1 FROM `sys_role_permission` rp + WHERE rp.`role_id` = r.id AND rp.`permission_id` = p.id + ); diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_92__mes_xsl_formula_spec_stage_total.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_92__mes_xsl_formula_spec_stage_total.sql new file mode 100644 index 00000000..079adc0b --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_92__mes_xsl_formula_spec_stage_total.sql @@ -0,0 +1,9 @@ +-- 配合示方:主表新增混合段1-7合计字段 +ALTER TABLE `mes_xsl_formula_spec` + ADD COLUMN `stage1_total` decimal(18,4) DEFAULT NULL COMMENT '混合段1合计' AFTER `total_phr`, + ADD COLUMN `stage2_total` decimal(18,4) DEFAULT NULL COMMENT '混合段2合计' AFTER `stage1_total`, + ADD COLUMN `stage3_total` decimal(18,4) DEFAULT NULL COMMENT '混合段3合计' AFTER `stage2_total`, + ADD COLUMN `stage4_total` decimal(18,4) DEFAULT NULL COMMENT '混合段4合计' AFTER `stage3_total`, + ADD COLUMN `stage5_total` decimal(18,4) DEFAULT NULL COMMENT '混合段5合计' AFTER `stage4_total`, + ADD COLUMN `stage6_total` decimal(18,4) DEFAULT NULL COMMENT '混合段6合计' AFTER `stage5_total`, + ADD COLUMN `stage7_total` decimal(18,4) DEFAULT NULL COMMENT '混合段7合计' AFTER `stage6_total`; diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_93__mes_xsl_formula_spec_category_dict.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_93__mes_xsl_formula_spec_category_dict.sql new file mode 100644 index 00000000..04a9164b --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_93__mes_xsl_formula_spec_category_dict.sql @@ -0,0 +1,15 @@ +-- 配合示方分类字典:标准示方 S / 临时示方 P / 试验示方 T / 消费示方 C +SET NAMES utf8mb4; + +UPDATE `sys_dict_item` SET `item_text` = '标准示方', `item_value` = 'S' WHERE `id` = '1995000000000001001'; +UPDATE `sys_dict_item` SET `item_text` = '临时示方', `item_value` = 'P' WHERE `id` = '1995000000000001002'; +UPDATE `sys_dict_item` SET `item_text` = '试验示方', `item_value` = 'T' WHERE `id` = '1995000000000001003'; +UPDATE `sys_dict_item` SET `item_text` = '消费示方', `item_value` = 'C' WHERE `id` = '1995000000000001004'; + +UPDATE `mes_xsl_formula_spec` SET `category` = 'S' WHERE `category` = 'standard'; +UPDATE `mes_xsl_formula_spec` SET `category` = 'P' WHERE `category` = 'temporary'; +UPDATE `mes_xsl_formula_spec` SET `category` = 'T' WHERE `category` = 'trial'; +UPDATE `mes_xsl_formula_spec` SET `category` = 'C' WHERE `category` = 'consumption'; + +ALTER TABLE `mes_xsl_formula_spec` + MODIFY COLUMN `category` varchar(32) DEFAULT 'S' COMMENT '分类(字典xslmes_formula_spec_category:S标准示方 P临时示方 T试验示方 C消费示方)'; diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_94__mes_xsl_formula_spec_rubber_material_id.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_94__mes_xsl_formula_spec_rubber_material_id.sql new file mode 100644 index 00000000..98ba7866 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_94__mes_xsl_formula_spec_rubber_material_id.sql @@ -0,0 +1,7 @@ +-- 配合示方:关联胶料主数据,支持胶料代号自动生成 +SET NAMES utf8mb4; + +ALTER TABLE `mes_xsl_formula_spec` + ADD COLUMN `rubber_material_id` varchar(32) DEFAULT NULL COMMENT '胶料ID(关联mes_material.id)' AFTER `rubber_code`; + +CREATE INDEX `idx_mxfs_rubber_material_id` ON `mes_xsl_formula_spec` (`rubber_material_id`); diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_95__mes_xsl_formula_spec_step_remove_b.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_95__mes_xsl_formula_spec_step_remove_b.sql new file mode 100644 index 00000000..a9b8cab2 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_95__mes_xsl_formula_spec_step_remove_b.sql @@ -0,0 +1,10 @@ +-- 配合示方 STEP 字典:删除字典值 B +SET NAMES utf8mb4; + +-- 已有业务数据若使用 B,清空以便重新选择 +UPDATE `mes_xsl_formula_spec_line` SET `step` = NULL WHERE `step` = 'B'; + +DELETE FROM `sys_dict_item` WHERE `id` = '1995000000000001012'; + +ALTER TABLE `mes_xsl_formula_spec_line` + MODIFY COLUMN `step` varchar(8) DEFAULT NULL COMMENT 'STEP(字典xslmes_formula_spec_step:A/Q)'; diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_96__mes_xsl_formula_spec_rubber_content_setting.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_96__mes_xsl_formula_spec_rubber_content_setting.sql new file mode 100644 index 00000000..edd6fac2 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_96__mes_xsl_formula_spec_rubber_content_setting.sql @@ -0,0 +1,20 @@ +-- 配合示方:含胶率物料小类配置(天然橡胶 / 合成橡胶) +DROP TABLE IF EXISTS `mes_xsl_formula_spec_setting`; +CREATE TABLE `mes_xsl_formula_spec_setting` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `natural_minor_category_ids` varchar(2000) DEFAULT NULL COMMENT '天然橡胶物料小类ID,逗号分隔', + `synthetic_minor_category_ids` varchar(2000) DEFAULT NULL COMMENT '合成橡胶物料小类ID,逗号分隔', + `create_by` varchar(50) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(50) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配合示方模块配置'; + +INSERT INTO `mes_xsl_formula_spec_setting` (`id`, `natural_minor_category_ids`, `synthetic_minor_category_ids`, `create_time`) +SELECT + '1993000000000000991', + (SELECT `id` FROM `sys_category` WHERE `code` = 'XSLMES_MATERIAL_RAW_AUX_TRJ' LIMIT 1), + (SELECT `id` FROM `sys_category` WHERE `code` = 'XSLMES_MATERIAL_RAW_AUX_HCJ' LIMIT 1), + NOW() +WHERE NOT EXISTS (SELECT 1 FROM `mes_xsl_formula_spec_setting` WHERE `id` = '1993000000000000991'); diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/logback-spring.xml b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/logback-spring.xml index 67be4774..0f8f77f6 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/logback-spring.xml +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/logback-spring.xml @@ -1,5 +1,9 @@ + + + + @@ -10,6 +14,7 @@ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n + ${CONSOLE_LOG_CHARSET} @@ -25,6 +30,7 @@ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n + ${FILE_LOG_CHARSET} diff --git a/jeecgboot-vue3/src/api/common/api.ts b/jeecgboot-vue3/src/api/common/api.ts index fee73867..b481a9be 100644 --- a/jeecgboot-vue3/src/api/common/api.ts +++ b/jeecgboot-vue3/src/api/common/api.ts @@ -1,8 +1,7 @@ import { defHttp } from '/@/utils/http/axios'; import { message } from 'ant-design-vue'; -import { useGlobSetting } from '/@/hooks/setting'; -const globSetting = useGlobSetting(); -const baseUploadUrl = globSetting.uploadUrl; +import { resolveApiBaseUrl } from '/@/utils/env/apiBaseUrl'; + enum Api { positionList = '/sys/position/list', userList = '/sys/user/list', @@ -25,9 +24,9 @@ enum Api { } /** - * 上传父路径 + * 上传地址(须含 context-path;开发环境 domain 仅为 host 时需拼 apiUrl) */ -export const uploadUrl = `${baseUploadUrl}/sys/common/upload`; +export const uploadUrl = `${resolveApiBaseUrl()}/sys/common/upload`; /** * 职务列表 diff --git a/jeecgboot-vue3/src/utils/common/compUtils.ts b/jeecgboot-vue3/src/utils/common/compUtils.ts index 0faab619..a864c428 100644 --- a/jeecgboot-vue3/src/utils/common/compUtils.ts +++ b/jeecgboot-vue3/src/utils/common/compUtils.ts @@ -1,4 +1,3 @@ -import { useGlobSetting } from '/@/hooks/setting'; import { merge, random } from 'lodash-es'; import { isArray } from '/@/utils/is'; import { FormSchema } from '/@/components/Form'; @@ -14,11 +13,10 @@ import { useI18n } from "@/hooks/web/useI18n"; import {$electron} from "@/electron"; import {router} from "@/router"; import {encryptByBase64} from "@/utils/cipher"; +import { resolveApiBaseUrl } from '/@/utils/env/apiBaseUrl'; //存放部门路径的数组 const departNamePath = ref>({}); -const globSetting = useGlobSetting(); -const baseApiUrl = globSetting.domainUrl; /** * 获取文件服务访问路径 * @param fileUrl 文件路径 @@ -31,10 +29,10 @@ export const getFileAccessHttpUrl = (fileUrl, prefix = 'http') => { //判断是否是数组格式 let isArray = fileUrl.indexOf('[') != -1; if (!isArray) { - let prefix = `${baseApiUrl}/sys/common/static/`; + const staticPrefix = `${resolveApiBaseUrl()}/sys/common/static/`; // 判断是否已包含前缀 - if (!fileUrl.startsWith(prefix)) { - result = `${prefix}${fileUrl}`; + if (!fileUrl.startsWith(staticPrefix)) { + result = `${staticPrefix}${fileUrl}`; } } } diff --git a/jeecgboot-vue3/src/utils/env/apiBaseUrl.ts b/jeecgboot-vue3/src/utils/env/apiBaseUrl.ts new file mode 100644 index 00000000..85ccf59e --- /dev/null +++ b/jeecgboot-vue3/src/utils/env/apiBaseUrl.ts @@ -0,0 +1,18 @@ +import { useGlobSetting } from '/@/hooks/setting'; + +/** + * 后端 API 根地址(含 servlet.context-path,如 /jeecg-boot) + * 开发环境 VITE_GLOB_DOMAIN_URL 常为 http://host:port,需与 VITE_GLOB_API_URL 拼接 + */ +export function resolveApiBaseUrl(): string { + const { domainUrl, apiUrl } = useGlobSetting(); + const domain = (domainUrl || '').replace(/\/$/, ''); + const api = apiUrl || ''; + if (!domain) { + return api; + } + if (!api || domain.endsWith(api) || domain.includes(`${api}/`)) { + return domain; + } + return `${domain}${api}`; +} diff --git a/jeecgboot-vue3/src/views/mes/material/MesMaterial.api.ts b/jeecgboot-vue3/src/views/mes/material/MesMaterial.api.ts index 37037614..256b2c9e 100644 --- a/jeecgboot-vue3/src/views/mes/material/MesMaterial.api.ts +++ b/jeecgboot-vue3/src/views/mes/material/MesMaterial.api.ts @@ -9,11 +9,13 @@ enum Api { deleteBatch = '/mes/material/material/deleteBatch', importExcel = '/mes/material/material/importExcel', exportXls = '/mes/material/material/exportXls', + queryById = '/mes/material/material/queryById', } export const getExportUrl = Api.exportXls; export const getImportUrl = Api.importExcel; export const list = (params) => defHttp.get({ url: Api.list, params }); +export const queryById = (params) => defHttp.get({ url: Api.queryById, params }, { successMessageMode: 'none' }); export const deleteOne = (params, handleSuccess) => defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => handleSuccess()); diff --git a/jeecgboot-vue3/src/views/mes/material/modules/MesMaterialSelectModal.vue b/jeecgboot-vue3/src/views/mes/material/modules/MesMaterialSelectModal.vue new file mode 100644 index 00000000..c2af6580 --- /dev/null +++ b/jeecgboot-vue3/src/views/mes/material/modules/MesMaterialSelectModal.vue @@ -0,0 +1,90 @@ + + + diff --git a/jeecgboot-vue3/src/views/mes/material/modules/MesMixerMaterialSelectModal.vue b/jeecgboot-vue3/src/views/mes/material/modules/MesMixerMaterialSelectModal.vue index 312bdc9b..0e72e83d 100644 --- a/jeecgboot-vue3/src/views/mes/material/modules/MesMixerMaterialSelectModal.vue +++ b/jeecgboot-vue3/src/views/mes/material/modules/MesMixerMaterialSelectModal.vue @@ -85,8 +85,12 @@ emit('select', { mixerMaterialId: row.id, materialName: row.materialName || '', + materialCode: row.materialCode || '', materialDesc: row.materialDesc || '', materialKind: buildKind(row), + minorCategoryId: row.minorCategoryId || '', + majorCategoryText: row.majorCategoryId_dictText || '', + minorCategoryText: row.minorCategoryId_dictText || '', }); closeModal(); } diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfig.api.ts b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfig.api.ts new file mode 100644 index 00000000..027bb048 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfig.api.ts @@ -0,0 +1,51 @@ +import { defHttp } from '/@/utils/http/axios'; +import { useMessage } from '/@/hooks/web/useMessage'; + +const { createConfirm } = useMessage(); + +enum Api { + list = '/xslmes/mesXslEquipInspectConfig/list', + save = '/xslmes/mesXslEquipInspectConfig/add', + edit = '/xslmes/mesXslEquipInspectConfig/edit', + deleteOne = '/xslmes/mesXslEquipInspectConfig/delete', + deleteBatch = '/xslmes/mesXslEquipInspectConfig/deleteBatch', + importExcel = '/xslmes/mesXslEquipInspectConfig/importExcel', + exportXls = '/xslmes/mesXslEquipInspectConfig/exportXls', + queryById = '/xslmes/mesXslEquipInspectConfig/queryById', + queryLineList = '/xslmes/mesXslEquipInspectConfig/queryLineListByConfigId', +} + +export const getExportUrl = Api.exportXls; +export const getImportUrl = Api.importExcel; + +export const list = (params) => defHttp.get({ url: Api.list, params }); + +export const queryById = (params: { id: string }) => defHttp.get({ url: Api.queryById, params }); + +export const queryLineListByConfigId = (params: { id: string }) => defHttp.get({ url: Api.queryLineList, params }); + +export const deleteOne = (params, handleSuccess) => { + return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => { + handleSuccess(); + }); +}; + +export const batchDelete = (params, handleSuccess) => { + createConfirm({ + iconType: 'warning', + title: '确认删除', + content: '是否删除选中数据', + okText: '确认', + cancelText: '取消', + onOk: () => { + return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => { + handleSuccess(); + }); + }, + }); +}; + +export const saveOrUpdate = (params, isUpdate) => { + const url = isUpdate ? Api.edit : Api.save; + return defHttp.post({ url, params }); +}; diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfig.data.ts b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfig.data.ts new file mode 100644 index 00000000..d9c97f17 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfig.data.ts @@ -0,0 +1,86 @@ +import { BasicColumn, FormSchema } from '/@/components/Table'; +import { JVxeColumn, JVxeTypes } from '/@/components/jeecg/JVxeTable/types'; + +export const columns: BasicColumn[] = [ + { title: '设备名称', align: 'center', dataIndex: 'equipmentName', width: 160 }, + { title: '设备编号', align: 'center', dataIndex: 'equipmentCode', width: 140 }, + { title: '类型', align: 'center', dataIndex: 'configType_dictText', width: 90 }, + { title: '创建人', align: 'center', dataIndex: 'createBy', width: 100 }, + { + title: '创建时间', + align: 'center', + dataIndex: 'createTime', + width: 165, + customRender: ({ text }) => (!text ? '' : String(text).length > 19 ? String(text).substring(0, 19) : text), + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { label: '设备名称', field: 'equipmentName', component: 'Input', colProps: { span: 6 } }, + { label: '设备编号', field: 'equipmentCode', component: 'Input', colProps: { span: 6 } }, + { + label: '类型', + field: 'configType', + component: 'JDictSelectTag', + componentProps: { dictCode: 'xslmes_im_item_category' }, + colProps: { span: 6 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { label: '', field: 'id', component: 'Input', show: false }, + { label: '', field: 'equipmentLedgerId', component: 'Input', show: false }, + { + label: '设备名称', + field: 'equipmentName', + component: 'Input', + slot: 'equipmentLedgerPicker', + dynamicRules: () => [{ required: true, message: '请选择设备台账' }], + }, + { + label: '设备编号', + field: 'equipmentCode', + component: 'Input', + componentProps: { readonly: true, placeholder: '选择设备后自动带出' }, + }, + { + label: '类型', + field: 'configType', + component: 'JDictSelectTag', + required: true, + componentProps: { dictCode: 'xslmes_im_item_category', placeholder: '点检/保养' }, + }, +]; + +export const lineJVxeColumns: JVxeColumn[] = [ + { title: '', key: 'inspectMaintainItemId', type: JVxeTypes.hidden }, + { title: '点检项目编号', key: 'itemCode', type: JVxeTypes.normal, width: 130, disabled: true }, + { title: '项目名称', key: 'itemName', type: JVxeTypes.normal, width: 140, disabled: true }, + { + title: '项目类别', + key: 'itemCategory', + type: JVxeTypes.select, + width: 100, + disabled: true, + dictCode: 'xslmes_im_item_category', + }, + { + title: '项目类型', + key: 'itemType', + type: JVxeTypes.select, + width: 100, + disabled: true, + dictCode: 'xslmes_im_item_type', + }, + { title: '设备部位', key: 'equipmentPartName', type: JVxeTypes.normal, width: 120, disabled: true }, + { title: '设备小部位', key: 'equipmentSubPartName', type: JVxeTypes.normal, width: 120, disabled: true }, + { + title: '点检方式', + key: 'inspectMethod', + type: JVxeTypes.select, + width: 100, + disabled: true, + dictCode: 'xslmes_im_inspect_method', + }, + { title: '判断基准', key: 'judgmentCriteria', type: JVxeTypes.normal, width: 180, disabled: true }, +]; diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfigList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfigList.vue new file mode 100644 index 00000000..8a7a751e --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfigList.vue @@ -0,0 +1,132 @@ + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipInspectConfigModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipInspectConfigModal.vue new file mode 100644 index 00000000..a3eed255 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipInspectConfigModal.vue @@ -0,0 +1,239 @@ + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerSelectModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerSelectModal.vue new file mode 100644 index 00000000..023e99be --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerSelectModal.vue @@ -0,0 +1,93 @@ + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslInspectMaintainItemSelectModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslInspectMaintainItemSelectModal.vue new file mode 100644 index 00000000..4e07ff2b --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslInspectMaintainItemSelectModal.vue @@ -0,0 +1,89 @@ + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.api.ts b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.api.ts new file mode 100644 index 00000000..9cecbf63 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.api.ts @@ -0,0 +1,65 @@ +import { defHttp } from '/@/utils/http/axios'; +import { useMessage } from '/@/hooks/web/useMessage'; + +const { createConfirm } = useMessage(); + +enum Api { + list = '/xslmes/mesXslEquipInspectRecord/list', + save = '/xslmes/mesXslEquipInspectRecord/add', + edit = '/xslmes/mesXslEquipInspectRecord/edit', + deleteOne = '/xslmes/mesXslEquipInspectRecord/delete', + deleteBatch = '/xslmes/mesXslEquipInspectRecord/deleteBatch', + importExcel = '/xslmes/mesXslEquipInspectRecord/importExcel', + exportXls = '/xslmes/mesXslEquipInspectRecord/exportXls', + queryById = '/xslmes/mesXslEquipInspectRecord/queryById', + queryLineList = '/xslmes/mesXslEquipInspectRecord/queryLineListByRecordId', + generateRecordNo = '/xslmes/mesXslEquipInspectRecord/generateRecordNo', + loadLinesByEquipment = '/xslmes/mesXslEquipInspectRecord/loadLinesByEquipment', + batchCreateFromEquipment = '/xslmes/mesXslEquipInspectRecord/batchCreateFromEquipment', + handleFail = '/xslmes/mesXslEquipInspectRecord/handleFail', +} + +export const getExportUrl = Api.exportXls; +export const getImportUrl = Api.importExcel; + +export const list = (params) => defHttp.get({ url: Api.list, params }); + +export const queryById = (params: { id: string }) => defHttp.get({ url: Api.queryById, params }); + +export const queryLineListByRecordId = (params: { id: string }) => defHttp.get({ url: Api.queryLineList, params }); + +export const generateRecordNo = () => defHttp.get({ url: Api.generateRecordNo }); + +export const loadLinesByEquipment = (params: { equipmentLedgerId: string; recordType: string }) => + defHttp.get({ url: Api.loadLinesByEquipment, params }); + +export const batchCreateFromEquipment = (params: { equipmentLedgerIds: string[]; recordType: string }) => + defHttp.post({ url: Api.batchCreateFromEquipment, params }); + +export const deleteOne = (params, handleSuccess) => { + return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => { + handleSuccess(); + }); +}; + +export const batchDelete = (params, handleSuccess) => { + createConfirm({ + iconType: 'warning', + title: '确认删除', + content: '是否删除选中数据', + okText: '确认', + cancelText: '取消', + onOk: () => { + return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => { + handleSuccess(); + }); + }, + }); +}; + +export const saveOrUpdate = (params, isUpdate) => { + const url = isUpdate ? Api.edit : Api.save; + return defHttp.post({ url, params }); +}; + +export const handleFailRecord = (params: Recordable) => defHttp.post({ url: Api.handleFail, params }); diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.data.ts b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.data.ts new file mode 100644 index 00000000..233c85e4 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecord.data.ts @@ -0,0 +1,222 @@ +import { BasicColumn, FormSchema } from '/@/components/Table'; +import { JVxeColumn, JVxeTypes } from '/@/components/jeecg/JVxeTable/types'; +import { uploadUrl } from '/@/api/common/api'; + +export const columns: BasicColumn[] = [ + { title: '记录编号', align: 'center', dataIndex: 'recordNo', width: 150 }, + { title: '计划单号', align: 'center', dataIndex: 'planNo', width: 130 }, + { title: '设备名称', align: 'center', dataIndex: 'equipmentName', width: 150 }, + { title: '设备编码', align: 'center', dataIndex: 'equipmentCode', width: 130 }, + { title: '类型', align: 'center', dataIndex: 'recordType_dictText', width: 80 }, + { title: '点检日期', align: 'center', dataIndex: 'inspectDate', width: 110 }, + { title: '点检人', align: 'center', dataIndex: 'inspectorRealname', width: 100 }, + { title: '点检结果', align: 'center', dataIndex: 'inspectResult_dictText', width: 90 }, + { title: '是否已处理', align: 'center', dataIndex: 'handledFlag_dictText', width: 90 }, + { title: '状态', align: 'center', dataIndex: 'recordStatus_dictText', width: 90 }, + { + title: '创建时间', + align: 'center', + dataIndex: 'createTime', + width: 165, + customRender: ({ text }) => (!text ? '' : String(text).length > 19 ? String(text).substring(0, 19) : text), + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { label: '记录编号', field: 'recordNo', component: 'Input', colProps: { span: 6 } }, + { label: '计划单号', field: 'planNo', component: 'Input', colProps: { span: 6 } }, + { label: '设备名称', field: 'equipmentName', component: 'Input', colProps: { span: 6 } }, + { + label: '类型', + field: 'recordType', + component: 'JDictSelectTag', + componentProps: { dictCode: 'xslmes_im_item_category' }, + colProps: { span: 6 }, + }, + { + label: '状态', + field: 'recordStatus', + component: 'JDictSelectTag', + componentProps: { dictCode: 'xslmes_im_record_status' }, + colProps: { span: 6 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { label: '', field: 'id', component: 'Input', show: false }, + { label: '', field: 'equipmentLedgerId', component: 'Input', show: false }, + { label: '', field: 'planId', component: 'Input', show: false }, + { label: '', field: 'equipInspectConfigId', component: 'Input', show: false }, + { label: '', field: 'inspectorUserId', component: 'Input', show: false }, + { label: '', field: 'inspectorUsername', component: 'Input', show: false }, + { + label: '记录编号', + field: 'recordNo', + component: 'Input', + componentProps: { readonly: true, placeholder: '保存时自动生成' }, + dynamicRules: () => [{ required: true, message: '记录编号不能为空' }], + }, + { label: '计划单号', field: 'planNo', component: 'Input' }, + { + label: '设备名称', + field: 'equipmentName', + component: 'Input', + componentProps: { readonly: true }, + }, + { + label: '设备编码', + field: 'equipmentCode', + component: 'Input', + componentProps: { readonly: true }, + }, + { + label: '类型', + field: 'recordType', + component: 'JDictSelectTag', + componentProps: { dictCode: 'xslmes_im_item_category', disabled: true }, + }, + { + label: '点检日期', + field: 'inspectDate', + component: 'DatePicker', + required: true, + componentProps: { valueFormat: 'YYYY-MM-DD', style: { width: '100%' } }, + }, + { + label: '点检人', + field: 'inspectorRealname', + component: 'Input', + componentProps: { readonly: true, placeholder: '当前登录用户' }, + dynamicRules: () => [{ required: true, message: '点检人不能为空' }], + }, + { + label: '点检结果', + field: 'inspectResult', + component: 'JDictSelectTag', + required: true, + componentProps: { dictCode: 'xslmes_im_inspect_result', placeholder: '合格/不合格' }, + }, + { + label: '状态', + field: 'recordStatus', + component: 'JDictSelectTag', + componentProps: { dictCode: 'xslmes_im_record_status', disabled: true }, + }, +]; + +/** 详情页:仅不合格记录展示的处理信息(只读) */ +export const processDisplayFormSchema: FormSchema[] = [ + { + label: '是否已处理', + field: 'handledFlag', + component: 'JDictSelectTag', + componentProps: { dictCode: 'yn', disabled: true }, + }, + { + label: '处理人', + field: 'handlerRealname', + component: 'Input', + componentProps: { readonly: true }, + }, + { + label: '处理时间', + field: 'handleTime', + component: 'DatePicker', + componentProps: { + showTime: true, + valueFormat: 'YYYY-MM-DD HH:mm:ss', + style: { width: '100%' }, + disabled: true, + }, + }, +]; + +/** 不合格记录处理弹窗 */ +export const handleFormSchema: FormSchema[] = [ + { label: '', field: 'id', component: 'Input', show: false }, + { label: '', field: 'handlerUsername', component: 'Input', show: false }, + { label: '', field: 'handlerRealname', component: 'Input', show: false }, + { + label: '处理人', + field: 'handlerUserId', + component: 'JSelectUser', + required: true, + componentProps: ({ formActionType }) => ({ + rowKey: 'id', + labelKey: 'realname', + isRadioSelection: true, + maxSelectCount: 1, + onOptionsChange: (options) => { + const row = options?.[0]; + if (row && formActionType) { + formActionType.setFieldsValue({ + handlerUsername: row.username, + handlerRealname: row.realname, + }); + } + }, + }), + }, + { + label: '处理时间', + field: 'handleTime', + component: 'DatePicker', + required: true, + componentProps: { + showTime: true, + valueFormat: 'YYYY-MM-DD HH:mm:ss', + style: { width: '100%' }, + }, + }, +]; + +export const lineJVxeColumns: JVxeColumn[] = [ + { title: '', key: 'equipInspectConfigLineId', type: JVxeTypes.hidden }, + { title: '', key: 'inspectMaintainItemId', type: JVxeTypes.hidden }, + { title: '点检项目编号', key: 'itemCode', type: JVxeTypes.normal, width: 120, disabled: true }, + { title: '点检项目', key: 'itemName', type: JVxeTypes.normal, width: 130, disabled: true }, + { + title: '项目类别', + key: 'itemCategory', + type: JVxeTypes.select, + width: 90, + disabled: true, + dictCode: 'xslmes_im_item_category', + filters: false, + sortable: false, + }, + { + title: '项目类型', + key: 'itemType', + type: JVxeTypes.select, + width: 90, + disabled: true, + dictCode: 'xslmes_im_item_type', + filters: false, + sortable: false, + }, + { title: '设备部位', key: 'equipmentPartName', type: JVxeTypes.normal, width: 100, disabled: true }, + { title: '设备小部位', key: 'equipmentSubPartName', type: JVxeTypes.normal, width: 100, disabled: true }, + { + title: '点检方式', + key: 'inspectMethod', + type: JVxeTypes.select, + width: 90, + disabled: true, + dictCode: 'xslmes_im_inspect_method', + filters: false, + sortable: false, + }, + { title: '判断基准', key: 'judgmentCriteria', type: JVxeTypes.normal, width: 150, disabled: true }, + { title: '点检描述', key: 'lineInspectResult', type: JVxeTypes.input, width: 140 }, + { + title: '图片', + key: 'pictureFiles', + type: JVxeTypes.image, + width: 160, + maxCount: 3, + token: true, + action: uploadUrl, + responseName: 'message', + }, +]; diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList.vue new file mode 100644 index 00000000..e2727d4a --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList.vue @@ -0,0 +1,153 @@ + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordHandleModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordHandleModal.vue new file mode 100644 index 00000000..9252bb2e --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordHandleModal.vue @@ -0,0 +1,63 @@ + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordModal.vue new file mode 100644 index 00000000..0570d684 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordModal.vue @@ -0,0 +1,173 @@ + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslEquipmentLedger/MesXslEquipmentLedgerList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslEquipmentLedger/MesXslEquipmentLedgerList.vue index 11fe9a1a..e6abef8d 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslEquipmentLedger/MesXslEquipmentLedgerList.vue +++ b/jeecgboot-vue3/src/views/xslmes/mesXslEquipmentLedger/MesXslEquipmentLedgerList.vue @@ -5,6 +5,24 @@ 新增 + + 点检 + + + 保养 + r.id).filter(Boolean); + const typeLabel = recordType === 'inspect' ? '点检' : '保养'; + createConfirm({ + iconType: 'info', + title: `生成${typeLabel}记录`, + content: `确定为选中的 ${ids.length} 台设备各生成一条${typeLabel}记录?`, + okText: '确定', + cancelText: '取消', + onOk: async () => { + try { + const res = await batchCreateFromEquipment({ equipmentLedgerIds: ids, recordType }); + const data = (res as any)?.result ?? res; + const failList: string[] = data?.failMessages || []; + const successCount = data?.successCount ?? 0; + if (successCount > 0 && !failList.length) { + createMessage.success(`成功生成 ${successCount} 条${typeLabel}记录`); + handleSuccess(); + } else if (successCount > 0 && failList.length) { + createMessage.warning(`成功生成 ${successCount} 条;未生成:${failList.join(';')}`); + handleSuccess(); + } else if (failList.length) { + createMessage.warning(failList.join(';')); + } else { + createMessage.warning((res as any)?.message || `未生成任何${typeLabel}记录`); + } + } catch (e: any) { + const errMsg = + e?.response?.data?.message || e?.message || `生成${typeLabel}记录失败`; + createMessage.warning(errMsg); + } + }, + }); + } + function getDropDownAction(record: Recordable) { return [ { label: '详情', onClick: handleDetail.bind(null, record) }, diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.api.ts b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.api.ts new file mode 100644 index 00000000..cd57ce49 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.api.ts @@ -0,0 +1,43 @@ +import { defHttp } from '/@/utils/http/axios'; +import { Modal } from 'ant-design-vue'; + +enum Api { + list = '/xslmes/mesXslFormulaSpec/list', + save = '/xslmes/mesXslFormulaSpec/add', + edit = '/xslmes/mesXslFormulaSpec/edit', + deleteOne = '/xslmes/mesXslFormulaSpec/delete', + deleteBatch = '/xslmes/mesXslFormulaSpec/deleteBatch', + importExcel = '/xslmes/mesXslFormulaSpec/importExcel', + exportXls = '/xslmes/mesXslFormulaSpec/exportXls', + queryById = '/xslmes/mesXslFormulaSpec/queryById', + queryLineList = '/xslmes/mesXslFormulaSpec/queryLineListByMainId', + generateRubberCode = '/xslmes/mesXslFormulaSpec/generateRubberCode', + getRubberContentSetting = '/xslmes/mesXslFormulaSpec/getRubberContentSetting', + saveRubberContentSetting = '/xslmes/mesXslFormulaSpec/saveRubberContentSetting', +} + +export const getExportUrl = Api.exportXls; +export const getImportUrl = Api.importExcel; +export const list = (params) => defHttp.get({ url: Api.list, params }); +export const queryById = (params) => defHttp.get({ url: Api.queryById, params }); +export const queryLineListByMainId = (params) => defHttp.get({ url: Api.queryLineList, params }); +export const generateRubberCode = (params) => + defHttp.get({ url: Api.generateRubberCode, params }, { successMessageMode: 'none' }); +export const getRubberContentSetting = () => defHttp.get({ url: Api.getRubberContentSetting }); +export const saveRubberContentSetting = (params) => defHttp.post({ url: Api.saveRubberContentSetting, params }); + +export const deleteOne = (params, handleSuccess) => + defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => handleSuccess()); + +export const batchDelete = (params, handleSuccess) => { + Modal.confirm({ + title: '确认删除', + content: '是否删除选中数据', + okText: '确认', + cancelText: '取消', + onOk: () => + defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => handleSuccess()), + }); +}; + +export const saveOrUpdate = (params, isUpdate) => defHttp.post({ url: isUpdate ? Api.edit : Api.save, params }); diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts new file mode 100644 index 00000000..90bdf7c4 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data.ts @@ -0,0 +1,1033 @@ +import { BasicColumn, FormSchema } from '/@/components/Table'; +import { JVxeColumn, JVxeTypes } from '/@/components/jeecg/JVxeTable/types'; +import { buildUUID } from '/@/utils/uuid'; +import { createLocalStorage } from '/@/utils/cache'; +import { loadCategoryData } from '/@/api/common/api'; +import { loadTreeData as loadCategoryTreeRoot } from '/@/views/system/category/category.api'; +import { MATERIAL_CATEGORY_ROOT_CODE } from '/@/views/mes/material/MesMixerMaterialSysCategory.api'; + +const formulaLineColumnStorage = createLocalStorage(); + +/** 明细列隐藏偏好 localStorage 键 */ +export const FORMULA_LINE_COLUMN_CACHE_KEY = 'mes_xsl_formula_spec_line_hidden_columns'; + +/** 不允许隐藏的明细列 */ +export const FORMULA_LINE_LOCKED_COLUMN_KEYS = ['phr', 'mixerMaterialId']; + +export interface FormulaLineColumnSettingItem { + key: string; + title: string; + locked?: boolean; +} + +const colHalf = { span: 12 }; +const colThird = { span: 8 }; +const colQuarter = { span: 6 }; + +/** 汇总区隐藏字段(明细表 footer 行录入,表单仅承载数据) */ +export const summaryFooterHiddenFields: FormSchema[] = [ + { field: 'aRubberTotalPhr', label: '', component: 'InputNumber', show: false }, + { field: 'totalPhr', label: '', component: 'InputNumber', show: false }, + ...Array.from({ length: 7 }, (_, index) => ({ + field: `stage${index + 1}Total`, + label: '', + component: 'InputNumber', + show: false, + })), +]; + +export const SUMMARY_FOOTER_FIELD_KEYS = [ + 'aRubberTotalPhr', + 'totalPhr', + 'stage1Total', + 'stage2Total', + 'stage3Total', + 'stage4Total', + 'stage5Total', + 'stage6Total', + 'stage7Total', +] as const; + +export const SUMMARY_METRICS_FIELD_KEYS = [ + 'naturalRubber', + 'syntheticRubber', + 'totalAmount', + 'weightUnitPrice', + 'volumeUnitPrice', + 'qRubberSg', + 'aRubberSg', +] as const; + +/** 汇总指标隐藏字段(自定义表格录入,表单仅承载数据) */ +export const summaryMetricsHiddenFields: FormSchema[] = SUMMARY_METRICS_FIELD_KEYS.map((field) => ({ + field, + label: '', + component: 'InputNumber', + show: false, +})); + +export const stageTotalNumberProps = { + min: 0, + precision: 4, + style: { width: '100%' }, + bordered: false, + controls: false, +}; + +export const summaryMetricNumberProps = { + min: 0, + precision: 4, + style: { width: '100%' }, + bordered: false, + controls: false, +}; + +export const summarySgNumberProps = { + min: 0, + precision: 6, + style: { width: '100%' }, + bordered: false, + controls: false, +}; + +/** 明细行 PHR 合计(作为重量%计算的分母) */ +export function calcTotalPhrFromLines(lines: Recordable[]): number | null { + const sum = (lines || []).reduce((acc, row) => { + const value = Number(row?.phr); + return acc + (Number.isFinite(value) ? value : 0); + }, 0); + return sum > 0 ? Number(sum.toFixed(4)) : null; +} + +/** 按 单条PHR / 总PHR × 100 回填各行重量% */ +export function applyWeightPercentToLines(lines: Recordable[]): void { + const totalPhr = calcTotalPhrFromLines(lines); + (lines || []).forEach((row) => { + if (!row) { + return; + } + const phr = Number(row.phr); + if (!Number.isFinite(phr) || totalPhr == null || totalPhr <= 0) { + row.weightPercent = null; + return; + } + row.weightPercent = Number(((phr / totalPhr) * 100).toFixed(1)); + }); +} + +/** STEP=A 的 PHR 合计(A胶 TOTAL PHR) */ +export function calcARubberTotalPhrFromLines(lines: Recordable[]): number | null { + const sum = (lines || []).reduce((acc, row) => { + if (row?.step !== 'A') { + return acc; + } + const value = Number(row?.phr); + return acc + (Number.isFinite(value) ? value : 0); + }, 0); + return sum > 0 ? Number(sum.toFixed(4)) : null; +} + +/** + * 混合段累计合计(仅统计可编辑段数): + * stage1Total=列1总和,stage2Total=列1+列2,…;超出混合段数的框置空。 + */ +export function calcStageTotalsFromLines(lines: Recordable[], mixingStages?: number | string | null): Recordable { + const totals: Recordable = {}; + const stageCount = getActiveStageCount(mixingStages); + + for (let i = 1; i <= 7; i++) { + totals[`stage${i}Total`] = null; + } + if (stageCount <= 0) { + return totals; + } + + const colSums: number[] = []; + for (let i = 1; i <= stageCount; i++) { + const key = `stage${i}`; + const sum = (lines || []).reduce((acc, row) => { + const value = Number(row?.[key]); + return acc + (Number.isFinite(value) ? value : 0); + }, 0); + colSums.push(sum); + } + + let cumulative = 0; + for (let i = 1; i <= stageCount; i++) { + cumulative += colSums[i - 1]; + totals[`stage${i}Total`] = cumulative > 0 ? Number(cumulative.toFixed(4)) : null; + } + return totals; +} + +/** 底部汇总区:A胶 TOTAL PHR、TOTAL PHR、混合段 1..N 累计合计(N=混合段数) */ +export function calcFooterSummaryFromLines(lines: Recordable[], mixingStages?: number | string | null): Recordable { + return { + aRubberTotalPhr: calcARubberTotalPhrFromLines(lines), + totalPhr: calcTotalPhrFromLines(lines), + ...calcStageTotalsFromLines(lines, mixingStages), + }; +} + +/** 明细行有效体积(优先使用已计算的 volume) */ +function getLineVolumeValue(row: Recordable): number | null { + const volume = Number(row?.volume); + return Number.isFinite(volume) && volume > 0 ? volume : null; +} + +/** + * A胶比重 = STEP=A 各行 PHR 合计 ÷ STEP=A 各行体积合计 + * 单行体积 = PHR ÷ 物料比重 + */ +export function calcARubberSgFromLines(lines: Recordable[]): number | null { + let totalPhr = 0; + let totalVolume = 0; + (lines || []).forEach((row) => { + if (row?.step !== 'A') { + return; + } + const phr = Number(row?.phr); + const volume = getLineVolumeValue(row); + if (!Number.isFinite(phr) || phr <= 0 || volume == null) { + return; + } + totalPhr += phr; + totalVolume += volume; + }); + if (totalPhr <= 0 || totalVolume <= 0) { + return null; + } + return Number((totalPhr / totalVolume).toFixed(6)); +} + +/** + * Q胶比重 = STEP=Q 各行 PHR 合计 ÷ STEP=Q 各行体积合计 + * 单行体积 = PHR ÷ 物料比重 + */ +export function calcQRubberSgFromLines(lines: Recordable[]): number | null { + let totalPhr = 0; + let totalVolume = 0; + (lines || []).forEach((row) => { + if (row?.step !== 'Q') { + return; + } + const phr = Number(row?.phr); + const volume = getLineVolumeValue(row); + if (!Number.isFinite(phr) || phr <= 0 || volume == null) { + return; + } + totalPhr += phr; + totalVolume += volume; + }); + if (totalPhr <= 0 || totalVolume <= 0) { + return null; + } + return Number((totalPhr / totalVolume).toFixed(6)); +} + +/** 默认物料小类编码(仅作初始配置参考) */ +export const MIXER_MINOR_CATEGORY_CODE = { + NATURAL_RUBBER: 'XSLMES_MATERIAL_RAW_AUX_TRJ', + SYNTHETIC_RUBBER: 'XSLMES_MATERIAL_RAW_AUX_HCJ', +} as const; + +export type RubberContentSetting = { + naturalMinorCategoryIds: string[]; + syntheticMinorCategoryIds: string[]; +}; + +export const EMPTY_RUBBER_CONTENT_SETTING: RubberContentSetting = { + naturalMinorCategoryIds: [], + syntheticMinorCategoryIds: [], +}; + +/** 将 MES物料分类 树递归展开为下拉选项(含大类、小类等全部节点) */ +function flattenMaterialCategoryTreeToOptions( + nodes: Recordable[], + parentLabel = '', +): Array<{ label: string; value: string }> { + const options: Array<{ label: string; value: string }> = []; + (nodes || []).forEach((node) => { + const id = String(node?.key ?? node?.id ?? node?.value ?? ''); + const name = String(node?.title ?? node?.name ?? node?.text ?? ''); + if (!id || !name) { + return; + } + const label = parentLabel ? `${parentLabel} / ${name}` : name; + options.push({ label, value: id }); + const children = (node?.children as Recordable[]) || []; + if (children.length) { + options.push(...flattenMaterialCategoryTreeToOptions(children, label)); + } + }); + return options; +} + +/** 一次性加载 MES物料分类 全部节点,供含胶率设置手动多选 */ +export async function fetchMaterialCategoryOptions(): Promise> { + try { + const list = await loadCategoryData({ code: MATERIAL_CATEGORY_ROOT_CODE }); + const rows = Array.isArray(list) ? list : []; + if (rows.length) { + return rows + .map((item: Recordable) => ({ + label: String(item?.text ?? item?.label ?? item?.title ?? item?.name ?? ''), + value: String(item?.value ?? item?.id ?? item?.key ?? ''), + })) + .filter((item) => item.value && item.label); + } + } catch { + // 回退到与密炼物料页一致的分类树加载 + } + const treeRaw = await loadCategoryTreeRoot({ async: false, pcode: MATERIAL_CATEGORY_ROOT_CODE }); + const tree = Array.isArray(treeRaw) ? treeRaw : []; + return flattenMaterialCategoryTreeToOptions(tree); +} + +/** @deprecated 请使用 fetchMaterialCategoryOptions */ +export const fetchMixerMinorCategoryOptions = fetchMaterialCategoryOptions; + +/** 汇总区比重指标:Q胶比重、A胶比重 */ +export function calcRubberSgMetricsFromLines(lines: Recordable[]): Recordable { + return { + qRubberSg: calcQRubberSgFromLines(lines), + aRubberSg: calcARubberSgFromLines(lines), + }; +} + +/** + * 含胶率:天然橡胶 / 合成橡胶 = 对应小类密炼物料的重量%之和,合计为两者之和 + */ +export function calcRubberContentMetricsFromLines( + lines: Recordable[], + naturalMinorCategoryIds?: string[] | null, + syntheticMinorCategoryIds?: string[] | null, +): Recordable { + const naturalIdSet = new Set((naturalMinorCategoryIds || []).filter(Boolean)); + const syntheticIdSet = new Set((syntheticMinorCategoryIds || []).filter(Boolean)); + let naturalRubber = 0; + let syntheticRubber = 0; + let hasNatural = false; + let hasSynthetic = false; + (lines || []).forEach((row) => { + if (!row?.mixerMinorCategoryId) { + return; + } + const weightPercent = Number(row?.weightPercent); + if (!Number.isFinite(weightPercent)) { + return; + } + if (naturalIdSet.has(row.mixerMinorCategoryId)) { + naturalRubber += weightPercent; + hasNatural = true; + } else if (syntheticIdSet.has(row.mixerMinorCategoryId)) { + syntheticRubber += weightPercent; + hasSynthetic = true; + } + }); + const naturalValue = hasNatural ? Number(naturalRubber.toFixed(4)) : null; + const syntheticValue = hasSynthetic ? Number(syntheticRubber.toFixed(4)) : null; + const totalAmount = + naturalValue != null || syntheticValue != null + ? Number(((naturalValue ?? 0) + (syntheticValue ?? 0)).toFixed(4)) + : null; + return { + naturalRubber: naturalValue, + syntheticRubber: syntheticValue, + totalAmount, + }; +} + +/** 明细行仅前端展示字段(不落库) */ +export const FORMULA_LINE_DISPLAY_FIELDS = ['mixerMajorCategoryText', 'mixerMinorCategoryText', 'mixerMinorCategoryId'] as const; + +/** 写入密炼物料关联的大类/小类展示文本 */ +export function applyMixerCategoryDisplay(row: Recordable, material?: Recordable | null) { + if (!row) { + return; + } + if (!material) { + row.mixerMajorCategoryText = ''; + row.mixerMinorCategoryText = ''; + row.mixerMinorCategoryId = null; + return; + } + row.mixerMajorCategoryText = material.majorCategoryId_dictText || material.majorCategoryText || ''; + row.mixerMinorCategoryText = material.minorCategoryId_dictText || material.minorCategoryText || ''; + row.mixerMinorCategoryId = material.minorCategoryId || null; +} + +let materialCategoryNameCache: Map | null = null; + +async function getMaterialCategoryNameCache(): Promise> { + if (materialCategoryNameCache) { + return materialCategoryNameCache; + } + try { + const list = await loadCategoryData({ code: MATERIAL_CATEGORY_ROOT_CODE }); + const rows = Array.isArray(list) ? list : []; + materialCategoryNameCache = new Map( + rows + .map((item: Recordable) => [String(item?.value ?? item?.id ?? ''), String(item?.text ?? item?.label ?? '')] as const) + .filter(([id, name]) => id && name), + ); + } catch { + materialCategoryNameCache = new Map(); + } + return materialCategoryNameCache; +} + +/** 关联查询并补全大类/小类展示(queryById 无 dictText 时回退分类字典) */ +export async function hydrateMixerCategoryDisplay(row: Recordable, material?: Recordable | null) { + applyMixerMaterialMeta(row, material); + if (!row || !material) { + return; + } + const needMajor = !row.mixerMajorCategoryText && material.majorCategoryId; + const needMinor = !row.mixerMinorCategoryText && material.minorCategoryId; + if (!needMajor && !needMinor) { + return; + } + const cache = await getMaterialCategoryNameCache(); + if (needMajor) { + row.mixerMajorCategoryText = cache.get(String(material.majorCategoryId)) || ''; + } + if (needMinor) { + row.mixerMinorCategoryText = cache.get(String(material.minorCategoryId)) || ''; + } +} + +/** 选择配合剂后回填物料关联信息(含大类/小类展示) */ +export function applyMixerMaterialMeta(row: Recordable, material?: Recordable | null) { + if (!row) { + return; + } + if (!material) { + row.mixerMaterialName = ''; + row.mixerMaterialCode = ''; + applyMixerCategoryDisplay(row, null); + return; + } + row.mixerMaterialName = material.materialName || row.mixerMaterialName || ''; + row.mixerMaterialCode = material.materialCode || row.mixerMaterialCode || ''; + applyMixerCategoryDisplay(row, material); + if (!row.materialDesc) { + row.materialDesc = material.materialDesc || material.materialName || ''; + } +} + +/** 提交前剔除明细行展示字段 */ +export function stripFormulaLineDisplayFields(line: Recordable) { + const { mixerMajorCategoryText, mixerMinorCategoryText, mixerMinorCategoryId, ...rest } = line; + return rest; +} + +/** 明细表默认空行数(参照原系统约 20 行) */ +export const DEFAULT_LINE_ROW_COUNT = 20; + +export function createEmptyLineRows(count = DEFAULT_LINE_ROW_COUNT): Recordable[] { + return Array.from({ length: count }, () => ({ id: buildUUID() })); +} + +/** 确保每行有唯一 id(JVxeTable rowKey 依赖 id,否则单元格无法渲染) */ +export function normalizeLineRows(rows: Recordable[]): Recordable[] { + return (rows || []).map((r) => ({ ...r, id: r?.id || buildUUID() })); +} + +function sectionTitle(label: string, field: string): FormSchema { + return { + field, + label, + component: 'Divider', + componentProps: { orientation: 'left', plain: false }, + colProps: { span: 24 }, + }; +} + +const hasWorkflowInfo = ({ values }) => + !!(values.proofreadBy || values.proofreadTime || values.auditBy || values.auditTime || values.approveBy || values.approveTime); + +export const columns: BasicColumn[] = [ + { title: '示方编号', align: 'center', dataIndex: 'specCode', width: 150, fixed: 'left' }, + { title: '发行编号', align: 'center', dataIndex: 'issueNumber', width: 140 }, + { title: '胶料代号', align: 'center', dataIndex: 'rubberCode', width: 140 }, + { title: '分类', align: 'center', dataIndex: 'category_dictText', width: 80 }, + { title: '用途', align: 'center', dataIndex: 'purpose', width: 120, ellipsis: true }, + { + title: '人工配料', + align: 'center', + dataIndex: 'hasManualBatch', + width: 90, + customRender: ({ text }) => (text === 1 ? '是' : '否'), + }, + { title: '发行日期', align: 'center', dataIndex: 'issueDate', width: 110 }, + { + title: '制定人', + align: 'center', + dataIndex: 'createBy', + width: 100, + customRender: ({ record }) => record?.createBy_dictText || record?.createBy || '', + }, + { title: '审核人', align: 'center', dataIndex: 'auditBy', width: 100, defaultHidden: true }, + { title: '批准人', align: 'center', dataIndex: 'approveBy', width: 100, defaultHidden: true }, + { title: '状态', align: 'center', dataIndex: 'status_dictText', width: 120 }, + { title: '混合段数', align: 'center', dataIndex: 'mixingStages', width: 90, defaultHidden: true }, + { title: 'TOTAL PHR', align: 'center', dataIndex: 'totalPhr', width: 100, defaultHidden: true }, + { title: '修改时间', align: 'center', dataIndex: 'updateTime', width: 165 }, +]; + +export const searchFormSchema: FormSchema[] = [ + { label: '关键字', field: 'keyword', component: 'Input', colProps: { span: 6 }, componentProps: { placeholder: '示方编号/胶料代号/发行编号/用途' } }, + { + label: '分类', + field: 'category', + component: 'JDictSelectTag', + componentProps: { dictCode: 'xslmes_formula_spec_category', placeholder: '请选择分类' }, + colProps: { span: 6 }, + }, + { + label: '状态', + field: 'status', + component: 'JDictSelectTag', + componentProps: { dictCode: 'xslmes_formula_spec_status', placeholder: '请选择状态' }, + colProps: { span: 6 }, + }, + { + label: '发行日期起', + field: 'issueDate_begin', + component: 'DatePicker', + componentProps: { valueFormat: 'YYYY-MM-DD', placeholder: '开始日期' }, + colProps: { span: 6 }, + }, + { + label: '发行日期止', + field: 'issueDate_end', + component: 'DatePicker', + componentProps: { valueFormat: 'YYYY-MM-DD', placeholder: '结束日期' }, + colProps: { span: 6 }, + }, +]; + +/** 基本信息(顶部) */ +export const basicFormSchema: FormSchema[] = [ + { label: '', field: 'id', component: 'Input', show: false }, + { + label: '分类', + field: 'category', + component: 'JDictSelectTag', + defaultValue: 'S', + show: false, + componentProps: { dictCode: 'xslmes_formula_spec_category', type: 'radioButton' }, + colProps: { span: 24 }, + }, + { + label: '示方编号', + field: 'specCode', + component: 'Input', + show: false, + dynamicRules: () => [{ required: true, message: '请选择胶料并生成示方编号' }], + }, + { + label: '胶料代号', + field: 'rubberCode', + component: 'Input', + show: false, + dynamicRules: () => [{ required: true, message: '请选择胶料并生成胶料代号' }], + }, + { + label: '', + field: 'rubberMaterialId', + component: 'Input', + show: false, + }, + { + label: '基本配合', + field: 'basicFormula', + component: 'Input', + show: false, + }, + { + label: '发行日期', + field: 'issueDate', + component: 'Input', + show: false, + }, + { + label: '发行编号', + field: 'issueNumber', + component: 'Input', + show: false, + }, + { + label: '用途', + field: 'purpose', + component: 'Input', + show: false, + }, + { + label: '混合段数', + field: 'mixingStages', + component: 'InputNumber', + show: false, + }, + { + label: '混合机器', + field: 'mixingMachine', + component: 'Input', + show: false, + }, + { + label: '发行部门', + field: 'issueDeptName', + component: 'Input', + show: false, + }, + { + label: '', + field: 'issueDeptId', + component: 'Input', + show: false, + }, + { + label: '状态', + field: 'status', + component: 'JDictSelectTag', + defaultValue: 'compile', + show: false, + componentProps: { dictCode: 'xslmes_formula_spec_status', disabled: true }, + colProps: colThird, + }, +]; + +/** 汇总信息(底部,参照原配合施工表布局) */ +export const summaryFormSchema: FormSchema[] = [ + ...summaryFooterHiddenFields, + ...summaryMetricsHiddenFields, + { + label: '发行理由', + field: 'issueReason', + component: 'InputTextArea', + colProps: { span: 24 }, + componentProps: { rows: 2, placeholder: '请输入发行理由', maxlength: 1000, showCount: true, bordered: false }, + }, +]; + +/** 审批记录(详情时展示) */ +export const workflowFormSchema: FormSchema[] = [ + sectionTitle('审批记录', 'dividerWorkflow'), + { + label: '校对人', + field: 'proofreadBy', + component: 'Input', + componentProps: { disabled: true, bordered: false }, + colProps: colHalf, + ifShow: ({ values }) => !!values.proofreadBy, + }, + { + label: '校对时间', + field: 'proofreadTime', + component: 'Input', + componentProps: { disabled: true, bordered: false }, + colProps: colHalf, + ifShow: ({ values }) => !!values.proofreadTime, + }, + { + label: '审核人', + field: 'auditBy', + component: 'Input', + componentProps: { disabled: true, bordered: false }, + colProps: colHalf, + ifShow: ({ values }) => !!values.auditBy, + }, + { + label: '审核时间', + field: 'auditTime', + component: 'Input', + componentProps: { disabled: true, bordered: false }, + colProps: colHalf, + ifShow: ({ values }) => !!values.auditTime, + }, + { + label: '批准人', + field: 'approveBy', + component: 'Input', + componentProps: { disabled: true, bordered: false }, + colProps: colHalf, + ifShow: ({ values }) => !!values.approveBy, + }, + { + label: '批准时间', + field: 'approveTime', + component: 'Input', + componentProps: { disabled: true, bordered: false }, + colProps: colHalf, + ifShow: ({ values }) => !!values.approveTime, + }, +]; + +/** 有效混合段数(1-7),未配置时返回 0 */ +export function getActiveStageCount(mixingStages?: number | string | null): number { + if (mixingStages == null || mixingStages === '') { + return 0; + } + const n = Number(mixingStages); + if (Number.isNaN(n) || n <= 0) { + return 0; + } + return Math.min(Math.max(Math.floor(n), 1), 7); +} + +/** + * STEP=A:PHR 写入第 1 混合段;STEP=Q:PHR 写入当前混合段数的最后一列。 + * 返回需写回表格的 stage1-stage7 补丁;非 A/Q 或无可编辑段时返回 null。 + */ +export function buildStepStageValues(row: Recordable, mixingStages?: number | null): Recordable | null { + const step = row?.step; + if (step !== 'A' && step !== 'Q') { + return null; + } + const stageCount = getActiveStageCount(mixingStages); + if (stageCount <= 0) { + return null; + } + const phrRaw = row?.phr; + const phr = + phrRaw != null && phrRaw !== '' && Number.isFinite(Number(phrRaw)) ? Number(phrRaw) : null; + const targetStage = step === 'A' ? 1 : stageCount; + const patch: Recordable = {}; + for (let i = 1; i <= 7; i++) { + patch[`stage${i}`] = i === targetStage ? phr : null; + } + return patch; +} + +/** 将 STEP 规则应用到行对象(就地修改) */ +export function applyStepPhrToLineRow(row: Recordable, mixingStages?: number | null): Recordable | null { + const patch = buildStepStageValues(row, mixingStages); + if (!patch) { + return null; + } + Object.assign(row, patch); + return patch; +} + +/** 解析行 PHR(无效时返回 null) */ +export function getLinePhrValue(row: Recordable): number | null { + const phr = Number(row?.phr); + return Number.isFinite(phr) && phr > 0 ? phr : null; +} + +/** 可编辑混合段列合计(仅统计 1..stageCount) */ +export function calcLineActiveStageSum(row: Recordable, stageCount: number): number { + let sum = 0; + for (let i = 1; i <= stageCount; i++) { + const v = Number(row[`stage${i}`]); + if (Number.isFinite(v)) { + sum += v; + } + } + return sum; +} + +/** 混合段合计超过 PHR 时,扣减当前编辑列 */ +export function clampStageToPhr(row: Recordable, stageCount: number, editedKey: string): number | null { + const phr = getLinePhrValue(row); + if (phr == null || stageCount <= 0) { + return null; + } + const total = calcLineActiveStageSum(row, stageCount); + if (total <= phr) { + return null; + } + const current = Number(row[editedKey]); + if (!Number.isFinite(current)) { + return null; + } + const clamped = Math.max(0, Number((current - (total - phr)).toFixed(4))); + row[editedKey] = clamped; + return clamped; +} + +/** STEP=A:手动编辑 2..N 列时,第 1 列 = PHR − 其余可编辑段之和 */ +export function balanceStepAStages(row: Recordable, stageCount: number, editedKey?: string): Recordable { + const patch: Recordable = {}; + if (editedKey === 'stage1') { + return patch; + } + const phr = getLinePhrValue(row); + if (phr == null || stageCount <= 0) { + return patch; + } + let otherSum = 0; + for (let i = 2; i <= stageCount; i++) { + const v = Number(row[`stage${i}`]); + if (Number.isFinite(v)) { + otherSum += v; + } + } + const stage1 = Math.max(0, Number((phr - otherSum).toFixed(4))); + const next = otherSum > 0 ? stage1 : phr; + if (Number(row.stage1) !== next) { + row.stage1 = next; + patch.stage1 = next; + } + return patch; +} + +/** STEP=Q:手动编辑非末列时,末列 = PHR − 其余可编辑段之和 */ +export function balanceStepQStages(row: Recordable, stageCount: number, editedKey?: string): Recordable { + const patch: Recordable = {}; + const phr = getLinePhrValue(row); + if (phr == null || stageCount <= 0) { + return patch; + } + const lastKey = `stage${stageCount}`; + if (editedKey === lastKey) { + return patch; + } + let otherSum = 0; + for (let i = 1; i < stageCount; i++) { + const v = Number(row[`stage${i}`]); + if (Number.isFinite(v)) { + otherSum += v; + } + } + const lastVal = Math.max(0, Number((phr - otherSum).toFixed(4))); + const next = otherSum > 0 ? lastVal : phr; + if (Number(row[lastKey]) !== next) { + row[lastKey] = next; + patch[lastKey] = next; + } + return patch; +} + +/** + * 混合段单元格编辑后:合计不超过 PHR;STEP=A/Q 自动平衡锚定列。 + * STEP=A 编辑 2..N 列、STEP=Q 编辑非末列时:先扣减锚定列,再判断是否需截断当前列。 + */ +export function processStageCellEdit( + row: Recordable, + editedKey: string, + mixingStages?: number | string | null +): { patch: Recordable; exceeded: boolean; needPhr: boolean } { + const patch: Recordable = {}; + const stageCount = getActiveStageCount(mixingStages); + if (stageCount <= 0 || !/^stage\d+$/.test(editedKey)) { + return { patch, exceeded: false, needPhr: false }; + } + const phr = getLinePhrValue(row); + if (phr == null) { + return { patch, exceeded: false, needPhr: true }; + } + + const lastKey = `stage${stageCount}`; + let exceeded = false; + + const mergePatch = (p: Recordable) => { + Object.keys(p).forEach((k) => { + patch[k] = p[k]; + }); + }; + + // STEP=A:编辑第 2..N 列时先从第 1 列扣减,避免误把当前列截断为 0 + if (row.step === 'A' && editedKey !== 'stage1') { + mergePatch(balanceStepAStages(row, stageCount, editedKey)); + const clamped = clampStageToPhr(row, stageCount, editedKey); + if (clamped != null) { + patch[editedKey] = clamped; + exceeded = true; + mergePatch(balanceStepAStages(row, stageCount, editedKey)); + } + return { patch, exceeded, needPhr: false }; + } + + // STEP=Q:编辑非末列时先从末列扣减 + if (row.step === 'Q' && editedKey !== lastKey) { + mergePatch(balanceStepQStages(row, stageCount, editedKey)); + const clamped = clampStageToPhr(row, stageCount, editedKey); + if (clamped != null) { + patch[editedKey] = clamped; + exceeded = true; + mergePatch(balanceStepQStages(row, stageCount, editedKey)); + } + return { patch, exceeded, needPhr: false }; + } + + // 编辑锚定列或无 STEP:仅截断当前列 + const clamped = clampStageToPhr(row, stageCount, editedKey); + if (clamped != null) { + patch[editedKey] = clamped; + exceeded = true; + } + + return { patch, exceeded, needPhr: false }; +} + +/** 根据混合段数动态生成明细列(1-7 段列按混合段数控制可编辑;未填混合段数时全部禁用) */ +export function buildLineJVxeColumns(mixingStages?: number | null, tableDisabled = false): JVxeColumn[] { + const stageCount = getActiveStageCount(mixingStages); + const hasStages = stageCount > 0; + + const baseCols: JVxeColumn[] = [ + { + title: 'PHR', + key: 'phr', + type: JVxeTypes.inputNumber, + minWidth: 90, + align: 'center', + }, + { + title: '配合剂', + key: 'mixerMaterialId', + type: JVxeTypes.slot, + slotName: 'mixerMaterialSlot', + minWidth: 200, + }, + { + title: '物料大类', + key: 'mixerMajorCategoryText', + type: JVxeTypes.normal, + minWidth: 110, + align: 'center', + }, + { + title: '物料小类', + key: 'mixerMinorCategoryText', + type: JVxeTypes.normal, + minWidth: 110, + align: 'center', + }, + { + title: '物料描述', + key: 'materialDesc', + type: JVxeTypes.input, + minWidth: 160, + }, + { + title: 'STEP', + key: 'step', + type: JVxeTypes.select, + minWidth: 80, + align: 'center', + dictCode: 'xslmes_formula_spec_step', + }, + { + title: '自动/人工', + key: 'weighMode', + type: JVxeTypes.select, + minWidth: 110, + align: 'center', + dictCode: 'xslmes_formula_spec_weigh_mode', + }, + { + title: '重量%', + key: 'weightPercent', + type: JVxeTypes.inputNumber, + minWidth: 90, + align: 'center', + }, + { + title: '体积', + key: 'volume', + type: JVxeTypes.inputNumber, + minWidth: 90, + align: 'center', + placeholder: '自动计算', + }, + { + title: '备注', + key: 'remark', + type: JVxeTypes.input, + minWidth: 80, + }, + ]; + + for (let i = 1; i <= 7; i++) { + const stageNo = i; + const stageDisabled = tableDisabled || !hasStages || stageNo > stageCount; + baseCols.push({ + title: String(i), + key: `stage${i}`, + type: JVxeTypes.inputNumber, + minWidth: 56, + align: 'center', + disabled: stageDisabled, + className: stageDisabled ? 'formula-stage-cell-disabled' : '', + headerClassName: stageDisabled ? 'formula-stage-header-disabled' : '', + props: { + isDisabledCell: () => stageDisabled, + }, + }); + } + return baseCols; +} + +/** 明细列设置项(1-7 段列固定展示在设置列表中) */ +export function getFormulaLineColumnSettingItems(): FormulaLineColumnSettingItem[] { + return buildLineJVxeColumns(null, false).map((col) => ({ + key: String(col.key), + title: String(col.title), + locked: FORMULA_LINE_LOCKED_COLUMN_KEYS.includes(String(col.key)), + })); +} + +/** 读取已隐藏的明细列 key */ +export function loadFormulaLineHiddenColumnKeys(): string[] { + const saved = formulaLineColumnStorage.get(FORMULA_LINE_COLUMN_CACHE_KEY); + if (!Array.isArray(saved)) { + return []; + } + const validKeys = new Set(getFormulaLineColumnSettingItems().map((item) => item.key)); + return saved.filter( + (key) => typeof key === 'string' && !FORMULA_LINE_LOCKED_COLUMN_KEYS.includes(key) && validKeys.has(key), + ); +} + +/** 保存已隐藏的明细列 key */ +export function saveFormulaLineHiddenColumnKeys(hiddenKeys: string[]) { + const validKeys = hiddenKeys.filter((key) => !FORMULA_LINE_LOCKED_COLUMN_KEYS.includes(key)); + if (validKeys.length) { + formulaLineColumnStorage.set(FORMULA_LINE_COLUMN_CACHE_KEY, validKeys); + return; + } + formulaLineColumnStorage.remove(FORMULA_LINE_COLUMN_CACHE_KEY); +} + +/** 按隐藏配置过滤明细列 */ +export function applyFormulaLineColumnVisibility(columns: JVxeColumn[], hiddenKeys: string[]): JVxeColumn[] { + if (!hiddenKeys?.length) { + return columns; + } + const hiddenSet = new Set(hiddenKeys); + return columns.filter((col) => !col.key || !hiddenSet.has(String(col.key))); +} + +/** 审批进度操作人展示:优先字典翻译姓名,其次当前登录用户匹配用户名时取 realname */ +export function resolveFormulaSpecUserDisplayName( + username?: string | null, + dictText?: string | null, + fallbackUser?: { username?: string; realname?: string }, +) { + if (dictText != null && dictText !== '') { + return String(dictText); + } + const user = fallbackUser || {}; + if (username != null && username !== '') { + const name = String(username); + if (user.username && name === user.username && user.realname) { + return user.realname; + } + return name; + } + return user.realname || user.username || ''; +} + +export const superQuerySchema = { + specCode: { title: '示方编号', order: 0, view: 'text' }, + rubberCode: { title: '胶料代号', order: 1, view: 'text' }, + issueNumber: { title: '发行编号', order: 2, view: 'text' }, + category: { title: '分类', order: 3, view: 'list', dictCode: 'xslmes_formula_spec_category' }, + purpose: { title: '用途', order: 4, view: 'text' }, + status: { title: '状态', order: 5, view: 'list', dictCode: 'xslmes_formula_spec_status' }, + issueDate: { title: '发行日期', order: 6, view: 'date' }, +}; diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpecList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpecList.vue new file mode 100644 index 00000000..1e000e98 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpecList.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaLineColumnSetting.vue b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaLineColumnSetting.vue new file mode 100644 index 00000000..f13f0ea0 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaLineColumnSetting.vue @@ -0,0 +1,168 @@ + + + + + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaRubberContentSettingModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaRubberContentSettingModal.vue new file mode 100644 index 00000000..6c447e84 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaRubberContentSettingModal.vue @@ -0,0 +1,240 @@ + + + + + + + + + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue new file mode 100644 index 00000000..3cdf834c --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue @@ -0,0 +1,2318 @@ + + + + + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/MesXslMixerPsCompile.data.ts b/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/MesXslMixerPsCompile.data.ts index f140f7ac..753a1f34 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/MesXslMixerPsCompile.data.ts +++ b/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/MesXslMixerPsCompile.data.ts @@ -145,7 +145,6 @@ export const formSchema: FormSchema[] = [ component: 'Input', componentProps: { disabled: true, bordered: false, placeholder: '保存后按创建人显示' }, colProps: colHalf, - itemProps: { class: 'ps-workflow-item' }, }, { label: '担当', @@ -225,7 +224,6 @@ export const formSchema: FormSchema[] = [ component: 'Input', componentProps: { disabled: true, bordered: false }, colProps: colHalf, - itemProps: { class: 'ps-workflow-item' }, ifShow: ({ values }) => !!values.proofreadBy, }, { @@ -234,7 +232,6 @@ export const formSchema: FormSchema[] = [ component: 'Input', componentProps: { disabled: true, bordered: false }, colProps: colHalf, - itemProps: { class: 'ps-workflow-item' }, ifShow: ({ values }) => !!values.proofreadTime, }, { @@ -243,7 +240,6 @@ export const formSchema: FormSchema[] = [ component: 'Input', componentProps: { disabled: true, bordered: false }, colProps: colHalf, - itemProps: { class: 'ps-workflow-item' }, ifShow: ({ values }) => !!values.auditBy, }, { @@ -252,7 +248,6 @@ export const formSchema: FormSchema[] = [ component: 'Input', componentProps: { disabled: true, bordered: false }, colProps: colHalf, - itemProps: { class: 'ps-workflow-item' }, ifShow: ({ values }) => !!values.auditTime, }, { @@ -261,7 +256,6 @@ export const formSchema: FormSchema[] = [ component: 'Input', componentProps: { disabled: true, bordered: false }, colProps: colHalf, - itemProps: { class: 'ps-workflow-item' }, ifShow: ({ values }) => !!values.approveBy, }, { @@ -270,7 +264,6 @@ export const formSchema: FormSchema[] = [ component: 'Input', componentProps: { disabled: true, bordered: false }, colProps: colHalf, - itemProps: { class: 'ps-workflow-item' }, ifShow: ({ values }) => !!values.approveTime, }, ]; diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/components/MesXslMixerPsCompileModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/components/MesXslMixerPsCompileModal.vue index 4adf8ea7..534409e9 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/components/MesXslMixerPsCompileModal.vue +++ b/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/components/MesXslMixerPsCompileModal.vue @@ -9,7 +9,7 @@ @ok="handleSubmit" >
- +
@@ -166,7 +166,13 @@ margin-bottom: 14px; } - :deep(.ps-workflow-item) { + :deep(#MesXslMixerPsCompileForm_compileBy), + :deep(#MesXslMixerPsCompileForm_proofreadBy), + :deep(#MesXslMixerPsCompileForm_proofreadTime), + :deep(#MesXslMixerPsCompileForm_auditBy), + :deep(#MesXslMixerPsCompileForm_auditTime), + :deep(#MesXslMixerPsCompileForm_approveBy), + :deep(#MesXslMixerPsCompileForm_approveTime) { margin-bottom: 8px; .ant-form-item-label > label { diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/components/MesXslMixerPsCompileSelectModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/components/MesXslMixerPsCompileSelectModal.vue new file mode 100644 index 00000000..3aecd1ae --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslMixerPsCompile/components/MesXslMixerPsCompileSelectModal.vue @@ -0,0 +1,101 @@ + + +