From 50cc133c1791488e1538d430c76ece36275a8fa2 Mon Sep 17 00:00:00 2001 From: zjh <15615273395@163.com> Date: Fri, 26 Dec 2025 09:51:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9:=E5=AF=B9=E6=A0=87=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 250 ++++++++++++++++-- .../common/UserPermissionGetter.java | 3 + .../xdap/self_development/pojo/Template.java | 3 +- .../pojo/view/TodoAndReportListView.java | 3 +- .../pojo/view/TodoAndReportView.java | 3 +- .../pojo/view/TodoAndTemplateView.java | 3 +- .../ParameterValueCalculationTimer.java | 57 +++- .../service/BenchmarkingReportService.java | 12 + .../impl/BenchmarkingReportServiceImpl.java | 34 +-- .../service/impl/ParameterServiceImpl.java | 3 +- .../service/impl/TemplateServiceImpl.java | 175 +++++++----- 11 files changed, 421 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index 5a247a7..66a722d 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,235 @@ -# 数据管理平台 +# 数据管理平台用户手册 -#### 介绍 -{**以下是 Gitee 平台说明,您可以替换此简介** -Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台 -无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)} +## 项目概述 -#### 软件架构 -软件架构说明 +数据管理平台是一个综合性的数据管理系统,主要用于发动机型号数据录入、参数配置管理、审批流程控制、基准报告生成等功能。该平台基于Spring Boot框架开发,集成了Activiti工作流引擎,支持数据录入、维护、审批等完整的业务流程。 +## 功能架构 -#### 安装教程 +### 1. 数据录入与引擎模型管理 +- **发动机型号管理**:支持发动机型号的录入、编辑、删除等操作 +- **Excel导入功能**:支持通过Excel批量导入发动机型号数据 +- **型号字段管理**:包括产品型号、产品编号、板块、平台、系列、细分市场、项目名称、项目编号、品牌、排放等信息 -1. xxxx -2. xxxx -3. xxxx +### 2. 参数与模板配置 +- **参数管理**:管理发动机相关的各类参数信息 +- **模板配置**:配置数据录入模板,支持参数模板的增删改查 +- **参数详情管理**:管理具体参数的详细信息和版本控制 -#### 使用说明 +### 3. 审批流程控制 +- **Activiti工作流**:基于Activiti引擎实现的审批流程 +- **参数审批**:支持参数修改的审批流程 +- **报告审批**:支持基准报告的审批流程 +- **审批节点配置**:可配置多级审批节点 +- **审批记录**:记录完整的审批过程和结果 -1. xxxx -2. xxxx -3. xxxx +### 4. 基准报告生成 +- **报告管理**:支持对标报告的创建、编辑、上传 +- **报告审批流程**:集成审批流程的报告管理 +- **文件上传**:支持报告附件上传功能 -#### 参与贡献 +### 5. 待办任务处理 +- **待办中心**:集中管理用户需要处理的审批任务 +- **已办任务**:查看已完成的任务记录 +- **发起任务**:查看用户发起的审批流程 -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request +### 6. 部门人员管理 +- **部门管理**:管理部门信息和层级关系 +- **人员管理**:管理各部门人员信息 +- **责任人员配置**:配置各部门的责任人 +## 主要模块说明 -#### 特技 +### 1. 数据录入模块 +- 路径:`/custom/dataEntry` +- 支持模板筛选、列表显示、添加模板、导入模板、查看、下载、版本管理、修改等功能 -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 -5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) +### 2. 引擎型号管理模块 +- 路径:`/custom/dataEntryEngineModel` +- 支持发动机型号的Excel导入功能 +- 管理发动机型号的基本信息 + +### 3. 参数管理模块 +- 路径:`/custom/parameter` +- 管理发动机相关的参数配置 + +### 4. 审批流程模块 +- 路径:`/custom/activitiProcess` +- 处理参数和报告的审批流程 + +### 5. 基准报告模块 +- 路径:`/custom/benchmark` +- 管理对标报告的创建、审批、查看等 + +### 6. 待办任务模块 +- 路径:`/custom/todoTask` +- 管理用户的待办、已办、发起任务 + +## 技术架构 + +### 后端技术栈 +- **Spring Boot 2.2.7.RELEASE**:核心框架 +- **Maven**:项目构建工具 +- **Java 1.8**:开发语言 +- **Lombok**:简化代码 +- **Hutool**:工具库 +- **MongoDB**:数据查询 +- **Activiti**:工作流引擎 +- **Groovy**:编译器集成 + +### 数据库 +- 使用MySQL作为主要数据存储 +- 支持多数据源配置 +- 通过MpaasQuery进行数据访问 + +### 接口规范 +- RESTful API设计 +- 统一的响应格式 +- 基于Response的返回结果封装 + +## 安装部署 + +### 环境要求 +- JDK 1.8 +- Maven 3.5+ +- MySQL 5.7+ +- Redis(可选) + +### 部置步骤 + +1. **克隆项目** + ```bash + git clone <项目地址> + ``` + +2. **配置数据库** + - 修改 [application.properties](file:///D:/JavaProjects/data-management-platform/src/main/resources/application.properties) 文件中的数据库连接信息 + - 执行 [sql.sql](file:///D:/JavaProjects/data-management-platform/src/main/resources/sql.sql) 初始化数据库表结构 + +3. **Maven构建** + ```bash + # 使用single profile构建可执行jar + mvn clean package -Psingle + + # 或使用lib profile构建库模式 + mvn clean package -Plib + ``` + +4. **启动项目** + ```bash + java -jar target/data-management-platform.jar + ``` + +## 使用指南 + +### 1. 发动机型号管理 + +#### 添加发动机型号 +1. 访问数据录入模块 +2. 可通过Excel导入或手动添加发动机型号 +3. 填写型号信息包括:产品型号、产品编号、板块、平台、系列等 +4. 提交后系统会自动为该型号绑定所有参数模板 + +#### Excel导入 +- 支持批量导入发动机型号数据 +- 需按照指定的Excel模板格式填写数据 +- 上传后系统会自动验证数据格式和重复性 + +### 2. 参数管理 + +#### 参数维护 +1. 选择具体的发动机型号 +2. 查看该型号绑定的参数列表 +3. 可编辑参数值、版本信息等 +4. 修改后需要提交审批 + +### 3. 审批流程 + +#### 发起审批 +1. 在参数编辑完成后,点击发起审批 +2. 系统会生成审批修改说明 +3. 选择审批流程和审批人 +4. 提交审批请求 + +#### 处理审批任务 +1. 在待办任务中查看需要处理的审批 +2. 查看审批详情和修改内容 +3. 选择通过、拒绝或转交操作 +4. 填写审批意见 + +### 4. 基准报告管理 + +#### 创建报告 +1. 进入基准报告模块 +2. 填写报告基本信息 +3. 上传报告文件 +4. 保存为草稿或提交审批 + +#### 报告审批 +1. 选择需要审批的报告 +2. 按照预设流程进行审批 +3. 查看审批进度和历史记录 + +## API接口 + +### 数据录入相关 +- `GET /custom/dataEntry/getTemplateByCondition` - 模板条件查询 +- `GET /custom/dataEntry/getParameterByCondition` - 参数条件查询 +- `POST /custom/dataEntryEngineModel/excelImport` - Excel导入发动机型号 + +### 审批流程相关 +- `POST /custom/activitiProcess/initiateApproval` - 发起参数审批 +- `POST /custom/activitiProcess/handleApproval` - 处理审批 +- `GET /custom/activitiProcess/getApprovalProcess` - 获取审批流程 + +### 报告管理相关 +- `POST /custom/benchmark/uploadFile` - 上传文件 +- `POST /custom/benchmark/insertReport` - 创建报告 +- `POST /custom/benchmark/updateReport` - 更新报告 +- `GET /custom/benchmark/getReportDetail` - 获取报告详情 + +### 任务管理相关 +- `GET /custom/todoTask/getTodoTaskList` - 获取待办任务列表 +- `GET /custom/todoTask/getCompletedTaskList` - 获取已办任务列表 +- `GET /custom/todoTask/getInitiatedTaskList` - 获取发起任务列表 + +## 系统配置 + +### 配置文件 +- [application.properties](file:///D:/JavaProjects/data-management-platform/src/main/resources/application.properties) - 主配置文件 +- [application-s.properties](file:///D:/JavaProjects/data-management-platform/src/main/resources/application-s.properties) - 服务配置文件 + +### 多数据源配置 +系统支持配置多个数据源,通过 `mpaas.datasource` 配置项进行设置。 + +## 常见问题 + +### 1. Excel导入失败 +- 检查文件格式是否为.xlsx或.xls +- 确认Excel模板格式是否正确 +- 验证数据是否符合字段要求 + +### 2. 审批流程异常 +- 确认审批人配置是否正确 +- 检查工作流配置是否完整 +- 查看系统日志获取详细错误信息 + +### 3. 数据库连接问题 +- 检查数据库连接参数 +- 确认数据库服务是否正常运行 +- 验证数据库用户权限 + +## 维护说明 + +### 日志管理 +- 系统日志文件默认位于 `log/xdap-app.log` +- 支持日志级别配置和日志轮转 + +### 数据备份 +- 定期备份数据库 +- 保留重要配置文件的备份 +- 建立数据恢复机制 + +## 版权声明 + +本项目为数据管理平台系统,所有权利保留。 \ No newline at end of file diff --git a/src/main/java/com/xdap/self_development/common/UserPermissionGetter.java b/src/main/java/com/xdap/self_development/common/UserPermissionGetter.java index 721ace9..f80c519 100644 --- a/src/main/java/com/xdap/self_development/common/UserPermissionGetter.java +++ b/src/main/java/com/xdap/self_development/common/UserPermissionGetter.java @@ -22,6 +22,9 @@ public class UserPermissionGetter { @Resource private RuntimeAppContextService runtimeAppContextService; + public String getUserId() { + return runtimeAppContextService.getCurrentUserId(); + } // 获取子系统下的零部件权限 public List getParamPermissions(String subsystem, String userId) { diff --git a/src/main/java/com/xdap/self_development/pojo/Template.java b/src/main/java/com/xdap/self_development/pojo/Template.java index 4ad9228..4ad6126 100644 --- a/src/main/java/com/xdap/self_development/pojo/Template.java +++ b/src/main/java/com/xdap/self_development/pojo/Template.java @@ -13,8 +13,9 @@ import java.sql.Timestamp; @SQL(view = "getLatestTemplateOrder", sql = "SELECT ranked.order_num, ranked.id, ranked.template_name, ranked.version, ranked.status , ranked.created_time, ranked.published_time, xu.username AS \"createBy\" FROM ( SELECT t.*, ROW_NUMBER() OVER (PARTITION BY template_name ORDER BY CASE WHEN status = 'COMPLETE' THEN 1 WHEN status = 'APPROVING' THEN 2 ELSE 3 END, version DESC) AS rn FROM ( SELECT DISTINCT id, template_name, version, status, created_time , published_time, order_num, create_by FROM yfsjglpt_model_template WHERE status IN ('COMPLETE', 'DRAFT', 'APPROVING') ) t ) ranked LEFT JOIN xdap_users xu ON xu.id = ranked.create_by WHERE rn = 1 ORDER BY CASE status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'RETURNED' THEN 4 WHEN 'REJECTED' THEN 5 ELSE 6 END ASC, ranked.order_num DESC"), // 查找每个模板的最新版本并且优先级按照已发布、审核中、草稿状态转变(只有这三种状态) + // CASE ranked.status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'RETURNED' THEN 4 WHEN 'REJECTED' THEN 5 ELSE 6 END ASC, @SQL(view = "getLatestTemplate", - sql = "SELECT ROW_NUMBER() OVER (ORDER BY CASE ranked.status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'RETURNED' THEN 4 WHEN 'REJECTED' THEN 5 ELSE 6 END ASC, ranked.order_num DESC) AS order_num, ranked.id, ranked.template_name, ranked.version , ranked.status, ranked.created_time, ranked.published_time, xu.username AS \"createBy\" FROM ( SELECT t.*, ROW_NUMBER() OVER (PARTITION BY template_name ORDER BY CASE WHEN status = 'COMPLETE' THEN 1 WHEN status = 'APPROVING' THEN 2 ELSE 3 END, version DESC) AS rn FROM yfsjglpt_model_template t WHERE status IN ('COMPLETE', 'DRAFT', 'APPROVING') ) ranked LEFT JOIN xdap_users xu ON xu.id = ranked.create_by WHERE rn = 1 ORDER BY CASE ranked.status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'RETURNED' THEN 4 WHEN 'REJECTED' THEN 5 ELSE 6 END ASC, ranked.order_num DESC" + sql = "SELECT ROW_NUMBER() OVER (ORDER BY CASE ranked.status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'RETURNED' THEN 4 WHEN 'REJECTED' THEN 5 ELSE 6 END ASC, ranked.order_num DESC) AS order_num, ranked.id, ranked.template_name, ranked.version , ranked.status, ranked.created_time, ranked.published_time, xu.username AS \"createBy\" FROM ( SELECT t.*, ROW_NUMBER() OVER (PARTITION BY template_name ORDER BY CASE WHEN status = 'COMPLETE' THEN 1 WHEN status = 'APPROVING' THEN 2 ELSE 3 END, version DESC) AS rn FROM yfsjglpt_model_template t WHERE status IN ('COMPLETE', 'DRAFT', 'APPROVING') ) ranked LEFT JOIN xdap_users xu ON xu.id = ranked.create_by WHERE rn = 1 ORDER BY ranked.order_num DESC" ), // 获取所有模板的最新版本号(包括所有状态) @SQL(view = "getNewTemplate", diff --git a/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportListView.java b/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportListView.java index c1426dc..814b774 100644 --- a/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportListView.java +++ b/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportListView.java @@ -9,9 +9,10 @@ import lombok.Data; import java.sql.Timestamp; import java.util.List; +// CASE af.flow_status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'REJECTED' THEN 4 ELSE 5 END ASC, @SQLQuery(value = { @SQL(view = "getAllReportApprovalList", - sql = "SELECT af.id AS \"flowId\", r.id AS \"reportId\", r.title AS \"title\", af.flow_status AS \"status\", af.create_by AS \"createBy\" , xu.username AS \"username\", af.created_time AS \"createdTime\", ac.assignees AS current_users FROM yfsjglpt_model_approval_flow af JOIN approval_config ac ON af.id = ac.approval_id AND af.current_node = ac.node_order JOIN yfsjglpt_model_benchmarking_report r ON af.template_id = r.id LEFT JOIN xdap_users xu ON xu.id = af.create_by WHERE af.flow_type = 2 AND r.title LIKE CONCAT('%', #title, '%') AND af.flow_status LIKE CONCAT('%', #status, '%') AND af.created_time LIKE CONCAT('%', #createdTime, '%') AND xu.username LIKE CONCAT('%', #username, '%') ORDER BY CASE af.flow_status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'REJECTED' THEN 4 ELSE 5 END ASC, af.created_time DESC") + sql = "SELECT af.id AS flowId, r.id AS reportId, r.title AS title, af.flow_status AS status, af.create_by AS createBy , xu.username AS username, af.created_time AS createdTime, ac.assignees AS current_users FROM yfsjglpt_model_approval_flow af LEFT JOIN approval_config ac ON af.id = ac.approval_id AND af.current_node = ac.node_order LEFT JOIN yfsjglpt_model_benchmarking_report r ON af.template_id = r.id LEFT JOIN xdap_users xu ON xu.id = af.create_by WHERE af.flow_type = 2 AND r.title LIKE CONCAT('%', #title, '%') AND af.flow_status LIKE CONCAT('%', #status, '%') AND af.created_time LIKE CONCAT('%', #createdTime, '%') AND xu.username LIKE CONCAT('%', #username, '%') ORDER BY af.created_time DESC") }) @Data public class TodoAndReportListView { diff --git a/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportView.java b/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportView.java index d4ba13b..b679336 100644 --- a/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportView.java +++ b/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportView.java @@ -8,8 +8,9 @@ import lombok.Data; import java.sql.Timestamp; @SQLQuery(value = { + // CASE br.status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'REJECTED' THEN 3 ELSE 4 END ASC , @SQL(view = "getAllReport", - sql = "SELECT br.id AS \"reportId\", br.* FROM yfsjglpt_model_benchmarking_report br WHERE br.is_delete = 0 and br.title like CONCAT('%', #title, '%') and br.manufacturer_name like CONCAT('%', #manufacturerName, '%') and br.model_name like CONCAT('%', #modelName, '%') and br.product_number like CONCAT('%', #productNumber, '%') and br.module like CONCAT('%', #module, '%') and br.plate like CONCAT('%', #plate, '%') and br.platform like CONCAT('%', #platform, '%') and br.series like CONCAT('%', #series, '%') and br.market_segment like CONCAT('%', #marketSegment, '%') and br.project_name like CONCAT('%', #projectName, '%') and br.project_number like CONCAT('%', #projectNumber, '%') and br.status like CONCAT('%', #status, '%') ORDER BY CASE br.status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'REJECTED' THEN 3 ELSE 4 END ASC , af.created_time DESC") + sql = "SELECT br.id AS \"reportId\", br.* FROM yfsjglpt_model_benchmarking_report br WHERE br.is_delete = 0 and br.title like CONCAT('%', #title, '%') and br.manufacturer_name like CONCAT('%', #manufacturerName, '%') and br.model_name like CONCAT('%', #modelName, '%') and br.product_number like CONCAT('%', #productNumber, '%') and br.module like CONCAT('%', #module, '%') and br.plate like CONCAT('%', #plate, '%') and br.platform like CONCAT('%', #platform, '%') and br.series like CONCAT('%', #series, '%') and br.market_segment like CONCAT('%', #marketSegment, '%') and br.project_name like CONCAT('%', #projectName, '%') and br.project_number like CONCAT('%', #projectNumber, '%') and br.status like CONCAT('%', #status, '%') ORDER BY br.upload_time DESC") }) @Data public class TodoAndReportView { diff --git a/src/main/java/com/xdap/self_development/pojo/view/TodoAndTemplateView.java b/src/main/java/com/xdap/self_development/pojo/view/TodoAndTemplateView.java index a60ab53..5b97de1 100644 --- a/src/main/java/com/xdap/self_development/pojo/view/TodoAndTemplateView.java +++ b/src/main/java/com/xdap/self_development/pojo/view/TodoAndTemplateView.java @@ -10,8 +10,9 @@ import java.sql.Timestamp; import java.util.List; @SQLQuery(value = { + // CASE af.flow_status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'REJECTED' THEN 4 ELSE 5 END ASC @SQL(view = "getAllApproval", - sql = "SELECT af.id AS \"flowId\", t.id AS \"templateId\", t.template_name AS \"templateName\", t.version AS \"version\", af.flow_status AS \"status\" , af.create_by AS \"createBy\", xu.username AS \"username\", af.created_time AS \"createdTime\", ac.assignees AS current_users FROM yfsjglpt_model_approval_flow af JOIN approval_config ac ON af.id = ac.approval_id AND af.current_node = ac.node_order JOIN yfsjglpt_model_template t ON af.template_id = t.id LEFT JOIN xdap_users xu ON xu.id = af.create_by WHERE t.template_name LIKE CONCAT('%', #templateName, '%') AND af.flow_status LIKE CONCAT('%', #status, '%') AND af.created_time LIKE CONCAT('%', #createdTime, '%') AND xu.username LIKE CONCAT('%', #username, '%') AND af.flow_type = 1 ORDER BY CASE af.flow_status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'REJECTED' THEN 4 ELSE 5 END ASC"), + sql = "SELECT af.id AS flowId, t.id AS templateId, t.template_name AS templateName, t.version AS version, af.flow_status AS status , af.create_by AS createBy, xu.username AS username, af.created_time AS createdTime, ac.assignees AS current_users FROM yfsjglpt_model_approval_flow af LEFT JOIN approval_config ac ON af.id = ac.approval_id AND af.current_node = ac.node_order LEFT JOIN yfsjglpt_model_template t ON af.template_id = t.id LEFT JOIN xdap_users xu ON xu.id = af.create_by WHERE t.template_name LIKE CONCAT('%', #templateName, '%') AND af.flow_status LIKE CONCAT('%', #status, '%') AND af.created_time LIKE CONCAT('%', #createdTime, '%') AND xu.username LIKE CONCAT('%', #username, '%') AND af.flow_type = 1 ORDER BY af.created_time desc"), @SQL(view = "getApprovalByUserIdAndIds", sql = "SELECT af.id AS \"flowId\", t.id AS \"templateId\", t.template_name AS \"templateName\", t.version AS \"version\", af.flow_status AS \"status\" , af.create_by AS \"createBy\", af.created_time AS \"createdTime\" , CASE WHEN current_node = 'PROOFREAD' THEN proofread_users WHEN current_node = 'REVIEW' THEN review_users WHEN current_node = 'COUNTERSIGN' THEN countersign_users WHEN current_node = 'APPROVE' THEN approve_users END AS current_users FROM yfsjglpt_model_approval_flow af JOIN yfsjglpt_model_template t ON af.template_id = t.id WHERE t.template_name like CONCAT('%',#templateName, '%') and af.flow_status like CONCAT('%',#status, '%') and af.flow_type = 1 and af.id NOT IN (#ids) AND af.create_by = #createBy"), @SQL(view = "getTodoAndTemplate", diff --git a/src/main/java/com/xdap/self_development/schedule/ParameterValueCalculationTimer.java b/src/main/java/com/xdap/self_development/schedule/ParameterValueCalculationTimer.java index 00af2fb..7d27ea8 100644 --- a/src/main/java/com/xdap/self_development/schedule/ParameterValueCalculationTimer.java +++ b/src/main/java/com/xdap/self_development/schedule/ParameterValueCalculationTimer.java @@ -7,7 +7,6 @@ import com.xdap.self_development.pojo.ClassificationAttribute; import com.xdap.self_development.pojo.EnginePartsCollection; import com.xdap.self_development.pojo.view.CalculationParameterView; import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -45,6 +44,14 @@ public class ParameterValueCalculationTimer { LocalDate today = LocalDate.now(); log.info("开始执行{}参数计算任务", today); myResponse.getErrors().add("开始执行"+today+"参数计算任务"); + + // 统计信息 + int totalParameters = 0; + int tcParameters = 0; + int calculatedParameters = 0; + int updatedFromTC = 0; + int failedToUpdateFromTC = 0; + List toUpdate = new ArrayList<>(); // 1.查询所有参数配置 @@ -52,20 +59,31 @@ public class ParameterValueCalculationTimer { .viewQueryMode(true) .view("getModelParameterValue") .doQuery(CalculationParameterView.class); + + totalParameters = parameterValues.size(); + log.info("共查询到{}个参数配置", totalParameters); + myResponse.getErrors().add("共查询到"+totalParameters+"个参数配置"); + if (parameterValues.isEmpty()) { log.info("无参数配置,跳过计算"); + myResponse.getErrors().add("无参数配置,跳过计算"); return myResponse; } // 2.从中台更新参数值 for (CalculationParameterView parameter : parameterValues) { if (Objects.equals(parameter.getParameterSource(), "TC分类表")) { + tcParameters++; try { EnginePartsCollection enginePartsCollection = bd.getBusinessDatabase() .eq("ztj", parameter.getProductNumber()) .eq("lbjmc", parameter.getPartsName()) .doQueryFirst(EnginePartsCollection.class); if (enginePartsCollection == null || enginePartsCollection.getLbjth() == null) { + log.warn("参数【{}】在TC分类表中未找到对应零部件,产品号:{},零部件名:{}", + parameter.getParameterName(), parameter.getProductNumber(), parameter.getPartsName()); + myResponse.getErrors().add("参数【"+parameter.getParameterName()+"】在TC分类表中未找到对应零部件"); + failedToUpdateFromTC++; continue; } ClassificationAttribute classificationAttribute = bd.getBusinessDatabase() @@ -73,14 +91,25 @@ public class ParameterValueCalculationTimer { .eq("idattrtbutehame", parameter.getParameterName()) .doQueryFirst(ClassificationAttribute.class); if (classificationAttribute != null && classificationAttribute.getFieldvalue() != null) { + String originalValue = parameter.getParameterValue(); parameter.setParameterValue(classificationAttribute.getFieldvalue()); + log.debug("参数【{}】从中台更新值:{} -> {}", parameter.getParameterName(), originalValue, classificationAttribute.getFieldvalue()); + updatedFromTC++; + } else { + log.warn("参数【{}】在TC分类表中未找到对应值", parameter.getParameterName()); + myResponse.getErrors().add("参数【"+parameter.getParameterName()+"】在TC分类表中未找到对应值"); + failedToUpdateFromTC++; } } catch (Exception e) { log.error("参数【{}】从中台更新值失败:{}", parameter.getParameterName(), e.getMessage(), e); myResponse.getErrors().add("参数【"+parameter.getParameterName()+"】从中台更新值失败:"+e.getMessage()); + failedToUpdateFromTC++; } } } + + log.info("从中台更新参数完成,共处理{}个TC参数,成功{}个,失败{}个", tcParameters, updatedFromTC, failedToUpdateFromTC); + myResponse.getErrors().add("从中台更新参数完成,共处理"+tcParameters+"个TC参数,成功"+updatedFromTC+"个,失败"+failedToUpdateFromTC+"个"); // 3.维护所有参数的原始值 Map> originalValueMap = convertMap(parameterValues); @@ -95,10 +124,12 @@ public class ParameterValueCalculationTimer { int failureCount = 0; for (CalculationParameterView parameterValue : parameterValues) { if (Objects.equals(parameterValue.getParameterSource(), "公式计算")) { + calculatedParameters++; String formula = parameterValue.getNumberOrFormula(); String modelId = parameterValue.getModelId(); try { String replacedFormula = replaceParametersInFormula(formula, parameterNames, originalValueMap, modelId); + log.debug("参数【{}】替换公式:{} -> {}", parameterValue.getParameterName(), formula, replacedFormula); Double result = calculateExpression(replacedFormula); String formattedResult = String.format("%.6f", result); parameterValue.setParameterValue(formattedResult); @@ -116,10 +147,14 @@ public class ParameterValueCalculationTimer { } } } + + log.info("公式计算参数完成,共处理{}个计算参数,成功{}个,失败{}个", calculatedParameters, successCount, failureCount); + myResponse.getErrors().add("公式计算参数完成,共处理"+calculatedParameters+"个计算参数,成功"+successCount+"个,失败"+failureCount+"个"); // 批量插入或更新计算结果 + int updatedCount = 0; + int dbUpdateFailures = 0; if (!toUpdate.isEmpty()) { - int updatedCount = 0; for (CalculationParameterView parameterValue : toUpdate) { try { if (parameterValue.getParameterValue() != null) { @@ -141,13 +176,24 @@ public class ParameterValueCalculationTimer { } catch (Exception e) { log.error("参数【{}】更新数据库失败:{}", parameterValue.getParameterName(), e.getMessage(), e); myResponse.getErrors().add("参数【"+parameterValue.getParameterName()+"】更新数据库失败:"+e.getMessage()); + dbUpdateFailures++; } } - log.info("{}参数计算完成,成功处理{}个参数,失败{}个参数,更新{}个参数", today, successCount, failureCount, updatedCount); + log.info("{}参数计算完成,成功处理{}个参数,失败{}个参数,更新{}个参数,数据库更新失败{}个", + today, successCount, failureCount, updatedCount, dbUpdateFailures); + myResponse.getErrors().add("数据库更新完成,成功更新"+updatedCount+"个参数,更新失败"+dbUpdateFailures+"个"); } else { log.info("{}参数计算完成,无需更新任何参数", today); + myResponse.getErrors().add("无需更新任何参数"); } - myResponse.getErrors().add("参数计算完成,成功处理"+successCount+"个参数,失败"+failureCount+"个参数"); + + // 添加汇总信息 + myResponse.getErrors().add("任务汇总:共处理"+totalParameters+"个参数,其中TC参数"+tcParameters+"个(成功"+updatedFromTC+"个,失败"+failedToUpdateFromTC+"个),计算参数"+calculatedParameters+"个(成功"+successCount+"个,失败"+failureCount+"个)"); + + log.info("{}参数计算任务结束,总参数数{},TC参数{}(成功{},失败{}),计算参数{}(成功{},失败{}),数据库更新{}(失败{})", + today, totalParameters, tcParameters, updatedFromTC, failedToUpdateFromTC, + calculatedParameters, successCount, failureCount, updatedCount, dbUpdateFailures); + return myResponse; } @@ -220,8 +266,7 @@ public class ParameterValueCalculationTimer { if (list == null) { return new HashMap<>(); } - // 参数名在所有子系统都唯一 - // 转为以参数名为key,(机型代号为key,参数值为值)为值的形式 + return list.stream() .filter(Objects::nonNull) .filter(item -> item.getParameterName() != null) diff --git a/src/main/java/com/xdap/self_development/service/BenchmarkingReportService.java b/src/main/java/com/xdap/self_development/service/BenchmarkingReportService.java index 19f30c5..62126ff 100644 --- a/src/main/java/com/xdap/self_development/service/BenchmarkingReportService.java +++ b/src/main/java/com/xdap/self_development/service/BenchmarkingReportService.java @@ -2,6 +2,8 @@ package com.xdap.self_development.service; import com.definesys.mpaas.query.db.PageQueryResult; import com.xdap.self_development.controller.form.*; +import com.xdap.self_development.pojo.ApprovalConfigPojo; +import com.xdap.self_development.pojo.ApprovalFlow; import com.xdap.self_development.pojo.BenchmarkingReport; import com.xdap.self_development.pojo.view.ApprovalFlowNodeView; import com.xdap.self_development.pojo.view.TodoAndReportListView; @@ -30,4 +32,14 @@ public interface BenchmarkingReportService { String uploadFile(MultipartFile file, @NotBlank String createBy); PageQueryResult getApprovalList(@Valid ApprovalListForm form); + + void processNextNode(ApprovalFlow flow, ApprovalConfigPojo currentNode, String userId); + + void processApprovalLogic(ApprovalFlow flow, HandleApprovalRequest request, ApprovalConfigPojo currentNode); + + void addNodeTodo(ApprovalFlow flow, ApprovalConfigPojo node, BenchmarkingReport report, String createBy); + + void cancelProcess(ApprovalFlow flow, String status); + + void updateTasks(ApprovalFlow flow, String status); } diff --git a/src/main/java/com/xdap/self_development/service/impl/BenchmarkingReportServiceImpl.java b/src/main/java/com/xdap/self_development/service/impl/BenchmarkingReportServiceImpl.java index 10126fe..c72b5d5 100644 --- a/src/main/java/com/xdap/self_development/service/impl/BenchmarkingReportServiceImpl.java +++ b/src/main/java/com/xdap/self_development/service/impl/BenchmarkingReportServiceImpl.java @@ -46,6 +46,8 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService private RedisLockUtil redisLockUtil; @Resource private XdapDeptUsersService xdapDeptUsersService; + @Resource + private BenchmarkingReportService myself; @Value("${apaas.token.clientId}") private String clientId; @@ -106,7 +108,7 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService TodoTaskPojo todoTask = new TodoTaskPojo(); todoTask.setCreatedById(form.getUserId()); todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(form.getUserId()).getUsername()); - todoTask.setCurrentNode(""); + todoTask.setCurrentNode(firstNode.getNodeName()); todoTask.setDataType("对标报告审核"); todoTask.setDocumentNo(flow.getId()); todoTask.setCreationDate(Timestamp.valueOf(LocalDateTime.now())); @@ -126,6 +128,7 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService InitiatedTaskPojo initiatedTask = new InitiatedTaskPojo(); initiatedTask.setDocumentNo(flow.getId()); initiatedTask.setCreatedById(form.getUserId()); + initiatedTask.setCreatedBy(xdapDeptUsersService.selectUserByID(form.getUserId()).getUsername()); initiatedTask.setCurrentNode(firstNode.getNodeName()); initiatedTask.setCurrentProcessor(JSON.toJSONString(firstNode.getAssignees())); initiatedTask.setDataType("对标报告审核"); @@ -305,7 +308,7 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService if (processedCount > 0) { throw new CommonException("此节点已被他人处理"); } - processApprovalLogic(flow, request, currentNode); + myself.processApprovalLogic(flow, request, currentNode); } finally { redisLockUtil.unlock(lockKey, lockValue); } @@ -339,6 +342,7 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService CompletedTaskPojo completedTaskPojo = new CompletedTaskPojo(); completedTaskPojo.setDocumentNo(flow.getId()); completedTaskPojo.setCreatedById(request.getUserId()); + completedTaskPojo.setCreatedBy(xdapDeptUsersService.selectUserByID(request.getUserId()).getUsername()); completedTaskPojo.setCurrentNode(currentNode.getNodeName()); completedTaskPojo.setCurrentProcessor(JSON.toJSONString(currentNode.getAssignees())); completedTaskPojo.setDataType("对标报告审核"); @@ -351,14 +355,14 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService // 处理驳回逻辑 if ("REJECT".equals(request.getResult())) { - cancelProcess(flow, "REJECTED"); + myself.cancelProcess(flow, "REJECTED"); return; } // 处理通过逻辑,流转到下一节点 - processNextNode(flow, currentNode, request.getUserId()); + myself.processNextNode(flow, currentNode, request.getUserId()); } - private void processNextNode(ApprovalFlow flow, ApprovalConfigPojo currentNode, String userId) { + public void processNextNode(ApprovalFlow flow, ApprovalConfigPojo currentNode, String userId) { // 查询报告状态 BenchmarkingReport report = bd.getBusinessDatabase() .eq("id", flow.getTemplateId()) @@ -378,10 +382,10 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService .update("status", report.getStatus()) .doUpdate(BenchmarkingReport.class); // 待办环节修改 - updateTasks(flow, "已完成"); + myself.updateTasks(flow, "已完成"); } else { - flow.setCurrentNode(1); - addNodeTodo(flow, nextNode, report, userId); + flow.setCurrentNode(nextNode.getNodeOrder()); + myself.addNodeTodo(flow, nextNode, report, userId); } bd.getBusinessDatabase() @@ -391,7 +395,7 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService .doUpdate(ApprovalFlow.class); } - private void addNodeTodo(ApprovalFlow flow, ApprovalConfigPojo node, BenchmarkingReport report, String createBy) { + public void addNodeTodo(ApprovalFlow flow, ApprovalConfigPojo node, BenchmarkingReport report, String createBy) { List users = JSON.parseArray(node.getAssignees()).toJavaList(String.class); // 新增待办 List list = new ArrayList<>(); @@ -399,7 +403,7 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService TodoTaskPojo todoTask = new TodoTaskPojo(); todoTask.setCreatedById(createBy); todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(createBy).getUsername()); - todoTask.setCurrentNode("1"); + todoTask.setCurrentNode(node.getNodeName()); todoTask.setDataType("对标报告审核"); todoTask.setDocumentNo(flow.getId()); todoTask.setCreationDate(Timestamp.valueOf(LocalDateTime.now())); @@ -410,19 +414,19 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService todoTask.setStatusCode(flow.getFlowStatus()); todoTask.setVersionNumber(1); todoTask.setOwnerId(person); - todoTask.setCurrentProcessor(JSON.toJSONString(node.getAssignees())); + todoTask.setCurrentProcessor(node.getAssignees()); list.add(todoTask); } // 更新已办和发起的状态 - updateTasks(flow, node.getNodeName()); + myself.updateTasks(flow, node.getNodeName()); if (!list.isEmpty()) { bd.getBusinessDatabase().doBatchInsert(list); } } - private void cancelProcess(ApprovalFlow flow, String status) { + public void cancelProcess(ApprovalFlow flow, String status) { flow.setFlowStatus(status); bd.getBusinessDatabase() .rowid("id", flow.getRowId()) @@ -438,10 +442,10 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService .update("status", report.getStatus()) .doUpdate(BenchmarkingReport.class); - updateTasks(flow, "已拒绝"); + myself.updateTasks(flow, "已拒绝"); } - private void updateTasks(ApprovalFlow flow, String status) { + public void updateTasks(ApprovalFlow flow, String status) { // 更新已办和发起的节点状态 bd.getBusinessDatabase() .eq("document_no", flow.getId()) diff --git a/src/main/java/com/xdap/self_development/service/impl/ParameterServiceImpl.java b/src/main/java/com/xdap/self_development/service/impl/ParameterServiceImpl.java index e284d03..ce342d9 100644 --- a/src/main/java/com/xdap/self_development/service/impl/ParameterServiceImpl.java +++ b/src/main/java/com/xdap/self_development/service/impl/ParameterServiceImpl.java @@ -44,8 +44,7 @@ public class ParameterServiceImpl implements ParameterService { if (template == null) { throw new CommonException("模板未找到"); } - - //todo 假定子系统名和模板名一致 +// List partsNames = permissionGetter.getParamPermissions(permissionGetter.getUserId()); // Set objects = new HashSet<>(); // objects.addAll(permissionGetter.getParamPermissions(template.getTemplateName())); // objects.addAll(bd.getBusinessDatabase() diff --git a/src/main/java/com/xdap/self_development/service/impl/TemplateServiceImpl.java b/src/main/java/com/xdap/self_development/service/impl/TemplateServiceImpl.java index b140207..655a508 100644 --- a/src/main/java/com/xdap/self_development/service/impl/TemplateServiceImpl.java +++ b/src/main/java/com/xdap/self_development/service/impl/TemplateServiceImpl.java @@ -273,91 +273,124 @@ public class TemplateServiceImpl implements TemplateService { // 页名和模板名不一致不允许导入 if (!Objects.equals(templateName, sheetName)) { problems.setFlag(true); - problems.getErrors().add("\"模板导入失败:\"+Excel页名与模板名不一致"); + problems.getErrors().add("模板导入失败:+Excel页名与模板名不一致"); return; } } - // 获取模板的最新版本 - Template lastTemplate = bd.getBusinessDatabase() - .viewQueryMode(true) - .view("getNewTemplate") + // 首先查找是否有草稿版本 + Template draftTemplate = bd.getBusinessDatabase() .eq("template_name", templateName) + .eq("status", "DRAFT") .doQueryFirst(Template.class); - // 如果有同名称模板 - if (lastTemplate != null) { - switch (lastTemplate.getStatus()) { - // 最新版本为草稿 - case "DRAFT": - // 查询最新模板参数 - List list = bd.getBusinessDatabase() - .eq("template_id", lastTemplate.getId()) - .doQuery(TemplateAndParameter.class); - // 最新模板有参数 - if (!list.isEmpty()) { - // insertAndUpdateParameters(List dataList, Template lastTemplate) - problems.setFlag(true); - problems.getErrors().add("模板导入失败:"+"模板‘"+templateName+"’已有参数,无法导入"); - return; - } - break; - case "APPROVING": - problems.setFlag(true); - problems.getErrors().add("模板导入失败:"+"模板‘"+templateName+"‘的最新版本正在审核中,无法导入"); - return; - // 最新版本已发布,增加版本号新增 - default: - lastTemplate = new Template( - templateName, lastTemplate.getVersion()+1, "DRAFT", - Timestamp.valueOf(LocalDateTime.now()), null, createBy, System.currentTimeMillis(), 0 - ); - bd.getBusinessDatabase() - .doInsert(lastTemplate); - } + Template targetTemplate; + if (draftTemplate != null) { + // 如果存在草稿版本,使用草稿版本 + targetTemplate = draftTemplate; } else { - lastTemplate = new Template( - templateName, 1, "DRAFT", Timestamp.valueOf(LocalDateTime.now()), - null, createBy, System.currentTimeMillis(), 0 - ); - bd.getBusinessDatabase() - .doInsert(lastTemplate); + // 如果没有草稿版本,创建新版本 + Template lastTemplate = bd.getBusinessDatabase() + .viewQueryMode(true) + .view("getNewTemplate") + .eq("template_name", templateName) + .doQueryFirst(Template.class); + + if (lastTemplate != null) { + // 基于最新版本创建新版本 + targetTemplate = new Template( + templateName, lastTemplate.getVersion() + 1, "DRAFT", + Timestamp.valueOf(LocalDateTime.now()), null, createBy, System.currentTimeMillis(), 0 + ); + } else { + // 如果没有同名模板,创建第一个版本 + targetTemplate = new Template( + templateName, 1, "DRAFT", Timestamp.valueOf(LocalDateTime.now()), + null, createBy, System.currentTimeMillis(), 0 + ); + } + bd.getBusinessDatabase().doInsert(targetTemplate); } - // 保存参数 - bd.getBusinessDatabase().doBatchInsert(dataList); + // 获取目标模板的现有参数 + List existingParameters = bd.getBusinessDatabase() + .viewQueryMode(true) + .view("selectParametersByTId") + .setVar("templateId", targetTemplate.getId()) + .doQuery(Parameter.class); - Template finalLastTemplate = lastTemplate; - List relations = dataList.stream() - .map(parameter -> { - TemplateAndParameter relation = new TemplateAndParameter(); - relation.setTemplateId(finalLastTemplate.getId()); - relation.setParameterId(parameter.getId()); - return relation; - }) - .collect(Collectors.toList()); + // 构建现有参数的映射,以参数名、子系统和零部件组合作为键 + Map existingParamMap = new HashMap<>(); + if (existingParameters != null && !existingParameters.isEmpty()) { + existingParamMap = existingParameters.stream() + .collect(Collectors.toMap( + param -> param.getParameterName() + "|" + + (param.getSubsystemName() != null ? param.getSubsystemName() : "") + "|" + + (param.getPartsName() != null ? param.getPartsName() : ""), + param -> param, + (existing, replacement) -> existing + )); + } - List revisionRecords = dataList.stream() - .map(parameter -> { - return new RevisionRecord( - finalLastTemplate.getTemplateName(), - finalLastTemplate.getVersion(), - parameter.getParameterNumber(), - "新增参数", - finalLastTemplate.getId(), - null, - Timestamp.valueOf(LocalDateTime.now()), - parameter.getId(), - finalLastTemplate.getReturnNum() - ); - }) - .collect(Collectors.toList()); + // 处理参数新增和更新 + List relationsToAdd = new ArrayList<>(); + List revisionRecords = new ArrayList<>(); - // 保存关联关系 - bd.getBusinessDatabase().doBatchInsert(relations); + for (Parameter newParam : dataList) { + String key = newParam.getParameterName() + "|" + + (newParam.getSubsystemName() != null ? newParam.getSubsystemName() : "") + "|" + + (newParam.getPartsName() != null ? newParam.getPartsName() : ""); + Parameter existingParam = existingParamMap.get(key); + if (existingParam != null) { + newParam.setId(existingParam.getId()); + bd.getBusinessDatabase() + .eq("id", newParam.getId()) + .doUpdate(newParam); - // 保存修改记录 - bd.getBusinessDatabase().doBatchInsert(revisionRecords); + // 记录修改记录 + revisionRecords.add(new RevisionRecord( + targetTemplate.getTemplateName(), + targetTemplate.getVersion(), + newParam.getParameterNumber(), + "更新参数", + targetTemplate.getId(), + existingParam.getId(), + Timestamp.valueOf(LocalDateTime.now()), + newParam.getId(), + targetTemplate.getReturnNum() + )); + } else { + newParam.setId(null); + bd.getBusinessDatabase().doInsert(newParam); + + TemplateAndParameter relation = new TemplateAndParameter(); + relation.setTemplateId(targetTemplate.getId()); + relation.setParameterId(newParam.getId()); + relationsToAdd.add(relation); + + revisionRecords.add(new RevisionRecord( + targetTemplate.getTemplateName(), + targetTemplate.getVersion(), + newParam.getParameterNumber(), + "新增参数", + targetTemplate.getId(), + null, + Timestamp.valueOf(LocalDateTime.now()), + newParam.getId(), + targetTemplate.getReturnNum() + )); + } + } + + // 批量保存关联关系 + if (!relationsToAdd.isEmpty()) { + bd.getBusinessDatabase().doBatchInsert(relationsToAdd); + } + + // 批量保存修改记录 + if (!revisionRecords.isEmpty()) { + bd.getBusinessDatabase().doBatchInsert(revisionRecords); + } // 返回问题 if (problems.getHasImported().toString().equals("已完成导入:无")) {