Browse Source

ly 可靠性

ly 1 month ago
parent
commit
5e7e2ff6c6
40 changed files with 4236 additions and 256 deletions
  1. 76 0
      master/sql/t_rel_compo_record.sql
  2. 57 0
      master/sql/t_rel_devplan.sql
  3. 24 9
      master/src/main/java/com/ruoyi/common/sms/SmsService.java
  4. 29 26
      master/src/main/java/com/ruoyi/config/ActivitiConfig.java
  5. 6 0
      master/src/main/java/com/ruoyi/project/common/CommonController.java
  6. 19 5
      master/src/main/java/com/ruoyi/project/production/controller/TFurnanceTemperatureController.java
  7. 146 8
      master/src/main/java/com/ruoyi/project/reliability/controller/TRelCompoController.java
  8. 132 8
      master/src/main/java/com/ruoyi/project/reliability/controller/TRelDeviceController.java
  9. 241 0
      master/src/main/java/com/ruoyi/project/reliability/controller/TRelMaintPlanController.java
  10. 103 0
      master/src/main/java/com/ruoyi/project/reliability/controller/TRelMaintRecordController.java
  11. 279 0
      master/src/main/java/com/ruoyi/project/reliability/domain/TRelMaintPlan.java
  12. 392 0
      master/src/main/java/com/ruoyi/project/reliability/domain/TRelMaintRecord.java
  13. 63 0
      master/src/main/java/com/ruoyi/project/reliability/mapper/TRelMaintPlanMapper.java
  14. 63 0
      master/src/main/java/com/ruoyi/project/reliability/mapper/TRelMaintRecordMapper.java
  15. 61 0
      master/src/main/java/com/ruoyi/project/reliability/service/ITRelMaintPlanService.java
  16. 61 0
      master/src/main/java/com/ruoyi/project/reliability/service/ITRelMaintRecordService.java
  17. 93 0
      master/src/main/java/com/ruoyi/project/reliability/service/impl/TRelMaintPlanServiceImpl.java
  18. 93 0
      master/src/main/java/com/ruoyi/project/reliability/service/impl/TRelMaintRecordServiceImpl.java
  19. 13 7
      master/src/main/resources/application.yml
  20. 141 0
      master/src/main/resources/mybatis/reliability/TRelMaintPlanMapper.xml
  21. 186 0
      master/src/main/resources/mybatis/reliability/TRelMaintRecordMapper.xml
  22. 50 0
      master/src/main/resources/processes/reliability/relMaintPlanProcess.bpmn
  23. BIN
      master/src/main/resources/static/template/reliability/rel_compo.xlsx
  24. BIN
      master/src/main/resources/static/template/reliability/rel_device.xlsx
  25. 8 0
      ui/src/api/reliability/rel_compo.js
  26. 8 0
      ui/src/api/reliability/rel_device.js
  27. 62 0
      ui/src/api/reliability/rel_maint_plan.js
  28. 53 0
      ui/src/api/reliability/rel_maint_record.js
  29. 0 0
      ui/src/assets/visio/diagram.svg
  30. 1 1
      ui/src/utils/constants.js
  31. 83 19
      ui/src/views/login.vue
  32. 18 76
      ui/src/views/login2.vue
  33. 33 8
      ui/src/views/plant/EOEGorganization/branch.vue
  34. 35 42
      ui/src/views/plant/EOEGorganization/index.vue
  35. 13 4
      ui/src/views/production/temperature/coil.vue
  36. 31 29
      ui/src/views/reliability/rel_compo/index.vue
  37. 13 11
      ui/src/views/reliability/rel_device/index.vue
  38. 5 3
      ui/src/views/reliability/rel_device/process-diagram.vue
  39. 958 0
      ui/src/views/reliability/rel_maint_plan/index.vue
  40. 587 0
      ui/src/views/reliability/rel_maint_record/index.vue

+ 76 - 0
master/sql/t_rel_compo_record.sql

@@ -0,0 +1,76 @@
+-- 部件维修记录表
+CREATE TABLE t_rel_compo_record (
+  RECORD_ID NUMBER(20) NOT NULL,
+  PLANT VARCHAR2(100),
+  DEV_NAME VARCHAR2(200),
+  DEV_TAG VARCHAR2(100),
+  COMPO_NAME VARCHAR2(200),
+  COMPO_ID VARCHAR2(100),
+  MAINT_TYPE VARCHAR2(50),
+  MAINT_DEPT VARCHAR2(100),
+  INSPECTOR VARCHAR2(100),
+  INSPECT_CONTENT VARCHAR2(500),
+  INSPECT_TIME DATE,
+  RESPONSIBLE VARCHAR2(100),
+  MAINT_CONTENT VARCHAR2(500),
+  MAINT_RESULT VARCHAR2(50),
+  MAINT_TIME DATE,
+  MAINT_COST NUMBER(18,2),
+  MAINT_DURATION NUMBER(10,2),
+  PROCESS_LOSS VARCHAR2(500),
+  ATTACHMENTS VARCHAR2(500),
+  DEL_FLAG NUMBER(1) DEFAULT 0,
+  CREATER_CODE VARCHAR2(64),
+  CREATEDATE DATE,
+  UPDATER_CODE VARCHAR2(64),
+  UPDATEDATE DATE,
+  DEPT_ID NUMBER(20),
+  REMARKS VARCHAR2(500),
+  CONSTRAINT pk_t_rel_compo_record PRIMARY KEY (RECORD_ID)
+);
+
+-- 添加表注释
+COMMENT ON TABLE t_rel_compo_record IS '部件维修记录表';
+
+-- 添加字段注释
+COMMENT ON COLUMN t_rel_compo_record.RECORD_ID IS '记录ID';
+COMMENT ON COLUMN t_rel_compo_record.PLANT IS '装置';
+COMMENT ON COLUMN t_rel_compo_record.DEV_NAME IS '设备名称';
+COMMENT ON COLUMN t_rel_compo_record.DEV_TAG IS '设备位号';
+COMMENT ON COLUMN t_rel_compo_record.COMPO_NAME IS '部件名称';
+COMMENT ON COLUMN t_rel_compo_record.COMPO_ID IS '部件ID';
+COMMENT ON COLUMN t_rel_compo_record.MAINT_TYPE IS '维修类型';
+COMMENT ON COLUMN t_rel_compo_record.MAINT_DEPT IS '维修部门';
+COMMENT ON COLUMN t_rel_compo_record.INSPECTOR IS '检查人';
+COMMENT ON COLUMN t_rel_compo_record.INSPECT_CONTENT IS '检查内容';
+COMMENT ON COLUMN t_rel_compo_record.INSPECT_TIME IS '检查时间';
+COMMENT ON COLUMN t_rel_compo_record.RESPONSIBLE IS '维修责任人';
+COMMENT ON COLUMN t_rel_compo_record.MAINT_CONTENT IS '维修内容';
+COMMENT ON COLUMN t_rel_compo_record.MAINT_RESULT IS '维修结果';
+COMMENT ON COLUMN t_rel_compo_record.MAINT_TIME IS '维修时间';
+COMMENT ON COLUMN t_rel_compo_record.MAINT_COST IS '维修费用';
+COMMENT ON COLUMN t_rel_compo_record.MAINT_DURATION IS '维修时长';
+COMMENT ON COLUMN t_rel_compo_record.PROCESS_LOSS IS '工艺损失';
+COMMENT ON COLUMN t_rel_compo_record.ATTACHMENTS IS '附件';
+COMMENT ON COLUMN t_rel_compo_record.DEL_FLAG IS '删除标志(0代表存在 2代表删除)';
+COMMENT ON COLUMN t_rel_compo_record.CREATER_CODE IS '创建人';
+COMMENT ON COLUMN t_rel_compo_record.CREATEDATE IS '创建时间';
+COMMENT ON COLUMN t_rel_compo_record.UPDATER_CODE IS '修改人';
+COMMENT ON COLUMN t_rel_compo_record.UPDATEDATE IS '修改时间';
+COMMENT ON COLUMN t_rel_compo_record.DEPT_ID IS '部门编号';
+COMMENT ON COLUMN t_rel_compo_record.REMARKS IS '备注';
+
+-- 创建序列
+CREATE SEQUENCE seq_t_rel_compo_record
+  START WITH 1
+  INCREMENT BY 1
+  NOCACHE
+  NOCYCLE;
+
+-- 创建索引
+CREATE INDEX idx_compo_record_dev_tag ON t_rel_compo_record(DEV_TAG);
+CREATE INDEX idx_compo_record_compo_id ON t_rel_compo_record(COMPO_ID);
+CREATE INDEX idx_compo_record_maint_time ON t_rel_compo_record(MAINT_TIME);
+CREATE INDEX idx_compo_record_inspect_time ON t_rel_compo_record(INSPECT_TIME);
+CREATE INDEX idx_compo_record_responsible ON t_rel_compo_record(RESPONSIBLE);
+CREATE INDEX idx_compo_record_dept_id ON t_rel_compo_record(DEPT_ID);

+ 57 - 0
master/sql/t_rel_devplan.sql

@@ -0,0 +1,57 @@
+-- 设备维修计划表
+CREATE TABLE t_rel_devplan (
+  PLAN_ID NUMBER(20) NOT NULL,
+  PLANT VARCHAR2(100),
+  DEV_NAME VARCHAR2(200),
+  DEV_TAG VARCHAR2(100),
+  PLAN_TIME DATE,
+  APPROVAL_STATUS VARCHAR2(50),
+  RESPONSIBLE VARCHAR2(100),
+  COMPLETION_STATUS VARCHAR2(50),
+  PROCESS_ID VARCHAR2(100),
+  APPROVER VARCHAR2(100),
+  DEL_FLAG NUMBER(1) DEFAULT 0,
+  CREATER_CODE VARCHAR2(64),
+  CREATEDATE DATE,
+  UPDATER_CODE VARCHAR2(64),
+  UPDATEDATE DATE,
+  DEPT_ID NUMBER(20),
+  REMARKS VARCHAR2(500),
+  CONSTRAINT pk_t_rel_devplan PRIMARY KEY (PLAN_ID)
+);
+
+-- 添加表注释
+COMMENT ON TABLE t_rel_devplan IS '设备维修计划表';
+
+-- 添加字段注释
+COMMENT ON COLUMN t_rel_devplan.PLAN_ID IS '计划ID';
+COMMENT ON COLUMN t_rel_devplan.PLANT IS '装置';
+COMMENT ON COLUMN t_rel_devplan.DEV_NAME IS '设备名称';
+COMMENT ON COLUMN t_rel_devplan.DEV_TAG IS '设备位号';
+COMMENT ON COLUMN t_rel_devplan.PLAN_TIME IS '计划维修时间';
+COMMENT ON COLUMN t_rel_devplan.APPROVAL_STATUS IS '计划审批状态';
+COMMENT ON COLUMN t_rel_devplan.RESPONSIBLE IS '责任人';
+COMMENT ON COLUMN t_rel_devplan.COMPLETION_STATUS IS '计划完成状态';
+COMMENT ON COLUMN t_rel_devplan.PROCESS_ID IS '审批流程ID';
+COMMENT ON COLUMN t_rel_devplan.APPROVER IS '审批人';
+COMMENT ON COLUMN t_rel_devplan.DEL_FLAG IS '删除标志(0代表存在 2代表删除)';
+COMMENT ON COLUMN t_rel_devplan.CREATER_CODE IS '创建人';
+COMMENT ON COLUMN t_rel_devplan.CREATEDATE IS '创建时间';
+COMMENT ON COLUMN t_rel_devplan.UPDATER_CODE IS '修改人';
+COMMENT ON COLUMN t_rel_devplan.UPDATEDATE IS '修改时间';
+COMMENT ON COLUMN t_rel_devplan.DEPT_ID IS '部门编号';
+COMMENT ON COLUMN t_rel_devplan.REMARKS IS '备注';
+
+-- 创建序列
+CREATE SEQUENCE seq_t_rel_devplan
+  START WITH 1
+  INCREMENT BY 1
+  NOCACHE
+  NOCYCLE;
+
+-- 创建索引
+CREATE INDEX idx_devplan_dev_tag ON t_rel_devplan(DEV_TAG);
+CREATE INDEX idx_devplan_plan_time ON t_rel_devplan(PLAN_TIME);
+CREATE INDEX idx_devplan_approval_status ON t_rel_devplan(APPROVAL_STATUS);
+CREATE INDEX idx_devplan_responsible ON t_rel_devplan(RESPONSIBLE);
+CREATE INDEX idx_devplan_dept_id ON t_rel_devplan(DEPT_ID);

+ 24 - 9
master/src/main/java/com/ruoyi/common/sms/SmsService.java

@@ -9,10 +9,14 @@ import static com.aliyun.teautil.Common.toJSONString;
 
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Service
 public class SmsService {
 
+    private static final Logger logger = LoggerFactory.getLogger(SmsService.class);
+
     @Value("${aliyun.sms.accessKeyId}")
     private String accessKeyId;
 
@@ -32,6 +36,8 @@ public class SmsService {
      * @return 是否发送成功
      */
     public boolean sendSms(String phoneNumber, String code) throws Exception {
+        logger.info("开始发送短信验证码,手机号:{},验证码:{}", phoneNumber, code);
+        
         Config config = new Config()
                 // 配置 AccessKey ID,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
                 .setAccessKeyId(accessKeyId)
@@ -40,9 +46,11 @@ public class SmsService {
 
         // 配置 Endpoint
         config.endpoint = "dysmsapi.aliyuncs.com";
+        logger.debug("阿里云短信服务配置完成,Endpoint:{}", config.endpoint);
 
         // 初始化请求客户端
         Client client = new Client(config);
+        logger.debug("阿里云短信客户端初始化完成");
 
         // 构造请求对象,请填入请求参数值
         SendSmsRequest sendSmsRequest = new SendSmsRequest()
@@ -50,22 +58,29 @@ public class SmsService {
                 .setSignName(signName)
                 .setTemplateCode(templateCode)
                 .setTemplateParam("{\"code\":\"" + code + "\"}");
-
-
-
+        
+        logger.debug("短信请求参数构建完成,签名:{},模板:{}", signName, templateCode);
         try {
+            logger.info("正在调用阿里云短信API发送短信...");
             // 获取响应对象
             SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);
             // 响应包含服务端响应的 body 和 headers
-            System.out.println(toJSONString(sendSmsResponse));
-            return true;
+            logger.info("短信发送API响应:{}", toJSONString(sendSmsResponse));
+            
+            if (sendSmsResponse.getBody() != null && "OK".equals(sendSmsResponse.getBody().getCode())) {
+                logger.info("短信发送成功,手机号:{},验证码:{}", phoneNumber, code);
+                return true;
+            } else {
+                logger.error("短信发送失败,手机号:{},错误码:{},错误信息:{}", 
+                    phoneNumber, 
+                    sendSmsResponse.getBody() != null ? sendSmsResponse.getBody().getCode() : "未知",
+                    sendSmsResponse.getBody() != null ? sendSmsResponse.getBody().getMessage() : "未知错误");
+                return false;
+            }
         } catch (Exception e) {
-            e.printStackTrace();
-
+            logger.error("短信发送异常,手机号:{},异常信息:{}", phoneNumber, e.getMessage(), e);
             return false;
         }
 
-
-
     }
 }

+ 29 - 26
master/src/main/java/com/ruoyi/config/ActivitiConfig.java

@@ -109,9 +109,9 @@ public class ActivitiConfig {
 //        Resource accident = resourceLoader.getResource("classpath:/processes/accident.bpmn"); //加载流程图资源文件
 //        deploymentBuilder2.enableDuplicateFiltering().addInputStream(accident.getFilename(), accident.getInputStream()).name("事件审批流程").deploy();//按流程id部署
 //
-        DeploymentBuilder deploymentBuilder3 = repositoryService().createDeployment();
-        Resource spec = resourceLoader.getResource("classpath:/processes/MyProcess.bpmn"); //加载流程图资源文件
-        deploymentBuilder3.enableDuplicateFiltering().addInputStream(spec.getFilename(), spec.getInputStream()).name("特种设备审批流程").deploy();//按流程id部署
+//        DeploymentBuilder deploymentBuilder3 = repositoryService().createDeployment();
+//        Resource spec = resourceLoader.getResource("classpath:/processes/MyProcess.bpmn"); //加载流程图资源文件
+//        deploymentBuilder3.enableDuplicateFiltering().addInputStream(spec.getFilename(), spec.getInputStream()).name("特种设备审批流程").deploy();//按流程id部署
 
 //        DeploymentBuilder deploymentBuilder4 = repositoryService().createDeployment();
 //        Resource spec2 = resourceLoader.getResource("classpath:/processes/his/semsAddDelProcess.bpmn"); //加载流程图资源文件
@@ -161,29 +161,29 @@ public class ActivitiConfig {
 //        Resource spec15 = resourceLoader.getResource("classpath:/processes/sems/semsWeekcheck.bpmn"); //加载流程图资源文件
 //        deploymentBuilder15.enableDuplicateFiltering().addInputStream(spec15.getFilename(), spec15.getInputStream()).name("每周安全排查报告").deploy();//按流程id部署
 //
-        DeploymentBuilder deploymentBuilder16 = repositoryService().createDeployment();
-        Resource spec16 = resourceLoader.getResource("classpath:/processes/bccnew/dsdtTraining.bpmn"); //加载流程图资源文件
-        deploymentBuilder16.enableDuplicateFiltering().addInputStream(spec16.getFilename(), spec16.getInputStream()).name("导师带徒经理签字").deploy();//按流程id部署
-
-        DeploymentBuilder deploymentBuilder17 = repositoryService().createDeployment();
-        Resource spec17 = resourceLoader.getResource("classpath:/processes/bccnew/dsdtNoPass.bpmn"); //加载流程图资源文件
-        deploymentBuilder17.enableDuplicateFiltering().addInputStream(spec17.getFilename(), spec17.getInputStream()).name("导师带徒学员成绩不合格审批").deploy();//按流程id部署
-
-        DeploymentBuilder pssr1Db = repositoryService().createDeployment();
-        Resource pssr1 = resourceLoader.getResource("classpath:/processes/pssr/pssr1confirm.bpmn"); //加载流程图资源文件
-        pssr1Db.enableDuplicateFiltering().addInputStream(pssr1.getFilename(), pssr1.getInputStream()).name("PSSR单确认人确认流程").deploy();//按流程id部署
-
-        DeploymentBuilder pssr2Db = repositoryService().createDeployment();
-        Resource pssr2 = resourceLoader.getResource("classpath:/processes/pssr/pssr2confirm.bpmn"); //加载流程图资源文件
-        pssr2Db.enableDuplicateFiltering().addInputStream(pssr2.getFilename(), pssr2.getInputStream()).name("PSSR双确认人确认流程").deploy();//按流程id部署
-
-        DeploymentBuilder pssr3Db = repositoryService().createDeployment();
-        Resource pssr3 = resourceLoader.getResource("classpath:/processes/pssr/pssr3confirm.bpmn"); //加载流程图资源文件
-        pssr3Db.enableDuplicateFiltering().addInputStream(pssr3.getFilename(), pssr3.getInputStream()).name("PSSR三确认人确认流程").deploy();//按流程id部署
-
-        DeploymentBuilder pssrMgrDb = repositoryService().createDeployment();
-        Resource pssrMgr = resourceLoader.getResource("classpath:/processes/pssr/pssrMgrConfirm.bpmn"); //加载流程图资源文件
-        pssrMgrDb.enableDuplicateFiltering().addInputStream(pssrMgr.getFilename(), pssrMgr.getInputStream()).name("PSSR经理确认流程").deploy();//按流程id部署
+//        DeploymentBuilder deploymentBuilder16 = repositoryService().createDeployment();
+//        Resource spec16 = resourceLoader.getResource("classpath:/processes/bccnew/dsdtTraining.bpmn"); //加载流程图资源文件
+//        deploymentBuilder16.enableDuplicateFiltering().addInputStream(spec16.getFilename(), spec16.getInputStream()).name("导师带徒经理签字").deploy();//按流程id部署
+//
+//        DeploymentBuilder deploymentBuilder17 = repositoryService().createDeployment();
+//        Resource spec17 = resourceLoader.getResource("classpath:/processes/bccnew/dsdtNoPass.bpmn"); //加载流程图资源文件
+//        deploymentBuilder17.enableDuplicateFiltering().addInputStream(spec17.getFilename(), spec17.getInputStream()).name("导师带徒学员成绩不合格审批").deploy();//按流程id部署
+//
+//        DeploymentBuilder pssr1Db = repositoryService().createDeployment();
+//        Resource pssr1 = resourceLoader.getResource("classpath:/processes/pssr/pssr1confirm.bpmn"); //加载流程图资源文件
+//        pssr1Db.enableDuplicateFiltering().addInputStream(pssr1.getFilename(), pssr1.getInputStream()).name("PSSR单确认人确认流程").deploy();//按流程id部署
+//
+//        DeploymentBuilder pssr2Db = repositoryService().createDeployment();
+//        Resource pssr2 = resourceLoader.getResource("classpath:/processes/pssr/pssr2confirm.bpmn"); //加载流程图资源文件
+//        pssr2Db.enableDuplicateFiltering().addInputStream(pssr2.getFilename(), pssr2.getInputStream()).name("PSSR双确认人确认流程").deploy();//按流程id部署
+//
+//        DeploymentBuilder pssr3Db = repositoryService().createDeployment();
+//        Resource pssr3 = resourceLoader.getResource("classpath:/processes/pssr/pssr3confirm.bpmn"); //加载流程图资源文件
+//        pssr3Db.enableDuplicateFiltering().addInputStream(pssr3.getFilename(), pssr3.getInputStream()).name("PSSR三确认人确认流程").deploy();//按流程id部署
+//
+//        DeploymentBuilder pssrMgrDb = repositoryService().createDeployment();
+//        Resource pssrMgr = resourceLoader.getResource("classpath:/processes/pssr/pssrMgrConfirm.bpmn"); //加载流程图资源文件
+//        pssrMgrDb.enableDuplicateFiltering().addInputStream(pssrMgr.getFilename(), pssrMgr.getInputStream()).name("PSSR经理确认流程").deploy();//按流程id部署
 
         DeploymentBuilder deploymentBuilder18 = repositoryService().createDeployment();
         Resource spec18 = resourceLoader.getResource("classpath:/processes/eoegsai/eoegSaiApply.bpmn"); //加载流程图资源文件
@@ -197,6 +197,9 @@ public class ActivitiConfig {
         Resource spec20 = resourceLoader.getResource("classpath:/processes/eoeg/eoegLock.bpmn"); //加载流程图资源文件
         deploymentBuilder20.enableDuplicateFiltering().addInputStream(spec20.getFilename(), spec20.getInputStream()).name("EOEG锁开锁关申请流程").deploy();//按流程id部署
 
+        DeploymentBuilder deploymentBuilder21 = repositoryService().createDeployment();
+        Resource spec21 = resourceLoader.getResource("classpath:/processes/reliability/relMaintPlanProcess.bpmn"); //加载流程图资源文件
+        deploymentBuilder21.enableDuplicateFiltering().addInputStream(spec21.getFilename(), spec21.getInputStream()).name("可靠性设备维修计划申请").deploy();//按流程id部署
     }
 }
 

+ 6 - 0
master/src/main/java/com/ruoyi/project/common/CommonController.java

@@ -478,6 +478,12 @@ public class CommonController extends BaseController
         } else if( type.equals("maintenance") ) {
             downloadname = "CTM文档管理导入模板.xlsx";
             url = "static/template/ldpe/ldpe-maintenance.xlsx";
+        }else if( type.equals("rel_device") ) {
+            downloadname = "可靠性设备清单导入模板.xlsx";
+            url = "static/template/reliability/rel_device.xlsx";
+        }else if( type.equals("rel_compo") ) {
+            downloadname = "可靠性部件清单导入模板.xlsx";
+            url = "static/template/reliability/rel_compo.xlsx";
         }
 
         InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(url);

+ 19 - 5
master/src/main/java/com/ruoyi/project/production/controller/TFurnanceTemperatureController.java

@@ -2243,13 +2243,27 @@ public class TFurnanceTemperatureController extends BaseController
                 }
             }
 
-            // 添加预测点位
+            // 添加预测点位(只有当斜率不为负时才添加)
             Map<String, Object> predictPoint = new HashMap<>();
             if (!"-".equals(predictedDate)) {
-                predictPoint.put("date", predictedDate);
-                predictPoint.put("value", 1080);
-                predictPoint.put("day", chartData.size() + 1); // 预测点位的天数
-                chartData.add(predictPoint);
+                // 判断斜率是否为负数
+                boolean shouldAddPredictPoint = true;
+                try {
+                    double slopeValue = Double.parseDouble(slope);
+                    if (slopeValue < 0) {
+                        shouldAddPredictPoint = false;
+                    }
+                } catch (Exception e) {
+                    // 如果解析斜率失败,仍然添加预测点
+                    shouldAddPredictPoint = true;
+                }
+
+                if (shouldAddPredictPoint) {
+                    predictPoint.put("date", predictedDate);
+                    predictPoint.put("value", 1080);
+                    predictPoint.put("day", chartData.size() + 1); // 预测点位的天数
+                    chartData.add(predictPoint);
+                }
             }
 
             Map<String, Object> result = new HashMap<>();

+ 146 - 8
master/src/main/java/com/ruoyi/project/reliability/controller/TRelCompoController.java

@@ -1,16 +1,16 @@
 package com.ruoyi.project.reliability.controller;
 
 import java.util.List;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.common.utils.file.ExcelUtils;
+import org.apache.poi.ss.usermodel.*;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.project.reliability.domain.TRelCompo;
@@ -19,6 +19,9 @@ import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.common.utils.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.project.system.service.ISysUserService;
 
 /**
  * 可靠性部件清单Controller
@@ -33,6 +36,9 @@ public class TRelCompoController extends BaseController
     @Autowired
     private ITRelCompoService tRelCompoService;
 
+    @Autowired
+    private ISysUserService userService;
+
     /**
      * 查询可靠性部件清单列表
      */
@@ -100,4 +106,136 @@ public class TRelCompoController extends BaseController
     {
         return toAjax(tRelCompoService.deleteTRelCompoByIds(compoIds));
     }
+
+    /**
+     * 下载可靠性部件清单模板
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_compo:import')")
+    @PostMapping("/importTemplate")
+    public AjaxResult importTemplate()
+    {
+        ExcelUtil<TRelCompo> util = new ExcelUtil<TRelCompo>(TRelCompo.class);
+        return util.importTemplateExcel("可靠性部件清单数据");
+    }
+
+    /**
+     * 批量导入可靠性部件清单
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_compo:add')")
+    @Log(title = "可靠性部件清单", businessType = BusinessType.IMPORT)
+    @PostMapping("/importData")
+    public AjaxResult importData(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", defaultValue = "0") String updateSupport) throws IOException
+    {
+        // 获取操作人员ID
+        Long userId = getUserId();
+        // 报错行数统计
+        List<Integer> failRow = new ArrayList<Integer>();
+        Workbook workbook = ExcelUtils.getWorkBook(file);
+        Sheet sheet = workbook.getSheetAt(0);
+        List<TRelCompo> list = new ArrayList<TRelCompo>();
+        int rowNum = sheet.getPhysicalNumberOfRows();
+        int failNumber = 0;
+        int successNumber = 0;
+
+        for (int i = 1; i < rowNum; i++) {
+            try {
+                logger.info("读取行数:" + i);
+                Row row = sheet.getRow(i);
+                if (row == null) continue;
+
+                TRelCompo entity = new TRelCompo();
+                
+                int cellNum = row.getPhysicalNumberOfCells();
+                for (int j = 0; j < cellNum; j++) {
+                    Cell cell = row.getCell(j);
+                    String cellValue = ExcelUtils.getCellValueText(cell);
+                    logger.info("cellValue[" + j + "]:" + cellValue);
+
+                    if (StringUtils.isEmpty(cellValue)) continue;
+
+                    // 根据列索引设置字段值(Excel列 -> 实体属性)
+                    // 第0列: 装置 -> plant
+                    // 第1列: 位置 -> devLoc
+                    // 第2列: 设备位号 -> devTag
+                    // 第3列: 部件名称 -> compoName
+                    // 第4列: 部件型号 -> compoModel
+                    // 第5列: 测厚点 -> thicknessPt
+                    // 第6列: 部件描述 -> compoDesc
+                    // 第7列: 检查人 -> inspector
+                    // 第8列: 维修更换人 -> fixer
+                    // 第9列: 检查频率 -> inspFreq
+                    // 第10列: 检查内容 -> inspContent
+                    // 第11列: 维修频率 -> fixFreq
+                    // 第12列: 维修内容 -> fixContent
+                    // 第13列: 更换频率 -> replaceFreq
+                    // 第14列: 更换内容 -> replaceContent
+                    // 第15列: 备注 -> remarks
+                    switch (j) {
+                        case 0: entity.setPlant(cellValue); break;                              // 装置
+                        case 1: entity.setDevLoc(cellValue); break;                            // 位置
+                        case 2: entity.setDevTag(cellValue); break;                            // 设备位号
+                        case 3: entity.setCompoName(cellValue); break;                         // 部件名称
+                        case 4: entity.setCompoModel(cellValue); break;                         // 部件型号
+                        case 5: entity.setThicknessPt(cellValue); break;                        // 测厚点
+                        case 6: entity.setCompoDesc(cellValue); break;                          // 部件描述
+                        case 7: entity.setInspector(cellValue); break;                          // 检查人
+                        case 8: entity.setFixer(cellValue); break;                              // 维修更换人
+                        case 9: entity.setInspFreq(cellValue); break;                           // 检查频率
+                        case 10: entity.setInspContent(cellValue); break;                       // 检查内容
+                        case 11: entity.setFixFreq(cellValue); break;                          // 维修频率
+                        case 12: entity.setFixContent(cellValue); break;                        // 维修内容
+                        case 13: entity.setReplaceFreq(cellValue); break;                      // 更换频率
+                        case 14: entity.setReplaceContent(cellValue); break;                   // 更换内容
+                        case 15: entity.setRemarks(cellValue); break;                          // 备注
+                    }
+                }
+
+                // 根据装置判断部门ID:如果plant是BCC,则deptId为103,否则使用当前用户的部门ID
+                if ("BCC".equalsIgnoreCase(entity.getPlant())) {
+                    entity.setDeptId(103L);
+                } else {
+                    entity.setDeptId(userService.selectUserById(userId).getDeptId());
+                }
+                
+                entity.setCreaterCode(userId.toString());
+                entity.setCreatedate(new Date());
+                entity.setDelFlag(0L);
+
+                logger.info("entity:" + entity);
+                list.add(entity);
+            } catch (Exception e) {
+                failNumber++;
+                failRow.add(i + 1);
+                logger.error("第" + (i + 1) + "行数据导入失败:", e);
+            }
+        }
+
+        // 批量保存数据
+        for (TRelCompo item : list) {
+            try {
+                // 根据设备位号和部件名称查询是否存在
+                TRelCompo query = new TRelCompo();
+                query.setDevTag(item.getDevTag());
+                query.setCompoName(item.getCompoName());
+                List<TRelCompo> existList = tRelCompoService.selectTRelCompoList(query);
+                if (existList != null && !existList.isEmpty()) {
+                    item.setCompoId(existList.get(0).getCompoId());
+                    tRelCompoService.updateTRelCompo(item);
+                } else {
+                    tRelCompoService.insertTRelCompo(item);
+                }
+                successNumber++;
+            } catch (Exception e) {
+                failNumber++;
+                logger.error("数据保存失败:", e);
+            }
+        }
+
+        logger.info("导入成功行数:" + successNumber + ",失败行数:" + failNumber);
+        if (failRow.size() > 0) {
+            logger.info("失败行号:" + JSON.toJSONString(failRow));
+        }
+
+        return AjaxResult.success("导入成功行数:" + successNumber + ",失败行数:" + failNumber);
+    }
 }

+ 132 - 8
master/src/main/java/com/ruoyi/project/reliability/controller/TRelDeviceController.java

@@ -1,16 +1,17 @@
 package com.ruoyi.project.reliability.controller;
 
 import java.util.List;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.common.utils.file.ExcelUtils;
+import org.apache.poi.ss.usermodel.*;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.project.reliability.domain.TRelDevice;
@@ -19,6 +20,9 @@ import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.common.utils.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.project.system.service.ISysUserService;
 
 /**
  * 可靠性设备清单Controller
@@ -33,6 +37,9 @@ public class TRelDeviceController extends BaseController
     @Autowired
     private ITRelDeviceService tRelDeviceService;
 
+    @Autowired
+    private ISysUserService userService;
+
     /**
      * 查询可靠性设备清单列表
      */
@@ -100,4 +107,121 @@ public class TRelDeviceController extends BaseController
     {
         return toAjax(tRelDeviceService.deleteTRelDeviceByIds(devIds));
     }
+
+    /**
+     * 下载可靠性设备清单模板
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_device:import')")
+    @PostMapping("/importTemplate")
+    public AjaxResult importTemplate()
+    {
+        ExcelUtil<TRelDevice> util = new ExcelUtil<TRelDevice>(TRelDevice.class);
+        return util.importTemplateExcel("可靠性设备清单数据");
+    }
+
+    /**
+     * 批量导入可靠性设备清单
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_device:add')")
+    @Log(title = "可靠性设备清单", businessType = BusinessType.IMPORT)
+    @PostMapping("/importData")
+    public AjaxResult importData(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", defaultValue = "0") String updateSupport) throws IOException
+    {
+        // 获取操作人员ID
+        Long userId = getUserId();
+        // 报错行数统计
+        List<Integer> failRow = new ArrayList<Integer>();
+        Workbook workbook = ExcelUtils.getWorkBook(file);
+        Sheet sheet = workbook.getSheetAt(0);
+        List<TRelDevice> list = new ArrayList<TRelDevice>();
+        int rowNum = sheet.getPhysicalNumberOfRows();
+        int failNumber = 0;
+        int successNumber = 0;
+
+        for (int i = 1; i < rowNum; i++) {
+            try {
+                logger.info("读取行数:" + i);
+                Row row = sheet.getRow(i);
+                if (row == null) continue;
+
+                TRelDevice entity = new TRelDevice();
+                
+                int cellNum = row.getPhysicalNumberOfCells();
+                for (int j = 0; j < cellNum; j++) {
+                    Cell cell = row.getCell(j);
+                    String cellValue = ExcelUtils.getCellValueText(cell);
+                    logger.info("cellValue[" + j + "]:" + cellValue);
+
+                    if (StringUtils.isEmpty(cellValue)) continue;
+
+                    // 根据列索引设置字段值(Excel列 -> 实体属性)
+                    // 第0列: 装置 -> plant
+                    // 第1列: 位置 -> devLoc
+                    // 第2列: 设备名称 -> devName
+                    // 第3列: 设备位号 -> devTag
+                    // 第4列: 设备类型 -> devType
+                    // 第5列: 设备描述 -> devDesc
+                    // 第6列: 区域 -> devArea
+                    // 第7列: 区域负责人 -> areaResponsible
+                    // 第8列: 备注 -> remarks
+                    switch (j) {
+                        case 0: entity.setPlant(cellValue); break;           // 装置
+                        case 1: entity.setDevLoc(cellValue); break;          // 位置
+                        case 2: entity.setDevName(cellValue); break;         // 设备名称
+                        case 3: entity.setDevTag(cellValue); break;          // 设备位号
+                        case 4: entity.setDevType(cellValue); break;         // 设备类型
+                        case 5: entity.setDevDesc(cellValue); break;         // 设备描述
+                        case 6: entity.setDevArea(cellValue); break;         // 区域
+                        case 7: entity.setAreaResponsible(cellValue); break; // 区域负责人
+                        case 8: entity.setRemarks(cellValue); break;         // 备注
+                    }
+                }
+
+                // 根据装置判断部门ID:如果plant是BCC,则deptId为103,否则使用当前用户的部门ID
+                if ("BCC".equalsIgnoreCase(entity.getPlant())) {
+                    entity.setDeptId(103L);
+                } else {
+                    entity.setDeptId(userService.selectUserById(userId).getDeptId());
+                }
+                
+                entity.setCreaterCode(userId.toString());
+                entity.setCreatedate(new Date());
+                entity.setDelFlag(0L);
+
+                logger.info("entity:" + entity);
+                list.add(entity);
+            } catch (Exception e) {
+                failNumber++;
+                failRow.add(i + 1);
+                logger.error("第" + (i + 1) + "行数据导入失败:", e);
+            }
+        }
+
+        // 批量保存数据
+        for (TRelDevice item : list) {
+            try {
+                // 根据设备位号查询是否存在
+                TRelDevice query = new TRelDevice();
+                query.setDevTag(item.getDevTag());
+                List<TRelDevice> existList = tRelDeviceService.selectTRelDeviceList(query);
+                if (existList != null && !existList.isEmpty()) {
+                    item.setDevId(existList.get(0).getDevId());
+                    tRelDeviceService.updateTRelDevice(item);
+                } else {
+                    tRelDeviceService.insertTRelDevice(item);
+                }
+                successNumber++;
+            } catch (Exception e) {
+                failNumber++;
+                logger.error("数据保存失败:", e);
+            }
+        }
+
+        logger.info("导入成功行数:" + successNumber + ",失败行数:" + failNumber);
+        if (failRow.size() > 0) {
+            logger.info("失败行号:" + JSON.toJSONString(failRow));
+        }
+
+        return AjaxResult.success("导入成功行数:" + successNumber + ",失败行数:" + failNumber);
+    }
 }

+ 241 - 0
master/src/main/java/com/ruoyi/project/reliability/controller/TRelMaintPlanController.java

@@ -0,0 +1,241 @@
+package com.ruoyi.project.reliability.controller;
+
+import java.util.*;
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.project.system.domain.SysMessage;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.project.system.service.ISysMessageService;
+import org.activiti.engine.*;
+import org.activiti.engine.impl.identity.Authentication;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.project.reliability.domain.TRelMaintPlan;
+import com.ruoyi.project.reliability.domain.TRelMaintRecord;
+import com.ruoyi.project.reliability.service.ITRelMaintPlanService;
+import com.ruoyi.project.reliability.service.ITRelMaintRecordService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.page.TableDataInfo;
+
+/**
+ * 设备维修计划Controller
+ *
+ * @author ly
+ * @date 2025-10-28
+ */
+@RestController
+@RequestMapping("/reliability/rel_maint_plan")
+public class TRelMaintPlanController extends BaseController
+{
+    private static final Logger logger = LoggerFactory.getLogger(TRelMaintPlanController.class);
+
+    @Autowired
+    private ITRelMaintPlanService tRelMaintPlanService;
+
+    @Autowired
+    private ISysMessageService sysMessageService;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    @Autowired
+    private ITRelMaintRecordService tRelMaintRecordService;
+
+    @Autowired
+    private RuntimeService runtimeService;
+
+    /**
+     * 查询设备维修计划列表
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_plan:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TRelMaintPlan tRelMaintPlan)
+    {
+        startPage();
+        List<TRelMaintPlan> list = tRelMaintPlanService.selectTRelMaintPlanList(tRelMaintPlan);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出设备维修计划列表
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_plan:list')")
+    @Log(title = "设备维修计划", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TRelMaintPlan tRelMaintPlan)
+    {
+        List<TRelMaintPlan> list = tRelMaintPlanService.selectTRelMaintPlanList(tRelMaintPlan);
+        ExcelUtil<TRelMaintPlan> util = new ExcelUtil<TRelMaintPlan>(TRelMaintPlan.class);
+        return util.exportExcel(list, "rel_maint_plan");
+    }
+
+    /**
+     * 获取设备维修计划详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_plan:query')")
+    @GetMapping(value = "/{planId}")
+    public AjaxResult getInfo(@PathVariable("planId") Long planId)
+    {
+        return AjaxResult.success(tRelMaintPlanService.selectTRelMaintPlanById(planId));
+    }
+
+    /**
+     * 新增设备维修计划
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_plan:add')")
+    @Log(title = "设备维修计划", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TRelMaintPlan tRelMaintPlan)
+    {
+        return toAjax(tRelMaintPlanService.insertTRelMaintPlan(tRelMaintPlan));
+    }
+
+    /**
+     * 提交维修计划申请(启动审批流程)
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_plan:add')")
+    @Log(title = "维修计划申请", businessType = BusinessType.INSERT)
+    @PostMapping("/submitApprove")
+    public AjaxResult submitApprove(@RequestBody TRelMaintPlan tRelMaintPlan)
+    {
+        try {
+            logger.info("维修计划申请" + JSON.toJSONString(tRelMaintPlan));
+            logger.info("维修部件数量: " + (tRelMaintPlan.getMaintComponents() != null ? tRelMaintPlan.getMaintComponents().size() : 0));
+
+            Long userId = getUserId();
+
+            // 设置基础信息
+            tRelMaintPlan.setCreaterCode(userId.toString());
+            tRelMaintPlan.setApprovalStatus("0"); // 待审批
+            tRelMaintPlan.setCompletionStatus("0"); // 未完成
+
+            // 先保存维修计划
+            tRelMaintPlanService.insertTRelMaintPlan(tRelMaintPlan);
+
+            // 生成审批编号(备用)
+            // Date dt = new Date();
+            // SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+            // String apNo = sdf.format(dt) + userId;
+
+            // 设置流程变量
+            Map<String, Object> variables = new HashMap<>();
+            variables.put("zzjlusers", tRelMaintPlan.getApprover());
+
+            long businessKey = tRelMaintPlan.getPlanId();
+            logger.info("businessKey:" + businessKey);
+            Authentication.setAuthenticatedUserId(userId.toString());
+
+            // 启动审批流程
+            ProcessInstance pi = runtimeService.startProcessInstanceByKey("relMaintPlanProcess", String.valueOf(businessKey), variables);
+            logger.info("流程部署id:" + pi.getDeploymentId());
+            logger.info("流程定义id:" + pi.getProcessDefinitionId());
+            logger.info("流程实例id:" + pi.getProcessInstanceId());
+            logger.info("流程定义对象:" + pi.getProcessVariables());
+
+            // 更新流程ID
+            tRelMaintPlan.setProcessId(pi.getProcessInstanceId());
+            tRelMaintPlanService.updateTRelMaintPlan(tRelMaintPlan);
+
+            // 处理部件维修记录
+            if (tRelMaintPlan.getMaintComponents() != null && !tRelMaintPlan.getMaintComponents().isEmpty()) {
+                processMaintComponents(tRelMaintPlan.getPlanId(), tRelMaintPlan.getMaintComponents(), tRelMaintPlan);
+            }
+
+            // 发送邮件通知审批人
+            try {
+                SysMessage message = new SysMessage();
+                String email = sysUserMapper.selectUserById(Long.parseLong(tRelMaintPlan.getApprover())).getEmail();
+                String username = sysUserMapper.selectUserById(Long.parseLong(tRelMaintPlan.getApprover())).getNickName();
+
+                logger.info("email:" + email);
+                logger.info("username:" + username);
+
+                message.setUserId(Long.parseLong(tRelMaintPlan.getApprover()));
+                message.setMsgTitle("您有一条维修计划待审核");
+                message.setMsgContent("您有一条维修计划待审核,请及时处理");
+
+                // 发送邮件(这里可以复用现有的邮件发送逻辑)
+                // PlanApproveMailThread sendEmailThread = new PlanApproveMailThread(email, apNo, username, usernameEN, mailService, tRelMaintPlan, sysMessageService, message, "0");
+                // Thread t = new Thread(sendEmailThread);
+                // t.start();
+
+                // 保存系统消息
+                sysMessageService.insertSysMessage(message);
+
+            } catch (Exception e) {
+                logger.error("邮件发送失败" + JSON.toJSONString(e));
+            }
+
+            return AjaxResult.success("维修计划申请提交成功");
+
+        } catch (Exception e) {
+            logger.error("维修计划申请失败", e);
+            return AjaxResult.error("维修计划申请失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 修改设备维修计划
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_plan:edit')")
+    @Log(title = "设备维修计划", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TRelMaintPlan tRelMaintPlan)
+    {
+        return toAjax(tRelMaintPlanService.updateTRelMaintPlan(tRelMaintPlan));
+    }
+
+    /**
+     * 删除设备维修计划
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_plan:remove')")
+    @Log(title = "设备维修计划", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{planIds}")
+    public AjaxResult remove(@PathVariable Long[] planIds)
+    {
+        return toAjax(tRelMaintPlanService.deleteTRelMaintPlanByIds(planIds));
+    }
+
+    /**
+     * 处理部件维修记录
+     */
+    private void processMaintComponents(Long planId, List<TRelMaintRecord> maintComponents, TRelMaintPlan tRelMaintPlan) {
+        try {
+            logger.info("开始处理维修部件,数量: " + maintComponents.size());
+            Date now = new Date();
+            for (TRelMaintRecord maintRecord : maintComponents) {
+                logger.info("处理部件: " + maintRecord.getCompoName() + ", 维修类型: " + maintRecord.getMaintType());
+                
+                // 设置基本信息
+                maintRecord.setPlant(tRelMaintPlan.getPlant());
+                maintRecord.setDevName(tRelMaintPlan.getDevName());
+                maintRecord.setDevTag(tRelMaintPlan.getDevTag());
+                
+                // 设置创建信息
+                maintRecord.setCreaterCode(tRelMaintPlan.getCreaterCode());
+                maintRecord.setCreatedate(now);
+                
+                // 保存维修记录
+                int result = tRelMaintRecordService.insertTRelMaintRecord(maintRecord);
+                logger.info("保存维修记录结果: " + result + ", 部件: " + maintRecord.getCompoName());
+            }
+            logger.info("完成处理维修部件");
+        } catch (Exception e) {
+            logger.error("处理部件维修记录失败", e);
+        }
+    }
+}

+ 103 - 0
master/src/main/java/com/ruoyi/project/reliability/controller/TRelMaintRecordController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.project.reliability.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.project.reliability.domain.TRelMaintRecord;
+import com.ruoyi.project.reliability.service.ITRelMaintRecordService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.page.TableDataInfo;
+
+/**
+ * 部件维修记录Controller
+ *
+ * @author ssy
+ * @date 2025-10-28
+ */
+@RestController
+@RequestMapping("/reliability/rel_maint_record")
+public class TRelMaintRecordController extends BaseController
+{
+    @Autowired
+    private ITRelMaintRecordService tRelMaintRecordService;
+
+    /**
+     * 查询部件维修记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_record:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TRelMaintRecord tRelMaintRecord)
+    {
+        startPage();
+        List<TRelMaintRecord> list = tRelMaintRecordService.selectTRelMaintRecordList(tRelMaintRecord);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出部件维修记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_record:list')")
+    @Log(title = "部件维修记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TRelMaintRecord tRelMaintRecord)
+    {
+        List<TRelMaintRecord> list = tRelMaintRecordService.selectTRelMaintRecordList(tRelMaintRecord);
+        ExcelUtil<TRelMaintRecord> util = new ExcelUtil<TRelMaintRecord>(TRelMaintRecord.class);
+        return util.exportExcel(list, "rel_maint_record");
+    }
+
+    /**
+     * 获取部件维修记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_record:query')")
+    @GetMapping(value = "/{recordId}")
+    public AjaxResult getInfo(@PathVariable("recordId") Long recordId)
+    {
+        return AjaxResult.success(tRelMaintRecordService.selectTRelMaintRecordById(recordId));
+    }
+
+    /**
+     * 新增部件维修记录
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_record:add')")
+    @Log(title = "部件维修记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TRelMaintRecord tRelMaintRecord)
+    {
+        return toAjax(tRelMaintRecordService.insertTRelMaintRecord(tRelMaintRecord));
+    }
+
+    /**
+     * 修改部件维修记录
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_record:edit')")
+    @Log(title = "部件维修记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TRelMaintRecord tRelMaintRecord)
+    {
+        return toAjax(tRelMaintRecordService.updateTRelMaintRecord(tRelMaintRecord));
+    }
+
+    /**
+     * 删除部件维修记录
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_record:remove')")
+    @Log(title = "部件维修记录", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{recordIds}")
+    public AjaxResult remove(@PathVariable Long[] recordIds)
+    {
+        return toAjax(tRelMaintRecordService.deleteTRelMaintRecordByIds(recordIds));
+    }
+}

+ 279 - 0
master/src/main/java/com/ruoyi/project/reliability/domain/TRelMaintPlan.java

@@ -0,0 +1,279 @@
+package com.ruoyi.project.reliability.domain;
+
+import java.util.Date;
+import java.util.List;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 设备维修计划对象 t_rel_maint_plan
+ *
+ * @author ly
+ * @date 2025-10-28
+ */
+public class TRelMaintPlan extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 计划ID */
+    private Long planId;
+
+    /** 装置 */
+    @Excel(name = "装置")
+    private String plant;
+
+    /** 设备名称 */
+    @Excel(name = "设备名称")
+    private String devName;
+
+    /** 设备位号 */
+    @Excel(name = "设备位号")
+    private String devTag;
+
+    /** 计划维修时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "计划维修时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date planTime;
+
+    /** 计划审批状态 */
+    @Excel(name = "计划审批状态")
+    private String approvalStatus;
+
+    /** 责任人 */
+    @Excel(name = "责任人")
+    private String responsible;
+
+    /** 计划完成状态 */
+    @Excel(name = "计划完成状态")
+    private String completionStatus;
+
+    /** 审批流程ID */
+    @Excel(name = "审批流程ID")
+    private String processId;
+
+    /** 审批人 */
+    @Excel(name = "审批人")
+    private String approver;
+
+    /** 删除标志(0代表存在 2代表删除) */
+    private Long delFlag;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createrCode;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdate;
+
+    /** 修改人 */
+    @Excel(name = "修改人")
+    private String updaterCode;
+
+    /** 修改时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedate;
+
+    /** 部门编号 */
+    @Excel(name = "部门编号")
+    private Long deptId;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    /** 维修部件列表(用于接收前端传递的部件数据,不存储到数据库) */
+    private List<TRelMaintRecord> maintComponents;
+
+    public void setPlanId(Long planId)
+    {
+        this.planId = planId;
+    }
+
+    public Long getPlanId()
+    {
+        return planId;
+    }
+    public void setPlant(String plant)
+    {
+        this.plant = plant;
+    }
+
+    public String getPlant()
+    {
+        return plant;
+    }
+    public void setDevName(String devName)
+    {
+        this.devName = devName;
+    }
+
+    public String getDevName()
+    {
+        return devName;
+    }
+    public void setDevTag(String devTag)
+    {
+        this.devTag = devTag;
+    }
+
+    public String getDevTag()
+    {
+        return devTag;
+    }
+    public void setPlanTime(Date planTime)
+    {
+        this.planTime = planTime;
+    }
+
+    public Date getPlanTime()
+    {
+        return planTime;
+    }
+    public void setApprovalStatus(String approvalStatus)
+    {
+        this.approvalStatus = approvalStatus;
+    }
+
+    public String getApprovalStatus()
+    {
+        return approvalStatus;
+    }
+    public void setResponsible(String responsible)
+    {
+        this.responsible = responsible;
+    }
+
+    public String getResponsible()
+    {
+        return responsible;
+    }
+    public void setCompletionStatus(String completionStatus)
+    {
+        this.completionStatus = completionStatus;
+    }
+
+    public String getCompletionStatus()
+    {
+        return completionStatus;
+    }
+    public void setProcessId(String processId)
+    {
+        this.processId = processId;
+    }
+
+    public String getProcessId()
+    {
+        return processId;
+    }
+    public void setApprover(String approver)
+    {
+        this.approver = approver;
+    }
+
+    public String getApprover()
+    {
+        return approver;
+    }
+    public void setDelFlag(Long delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setCreaterCode(String createrCode)
+    {
+        this.createrCode = createrCode;
+    }
+
+    public String getCreaterCode()
+    {
+        return createrCode;
+    }
+    public void setCreatedate(Date createdate)
+    {
+        this.createdate = createdate;
+    }
+
+    public Date getCreatedate()
+    {
+        return createdate;
+    }
+    public void setUpdaterCode(String updaterCode)
+    {
+        this.updaterCode = updaterCode;
+    }
+
+    public String getUpdaterCode()
+    {
+        return updaterCode;
+    }
+    public void setUpdatedate(Date updatedate)
+    {
+        this.updatedate = updatedate;
+    }
+
+    public Date getUpdatedate()
+    {
+        return updatedate;
+    }
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    public void setMaintComponents(List<TRelMaintRecord> maintComponents)
+    {
+        this.maintComponents = maintComponents;
+    }
+
+    public List<TRelMaintRecord> getMaintComponents()
+    {
+        return maintComponents;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("planId", getPlanId())
+            .append("plant", getPlant())
+            .append("devName", getDevName())
+            .append("devTag", getDevTag())
+            .append("planTime", getPlanTime())
+            .append("approvalStatus", getApprovalStatus())
+            .append("responsible", getResponsible())
+            .append("completionStatus", getCompletionStatus())
+            .append("processId", getProcessId())
+            .append("approver", getApprover())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}

+ 392 - 0
master/src/main/java/com/ruoyi/project/reliability/domain/TRelMaintRecord.java

@@ -0,0 +1,392 @@
+package com.ruoyi.project.reliability.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 部件维修记录对象 t_rel_maint_record
+ *
+ * @author ssy
+ * @date 2025-10-28
+ */
+public class TRelMaintRecord extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 记录ID */
+    private Long recordId;
+
+    /** 装置 */
+    @Excel(name = "装置")
+    private String plant;
+
+    /** 设备名称 */
+    @Excel(name = "设备名称")
+    private String devName;
+
+    /** 设备位号 */
+    @Excel(name = "设备位号")
+    private String devTag;
+
+    /** 部件名称 */
+    @Excel(name = "部件名称")
+    private String compoName;
+
+    /** 部件ID */
+    @Excel(name = "部件ID")
+    private String compoId;
+
+    /** 维修类型 */
+    @Excel(name = "维修类型")
+    private String maintType;
+
+    /** 维修部门 */
+    @Excel(name = "维修部门")
+    private String maintDept;
+
+    /** 检查人 */
+    @Excel(name = "检查人")
+    private String inspector;
+
+    /** 检查内容 */
+    @Excel(name = "检查内容")
+    private String inspectContent;
+
+    /** 检查时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "检查时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date inspectTime;
+
+    /** 维修责任人 */
+    @Excel(name = "维修责任人")
+    private String responsible;
+
+    /** 维修内容 */
+    @Excel(name = "维修内容")
+    private String maintContent;
+
+    /** 维修结果 */
+    @Excel(name = "维修结果")
+    private String maintResult;
+
+    /** 维修时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "维修时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date maintTime;
+
+    /** 维修费用 */
+    @Excel(name = "维修费用")
+    private Long maintCost;
+
+    /** 维修时长 */
+    @Excel(name = "维修时长")
+    private Long maintDuration;
+
+    /** 工艺损失 */
+    @Excel(name = "工艺损失")
+    private String processLoss;
+
+    /** 附件 */
+    @Excel(name = "附件")
+    private String attachments;
+
+    /** 删除标志(0代表存在 2代表删除) */
+    private Long delFlag;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createrCode;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdate;
+
+    /** 修改人 */
+    @Excel(name = "修改人")
+    private String updaterCode;
+
+    /** 修改时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedate;
+
+    /** 部门编号 */
+    @Excel(name = "部门编号")
+    private Long deptId;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    public void setRecordId(Long recordId)
+    {
+        this.recordId = recordId;
+    }
+
+    public Long getRecordId()
+    {
+        return recordId;
+    }
+    public void setPlant(String plant)
+    {
+        this.plant = plant;
+    }
+
+    public String getPlant()
+    {
+        return plant;
+    }
+    public void setDevName(String devName)
+    {
+        this.devName = devName;
+    }
+
+    public String getDevName()
+    {
+        return devName;
+    }
+    public void setDevTag(String devTag)
+    {
+        this.devTag = devTag;
+    }
+
+    public String getDevTag()
+    {
+        return devTag;
+    }
+    public void setCompoName(String compoName)
+    {
+        this.compoName = compoName;
+    }
+
+    public String getCompoName()
+    {
+        return compoName;
+    }
+    public void setCompoId(String compoId)
+    {
+        this.compoId = compoId;
+    }
+
+    public String getCompoId()
+    {
+        return compoId;
+    }
+    public void setMaintType(String maintType)
+    {
+        this.maintType = maintType;
+    }
+
+    public String getMaintType()
+    {
+        return maintType;
+    }
+    public void setMaintDept(String maintDept)
+    {
+        this.maintDept = maintDept;
+    }
+
+    public String getMaintDept()
+    {
+        return maintDept;
+    }
+    public void setInspector(String inspector)
+    {
+        this.inspector = inspector;
+    }
+
+    public String getInspector()
+    {
+        return inspector;
+    }
+    public void setInspectContent(String inspectContent)
+    {
+        this.inspectContent = inspectContent;
+    }
+
+    public String getInspectContent()
+    {
+        return inspectContent;
+    }
+    public void setInspectTime(Date inspectTime)
+    {
+        this.inspectTime = inspectTime;
+    }
+
+    public Date getInspectTime()
+    {
+        return inspectTime;
+    }
+    public void setResponsible(String responsible)
+    {
+        this.responsible = responsible;
+    }
+
+    public String getResponsible()
+    {
+        return responsible;
+    }
+    public void setMaintContent(String maintContent)
+    {
+        this.maintContent = maintContent;
+    }
+
+    public String getMaintContent()
+    {
+        return maintContent;
+    }
+    public void setMaintResult(String maintResult)
+    {
+        this.maintResult = maintResult;
+    }
+
+    public String getMaintResult()
+    {
+        return maintResult;
+    }
+    public void setMaintTime(Date maintTime)
+    {
+        this.maintTime = maintTime;
+    }
+
+    public Date getMaintTime()
+    {
+        return maintTime;
+    }
+    public void setMaintCost(Long maintCost)
+    {
+        this.maintCost = maintCost;
+    }
+
+    public Long getMaintCost()
+    {
+        return maintCost;
+    }
+    public void setMaintDuration(Long maintDuration)
+    {
+        this.maintDuration = maintDuration;
+    }
+
+    public Long getMaintDuration()
+    {
+        return maintDuration;
+    }
+    public void setProcessLoss(String processLoss)
+    {
+        this.processLoss = processLoss;
+    }
+
+    public String getProcessLoss()
+    {
+        return processLoss;
+    }
+    public void setAttachments(String attachments)
+    {
+        this.attachments = attachments;
+    }
+
+    public String getAttachments()
+    {
+        return attachments;
+    }
+    public void setDelFlag(Long delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setCreaterCode(String createrCode)
+    {
+        this.createrCode = createrCode;
+    }
+
+    public String getCreaterCode()
+    {
+        return createrCode;
+    }
+    public void setCreatedate(Date createdate)
+    {
+        this.createdate = createdate;
+    }
+
+    public Date getCreatedate()
+    {
+        return createdate;
+    }
+    public void setUpdaterCode(String updaterCode)
+    {
+        this.updaterCode = updaterCode;
+    }
+
+    public String getUpdaterCode()
+    {
+        return updaterCode;
+    }
+    public void setUpdatedate(Date updatedate)
+    {
+        this.updatedate = updatedate;
+    }
+
+    public Date getUpdatedate()
+    {
+        return updatedate;
+    }
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("recordId", getRecordId())
+            .append("plant", getPlant())
+            .append("devName", getDevName())
+            .append("devTag", getDevTag())
+            .append("compoName", getCompoName())
+            .append("compoId", getCompoId())
+            .append("maintType", getMaintType())
+            .append("maintDept", getMaintDept())
+            .append("inspector", getInspector())
+            .append("inspectContent", getInspectContent())
+            .append("inspectTime", getInspectTime())
+            .append("responsible", getResponsible())
+            .append("maintContent", getMaintContent())
+            .append("maintResult", getMaintResult())
+            .append("maintTime", getMaintTime())
+            .append("maintCost", getMaintCost())
+            .append("maintDuration", getMaintDuration())
+            .append("processLoss", getProcessLoss())
+            .append("attachments", getAttachments())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/reliability/mapper/TRelMaintPlanMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.reliability.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.reliability.domain.TRelMaintPlan;
+
+/**
+ * 设备维修计划Mapper接口
+ * 
+ * @author ly
+ * @date 2025-10-28
+ */
+public interface TRelMaintPlanMapper 
+{
+    /**
+     * 查询设备维修计划
+     * 
+     * @param planId 设备维修计划ID
+     * @return 设备维修计划
+     */
+    public TRelMaintPlan selectTRelMaintPlanById(Long planId);
+
+    /**
+     * 查询设备维修计划列表
+     * 
+     * @param tRelMaintPlan 设备维修计划
+     * @return 设备维修计划集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TRelMaintPlan> selectTRelMaintPlanList(TRelMaintPlan tRelMaintPlan);
+
+    /**
+     * 新增设备维修计划
+     * 
+     * @param tRelMaintPlan 设备维修计划
+     * @return 结果
+     */
+    public int insertTRelMaintPlan(TRelMaintPlan tRelMaintPlan);
+
+    /**
+     * 修改设备维修计划
+     * 
+     * @param tRelMaintPlan 设备维修计划
+     * @return 结果
+     */
+    public int updateTRelMaintPlan(TRelMaintPlan tRelMaintPlan);
+
+    /**
+     * 删除设备维修计划
+     * 
+     * @param planId 设备维修计划ID
+     * @return 结果
+     */
+    public int deleteTRelMaintPlanById(Long planId);
+
+    /**
+     * 批量删除设备维修计划
+     * 
+     * @param planIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTRelMaintPlanByIds(Long[] planIds);
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/reliability/mapper/TRelMaintRecordMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.reliability.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.reliability.domain.TRelMaintRecord;
+
+/**
+ * 部件维修记录Mapper接口
+ * 
+ * @author ssy
+ * @date 2025-10-28
+ */
+public interface TRelMaintRecordMapper 
+{
+    /**
+     * 查询部件维修记录
+     * 
+     * @param recordId 部件维修记录ID
+     * @return 部件维修记录
+     */
+    public TRelMaintRecord selectTRelMaintRecordById(Long recordId);
+
+    /**
+     * 查询部件维修记录列表
+     * 
+     * @param tRelMaintRecord 部件维修记录
+     * @return 部件维修记录集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TRelMaintRecord> selectTRelMaintRecordList(TRelMaintRecord tRelMaintRecord);
+
+    /**
+     * 新增部件维修记录
+     * 
+     * @param tRelMaintRecord 部件维修记录
+     * @return 结果
+     */
+    public int insertTRelMaintRecord(TRelMaintRecord tRelMaintRecord);
+
+    /**
+     * 修改部件维修记录
+     * 
+     * @param tRelMaintRecord 部件维修记录
+     * @return 结果
+     */
+    public int updateTRelMaintRecord(TRelMaintRecord tRelMaintRecord);
+
+    /**
+     * 删除部件维修记录
+     * 
+     * @param recordId 部件维修记录ID
+     * @return 结果
+     */
+    public int deleteTRelMaintRecordById(Long recordId);
+
+    /**
+     * 批量删除部件维修记录
+     * 
+     * @param recordIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTRelMaintRecordByIds(Long[] recordIds);
+}

+ 61 - 0
master/src/main/java/com/ruoyi/project/reliability/service/ITRelMaintPlanService.java

@@ -0,0 +1,61 @@
+package com.ruoyi.project.reliability.service;
+
+import java.util.List;
+import com.ruoyi.project.reliability.domain.TRelMaintPlan;
+
+/**
+ * 设备维修计划Service接口
+ * 
+ * @author ly
+ * @date 2025-10-28
+ */
+public interface ITRelMaintPlanService 
+{
+    /**
+     * 查询设备维修计划
+     * 
+     * @param planId 设备维修计划ID
+     * @return 设备维修计划
+     */
+    public TRelMaintPlan selectTRelMaintPlanById(Long planId);
+
+    /**
+     * 查询设备维修计划列表
+     * 
+     * @param tRelMaintPlan 设备维修计划
+     * @return 设备维修计划集合
+     */
+    public List<TRelMaintPlan> selectTRelMaintPlanList(TRelMaintPlan tRelMaintPlan);
+
+    /**
+     * 新增设备维修计划
+     * 
+     * @param tRelMaintPlan 设备维修计划
+     * @return 结果
+     */
+    public int insertTRelMaintPlan(TRelMaintPlan tRelMaintPlan);
+
+    /**
+     * 修改设备维修计划
+     * 
+     * @param tRelMaintPlan 设备维修计划
+     * @return 结果
+     */
+    public int updateTRelMaintPlan(TRelMaintPlan tRelMaintPlan);
+
+    /**
+     * 批量删除设备维修计划
+     * 
+     * @param planIds 需要删除的设备维修计划ID
+     * @return 结果
+     */
+    public int deleteTRelMaintPlanByIds(Long[] planIds);
+
+    /**
+     * 删除设备维修计划信息
+     * 
+     * @param planId 设备维修计划ID
+     * @return 结果
+     */
+    public int deleteTRelMaintPlanById(Long planId);
+}

+ 61 - 0
master/src/main/java/com/ruoyi/project/reliability/service/ITRelMaintRecordService.java

@@ -0,0 +1,61 @@
+package com.ruoyi.project.reliability.service;
+
+import java.util.List;
+import com.ruoyi.project.reliability.domain.TRelMaintRecord;
+
+/**
+ * 部件维修记录Service接口
+ * 
+ * @author ssy
+ * @date 2025-10-28
+ */
+public interface ITRelMaintRecordService 
+{
+    /**
+     * 查询部件维修记录
+     * 
+     * @param recordId 部件维修记录ID
+     * @return 部件维修记录
+     */
+    public TRelMaintRecord selectTRelMaintRecordById(Long recordId);
+
+    /**
+     * 查询部件维修记录列表
+     * 
+     * @param tRelMaintRecord 部件维修记录
+     * @return 部件维修记录集合
+     */
+    public List<TRelMaintRecord> selectTRelMaintRecordList(TRelMaintRecord tRelMaintRecord);
+
+    /**
+     * 新增部件维修记录
+     * 
+     * @param tRelMaintRecord 部件维修记录
+     * @return 结果
+     */
+    public int insertTRelMaintRecord(TRelMaintRecord tRelMaintRecord);
+
+    /**
+     * 修改部件维修记录
+     * 
+     * @param tRelMaintRecord 部件维修记录
+     * @return 结果
+     */
+    public int updateTRelMaintRecord(TRelMaintRecord tRelMaintRecord);
+
+    /**
+     * 批量删除部件维修记录
+     * 
+     * @param recordIds 需要删除的部件维修记录ID
+     * @return 结果
+     */
+    public int deleteTRelMaintRecordByIds(Long[] recordIds);
+
+    /**
+     * 删除部件维修记录信息
+     * 
+     * @param recordId 部件维修记录ID
+     * @return 结果
+     */
+    public int deleteTRelMaintRecordById(Long recordId);
+}

+ 93 - 0
master/src/main/java/com/ruoyi/project/reliability/service/impl/TRelMaintPlanServiceImpl.java

@@ -0,0 +1,93 @@
+package com.ruoyi.project.reliability.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.reliability.mapper.TRelMaintPlanMapper;
+import com.ruoyi.project.reliability.domain.TRelMaintPlan;
+import com.ruoyi.project.reliability.service.ITRelMaintPlanService;
+
+/**
+ * 设备维修计划Service业务层处理
+ *
+ * @author ly
+ * @date 2025-10-28
+ */
+@Service
+public class TRelMaintPlanServiceImpl implements ITRelMaintPlanService
+{
+    @Autowired
+    private TRelMaintPlanMapper tRelMaintPlanMapper;
+
+    /**
+     * 查询设备维修计划
+     *
+     * @param planId 设备维修计划ID
+     * @return 设备维修计划
+     */
+    @Override
+    public TRelMaintPlan selectTRelMaintPlanById(Long planId)
+    {
+        return tRelMaintPlanMapper.selectTRelMaintPlanById(planId);
+    }
+
+    /**
+     * 查询设备维修计划列表
+     *
+     * @param tRelMaintPlan 设备维修计划
+     * @return 设备维修计划
+     */
+    @Override
+    public List<TRelMaintPlan> selectTRelMaintPlanList(TRelMaintPlan tRelMaintPlan)
+    {
+        return tRelMaintPlanMapper.selectTRelMaintPlanList(tRelMaintPlan);
+    }
+
+    /**
+     * 新增设备维修计划
+     *
+     * @param tRelMaintPlan 设备维修计划
+     * @return 结果
+     */
+    @Override
+    public int insertTRelMaintPlan(TRelMaintPlan tRelMaintPlan)
+    {
+        return tRelMaintPlanMapper.insertTRelMaintPlan(tRelMaintPlan);
+    }
+
+    /**
+     * 修改设备维修计划
+     *
+     * @param tRelMaintPlan 设备维修计划
+     * @return 结果
+     */
+    @Override
+    public int updateTRelMaintPlan(TRelMaintPlan tRelMaintPlan)
+    {
+        return tRelMaintPlanMapper.updateTRelMaintPlan(tRelMaintPlan);
+    }
+
+    /**
+     * 批量删除设备维修计划
+     *
+     * @param planIds 需要删除的设备维修计划ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTRelMaintPlanByIds(Long[] planIds)
+    {
+        return tRelMaintPlanMapper.deleteTRelMaintPlanByIds(planIds);
+    }
+
+    /**
+     * 删除设备维修计划信息
+     *
+     * @param planId 设备维修计划ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTRelMaintPlanById(Long planId)
+    {
+        return tRelMaintPlanMapper.deleteTRelMaintPlanById(planId);
+    }
+}

+ 93 - 0
master/src/main/java/com/ruoyi/project/reliability/service/impl/TRelMaintRecordServiceImpl.java

@@ -0,0 +1,93 @@
+package com.ruoyi.project.reliability.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.reliability.mapper.TRelMaintRecordMapper;
+import com.ruoyi.project.reliability.domain.TRelMaintRecord;
+import com.ruoyi.project.reliability.service.ITRelMaintRecordService;
+
+/**
+ * 部件维修记录Service业务层处理
+ *
+ * @author ssy
+ * @date 2025-10-28
+ */
+@Service
+public class TRelMaintRecordServiceImpl implements ITRelMaintRecordService
+{
+    @Autowired
+    private TRelMaintRecordMapper tRelMaintRecordMapper;
+
+    /**
+     * 查询部件维修记录
+     *
+     * @param recordId 部件维修记录ID
+     * @return 部件维修记录
+     */
+    @Override
+    public TRelMaintRecord selectTRelMaintRecordById(Long recordId)
+    {
+        return tRelMaintRecordMapper.selectTRelMaintRecordById(recordId);
+    }
+
+    /**
+     * 查询部件维修记录列表
+     *
+     * @param tRelMaintRecord 部件维修记录
+     * @return 部件维修记录
+     */
+    @Override
+    public List<TRelMaintRecord> selectTRelMaintRecordList(TRelMaintRecord tRelMaintRecord)
+    {
+        return tRelMaintRecordMapper.selectTRelMaintRecordList(tRelMaintRecord);
+    }
+
+    /**
+     * 新增部件维修记录
+     *
+     * @param tRelMaintRecord 部件维修记录
+     * @return 结果
+     */
+    @Override
+    public int insertTRelMaintRecord(TRelMaintRecord tRelMaintRecord)
+    {
+        return tRelMaintRecordMapper.insertTRelMaintRecord(tRelMaintRecord);
+    }
+
+    /**
+     * 修改部件维修记录
+     *
+     * @param tRelMaintRecord 部件维修记录
+     * @return 结果
+     */
+    @Override
+    public int updateTRelMaintRecord(TRelMaintRecord tRelMaintRecord)
+    {
+        return tRelMaintRecordMapper.updateTRelMaintRecord(tRelMaintRecord);
+    }
+
+    /**
+     * 批量删除部件维修记录
+     *
+     * @param recordIds 需要删除的部件维修记录ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTRelMaintRecordByIds(Long[] recordIds)
+    {
+        return tRelMaintRecordMapper.deleteTRelMaintRecordByIds(recordIds);
+    }
+
+    /**
+     * 删除部件维修记录信息
+     *
+     * @param recordId 部件维修记录ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTRelMaintRecordById(Long recordId)
+    {
+        return tRelMaintRecordMapper.deleteTRelMaintRecordById(recordId);
+    }
+}

+ 13 - 7
master/src/main/resources/application.yml

@@ -215,11 +215,17 @@ jasypt:
     password: test
 aliyun:
   sms:
-    accessKeyId: LTAI5tS2Jen6mrzQN6fc2NKn       # Access Key ID
-    accessKeySecret: CSDeBYYj7UJqv5aUNJNxmydZemqEbd  #  Access Key Secret
-    signName: CPMS系统           # 短信签名
-    templateCode: SMS_478990299    # 短信模板ID
-#    accessKeyId: LTAI5tMGeoYNK1GKurAKtdze       # Access Key ID
-#    accessKeySecret: JN2iFAiqRPeTG5uFKEsc5gFDNRT5xc  #  Access Key Secret
+#    accessKeyId: LTAI5tHwJVXsLty9jwq9kX5e       # Access Key ID
+#    accessKeySecret: uNJogYq1UavGpYWoKkpuUPBmIfQvJ3  #  Access Key Secret
 #    signName: 扬子石化巴斯夫           # 短信签名
-#    templateCode: SMS_479005213    # 短信模板ID
+#    templateCode: SMS_486295071    # 短信模板ID
+
+    accessKeyId: LTAI5tMRkg1eks5w2i6UQ8va       # Access Key ID
+    accessKeySecret: MSh8r2o4L4O17OW5mK8vQ69a4qMJ7d  #  Access Key Secret
+    signName: 扬子石化巴斯夫           # 短信签名
+    templateCode: SMS_486295071    # 短信模板ID
+
+#    accessKeyId: LTAI5tS2Jen6mrzQN6fc2NKn       # Access Key ID
+#    accessKeySecret: CSDeBYYj7UJqv5aUNJNxmydZemqEbd  #  Access Key Secret
+#    signName: CPMS系统           # 短信签名
+#    templateCode: SMS_478990299    # 短信模板ID

+ 141 - 0
master/src/main/resources/mybatis/reliability/TRelMaintPlanMapper.xml

@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.project.reliability.mapper.TRelMaintPlanMapper">
+
+    <resultMap type="TRelMaintPlan" id="TRelMaintPlanResult">
+        <result property="planId"    column="plan_id"    />
+        <result property="plant"    column="plant"    />
+        <result property="devName"    column="dev_name"    />
+        <result property="devTag"    column="dev_tag"    />
+        <result property="planTime"    column="plan_time"    />
+        <result property="approvalStatus"    column="approval_status"    />
+        <result property="responsible"    column="responsible"    />
+        <result property="completionStatus"    column="completion_status"    />
+        <result property="processId"    column="process_id"    />
+        <result property="approver"    column="approver"    />
+        <result property="delFlag"    column="del_flag"    />
+        <result property="createrCode"    column="creater_code"    />
+        <result property="createdate"    column="createdate"    />
+        <result property="updaterCode"    column="updater_code"    />
+        <result property="updatedate"    column="updatedate"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTRelMaintPlanVo">
+        select d.plan_id, d.plant, d.dev_name, d.dev_tag, d.plan_time, d.approval_status, d.responsible, d.completion_status, d.process_id, d.approver, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks ,s.dept_name from t_rel_maint_plan d
+      left join sys_dept s on s.dept_id = d.dept_id
+    </sql>
+
+    <select id="selectTRelMaintPlanList" parameterType="TRelMaintPlan" resultMap="TRelMaintPlanResult">
+        <include refid="selectTRelMaintPlanVo"/>
+        <where>
+            <if test="plant != null  and plant != ''"> and plant = #{plant}</if>
+            <if test="devName != null  and devName != ''"> and dev_name like concat(concat('%', #{devName}), '%')</if>
+            <if test="devTag != null  and devTag != ''"> and dev_tag = #{devTag}</if>
+            <if test="planTime != null "> and plan_time = #{planTime}</if>
+            <if test="approvalStatus != null  and approvalStatus != ''"> and approval_status = #{approvalStatus}</if>
+            <if test="responsible != null  and responsible != ''"> and responsible = #{responsible}</if>
+            <if test="completionStatus != null  and completionStatus != ''"> and completion_status = #{completionStatus}</if>
+            <if test="processId != null  and processId != ''"> and process_id = #{processId}</if>
+            <if test="approver != null  and approver != ''"> and approver = #{approver}</if>
+            <if test="createrCode != null  and createrCode != ''"> and creater_code = #{createrCode}</if>
+            <if test="createdate != null "> and createdate = #{createdate}</if>
+            <if test="updaterCode != null  and updaterCode != ''"> and updater_code = #{updaterCode}</if>
+            <if test="updatedate != null "> and updatedate = #{updatedate}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTRelMaintPlanById" parameterType="Long" resultMap="TRelMaintPlanResult">
+        <include refid="selectTRelMaintPlanVo"/>
+        where plan_id = #{planId}
+    </select>
+
+    <insert id="insertTRelMaintPlan" parameterType="TRelMaintPlan">
+        <selectKey keyProperty="planId" resultType="long" order="BEFORE">
+            SELECT seq_t_rel_maint_plan.NEXTVAL as planId FROM DUAL
+        </selectKey>
+        insert into t_rel_maint_plan
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="planId != null">plan_id,</if>
+            <if test="plant != null">plant,</if>
+            <if test="devName != null">dev_name,</if>
+            <if test="devTag != null">dev_tag,</if>
+            <if test="planTime != null">plan_time,</if>
+            <if test="approvalStatus != null">approval_status,</if>
+            <if test="responsible != null">responsible,</if>
+            <if test="completionStatus != null">completion_status,</if>
+            <if test="processId != null">process_id,</if>
+            <if test="approver != null">approver,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createrCode != null">creater_code,</if>
+            <if test="createdate != null">createdate,</if>
+            <if test="updaterCode != null">updater_code,</if>
+            <if test="updatedate != null">updatedate,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="planId != null">#{planId},</if>
+            <if test="plant != null">#{plant},</if>
+            <if test="devName != null">#{devName},</if>
+            <if test="devTag != null">#{devTag},</if>
+            <if test="planTime != null">#{planTime},</if>
+            <if test="approvalStatus != null">#{approvalStatus},</if>
+            <if test="responsible != null">#{responsible},</if>
+            <if test="completionStatus != null">#{completionStatus},</if>
+            <if test="processId != null">#{processId},</if>
+            <if test="approver != null">#{approver},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createrCode != null">#{createrCode},</if>
+            <if test="createdate != null">#{createdate},</if>
+            <if test="updaterCode != null">#{updaterCode},</if>
+            <if test="updatedate != null">#{updatedate},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTRelMaintPlan" parameterType="TRelMaintPlan">
+        update t_rel_maint_plan
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="plant != null">plant = #{plant},</if>
+            <if test="devName != null">dev_name = #{devName},</if>
+            <if test="devTag != null">dev_tag = #{devTag},</if>
+            <if test="planTime != null">plan_time = #{planTime},</if>
+            <if test="approvalStatus != null">approval_status = #{approvalStatus},</if>
+            <if test="responsible != null">responsible = #{responsible},</if>
+            <if test="completionStatus != null">completion_status = #{completionStatus},</if>
+            <if test="processId != null">process_id = #{processId},</if>
+            <if test="approver != null">approver = #{approver},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createrCode != null">creater_code = #{createrCode},</if>
+            <if test="createdate != null">createdate = #{createdate},</if>
+            <if test="updaterCode != null">updater_code = #{updaterCode},</if>
+            <if test="updatedate != null">updatedate = #{updatedate},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where plan_id = #{planId}
+    </update>
+
+    <update id="deleteTRelMaintPlanById" parameterType="Long">
+        update t_rel_maint_plan set del_flag = 2 where plan_id = #{planId}
+    </update>
+
+    <update id="deleteTRelMaintPlanByIds" parameterType="String">
+        update t_rel_maint_plan set del_flag = 2 where plan_id in
+        <foreach item="planId" collection="array" open="(" separator="," close=")">
+            #{planId}
+        </foreach>
+    </update>
+
+</mapper>

+ 186 - 0
master/src/main/resources/mybatis/reliability/TRelMaintRecordMapper.xml

@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.project.reliability.mapper.TRelMaintRecordMapper">
+
+    <resultMap type="TRelMaintRecord" id="TRelMaintRecordResult">
+        <result property="recordId"    column="record_id"    />
+        <result property="plant"    column="plant"    />
+        <result property="devName"    column="dev_name"    />
+        <result property="devTag"    column="dev_tag"    />
+        <result property="compoName"    column="compo_name"    />
+        <result property="compoId"    column="compo_id"    />
+        <result property="maintType"    column="maint_type"    />
+        <result property="maintDept"    column="maint_dept"    />
+        <result property="inspector"    column="inspector"    />
+        <result property="inspectContent"    column="inspect_content"    />
+        <result property="inspectTime"    column="inspect_time"    />
+        <result property="responsible"    column="responsible"    />
+        <result property="maintContent"    column="maint_content"    />
+        <result property="maintResult"    column="maint_result"    />
+        <result property="maintTime"    column="maint_time"    />
+        <result property="maintCost"    column="maint_cost"    />
+        <result property="maintDuration"    column="maint_duration"    />
+        <result property="processLoss"    column="process_loss"    />
+        <result property="attachments"    column="attachments"    />
+        <result property="delFlag"    column="del_flag"    />
+        <result property="createrCode"    column="creater_code"    />
+        <result property="createdate"    column="createdate"    />
+        <result property="updaterCode"    column="updater_code"    />
+        <result property="updatedate"    column="updatedate"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTRelMaintRecordVo">
+        select d.record_id, d.plant, d.dev_name, d.dev_tag, d.compo_name, d.compo_id, d.maint_type, d.maint_dept, d.inspector, d.inspect_content, d.inspect_time, d.responsible, d.maint_content, d.maint_result, d.maint_time, d.maint_cost, d.maint_duration, d.process_loss, d.attachments, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks ,s.dept_name from t_rel_maint_record d
+      left join sys_dept s on s.dept_id = d.dept_id
+    </sql>
+
+    <select id="selectTRelMaintRecordList" parameterType="TRelMaintRecord" resultMap="TRelMaintRecordResult">
+        <include refid="selectTRelMaintRecordVo"/>
+        <where>
+            <if test="plant != null  and plant != ''"> and plant = #{plant}</if>
+            <if test="devName != null  and devName != ''"> and dev_name like concat(concat('%', #{devName}), '%')</if>
+            <if test="devTag != null  and devTag != ''"> and dev_tag = #{devTag}</if>
+            <if test="compoName != null  and compoName != ''"> and compo_name like concat(concat('%', #{compoName}), '%')</if>
+            <if test="compoId != null  and compoId != ''"> and compo_id = #{compoId}</if>
+            <if test="maintType != null  and maintType != ''"> and maint_type = #{maintType}</if>
+            <if test="maintDept != null  and maintDept != ''"> and maint_dept = #{maintDept}</if>
+            <if test="inspector != null  and inspector != ''"> and inspector = #{inspector}</if>
+            <if test="inspectContent != null  and inspectContent != ''"> and inspect_content = #{inspectContent}</if>
+            <if test="inspectTime != null "> and inspect_time = #{inspectTime}</if>
+            <if test="responsible != null  and responsible != ''"> and responsible = #{responsible}</if>
+            <if test="maintContent != null  and maintContent != ''"> and maint_content = #{maintContent}</if>
+            <if test="maintResult != null  and maintResult != ''"> and maint_result = #{maintResult}</if>
+            <if test="maintTime != null "> and maint_time = #{maintTime}</if>
+            <if test="maintCost != null "> and maint_cost = #{maintCost}</if>
+            <if test="maintDuration != null "> and maint_duration = #{maintDuration}</if>
+            <if test="processLoss != null  and processLoss != ''"> and process_loss = #{processLoss}</if>
+            <if test="attachments != null  and attachments != ''"> and attachments = #{attachments}</if>
+            <if test="createrCode != null  and createrCode != ''"> and creater_code = #{createrCode}</if>
+            <if test="createdate != null "> and createdate = #{createdate}</if>
+            <if test="updaterCode != null  and updaterCode != ''"> and updater_code = #{updaterCode}</if>
+            <if test="updatedate != null "> and updatedate = #{updatedate}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTRelMaintRecordById" parameterType="Long" resultMap="TRelMaintRecordResult">
+        <include refid="selectTRelMaintRecordVo"/>
+        where record_id = #{recordId}
+    </select>
+
+    <insert id="insertTRelMaintRecord" parameterType="TRelMaintRecord">
+        <selectKey keyProperty="recordId" resultType="long" order="BEFORE">
+            SELECT seq_t_rel_maint_record.NEXTVAL as recordId FROM DUAL
+        </selectKey>
+        insert into t_rel_maint_record
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="recordId != null">record_id,</if>
+            <if test="plant != null">plant,</if>
+            <if test="devName != null">dev_name,</if>
+            <if test="devTag != null">dev_tag,</if>
+            <if test="compoName != null">compo_name,</if>
+            <if test="compoId != null">compo_id,</if>
+            <if test="maintType != null">maint_type,</if>
+            <if test="maintDept != null">maint_dept,</if>
+            <if test="inspector != null">inspector,</if>
+            <if test="inspectContent != null">inspect_content,</if>
+            <if test="inspectTime != null">inspect_time,</if>
+            <if test="responsible != null">responsible,</if>
+            <if test="maintContent != null">maint_content,</if>
+            <if test="maintResult != null">maint_result,</if>
+            <if test="maintTime != null">maint_time,</if>
+            <if test="maintCost != null">maint_cost,</if>
+            <if test="maintDuration != null">maint_duration,</if>
+            <if test="processLoss != null">process_loss,</if>
+            <if test="attachments != null">attachments,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createrCode != null">creater_code,</if>
+            <if test="createdate != null">createdate,</if>
+            <if test="updaterCode != null">updater_code,</if>
+            <if test="updatedate != null">updatedate,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="recordId != null">#{recordId},</if>
+            <if test="plant != null">#{plant},</if>
+            <if test="devName != null">#{devName},</if>
+            <if test="devTag != null">#{devTag},</if>
+            <if test="compoName != null">#{compoName},</if>
+            <if test="compoId != null">#{compoId},</if>
+            <if test="maintType != null">#{maintType},</if>
+            <if test="maintDept != null">#{maintDept},</if>
+            <if test="inspector != null">#{inspector},</if>
+            <if test="inspectContent != null">#{inspectContent},</if>
+            <if test="inspectTime != null">#{inspectTime},</if>
+            <if test="responsible != null">#{responsible},</if>
+            <if test="maintContent != null">#{maintContent},</if>
+            <if test="maintResult != null">#{maintResult},</if>
+            <if test="maintTime != null">#{maintTime},</if>
+            <if test="maintCost != null">#{maintCost},</if>
+            <if test="maintDuration != null">#{maintDuration},</if>
+            <if test="processLoss != null">#{processLoss},</if>
+            <if test="attachments != null">#{attachments},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createrCode != null">#{createrCode},</if>
+            <if test="createdate != null">#{createdate},</if>
+            <if test="updaterCode != null">#{updaterCode},</if>
+            <if test="updatedate != null">#{updatedate},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTRelMaintRecord" parameterType="TRelMaintRecord">
+        update t_rel_maint_record
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="plant != null">plant = #{plant},</if>
+            <if test="devName != null">dev_name = #{devName},</if>
+            <if test="devTag != null">dev_tag = #{devTag},</if>
+            <if test="compoName != null">compo_name = #{compoName},</if>
+            <if test="compoId != null">compo_id = #{compoId},</if>
+            <if test="maintType != null">maint_type = #{maintType},</if>
+            <if test="maintDept != null">maint_dept = #{maintDept},</if>
+            <if test="inspector != null">inspector = #{inspector},</if>
+            <if test="inspectContent != null">inspect_content = #{inspectContent},</if>
+            <if test="inspectTime != null">inspect_time = #{inspectTime},</if>
+            <if test="responsible != null">responsible = #{responsible},</if>
+            <if test="maintContent != null">maint_content = #{maintContent},</if>
+            <if test="maintResult != null">maint_result = #{maintResult},</if>
+            <if test="maintTime != null">maint_time = #{maintTime},</if>
+            <if test="maintCost != null">maint_cost = #{maintCost},</if>
+            <if test="maintDuration != null">maint_duration = #{maintDuration},</if>
+            <if test="processLoss != null">process_loss = #{processLoss},</if>
+            <if test="attachments != null">attachments = #{attachments},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createrCode != null">creater_code = #{createrCode},</if>
+            <if test="createdate != null">createdate = #{createdate},</if>
+            <if test="updaterCode != null">updater_code = #{updaterCode},</if>
+            <if test="updatedate != null">updatedate = #{updatedate},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where record_id = #{recordId}
+    </update>
+
+    <update id="deleteTRelMaintRecordById" parameterType="Long">
+        update t_rel_maint_record set del_flag = 2 where record_id = #{recordId}
+    </update>
+
+    <update id="deleteTRelMaintRecordByIds" parameterType="String">
+        update t_rel_maint_record set del_flag = 2 where record_id in
+        <foreach item="recordId" collection="array" open="(" separator="," close=")">
+            #{recordId}
+        </foreach>
+    </update>
+
+</mapper>

+ 50 - 0
master/src/main/resources/processes/reliability/relMaintPlanProcess.bpmn

@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
+  <process id="relMaintPlanProcess" name="可靠性设备维修计划申请" isExecutable="true">
+    <startEvent id="startevent1" name="Start"></startEvent>
+    <endEvent id="endSpecTrainingPlan" name="End"></endEvent>
+    <userTask id="zzjlTask" name="装置经理审批" activiti:assignee="#{zzjlusers}"></userTask>
+    <endEvent id="endSpecTrainingPlan2" name="End"></endEvent>
+    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="zzjlTask"></sequenceFlow>
+    <sequenceFlow id="flow2" name="通过" sourceRef="zzjlTask" targetRef="endSpecTrainingPlan">
+      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${condition == 1}]]></conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="flow3" name="不通过" sourceRef="zzjlTask" targetRef="endSpecTrainingPlan2">
+      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${condition == 0}]]></conditionExpression>
+    </sequenceFlow>
+  </process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_relMaintPlanProcess">
+    <bpmndi:BPMNPlane bpmnElement="relMaintPlanProcess" id="BPMNPlane_relMaintPlanProcess">
+      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
+        <omgdc:Bounds height="35.0" width="35.0" x="60.0" y="40.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="endSpecTrainingPlan" id="BPMNShape_endSpecTrainingPlan">
+        <omgdc:Bounds height="35.0" width="35.0" x="370.0" y="40.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="zzjlTask" id="BPMNShape_zzjlTask">
+        <omgdc:Bounds height="55.0" width="105.0" x="180.0" y="30.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="endSpecTrainingPlan2" id="BPMNShape_endSpecTrainingPlan2">
+        <omgdc:Bounds height="35.0" width="35.0" x="215.0" y="140.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
+        <omgdi:waypoint x="95.0" y="57.0"></omgdi:waypoint>
+        <omgdi:waypoint x="180.0" y="57.0"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
+        <omgdi:waypoint x="285.0" y="57.0"></omgdi:waypoint>
+        <omgdi:waypoint x="370.0" y="57.0"></omgdi:waypoint>
+        <bpmndi:BPMNLabel>
+          <omgdc:Bounds height="16.0" width="32.0" x="304.0" y="69.0"></omgdc:Bounds>
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
+        <omgdi:waypoint x="232.0" y="85.0"></omgdi:waypoint>
+        <omgdi:waypoint x="232.0" y="140.0"></omgdi:waypoint>
+        <bpmndi:BPMNLabel>
+          <omgdc:Bounds height="16.0" width="48.0" x="240.0" y="109.0"></omgdc:Bounds>
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</definitions>

BIN
master/src/main/resources/static/template/reliability/rel_compo.xlsx


BIN
master/src/main/resources/static/template/reliability/rel_device.xlsx


+ 8 - 0
ui/src/api/reliability/rel_compo.js

@@ -51,3 +51,11 @@ export function exportRel_compo(query) {
     params: query
   })
 }
+
+// 用户导入模板
+export function importTemplate() {
+  return request({
+    url: '/reliability/rel_compo/importTemplate',
+    method: 'post'
+  })
+}

+ 8 - 0
ui/src/api/reliability/rel_device.js

@@ -51,3 +51,11 @@ export function exportRel_device(query) {
     params: query
   })
 }
+
+// 用户导入模板
+export function importTemplate() {
+  return request({
+    url: '/reliability/rel_device/importTemplate',
+    method: 'post'
+  })
+}

+ 62 - 0
ui/src/api/reliability/rel_maint_plan.js

@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+// 查询设备维修计划列表
+export function listRel_maint_plan(query) {
+  return request({
+    url: '/reliability/rel_maint_plan/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询设备维修计划详细
+export function getRel_maint_plan(planId) {
+  return request({
+    url: '/reliability/rel_maint_plan/' + planId,
+    method: 'get'
+  })
+}
+
+// 新增设备维修计划
+export function addRel_maint_plan(data) {
+  return request({
+    url: '/reliability/rel_maint_plan',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改设备维修计划
+export function updateRel_maint_plan(data) {
+  return request({
+    url: '/reliability/rel_maint_plan',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除设备维修计划
+export function delRel_maint_plan(planId) {
+  return request({
+    url: '/reliability/rel_maint_plan/' + planId,
+    method: 'delete'
+  })
+}
+
+// 导出设备维修计划
+export function exportRel_maint_plan(query) {
+  return request({
+    url: '/reliability/rel_maint_plan/export',
+    method: 'get',
+    params: query
+  })
+}
+
+// 提交维修计划申请
+export function submitApprove(data) {
+  return request({
+    url: '/reliability/rel_maint_plan/submitApprove',
+    method: 'post',
+    data: data
+  })
+}

+ 53 - 0
ui/src/api/reliability/rel_maint_record.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询部件维修记录列表
+export function listRel_maint_record(query) {
+  return request({
+    url: '/reliability/rel_maint_record/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询部件维修记录详细
+export function getRel_maint_record(recordId) {
+  return request({
+    url: '/reliability/rel_maint_record/' + recordId,
+    method: 'get'
+  })
+}
+
+// 新增部件维修记录
+export function addRel_maint_record(data) {
+  return request({
+    url: '/reliability/rel_maint_record',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改部件维修记录
+export function updateRel_maint_record(data) {
+  return request({
+    url: '/reliability/rel_maint_record',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除部件维修记录
+export function delRel_maint_record(recordId) {
+  return request({
+    url: '/reliability/rel_maint_record/' + recordId,
+    method: 'delete'
+  })
+}
+
+// 导出部件维修记录
+export function exportRel_maint_record(query) {
+  return request({
+    url: '/reliability/rel_maint_record/export',
+    method: 'get',
+    params: query
+  })
+}

+ 0 - 0
ui/public/visio/diagram.svg → ui/src/assets/visio/diagram.svg


+ 1 - 1
ui/src/utils/constants.js

@@ -3,7 +3,7 @@
  */
 
 // 默认查询的部门单位ID列表
-export const DEFAULT_UNITS = "10,18,20,30,34,38"
+export const DEFAULT_UNITS = "10,18,20,30,34,38,40,42,44"
 
 // 其他全局常量可以添加在这里
 // 例如:

+ 83 - 19
ui/src/views/login.vue

@@ -17,25 +17,26 @@
           show-password
           auto-complete="off"
           :placeholder="$t('login.password')"
-          @keyup.enter.native="handleLogin"
+          @keyup.enter.native="handleLoginWithSms"
         >
           <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>
         </el-input>
       </el-form-item>
-      <!--      <el-form-item prop="code">-->
-      <!--        <el-input-->
-      <!--          v-model="loginForm.code"-->
-      <!--          auto-complete="off"-->
-      <!--          :placeholder="$t('login.code')"-->
-      <!--          style="width: 63%"-->
-      <!--          @keyup.enter.native="handleLogin"-->
-      <!--        >-->
-      <!--          <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />-->
-      <!--        </el-input>-->
-      <!--        <div class="login-code">-->
-      <!--          <img :src="codeUrl" @click="getCode" class="login-code-img"/>-->
-      <!--        </div>-->
-      <!--      </el-form-item>-->
+            <el-form-item prop="code">
+              <el-input
+                v-model="loginForm.code"
+                auto-complete="off"
+                :placeholder="$t('login.code')"
+                style="width: 63%"
+                @keyup.enter.native="handleLoginWithSms"
+              >
+                <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
+              </el-input>
+              <div class="login-code">
+                <el-button size="mini" type="primary" style="width:100%;" class="sendCode" @click="sendSmsCode()"
+                           :disabled="isSending">{{ isSending ? `${countdown}秒后重新发送` : '发送验证码' }}</el-button>
+              </div>
+            </el-form-item>
       <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">{{
           $t('login.rememberPassword')
         }}
@@ -46,7 +47,7 @@
           size="medium"
           type="primary"
           style="width:100%;"
-          @click.native.prevent="handleLogin"
+          @click.native.prevent="handleLoginWithSms"
         >
           <span v-if="!loading"> {{ $t('login.logIn') }}</span>
           <span v-else>{{ $t('login.loading') }}</span>
@@ -97,7 +98,7 @@
 </template>
 
 <script>
-import {getCodeImg} from "@/api/login";
+import {getCodeImg,sendSms} from "@/api/login";
 import Cookies from "js-cookie";
 import {encrypt, decrypt} from '@/utils/jsencrypt'
 import LangSelect from '@/components/LangSelect'
@@ -109,6 +110,8 @@ export default {
     return {
       codeUrl: "",
       cookiePassword: "",
+      isSending: false,
+      countdown: 60,
       loginForm: {
         username: "",
         password: "",
@@ -154,6 +157,41 @@ export default {
         this.loginForm.uuid = res.uuid;
       });
     },
+    sendSmsCode(){
+
+      let hasError = false;
+      this.$refs.loginForm.validateField(['username', 'password'], err => {
+        if (err) {
+          hasError = true;
+          this.$message.warning('请检查必填项是否填写完整/正确')
+          return false;
+        }
+      })
+      if (!hasError) {
+        // 校验通过
+          sendSms(this.loginForm).then(res => {
+            if(res.code === 200){
+              this.$message.success(res.msg)
+              this.startCountdown()
+            }else{
+              this.$message.error(res.msg)
+            }
+          }).catch(() => {});
+      }
+    },
+    // 验证码重新发送倒计时方法
+    startCountdown () {
+      this.isSending = true;
+      const timer = setInterval(() => {
+        if (this.countdown > 0) {
+          this.countdown--;
+        } else {
+          this.isSending = false;
+          this.countdown = 60;
+          clearInterval(timer);
+        }
+      }, 1000);
+    },
     getCookie() {
       const username = Cookies.get("username");
       const password = Cookies.get("password");
@@ -164,6 +202,31 @@ export default {
         rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
       };
     },
+    handleLoginWithSms() {
+      this.$refs.loginForm.validate(valid => {
+        if (valid) {
+          this.loading = true;
+          if (this.loginForm.rememberMe) {
+            Cookies.set("username", this.loginForm.username, {expires: 30});
+            Cookies.set("password", encrypt(this.loginForm.password), {expires: 30});
+            Cookies.set('rememberMe', this.loginForm.rememberMe, {expires: 30});
+          } else {
+            Cookies.remove("username");
+            Cookies.remove("password");
+            Cookies.remove('rememberMe');
+          }
+          this.$store
+            .dispatch("LoginWithSms", this.loginForm)
+            .then(() => {
+              this.$router.push({path: this.redirect || "/404"});
+            })
+            .catch(() => {
+              this.loading = false;
+              this.getCode();
+            });
+        }
+      });
+    },
     handleLogin() {
       this.$refs.loginForm.validate(valid => {
         if (valid) {
@@ -261,8 +324,8 @@ export default {
   justify-content: center;
   align-items: center;
   height: 100%;
-  //background-image: url("../assets/image/CPMS20210107.jpg");
-  background-image: url("../assets/image/cpms-test.jpg");
+  background-image: url("../assets/image/CPMS20210107.jpg");
+  //background-image: url("../assets/image/cpms-test.jpg");
   background-size: cover;
 }
 
@@ -325,6 +388,7 @@ export default {
   color: #ffffff;
 }
 
+
 .el-login-footer {
   height: 40px;
   line-height: 40px;

+ 18 - 76
ui/src/views/login2.bak → ui/src/views/login2.vue

@@ -17,26 +17,25 @@
           show-password
           auto-complete="off"
           :placeholder="$t('login.password')"
-          @keyup.enter.native="handleLoginWithSms"
+          @keyup.enter.native="handleLogin"
         >
           <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>
         </el-input>
       </el-form-item>
-            <el-form-item prop="code">
-              <el-input
-                v-model="loginForm.code"
-                auto-complete="off"
-                :placeholder="$t('login.code')"
-                style="width: 63%"
-                @keyup.enter.native="handleLoginWithSms"
-              >
-                <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
-              </el-input>
-              <div class="login-code">
-                <el-button size="mini" type="primary" style="width:100%;" class="sendCode" @click="sendSmsCode()"
-                           :disabled="isSending">{{ isSending ? `${countdown}秒后重新发送` : '发送验证码' }}</el-button>
-              </div>
-            </el-form-item>
+      <!--      <el-form-item prop="code">-->
+      <!--        <el-input-->
+      <!--          v-model="loginForm.code"-->
+      <!--          auto-complete="off"-->
+      <!--          :placeholder="$t('login.code')"-->
+      <!--          style="width: 63%"-->
+      <!--          @keyup.enter.native="handleLogin"-->
+      <!--        >-->
+      <!--          <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />-->
+      <!--        </el-input>-->
+      <!--        <div class="login-code">-->
+      <!--          <img :src="codeUrl" @click="getCode" class="login-code-img"/>-->
+      <!--        </div>-->
+      <!--      </el-form-item>-->
       <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">{{
           $t('login.rememberPassword')
         }}
@@ -47,7 +46,7 @@
           size="medium"
           type="primary"
           style="width:100%;"
-          @click.native.prevent="handleLoginWithSms"
+          @click.native.prevent="handleLogin"
         >
           <span v-if="!loading"> {{ $t('login.logIn') }}</span>
           <span v-else>{{ $t('login.loading') }}</span>
@@ -98,7 +97,7 @@
 </template>
 
 <script>
-import {getCodeImg,sendSms} from "@/api/login";
+import {getCodeImg} from "@/api/login";
 import Cookies from "js-cookie";
 import {encrypt, decrypt} from '@/utils/jsencrypt'
 import LangSelect from '@/components/LangSelect'
@@ -110,8 +109,6 @@ export default {
     return {
       codeUrl: "",
       cookiePassword: "",
-      isSending: false,
-      countdown: 60,
       loginForm: {
         username: "",
         password: "",
@@ -157,36 +154,6 @@ export default {
         this.loginForm.uuid = res.uuid;
       });
     },
-    sendSmsCode(){
-
-      let hasError = false;
-      this.$refs.loginForm.validateField(['username', 'password'], err => {
-        if (err) {
-          hasError = true;
-          this.$message.warning('请检查必填项是否填写完整/正确')
-          return false;
-        }
-      })
-      if (!hasError) {
-        // 校验通过
-          sendSms(this.loginForm).then(res => {
-            this.startCountdown ()
-          });
-      }
-    },
-    // 验证码重新发送倒计时方法
-    startCountdown () {
-      this.isSending = true;
-      const timer = setInterval(() => {
-        if (this.countdown > 0) {
-          this.countdown--;
-        } else {
-          this.isSending = false;
-          this.countdown = 60;
-          clearInterval(timer);
-        }
-      }, 1000);
-    },
     getCookie() {
       const username = Cookies.get("username");
       const password = Cookies.get("password");
@@ -197,31 +164,6 @@ export default {
         rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
       };
     },
-    handleLoginWithSms() {
-      this.$refs.loginForm.validate(valid => {
-        if (valid) {
-          this.loading = true;
-          if (this.loginForm.rememberMe) {
-            Cookies.set("username", this.loginForm.username, {expires: 30});
-            Cookies.set("password", encrypt(this.loginForm.password), {expires: 30});
-            Cookies.set('rememberMe', this.loginForm.rememberMe, {expires: 30});
-          } else {
-            Cookies.remove("username");
-            Cookies.remove("password");
-            Cookies.remove('rememberMe');
-          }
-          this.$store
-            .dispatch("LoginWithSms", this.loginForm)
-            .then(() => {
-              this.$router.push({path: this.redirect || "/404"});
-            })
-            .catch(() => {
-              this.loading = false;
-              this.getCode();
-            });
-        }
-      });
-    },
     handleLogin() {
       this.$refs.loginForm.validate(valid => {
         if (valid) {
@@ -379,7 +321,7 @@ export default {
   color: #ffffff;
 }
 
-.el-checkbox {
+.login-form .el-checkbox {
   color: #ffffff;
 }
 

+ 33 - 8
ui/src/views/plant/EOEGorganization/branch.vue

@@ -1,11 +1,11 @@
 <template>
-    <ul :class="{'double': isHaveChild(dataArray)}">
+    <ul :class="{'double': isHaveChild(dataArray), 'shift-leader-row': dataArray && dataArray.some(item => item.post && item.post.trim() === '倒班班长')}">
       <li v-for="(item, index) in dataArray" :key="index" v-if="!item.level" :class="[{
         'liequal': item.post.trim()==='安全专员'},{
         'litop': item.post.trim()==='首席经理'
         }]">
         <div class="branch-box" @click.prevent="clickHandle(item)" v-if="item.post.trim() !== 'EHS督导'">
-          <div class="branch-title">{{item.post}}</div>
+          <div class="branch-title">{{formatPost(item.post)}}</div>
           <img class="branch-pic" :src=item.img>
           <div class="branch-name">{{item.label}}</div>
           <div class="bz-box">
@@ -26,7 +26,7 @@
         </div>
         <!-- 平级 -->
         <div class="branch-box" :class="item.post.trim() === '安全专员' ? 'equal':''" @click.prevent="clickHandle(item)" v-if="item.post.trim() === '安全专员'">
-          <div class="branch-title">{{item.post}}</div>
+          <div class="branch-title">{{formatPost(item.post)}}</div>
           <img class="branch-pic" :src=item.img>
           <div class="branch-name">{{item.label}}</div>
           <div class="bz-box">
@@ -47,9 +47,9 @@
         <template v-if="item.secretary">
           <ul class="level" v-for="(secretary, se) in item.secretary" :key="se">
             <template v-for="(child, cIndex) in secretary">
-              <li v-if="child.children" :class="{'odd': ((secretary.length%2) === 1)}" :key="'child-' + cIndex">
+              <li v-if="child.children" :class="{'odd': ((secretary.length%2) === 1), 'safe-officer': child.post.trim() === '安全专员'}" :key="'child-' + cIndex">
                 <div class="branch-box" @click.prevent="clickHandle(child)">
-                  <div class="branch-title">{{child.post}}</div>
+                  <div class="branch-title">{{formatPost(child.post)}}</div>
                   <img class="branch-pic" :src=child.img>
                   <div class="branch-name">{{child.label}}</div>
                   <div class="bz-box">
@@ -70,7 +70,7 @@
                 <ul :style="{'width': ulWidth + 'px'}">
                   <li v-for="(schild, chIndex) in child.children" :key="chIndex">
                     <div class="branch-box" @click.prevent="clickHandle(schild)">
-                      <div class="branch-title">{{schild.post}}</div>
+                      <div class="branch-title">{{formatPost(schild.post)}}</div>
                       <img class="branch-pic" :src=schild.img>
                       <div class="branch-name">{{schild.label}}</div>
                       <div class="bz-box">
@@ -92,9 +92,9 @@
                   </li>
                 </ul>
               </li>
-              <li v-else :key="'no-child-' + cIndex" :class="{'odd': ((secretary.length%2) === 1&&!child.children)}">
+              <li v-else :key="'no-child-' + cIndex" :class="{'odd': ((secretary.length%2) === 1&&!child.children), 'safe-officer': child.post.trim() === '安全专员'}">
                 <div class="branch-box" @click.prevent="clickHandle(child)">
-                  <div class="branch-title">{{child.post}}</div>
+                  <div class="branch-title">{{formatPost(child.post)}}</div>
                   <img class="branch-pic" :src=child.img>
                   <div class="branch-name">{{child.label}}</div>
                   <div class="bz-box">
@@ -171,6 +171,14 @@ export default {
         }
       }
       return true
+    },
+    formatPost(post) {
+      if (!post) return ''
+      const postMap = {
+        '片区工长': '工长',
+        '职员': '计划员/文员'
+      }
+      return postMap[post.trim()] || post
     }
   }
 }
@@ -260,6 +268,11 @@ export default {
   ul li:only-child{
     padding-top: 0;
   }
+  // 倒班班长这一行增加卡牌的margin
+  ul.shift-leader-row li .branch-box {
+    margin-left: 160px;
+    margin-right: 160px;
+  }
   ul li:before{
     content: '';
     position: absolute;
@@ -285,6 +298,18 @@ export default {
   ul li:first-child:before,ul li:last-child:after{
     content: none;
   }
+  // 安全专员使用虚线
+  ul li.safe-officer:not(:first-child):before{
+    border-top: 2px dashed #2E6491;
+    border-right: 2px dashed #2E6491;
+  }
+  ul li.safe-officer:last-child:after{
+    content: none;
+  }
+  ul li.safe-officer:not(:last-child):after{
+    border-top: 2px dashed #2E6491;
+    border-left: 2px dashed #2E6491;
+  }
   ul:before{
     content: '';
     height: 22px;

+ 35 - 42
ui/src/views/plant/EOEGorganization/index.vue

@@ -148,7 +148,7 @@ export default {
       },
       units: [],
       teams: [],
-      actualposts: ["24","25", "26", "14", "16", "18", "20", "12", "10", "34", "36","15","11"],
+      actualposts: ["24","25", "26", "14", "16", "18", "20", "12", "10", "34", "36","15","11","22"],
       drawer: false,
       info: {},
       list0: [],
@@ -367,54 +367,28 @@ export default {
           console.log('安全专员')
           item.secretary = null
         }
-        if(this.$store.state.user.homeType == 5) { //合成器生产主管和工程师再一个位置
-          if (item.pId !== 0 && map[item.pId]) {
-            // map[item.pId].children ? map[item.pId].children.push(item) : map[item.pId].children = [item];
-            if (item.post == '安全专员' || item.post == '首席专家') {
-              map[item.pId].secretary ? map[item.pId].secretary[0].push(item) : map[item.pId].secretary[0] = [item];
-            } else if (item.post == '装置经理') {
-              map[item.pId].secretary ? map[item.pId].secretary[1].push(item) : map[item.pId].secretary[1] = [item];
-            } else if (item.post == '生产主管' || item.post == '工长') {
-              map[item.pId].secretary[2].push(item)
-            }else if ((item.post == '资深工程师' || item.post == '工程师') && map[item.pId].pId == 0) { //直属装置经理的资深工程师
-              map[item.pId].secretary ? map[item.pId].secretary[2].push(item) : map[item.pId].secretary[2] = [item];
-            } else if (item.post == '片区工长' || item.post == '职员' || item.post == '主操(白班)') {
-              // 如果是直接汇报给资深工程师,则放在资深工程师的下级层级
-              if (map[item.pId] && (map[item.pId].post == '资深工程师' || map[item.pId].post == '工程师')) {
-                map[item.pId].children ? map[item.pId].children.push(item) : map[item.pId].children = [item];
-              } else {
-                map[item.pId].secretary ? map[item.pId].secretary[3].push(item) : map[item.pId].secretary[3] = [item];
-              }
-            } else {
+        if (item.pId !== 0 && map[item.pId]) {
+          // map[item.pId].children ? map[item.pId].children.push(item) : map[item.pId].children = [item];
+          if (item.post == '首席专家' || item.post == '装置经理') {
+            map[item.pId].secretary ? map[item.pId].secretary[0].push(item) : map[item.pId].secretary[0] = [item];
+          } else if (item.post == '安全专员' || item.post == '生产主管' || item.post == '工长') {
+            map[item.pId].secretary ? map[item.pId].secretary[2].push(item) : map[item.pId].secretary[2] = [item];
+          }else if ((item.post == '资深工程师' || item.post == '工程师') && map[item.pId].pId == 0) { //直属装置经理的资深工程师
+            map[item.pId].secretary ? map[item.pId].secretary[2].push(item) : map[item.pId].secretary[2] = [item];
+          } else if (item.post == '片区工长' || item.post == '职员' || item.post == '主操(白班)') {
+            // 如果是直接汇报给资深工程师,则放在资深工程师的下级层级
+            if (map[item.pId] && (map[item.pId].post == '资深工程师' || map[item.pId].post == '工程师')) {
               map[item.pId].children ? map[item.pId].children.push(item) : map[item.pId].children = [item];
-            }
-          }
-        }else {
-          if (item.pId !== 0 && map[item.pId]) {
-            // map[item.pId].children ? map[item.pId].children.push(item) : map[item.pId].children = [item];
-            if (item.post == '安全专员'|| item.post == '首席专家') {
-              map[item.pId].secretary ? map[item.pId].secretary[0].push(item) : map[item.pId].secretary[0] = [item];
-            } else if (item.post == '装置经理') {
-              map[item.pId].secretary ? map[item.pId].secretary[1].push(item) : map[item.pId].secretary[1] = [item];
-            } else if (item.post == '生产主管' || item.post == '工长') {
-              map[item.pId].secretary[2].push(item)
-            }else if ((item.post == '资深工程师' || item.post == '工程师') && map[item.pId].pId == 0) { //直属装置经理的资深工程师
-              map[item.pId].secretary ? map[item.pId].secretary[2].push(item) : map[item.pId].secretary[2] = [item];
-            } else if (item.post == '片区工长' || item.post == '职员' || item.post == '主操(白班)') {
-              // 如果是直接汇报给资深工程师,则放在资深工程师的下级层级
-              if (map[item.pId] && (map[item.pId].post == '资深工程师' || map[item.pId].post == '工程师')) {
-                map[item.pId].children ? map[item.pId].children.push(item) : map[item.pId].children = [item];
-              } else {
-                map[item.pId].secretary ? map[item.pId].secretary[3].push(item) : map[item.pId].secretary[3] = [item];
-              }
             } else {
-              map[item.pId].children ? map[item.pId].children.push(item) : map[item.pId].children = [item];
+              map[item.pId].secretary ? map[item.pId].secretary[3].push(item) : map[item.pId].secretary[3] = [item];
             }
+          } else {
+            map[item.pId].children ? map[item.pId].children.push(item) : map[item.pId].children = [item];
           }
         }
       });
 
-      // 对每个节点的children进行重新排序
+      // 对每个节点的children和secretary进行重新排序
       list.forEach(item => {
         if (item.children && item.children.length > 0) {
           // 按照职位优先级排序:炉区工长 -> 装置副经理 -> 生产主管 -> 工长 -> 职员 -> 倒班班长 -> 主操(白班)
@@ -434,6 +408,25 @@ export default {
             return getPriority(a.post) - getPriority(b.post);
           });
         }
+        // 对secretary[2]进行排序,让安全专员排在最后
+        if (item.secretary && item.secretary[2] && item.secretary[2].length > 0) {
+          item.secretary[2].sort((a, b) => {
+            // 安全专员排在最后,其他按原顺序
+            if (a.post === '安全专员') return 1;
+            if (b.post === '安全专员') return -1;
+            // 其他职位按优先级排序
+            const getPriority = (post) => {
+              switch(post) {
+                case '生产主管': return 1;
+                case '工长': return 2;
+                case '资深工程师': return 3;
+                case '工程师': return 4;
+                default: return 5;
+              }
+            };
+            return getPriority(a.post) - getPriority(b.post);
+          });
+        }
       });
 
       return list.filter(item => {

+ 13 - 4
ui/src/views/production/temperature/coil.vue

@@ -454,9 +454,16 @@
             const historicalData = [];
             const predictPoints = [];
 
+            // 获取斜率值,用于判断是否显示预测点
+            const slope = parseFloat(chartData.slope) || 0;
+
             chartData.chartData.forEach(item => {
               if (item.value === 1080 && chartData.predictedDate && item.date === chartData.predictedDate) {
-                predictPoints.push([item.date, item.value]);
+                // 只有当斜率不为负时才添加预测点
+                if (slope >= 0) {
+                  predictPoints.push([item.date, item.value]);
+                }
+                // 斜率为负时,不添加预测点
               } else {
                 historicalData.push([item.date, item.value]);
               }
@@ -529,14 +536,16 @@
         const dates = this.predictChartData.scatterData.map(item => item[0]).sort();
         const minDate = dates[0];
         const maxDate = dates[dates.length - 1];
-        const endDate = this.predictChartData.predictedDate && this.predictChartData.predictedDate !== '-'
-          ? this.predictChartData.predictedDate : maxDate;
+
+        // 判断斜率是否为负,如果为负则只显示到最大历史数据日期
+        const slope = parseFloat(this.predictChartData.slope) || 0;
+        const endDate = (slope < 0 || !this.predictChartData.predictedDate || this.predictChartData.predictedDate === '-')
+          ? maxDate : this.predictChartData.predictedDate;
 
         // 生成完整时间轴
         const fullDateRange = generateFullDateRange(minDate, endDate);
 
         // 计算回归线端点
-        const slope = parseFloat(this.predictChartData.slope) || 0;
         const intercept = extractIntercept(this.predictChartData.equation || "y = 0x + 0");
         const minDay = Math.floor((new Date(minDate) - new Date(minDate)) / (1000 * 60 * 60 * 24)) + 1;
         const endDay = Math.floor((new Date(endDate) - new Date(minDate)) / (1000 * 60 * 60 * 24)) + 1;

+ 31 - 29
ui/src/views/reliability/rel_compo/index.vue

@@ -132,10 +132,10 @@
       <el-table-column label="部件描述" align="center" prop="compoDesc" width="180" :show-overflow-tooltip="true"/>
       <el-table-column label="部件照片" align="center" prop="compoPhoto" width="100">
         <template slot-scope="scope">
-          <el-button 
-            v-if="scope.row.compoPhoto" 
-            size="mini" 
-            type="text" 
+          <el-button
+            v-if="scope.row.compoPhoto"
+            size="mini"
+            type="text"
             icon="el-icon-picture"
             @click="handleViewPhoto(scope.row.compoPhoto)">
             查看
@@ -269,7 +269,7 @@
           <el-row :gutter="20">
             <el-col :span="24">
               <el-form-item label="部件描述" prop="compoDesc">
-                <el-input v-model="form.compoDesc" type="textarea" :rows="2" placeholder="请输入部件描述" />
+                <el-input v-model="form.compoDesc" type="textarea" :rows="1" placeholder="请输入部件描述" />
               </el-form-item>
             </el-col>
           </el-row>
@@ -298,7 +298,7 @@
           <el-row :gutter="20">
             <el-col :span="24">
               <el-form-item label="备注" prop="remarks">
-                <el-input v-model="form.remarks" type="textarea" :rows="2" placeholder="请输入备注" />
+                <el-input v-model="form.remarks" type="textarea" :rows="1" placeholder="请输入备注" />
               </el-form-item>
             </el-col>
           </el-row>
@@ -359,7 +359,7 @@
           <el-row :gutter="20">
             <el-col :span="24">
               <el-form-item label="检查内容" prop="inspContent">
-                <el-input v-model="form.inspContent" type="textarea" :rows="3" placeholder="请输入检查内容" />
+                <el-input v-model="form.inspContent" type="textarea" :rows="1" placeholder="请输入检查内容" />
               </el-form-item>
             </el-col>
           </el-row>
@@ -386,7 +386,7 @@
           <el-row :gutter="20">
             <el-col :span="24">
               <el-form-item label="维修内容" prop="fixContent">
-                <el-input v-model="form.fixContent" type="textarea" :rows="3" placeholder="请输入维修内容" />
+                <el-input v-model="form.fixContent" type="textarea" :rows="1" placeholder="请输入维修内容" />
               </el-form-item>
             </el-col>
           </el-row>
@@ -413,7 +413,7 @@
           <el-row :gutter="20">
             <el-col :span="24">
               <el-form-item label="更换内容" prop="replaceContent">
-                <el-input v-model="form.replaceContent" type="textarea" :rows="3" placeholder="请输入更换内容" />
+                <el-input v-model="form.replaceContent" type="textarea" :rows="1" placeholder="请输入更换内容" />
               </el-form-item>
             </el-col>
           </el-row>
@@ -432,7 +432,7 @@
                   :limit="1"
                   accept=".xlsx, .xls"
                   :headers="upload.headers"
-                  :action="upload.url + '?updateSupport=' + upload.updateSupport"
+                  :action="upload.url + '?updateSupport=1'"
                   :disabled="upload.isUploading"
                   :on-progress="handleFileUploadProgress"
                   :on-success="handleFileSuccess"
@@ -445,8 +445,10 @@
                   <em>点击上传</em>
               </div>
               <div class="el-upload__tip" slot="tip">
-                  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
                   <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+                  <form ref="downloadFileForm" :action="upload.downloadAction" target="FORMSUBMIT">
+                    <input name="type" :value="upload.type" hidden/>
+                  </form>
               </div>
               <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
           </el-upload>
@@ -503,18 +505,20 @@ export default {
       open: false,
         // 用户导入参数
         upload: {
-            // 是否显示弹出层(用户导入)
-            open: false,
-            // 弹出层标题(用户导入)
-            title: "",
-            // 是否禁用上传
-            isUploading: false,
-            // 是否更新已经存在的用户数据
-            updateSupport: 0,
-            // 设置上传的请求头部
-            headers: { Authorization: "Bearer " + getToken() },
-            // 上传的地址
-            url: process.env.VUE_APP_BASE_API + "/reliability/rel_compo/importData"
+          //下载模板请求地址
+          downloadAction: process.env.VUE_APP_BASE_API + '/common/template',
+          //下载模板类型
+          type: 'rel_compo',
+          // 是否显示弹出层(用户导入)
+          open: false,
+          // 弹出层标题(用户导入)
+          title: "",
+          // 是否禁用上传
+          isUploading: false,
+          // 设置上传的请求头部
+          headers: { Authorization: "Bearer " + getToken() },
+          // 上传的地址
+          url: process.env.VUE_APP_BASE_API + "/reliability/rel_compo/importData"
         },
       // 部件照片上传参数
       uploadPhoto: {
@@ -771,9 +775,7 @@ export default {
       },
       /** 下载模板操作 */
       importTemplate() {
-          importTemplate().then(response => {
-              this.download(response.msg);
-          });
+        this.$refs['downloadFileForm'].submit()
       },
       // 文件上传中处理
       handleFileUploadProgress(event, file, fileList) {
@@ -811,18 +813,18 @@ export default {
       /** 图片上传成功回调 */
       handlePhotoSuccess(response, file, fileList) {
         console.log('上传接口返回数据:', response);
-        
+
         // 若依框架上传接口返回格式
         if (response && response.fileName) {
           // 保存文件路径到表单(相对路径)
           this.form.compoPhoto = response.fileName;
-          
+
           // 构建完整URL用于预览
           let imageUrl = response.url || response.fileName;
           if (imageUrl && !imageUrl.startsWith('http')) {
             imageUrl = process.env.VUE_APP_BASE_API + imageUrl;
           }
-          
+
           this.photoFileList = [{
             name: file.name,
             url: imageUrl

+ 13 - 11
ui/src/views/reliability/rel_device/index.vue

@@ -149,10 +149,10 @@
       </el-table-column>
       <el-table-column label="设备照片" align="center" prop="devPhoto" width="100">
         <template slot-scope="scope">
-          <el-button 
-            v-if="scope.row.devPhoto" 
-            size="mini" 
-            type="text" 
+          <el-button
+            v-if="scope.row.devPhoto"
+            size="mini"
+            type="text"
             icon="el-icon-picture"
             @click="handleViewPhoto(scope.row.devPhoto)">
             查看
@@ -254,7 +254,7 @@
                   :limit="1"
                   accept=".xlsx, .xls"
                   :headers="upload.headers"
-                  :action="upload.url + '?updateSupport=' + upload.updateSupport"
+                  :action="upload.url + '?updateSupport=1'"
                   :disabled="upload.isUploading"
                   :on-progress="handleFileUploadProgress"
                   :on-success="handleFileSuccess"
@@ -267,8 +267,10 @@
                   <em>点击上传</em>
               </div>
               <div class="el-upload__tip" slot="tip">
-                  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
                   <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+                <form ref="downloadFileForm" :action="upload.downloadAction" target="FORMSUBMIT">
+                  <input name="type" :value="upload.type" hidden/>
+                </form>
               </div>
               <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
           </el-upload>
@@ -325,14 +327,16 @@ export default {
       open: false,
         // 用户导入参数
         upload: {
+          //下载模板请求地址
+          downloadAction: process.env.VUE_APP_BASE_API + '/common/template',
+          //下载模板类型
+          type: 'rel_device',
             // 是否显示弹出层(用户导入)
             open: false,
             // 弹出层标题(用户导入)
             title: "",
             // 是否禁用上传
             isUploading: false,
-            // 是否更新已经存在的用户数据
-            updateSupport: 0,
             // 设置上传的请求头部
             headers: { Authorization: "Bearer " + getToken() },
             // 上传的地址
@@ -551,9 +555,7 @@ export default {
       },
       /** 下载模板操作 */
       importTemplate() {
-          importTemplate().then(response => {
-              this.download(response.msg);
-          });
+        this.$refs['downloadFileForm'].submit()
       },
       // 文件上传中处理
       handleFileUploadProgress(event, file, fileList) {

+ 5 - 3
ui/src/views/reliability/rel_device/process-diagram.vue

@@ -29,7 +29,7 @@
 		>
 		  <object
 			ref="svgObject"
-			:data="svgPath"
+			:data= this.defaultSvgPath
 			type="image/svg+xml"
 			@load="initSvg"
 			class="svg-object"
@@ -100,11 +100,13 @@
       // SVG文件路径
       svgPath: {
         type: String,
-        default: '/visio/diagram.svg'
+        default: ''
       }
     },
     data() {
       return {
+        // 默认 SVG 路径
+        defaultSvgPath: require('@/assets/visio/diagram.svg'),
         // vue-draggable-resizable 相关
         svgPosition: { x: 0, y: 0 },
         svgSize: { width: 1200, height: 900 },
@@ -157,7 +159,7 @@
       // 计算缩放百分比
       scalePercentage() {
         return Math.round(this.scale * 100);
-      }
+      },
     },
 
     methods: {

+ 958 - 0
ui/src/views/reliability/rel_maint_plan/index.vue

@@ -0,0 +1,958 @@
+<template>
+  <div class="app-container rel-maint-plan-page">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="装置" prop="plant">
+        <el-input
+          v-model="queryParams.plant"
+          placeholder="请输入装置"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="设备名称" prop="devName">
+        <el-input
+          v-model="queryParams.devName"
+          placeholder="请输入设备名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="设备位号" prop="devTag">
+        <el-input
+          v-model="queryParams.devTag"
+          placeholder="请输入设备位号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="计划维修时间" prop="planTime">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.planTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择计划维修时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="计划审批状态" prop="approvalStatus">
+        <el-select v-model="queryParams.approvalStatus" placeholder="请选择计划审批状态" clearable size="small">
+          <el-option label="待审批" value="0" />
+          <el-option label="已通过" value="1" />
+          <el-option label="未通过" value="-1" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="计划完成状态" prop="completionStatus">
+        <el-select v-model="queryParams.completionStatus" placeholder="请选择计划完成状态" clearable size="small">
+          <el-option label="未完成" value="0" />
+          <el-option label="已完成" value="1" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['reliability:rel_maint_plan:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5" v-if="!hasApprovalStatus">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['reliability:rel_maint_plan:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5" v-if="!hasApprovalStatus">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['reliability:rel_maint_plan:remove']"
+        >删除</el-button>
+      </el-col>
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="warning"-->
+<!--          icon="el-icon-download"-->
+<!--          size="mini"-->
+<!--          @click="handleExport"-->
+<!--          v-hasPermi="['reliability:rel_maint_plan:list']"-->
+<!--        >导出</el-button>-->
+<!--      </el-col>-->
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="rel_maint_planList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="装置" align="center" prop="plant" width="120" :show-overflow-tooltip="true"/>
+      <el-table-column label="设备名称" align="center" prop="devName" width="150" :show-overflow-tooltip="true"/>
+      <el-table-column label="设备位号" align="center" prop="devTag" width="150" :show-overflow-tooltip="true"/>
+      <el-table-column label="计划维修时间" align="center" prop="planTime" width="120">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.planTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="计划审批状态" align="center" prop="approvalStatus" width="120" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.approvalStatus === '0'" type="warning" size="mini">待审批</el-tag>
+          <el-tag v-else-if="scope.row.approvalStatus === '1'" type="success" size="mini">已通过</el-tag>
+          <el-tag v-else-if="scope.row.approvalStatus === '-1'" type="danger" size="mini">未通过</el-tag>
+          <span v-else>{{ scope.row.approvalStatus }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="责任人" align="center" prop="responsible" width="100" :show-overflow-tooltip="true"/>
+      <el-table-column label="计划完成状态" align="center" prop="completionStatus" width="120" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.completionStatus === '0'" type="info" size="mini">未完成</el-tag>
+          <el-tag v-else-if="scope.row.completionStatus === '1'" type="success" size="mini">已完成</el-tag>
+          <span v-else>{{ scope.row.completionStatus }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="审批人" align="center" prop="approver" width="100" :show-overflow-tooltip="true"/>
+      <el-table-column label="备注" align="center" prop="remarks"  :show-overflow-tooltip="true"/>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['reliability:rel_maint_plan:edit']"
+          >修改</el-button>
+          <el-button
+            v-if="scope.row.approvalStatus !== '0'"
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['reliability:rel_maint_plan:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改设备维修计划对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="1200px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <!-- 基础信息区域 -->
+        <div class="form-section">
+          <div class="section-header">
+            <i class="el-icon-info"></i>
+            <span class="section-title">基础信息</span>
+          </div>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="选择设备" prop="devId">
+                <el-select
+                  v-model="form.devId"
+                  filterable
+                  remote
+                  :remote-method="searchDevice"
+                  :loading="deviceLoading"
+                  placeholder="请输入设备位号或名称搜索"
+                  style="width: 100%"
+                  @change="handleDeviceChange"
+                  @focus="handleDeviceFocus"
+                  :disabled="!!form.planId"
+                  clearable>
+                  <el-option
+                    v-for="device in deviceOptions"
+                    :key="device.devId"
+                    :label="`${device.devTag} - ${device.devName}`"
+                    :value="device.devId">
+                    <span style="float: left">{{ device.devTag }}</span>
+                    <span style="float: right; color: #8492a6; font-size: 13px">{{ device.devName }}</span>
+                  </el-option>
+                  <div v-if="deviceOptions.length === 0 && !deviceLoading" style="padding: 10px; text-align: center; color: #909399;">
+                    请输入设备位号或名称进行搜索
+                  </div>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="计划维修时间" prop="planTime">
+                <el-date-picker
+                  v-model="form.planTime"
+                  type="date"
+                  value-format="yyyy-MM-dd"
+                  placeholder="选择计划维修时间"
+                  style="width: 100%">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="责任人" prop="responsible">
+                <el-input v-model="form.responsible" placeholder="请输入责任人" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="审批人" prop="approver">
+                <el-select
+                  v-model="form.approver"
+                  placeholder="请选择审批人"
+                  style="width: 100%"
+                  clearable
+                  filterable>
+                  <el-option
+                    v-for="staff in staffOptions"
+                    :key="staff.staffid"
+                    :label="staff.name"
+                    :value="staff.name">
+                  </el-option>
+                  <div v-if="staffOptions.length === 0" style="padding: 10px; text-align: center; color: #909399;">
+                    暂无人员数据
+                  </div>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="24">
+              <el-form-item label="备注" prop="remarks">
+                <el-input v-model="form.remarks" type="textarea" :rows="2" placeholder="请输入备注" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </div>
+
+        <!-- 设备信息展示 -->
+        <div class="form-section" v-if="selectedDevice">
+          <div class="section-header">
+            <i class="el-icon-s-platform"></i>
+            <span class="section-title">设备信息</span>
+          </div>
+          <el-descriptions :column="3" border size="small">
+            <el-descriptions-item label="装置">{{ selectedDevice.plant }}</el-descriptions-item>
+            <el-descriptions-item label="设备位号">{{ selectedDevice.devTag }}</el-descriptions-item>
+            <el-descriptions-item label="设备名称">{{ selectedDevice.devName }}</el-descriptions-item>
+            <el-descriptions-item label="位置">{{ selectedDevice.devLoc }}</el-descriptions-item>
+            <el-descriptions-item label="设备类型">{{ selectedDevice.devType }}</el-descriptions-item>
+            <el-descriptions-item label="区域负责人">{{ selectedDevice.areaResponsible }}</el-descriptions-item>
+          </el-descriptions>
+        </div>
+
+        <!-- 部件列表及维修记录选择 -->
+        <div class="form-section" v-if="compoList.length > 0">
+          <div class="section-header">
+            <i class="el-icon-s-grid"></i>
+            <span class="section-title">部件维修选择</span>
+          </div>
+          <el-table
+            :data="compoList"
+            border
+            size="small"
+            :height="500"
+            style="margin-top: 10px">
+            <el-table-column type="index" label="序号" width="60" align="center" />
+            <el-table-column label="部件名称" prop="compoName" width="150" :show-overflow-tooltip="true" />
+            <el-table-column label="检查频率/日期" width="120" align="center">
+              <template slot-scope="scope">
+                <div style="line-height: 1.2;">
+                  <div style="font-weight: bold; margin-bottom: 2px;">{{ translateFrequency(scope.row.checkFreq) || '-' }}</div>
+                  <div style="font-size: 12px; color: #666;">{{ scope.row.lastCheckDate ? parseTime(scope.row.lastCheckDate, '{y}-{m}-{d}') : '-' }}</div>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="维修频率/日期" width="120" align="center">
+              <template slot-scope="scope">
+                <div style="line-height: 1.2;">
+                  <div style="font-weight: bold; margin-bottom: 2px;">{{ translateFrequency(scope.row.maintFreq) || '-' }}</div>
+                  <div style="font-size: 12px; color: #666;">{{ scope.row.lastMaintDate ? parseTime(scope.row.lastMaintDate, '{y}-{m}-{d}') : '-' }}</div>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="更换频率/日期" width="120" align="center">
+              <template slot-scope="scope">
+                <div style="line-height: 1.2;">
+                  <div style="font-weight: bold; margin-bottom: 2px;">{{ translateFrequency(scope.row.replaceFreq) || '-' }}</div>
+                  <div style="font-size: 12px; color: #666;">{{ scope.row.lastReplaceDate ? parseTime(scope.row.lastReplaceDate, '{y}-{m}-{d}') : '-' }}</div>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="本次维修" width="100" align="center">
+              <template slot-scope="scope">
+                <el-checkbox v-model="scope.row.needMaint" @change="handleMaintCheckChange(scope.row)">需要维修</el-checkbox>
+              </template>
+            </el-table-column>
+            <el-table-column label="维修形式" width="200" align="center">
+              <template slot-scope="scope">
+                <el-radio-group
+                  v-model="scope.row.maintType"
+                  :disabled="!scope.row.needMaint"
+                  @change="handleMaintTypeChange(scope.row)"
+                  style="display: flex; flex-direction: row; gap: 0px;">
+                  <el-radio label="1" style="margin-right: 0; margin-left: 0;">检查</el-radio>
+                  <el-radio label="2" style="margin-right: 0; margin-left: 0;">维修</el-radio>
+                  <el-radio label="3" style="margin-right: 0; margin-left: 0;">更换</el-radio>
+                </el-radio-group>
+              </template>
+            </el-table-column>
+            <el-table-column label="负责人" width="150" align="center">
+              <template slot-scope="scope">
+                <el-select
+                  v-model="scope.row.maintResponsible"
+                  :placeholder="getResponsiblePlaceholder(scope.row.maintType)"
+                  style="width: 100%"
+                  :disabled="!scope.row.needMaint"
+                  clearable
+                  filterable>
+                  <el-option
+                    v-for="staff in staffOptions"
+                    :key="staff.staffid"
+                    :label="staff.name"
+                    :value="staff.name">
+                  </el-option>
+                </el-select>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+
+        <!-- 修改模式额外字段 -->
+        <div class="form-section" v-if="form.planId">
+          <div class="section-header">
+            <i class="el-icon-setting"></i>
+            <span class="section-title">状态管理</span>
+          </div>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="计划审批状态">
+                <el-radio-group v-model="form.approvalStatus">
+                  <el-radio label="0">待审批</el-radio>
+                  <el-radio label="1">已通过</el-radio>
+                  <el-radio label="-1">未通过</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="计划完成状态">
+                <el-radio-group v-model="form.completionStatus">
+                  <el-radio label="0">未完成</el-radio>
+                  <el-radio label="1">已完成</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </div>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm" v-if="!form.planId">提交申请</el-button>
+        <el-button type="primary" @click="submitForm" v-else>确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+      <!-- 用户导入对话框 -->
+      <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+          <el-upload
+                  ref="upload"
+                  :limit="1"
+                  accept=".xlsx, .xls"
+                  :headers="upload.headers"
+                  :action="upload.url + '?updateSupport=' + upload.updateSupport"
+                  :disabled="upload.isUploading"
+                  :on-progress="handleFileUploadProgress"
+                  :on-success="handleFileSuccess"
+                  :auto-upload="false"
+                  drag
+          >
+              <i class="el-icon-upload"></i>
+              <div class="el-upload__text">
+                  将文件拖到此处,或
+                  <em>点击上传</em>
+              </div>
+              <div class="el-upload__tip" slot="tip">
+                  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
+                  <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+              </div>
+              <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+          </el-upload>
+          <div slot="footer" class="dialog-footer">
+              <el-button type="primary" @click="submitFileForm">确 定</el-button>
+              <el-button @click="upload.open = false">取 消</el-button>
+          </div>
+      </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listRel_maint_plan, getRel_maint_plan, delRel_maint_plan, addRel_maint_plan, updateRel_maint_plan, exportRel_maint_plan, importTemplate, submitApprove} from "@/api/reliability/rel_maint_plan";
+import { listRel_device, getRel_device } from "@/api/reliability/rel_device";
+import { listRel_compo } from "@/api/reliability/rel_compo";
+import { listRel_maint_record } from "@/api/reliability/rel_maint_record";
+import { listUser } from "@/api/system/user";
+import { listStaffmgr, listStaffmgrAll } from "@/api/plant/staffmgr";
+import { treeselect } from "@/api/system/dept";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "Rel_maint_plan",
+  components: { Treeselect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 设备维修计划表格数据
+      rel_maint_planList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+        // 用户导入参数
+        upload: {
+            // 是否显示弹出层(用户导入)
+            open: false,
+            // 弹出层标题(用户导入)
+            title: "",
+            // 是否禁用上传
+            isUploading: false,
+            // 是否更新已经存在的用户数据
+            updateSupport: 0,
+            // 设置上传的请求头部
+            headers: { Authorization: "Bearer " + getToken() },
+            // 上传的地址
+            url: process.env.VUE_APP_BASE_API + "/reliability/rel_maint_plan/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        plant: null,
+        devName: null,
+        devTag: null,
+        planTime: null,
+        approvalStatus: null,
+        responsible: null,
+        completionStatus: null,
+        processId: null,
+        approver: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        devId: [
+          { required: true, message: "请选择设备", trigger: "change" }
+        ],
+        planTime: [
+          { required: true, message: "请选择计划维修时间", trigger: "change" }
+        ],
+        approver: [
+          { required: true, message: "请选择审批人", trigger: "change" }
+        ]
+      },
+      // 设备相关
+      deviceOptions: [],
+      deviceLoading: false,
+      selectedDevice: null,
+      // 部件相关
+      compoList: [],
+      // 审批人相关
+      approverOptions: [],
+      approverLoading: false,
+      // 所有人员选项
+      staffOptions: []
+    };
+  },
+  computed: {
+    // 判断选中的条目中是否有审批中的状态
+    hasApprovalStatus() {
+      return this.ids.some(id => {
+        const item = this.rel_maint_planList.find(row => row.planId === id);
+        return item && item.approvalStatus === '0';
+      });
+    }
+  },
+  watch: {
+        // 根据名称筛选部门树
+        deptName(val) {
+            this.$refs.tree.filter(val);
+        }
+   },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+    this.getStaffList(); // 加载所有人员
+  },
+  methods: {
+    /** 查询人员列表 */
+    getStaffList() {
+      listStaffmgrAll().then(response => {
+        console.log('人员数据响应:', response);
+        this.staffOptions = response.rows || response.data || [];
+        console.log('staffOptions:', this.staffOptions);
+      }).catch(error => {
+        console.error('加载人员数据失败:', error);
+      });
+    },
+    getList() {
+      this.loading = true;
+      listRel_maint_plan(this.queryParams).then(response => {
+        this.rel_maint_planList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        planId: null,
+        devId: null,
+        plant: null,
+        devName: null,
+        devTag: null,
+        planTime: null,
+        approvalStatus: "0",
+        responsible: null,
+        completionStatus: "0",
+        processId: null,
+        approver: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null,
+        // 维修记录关联
+        compoRecords: []
+      };
+      this.selectedDevice = null;
+      this.compoList = [];
+      this.deviceOptions = [];
+      this.approverOptions = [];
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.planId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加设备维修计划";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const planId = row.planId || this.ids
+      getRel_maint_plan(planId).then(response => {
+        this.form = response.data;
+
+        // 如果有设备ID,加载设备信息和部件列表
+        if (this.form.devId) {
+          this.loadDeviceInfo(this.form.devId);
+        }
+
+        this.open = true;
+        this.title = "修改设备维修计划";
+      });
+    },
+    /** 设备下拉框获得焦点 */
+    handleDeviceFocus() {
+      // 如果没有数据且没有在加载,可以加载一些初始数据
+      if (this.deviceOptions.length === 0 && !this.deviceLoading) {
+        // 可以加载最近的设备或空列表
+        // this.searchDevice('');
+      }
+    },
+    /** 设备选择改变 */
+    handleDeviceChange(devId) {
+      if (!devId) {
+        this.selectedDevice = null;
+        this.compoList = [];
+        return;
+      }
+
+      // 获取设备详情
+      getRel_device(devId).then(response => {
+        this.selectedDevice = response.data;
+        this.form.plant = response.data.plant;
+        this.form.devName = response.data.devName;
+        this.form.devTag = response.data.devTag;
+
+        // 加载该设备的部件列表
+        this.loadCompoList(devId);
+      });
+    },
+    /** 搜索设备 */
+    searchDevice(query) {
+      if (query !== '') {
+        this.deviceLoading = true;
+        listRel_device({
+          devTag: query,
+          devName: query,
+          pageNum: 1,
+          pageSize: 50
+        }).then(response => {
+          this.deviceOptions = response.rows || [];
+          this.deviceLoading = false;
+        }).catch(() => {
+          this.deviceLoading = false;
+          this.deviceOptions = [];
+        });
+      } else {
+        this.deviceOptions = [];
+      }
+    },
+    /** 加载设备信息 */
+    loadDeviceInfo(devId) {
+      // 获取设备详情
+      getRel_device(devId).then(response => {
+        this.selectedDevice = response.data;
+
+        // 加载该设备的部件列表
+        this.loadCompoList(devId);
+      });
+    },
+    /** 加载部件列表 */
+    loadCompoList(devId) {
+      listRel_compo({
+        devTag: this.selectedDevice.devTag,
+        pageNum: 1,
+        pageSize: 1000
+      }).then(response => {
+        const compos = response.rows || [];
+        // 为每个部件初始化维修记录数组
+        this.compoList = compos.map(compo => ({
+          ...compo,
+          // 维修计划相关字段
+          needMaint: false,
+          maintType: '',
+          maintResponsible: '',
+          // 频率和日期字段 - 使用正确的字段名
+          checkFreq: compo.inspFreq || '',
+          lastCheckDate: compo.lastInspDate || '',
+          maintFreq: compo.fixFreq || '',
+          lastMaintDate: compo.lastFixDate || '',
+          replaceFreq: compo.replaceFreq || '',
+          lastReplaceDate: compo.lastReplaceDate || '',
+          // 负责人字段
+          inspector: compo.inspector || '',  // 检查人
+          fixer: compo.fixer || '',          // 维修更换人
+          inspectorName: compo.inspectorName || '',  // 检查人姓名
+          fixerName: compo.fixerName || '',          // 维修更换人姓名
+          // 负责人搜索相关
+          responsibleOptions: [],
+          responsibleLoading: false,
+          // 原有的维修记录相关(保留用于修改模式)
+          selectedRecords: [],
+          maintRecords: [],
+          recordLoading: false
+        }));
+
+        // 为每个部件加载可选的维修记录(修改模式)
+        if (this.form.planId) {
+          this.compoList.forEach(compo => {
+            this.loadMaintRecords(compo);
+          });
+        }
+      });
+    },
+    /** 加载维修记录 */
+    loadMaintRecords(compo) {
+      compo.recordLoading = true;
+      listRel_maint_record({
+        compoId: compo.compoId,
+        pageNum: 1,
+        pageSize: 1000
+      }).then(response => {
+        compo.maintRecords = (response.rows || []).map(record => ({
+          ...record,
+          // 确保maintContent是纯文本(去除HTML标签)
+          maintContent: record.maintContent ? String(record.maintContent).replace(/<[^>]+>/g, '').trim() : ''
+        }));
+        compo.recordLoading = false;
+      }).catch(() => {
+        compo.recordLoading = false;
+        compo.maintRecords = [];
+      });
+    },
+    /** 维修记录选择改变 */
+    handleRecordChange(compo) {
+      // 可以在这里添加其他逻辑
+    },
+    /** 维修负责人搜索 */
+    /** 维修选择改变 */
+    handleMaintCheckChange(compo) {
+      if (!compo.needMaint) {
+        // 如果取消维修,清空相关字段
+        compo.maintType = '';
+        compo.maintResponsible = '';
+      }
+    },
+    /** 维修形式改变 */
+    handleMaintTypeChange(compo) {
+      // 根据维修形式自动设置负责人
+      if (compo.maintType === '1') {
+        // 检查 - 使用检查人姓名
+        compo.maintResponsible = compo.inspectorName || '';
+      } else if (compo.maintType === '2' || compo.maintType === '3') {
+        // 维修或更换 - 使用维修更换人姓名
+        compo.maintResponsible = compo.fixerName || '';
+      } else {
+        // 其他情况清空负责人选择
+        compo.maintResponsible = '';
+      }
+    },
+    /** 根据姓名获取工号 */
+    getStaffIdByName(name) {
+      if (!name) return '';
+      const staff = this.staffOptions.find(s => s.name === name);
+      return staff ? staff.staffid : '';
+    },
+    getResponsiblePlaceholder(maintType) {
+      switch(maintType) {
+        case '1': return '选择检查人';
+        case '2': return '选择维修人';
+        case '3': return '选择更换人';
+        default: return '选择负责人';
+      }
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          // 收集需要维修的部件信息
+          if (!this.form.planId && this.compoList.length > 0) {
+            // 收集需要维修的部件,转换为TRelMaintRecord格式
+            const maintComponents = this.compoList
+              .filter(compo => compo.needMaint)
+              .map(compo => ({
+                compoId: compo.compoId,
+                compoName: compo.compoName,
+                maintType: compo.maintType,
+                responsible: this.getStaffIdByName(compo.maintResponsible), // 转换为工号
+                // 可以添加其他需要的字段
+                inspectContent: '', // 检查内容
+                maintContent: '', // 维修内容
+                maintResult: '', // 维修结果
+                maintCost: null, // 维修费用
+                maintDuration: null, // 维修时长
+                processLoss: '', // 工艺损失
+                attachments: '', // 附件
+                remarks: '' // 备注
+              }));
+
+            this.form.maintComponents = maintComponents;
+            console.log('收集到的维修部件:', maintComponents);
+          }
+
+          console.log('提交的表单数据:', this.form);
+
+          // 转换审批人姓名为工号
+          if (this.form.approver) {
+            this.form.approver = this.getStaffIdByName(this.form.approver);
+          }
+
+          if (this.form.planId != null) {
+            // 修改模式
+            updateRel_maint_plan(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            // 新增模式 - 提交申请
+            submitApprove(this.form).then(response => {
+              this.msgSuccess("维修计划申请提交成功");
+              this.open = false;
+              this.getList();
+            }).catch(error => {
+              this.msgError("提交失败:" + (error.message || "未知错误"));
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const planIds = row.planId || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delRel_maint_plan(planIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有设备维修计划数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportRel_maint_plan(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        })
+    },
+      /** 导入按钮操作 */
+      handleImport() {
+          this.upload.title = "用户导入";
+          this.upload.open = true;
+      },
+      /** 下载模板操作 */
+      importTemplate() {
+          importTemplate().then(response => {
+              this.download(response.msg);
+          });
+      },
+      // 文件上传中处理
+      handleFileUploadProgress(event, file, fileList) {
+          this.upload.isUploading = true;
+      },
+      // 文件上传成功处理
+      handleFileSuccess(response, file, fileList) {
+          this.upload.open = false;
+          this.upload.isUploading = false;
+          this.$refs.upload.clearFiles();
+          this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
+          this.getList();
+      },
+      // 提交上传文件
+      submitFileForm() {
+          this.$refs.upload.submit();
+      },
+      /** 翻译频率字段 */
+      translateFrequency(frequency) {
+        if (!frequency) return '';
+
+        // 匹配数字和单位
+        const match = frequency.match(/^(\d+)([ym])$/);
+        if (match) {
+          const number = match[1];
+          const unit = match[2];
+
+          switch (unit) {
+            case 'y':
+              return `${number}年一次`;
+            case 'm':
+              return `${number}月一次`;
+            default:
+              return frequency;
+          }
+        }
+
+        return frequency;
+      }
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.form-section {
+  margin-bottom: 20px;
+
+  .section-header {
+    display: flex;
+    align-items: center;
+    margin-bottom: 15px;
+    padding-bottom: 10px;
+    border-bottom: 1px solid #e4e7ed;
+
+    .el-icon-info,
+    .el-icon-s-platform,
+    .el-icon-s-grid {
+      font-size: 18px;
+      color: #409EFF;
+      margin-right: 8px;
+    }
+
+    .section-title {
+      font-size: 16px;
+      font-weight: 600;
+      color: #303133;
+    }
+  }
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+// 紧凑的radio按钮样式 - 仅影响维修计划页面的维修形式列
+.rel-maint-plan-page ::v-deep .el-table .el-radio__label {
+  padding-left: 2px !important;
+}
+</style>

+ 587 - 0
ui/src/views/reliability/rel_maint_record/index.vue

@@ -0,0 +1,587 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="装置" prop="plant">
+        <el-input
+          v-model="queryParams.plant"
+          placeholder="请输入装置"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="设备名称" prop="devName">
+        <el-input
+          v-model="queryParams.devName"
+          placeholder="请输入设备名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="设备位号" prop="devTag">
+        <el-input
+          v-model="queryParams.devTag"
+          placeholder="请输入设备位号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="部件名称" prop="compoName">
+        <el-input
+          v-model="queryParams.compoName"
+          placeholder="请输入部件名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="维修类型" prop="maintType">
+        <el-select v-model="queryParams.maintType" placeholder="请选择维修类型" clearable size="small">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="维修部门" prop="maintDept">
+        <el-input
+          v-model="queryParams.maintDept"
+          placeholder="请输入维修部门"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['reliability:rel_maint_record:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['reliability:rel_maint_record:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['reliability:rel_maint_record:remove']"
+        >删除</el-button>
+      </el-col>
+        <el-col :span="1.5">
+            <el-button
+                    type="info"
+                    icon="el-icon-upload2"
+                    size="mini"
+                    @click="handleImport"
+                    v-hasPermi="['reliability:rel_maint_record:edit']"
+            >导入</el-button>
+        </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['reliability:rel_maint_record:list']"
+        >导出</el-button>
+      </el-col>
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="rel_maint_recordList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="记录ID" align="center" prop="recordId" :show-overflow-tooltip="true"/>
+      <el-table-column label="装置" align="center" prop="plant" :show-overflow-tooltip="true"/>
+      <el-table-column label="设备名称" align="center" prop="devName" :show-overflow-tooltip="true"/>
+      <el-table-column label="设备位号" align="center" prop="devTag" :show-overflow-tooltip="true"/>
+      <el-table-column label="部件名称" align="center" prop="compoName" :show-overflow-tooltip="true"/>
+      <el-table-column label="部件ID" align="center" prop="compoId" :show-overflow-tooltip="true"/>
+      <el-table-column label="维修类型" align="center" prop="maintType" :show-overflow-tooltip="true"/>
+      <el-table-column label="维修部门" align="center" prop="maintDept" :show-overflow-tooltip="true"/>
+      <el-table-column label="检查人" align="center" prop="inspector" :show-overflow-tooltip="true"/>
+      <el-table-column label="检查内容" align="center" prop="inspectContent" :show-overflow-tooltip="true"/>
+      <el-table-column label="检查时间" align="center" prop="inspectTime" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.inspectTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="维修责任人" align="center" prop="responsible" :show-overflow-tooltip="true"/>
+      <el-table-column label="维修内容" align="center" prop="maintContent" :show-overflow-tooltip="true"/>
+      <el-table-column label="维修结果" align="center" prop="maintResult" :show-overflow-tooltip="true"/>
+      <el-table-column label="维修时间" align="center" prop="maintTime" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.maintTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="维修费用" align="center" prop="maintCost" :show-overflow-tooltip="true"/>
+      <el-table-column label="维修时长" align="center" prop="maintDuration" :show-overflow-tooltip="true"/>
+      <el-table-column label="工艺损失" align="center" prop="processLoss" :show-overflow-tooltip="true"/>
+      <el-table-column label="附件" align="center" prop="attachments" :show-overflow-tooltip="true"/>
+      <el-table-column label="创建人" align="center" prop="createrCode" :show-overflow-tooltip="true"/>
+      <el-table-column label="创建时间" align="center" prop="createdate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createdate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="修改人" align="center" prop="updaterCode" :show-overflow-tooltip="true"/>
+      <el-table-column label="修改时间" align="center" prop="updatedate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.updatedate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="部门编号" align="center" prop="deptId" :show-overflow-tooltip="true"/>
+      <el-table-column label="备注" align="center" prop="remarks" :show-overflow-tooltip="true"/>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['reliability:rel_maint_record:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['reliability:rel_maint_record:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改部件维修记录对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="装置" prop="plant">
+          <el-input v-model="form.plant" placeholder="请输入装置" />
+        </el-form-item>
+        <el-form-item label="设备名称" prop="devName">
+          <el-input v-model="form.devName" placeholder="请输入设备名称" />
+        </el-form-item>
+        <el-form-item label="设备位号" prop="devTag">
+          <el-input v-model="form.devTag" placeholder="请输入设备位号" />
+        </el-form-item>
+        <el-form-item label="部件名称" prop="compoName">
+          <el-input v-model="form.compoName" placeholder="请输入部件名称" />
+        </el-form-item>
+        <el-form-item label="部件ID" prop="compoId">
+          <el-input v-model="form.compoId" placeholder="请输入部件ID" />
+        </el-form-item>
+        <el-form-item label="维修类型" prop="maintType">
+          <el-select v-model="form.maintType" placeholder="请选择维修类型">
+            <el-option label="请选择字典生成" value="" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="维修部门" prop="maintDept">
+          <el-input v-model="form.maintDept" placeholder="请输入维修部门" />
+        </el-form-item>
+        <el-form-item label="检查人" prop="inspector">
+          <el-input v-model="form.inspector" placeholder="请输入检查人" />
+        </el-form-item>
+        <el-form-item label="检查内容">
+          <editor v-model="form.inspectContent" :min-height="192"/>
+        </el-form-item>
+        <el-form-item label="检查时间" prop="inspectTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.inspectTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择检查时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="维修责任人" prop="responsible">
+          <el-input v-model="form.responsible" placeholder="请输入维修责任人" />
+        </el-form-item>
+        <el-form-item label="维修内容">
+          <editor v-model="form.maintContent" :min-height="192"/>
+        </el-form-item>
+        <el-form-item label="维修结果" prop="maintResult">
+          <el-input v-model="form.maintResult" placeholder="请输入维修结果" />
+        </el-form-item>
+        <el-form-item label="维修时间" prop="maintTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.maintTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择维修时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="维修费用" prop="maintCost">
+          <el-input v-model="form.maintCost" placeholder="请输入维修费用" />
+        </el-form-item>
+        <el-form-item label="维修时长" prop="maintDuration">
+          <el-input v-model="form.maintDuration" placeholder="请输入维修时长" />
+        </el-form-item>
+        <el-form-item label="工艺损失" prop="processLoss">
+          <el-input v-model="form.processLoss" placeholder="请输入工艺损失" />
+        </el-form-item>
+        <el-form-item label="附件" prop="attachments">
+          <el-input v-model="form.attachments" placeholder="请输入附件" />
+        </el-form-item>
+        <el-form-item label="删除标志" prop="delFlag">
+          <el-input v-model="form.delFlag" placeholder="请输入删除标志" />
+        </el-form-item>
+        <el-form-item label="创建人" prop="createrCode">
+          <el-input v-model="form.createrCode" placeholder="请输入创建人" />
+        </el-form-item>
+        <el-form-item label="创建时间" prop="createdate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.createdate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择创建时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="修改人" prop="updaterCode">
+          <el-input v-model="form.updaterCode" placeholder="请输入修改人" />
+        </el-form-item>
+        <el-form-item label="修改时间" prop="updatedate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.updatedate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择修改时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="部门编号" prop="deptId">
+          <el-input v-model="form.deptId" placeholder="请输入部门编号" />
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="请输入备注" />
+        </el-form-item>
+          <el-form-item label="归属部门" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+          </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+      <!-- 用户导入对话框 -->
+      <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+          <el-upload
+                  ref="upload"
+                  :limit="1"
+                  accept=".xlsx, .xls"
+                  :headers="upload.headers"
+                  :action="upload.url + '?updateSupport=' + upload.updateSupport"
+                  :disabled="upload.isUploading"
+                  :on-progress="handleFileUploadProgress"
+                  :on-success="handleFileSuccess"
+                  :auto-upload="false"
+                  drag
+          >
+              <i class="el-icon-upload"></i>
+              <div class="el-upload__text">
+                  将文件拖到此处,或
+                  <em>点击上传</em>
+              </div>
+              <div class="el-upload__tip" slot="tip">
+                  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
+                  <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+              </div>
+              <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+          </el-upload>
+          <div slot="footer" class="dialog-footer">
+              <el-button type="primary" @click="submitFileForm">确 定</el-button>
+              <el-button @click="upload.open = false">取 消</el-button>
+          </div>
+      </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listRel_maint_record, getRel_maint_record, delRel_maint_record, addRel_maint_record, updateRel_maint_record, exportRel_maint_record, importTemplate} from "@/api/reliability/rel_maint_record";
+import { treeselect } from "@/api/system/dept";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import Editor from '@/components/Editor';
+
+export default {
+  name: "Rel_maint_record",
+  components: { Treeselect },
+  // components: { Editor },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 部件维修记录表格数据
+      rel_maint_recordList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+        // 用户导入参数
+        upload: {
+            // 是否显示弹出层(用户导入)
+            open: false,
+            // 弹出层标题(用户导入)
+            title: "",
+            // 是否禁用上传
+            isUploading: false,
+            // 是否更新已经存在的用户数据
+            updateSupport: 0,
+            // 设置上传的请求头部
+            headers: { Authorization: "Bearer " + getToken() },
+            // 上传的地址
+            url: process.env.VUE_APP_BASE_API + "/reliability/rel_maint_record/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        plant: null,
+        devName: null,
+        devTag: null,
+        compoName: null,
+        compoId: null,
+        maintType: null,
+        maintDept: null,
+        inspector: null,
+        inspectContent: null,
+        inspectTime: null,
+        responsible: null,
+        maintContent: null,
+        maintResult: null,
+        maintTime: null,
+        maintCost: null,
+        maintDuration: null,
+        processLoss: null,
+        attachments: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+        // 根据名称筛选部门树
+        deptName(val) {
+            this.$refs.tree.filter(val);
+        }
+   },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询部件维修记录列表 */
+    getList() {
+      this.loading = true;
+      listRel_maint_record(this.queryParams).then(response => {
+        this.rel_maint_recordList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        recordId: null,
+        plant: null,
+        devName: null,
+        devTag: null,
+        compoName: null,
+        compoId: null,
+        maintType: null,
+        maintDept: null,
+        inspector: null,
+        inspectContent: null,
+        inspectTime: null,
+        responsible: null,
+        maintContent: null,
+        maintResult: null,
+        maintTime: null,
+        maintCost: null,
+        maintDuration: null,
+        processLoss: null,
+        attachments: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.recordId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加部件维修记录";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const recordId = row.recordId || this.ids
+      getRel_maint_record(recordId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改部件维修记录";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.recordId != null) {
+            updateRel_maint_record(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addRel_maint_record(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const recordIds = row.recordId || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delRel_maint_record(recordIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有部件维修记录数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportRel_maint_record(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        })
+    },
+      /** 导入按钮操作 */
+      handleImport() {
+          this.upload.title = "用户导入";
+          this.upload.open = true;
+      },
+      /** 下载模板操作 */
+      importTemplate() {
+          importTemplate().then(response => {
+              this.download(response.msg);
+          });
+      },
+      // 文件上传中处理
+      handleFileUploadProgress(event, file, fileList) {
+          this.upload.isUploading = true;
+      },
+      // 文件上传成功处理
+      handleFileSuccess(response, file, fileList) {
+          this.upload.open = false;
+          this.upload.isUploading = false;
+          this.$refs.upload.clearFiles();
+          this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
+          this.getList();
+      },
+      // 提交上传文件
+      submitFileForm() {
+          this.$refs.upload.submit();
+      }
+  }
+};
+</script>