Browse Source

ly 可靠性 预防性维修

ly 4 weeks ago
parent
commit
3edfa92cd1

+ 11 - 12
master/src/main/java/com/ruoyi/project/plant/controller/TStaffmgrController.java

@@ -381,12 +381,12 @@ public class TStaffmgrController extends BaseController {
         logger.info("selectTime 人员列表数量:{}", list.size());
         List<TTrainingParticipants> tTrainingParticipants = tTrainingParticipantsService.selectTTrainingParticipantsList(new TTrainingParticipants());
         logger.info("培训记录总数:{}", tTrainingParticipants.size());
-        
+
         if (list.isEmpty()) {
             logger.warn("人员列表为空,无法计算培训时长");
             return getDataTable(list);
         }
-        
+
         if (tTrainingParticipants.isEmpty()) {
             logger.warn("培训记录为空,所有人员培训时长将为0");
         }
@@ -409,22 +409,22 @@ public class TStaffmgrController extends BaseController {
                     double time = 0;
                     int matchCount = 0; // 匹配到的记录数
                     int currentYearCount = 0; // 当年的记录数
-                    
+
                     for (TTrainingParticipants t : tTrainingParticipants) {
                         // 空值判断,避免NPE
                         if (t.getStaffId() == null || staffId == null) {
                             continue;
                         }
-                        
+
                         if (t.getStaffId().equals(staffId)) {
                             matchCount++;
-                            
+
                             if (t.getStartDate() != null) {
                                 String trainingYear = sdf.format(t.getStartDate());
-                                
+
                                 if (trainingYear.equals(currentYear)) {
                                     currentYearCount++;
-                                    
+
                                     if (t.getTrainingDuration() != null && !t.getTrainingDuration().trim().isEmpty()) {
                                         try {
                                             double duration = Double.parseDouble(t.getTrainingDuration().trim());
@@ -438,11 +438,11 @@ public class TStaffmgrController extends BaseController {
                             }
                         }
                     }
-                    
+
                     staff.setTrainingTime(String.valueOf(time));
-                    logger.info("员工[{}({})] 计算完成:培训时长={} 小时,匹配记录={} 条,当年记录={} 条", 
+                    logger.info("员工[{}({})] 计算完成:培训时长={} 小时,匹配记录={} 条,当年记录={} 条",
                         staffName, staffId, time, matchCount, currentYearCount);
-                        
+
                 } catch (Exception e) {
                     logger.error("计算员工培训时长异常,索引:{}", finalI, e);
                 } finally {
@@ -456,7 +456,7 @@ public class TStaffmgrController extends BaseController {
             logger.error("等待线程池执行完毕时被中断", e);
         }
         executorService.shutdown();
-        
+
         logger.info("selectTime 接口执行完成,返回数据量:{}", list.size());
         return getDataTable(list);
     }
@@ -466,7 +466,6 @@ public class TStaffmgrController extends BaseController {
      *
      * @return
      */
-    @PreAuthorize("@ss.hasPermi('plant:staffmgr:list')")
     @GetMapping("/ogzList")
     public List<TStaffmgr> ogzList(TStaffmgr tStaffmgr) {
         List<TStaffmgr> list = tStaffmgrService.selectTStaffmgrList(tStaffmgr);

+ 93 - 2
master/src/main/java/com/ruoyi/project/reliability/controller/TRelMaintPlanController.java

@@ -160,8 +160,9 @@ public class TRelMaintPlanController extends BaseController
             logger.info("流程实例id:" + pi.getProcessInstanceId());
             logger.info("流程定义对象:" + pi.getProcessVariables());
 
-            // 更新流程ID
+            // 更新流程ID(只更新计划本身,不触发syncMaintRecords)
             tRelMaintPlan.setProcessId(pi.getProcessInstanceId());
+            // 使用不同步的更新方法
             tRelMaintPlanService.updateTRelMaintPlan(tRelMaintPlan);
 
             // 处理部件维修记录
@@ -210,7 +211,97 @@ public class TRelMaintPlanController extends BaseController
     @PutMapping
     public AjaxResult edit(@RequestBody TRelMaintPlan tRelMaintPlan)
     {
-        return toAjax(tRelMaintPlanService.updateTRelMaintPlan(tRelMaintPlan));
+        return toAjax(tRelMaintPlanService.updateTRelMaintPlanWithSync(tRelMaintPlan));
+    }
+
+    /**
+     * 已通过的维修计划再次提交申请(重新启动审批流程)
+     */
+    @PreAuthorize("@ss.hasPermi('reliability:rel_maint_plan:edit')")
+    @Log(title = "维修计划再次提交申请", businessType = BusinessType.UPDATE)
+    @PostMapping("/resubmitApprove")
+    public AjaxResult resubmitApprove(@RequestBody TRelMaintPlan tRelMaintPlan)
+    {
+        try {
+            logger.info("维修计划再次提交申请" + JSON.toJSONString(tRelMaintPlan));
+            logger.info("维修部件数量: " + (tRelMaintPlan.getMaintComponents() != null ? tRelMaintPlan.getMaintComponents().size() : 0));
+
+            Long userId = getUserId();
+
+            // 检查计划是否存在且审批状态为已通过
+            if (tRelMaintPlan.getPlanId() == null) {
+                return AjaxResult.error("计划ID不能为空");
+            }
+            TRelMaintPlan existingPlan = tRelMaintPlanService.selectTRelMaintPlanById(tRelMaintPlan.getPlanId());
+            if (existingPlan == null) {
+                return AjaxResult.error("维修计划不存在");
+            }
+            if (!"1".equals(existingPlan.getApprovalStatus())) {
+                return AjaxResult.error("只有已通过的计划才能再次提交申请");
+            }
+
+            // 设置基础信息
+            tRelMaintPlan.setUpdaterCode(userId.toString());
+            tRelMaintPlan.setApprovalStatus("0"); // 重置为待审批
+            tRelMaintPlan.setCompletionStatus("0"); // 重置为未完成
+
+            // 先同步维修记录并更新计划
+            tRelMaintPlanService.updateTRelMaintPlanWithSync(tRelMaintPlan);
+
+            // 设置流程变量
+            Map<String, Object> variables = new HashMap<>();
+            // 通过员工号查询sys_user的ID
+            String approverStaffId = tRelMaintPlan.getApprover();
+            SysUser approverUser = sysUserMapper.selectUserByStaffId(approverStaffId);
+            if (approverUser != null && approverUser.getUserId() != null) {
+                variables.put("zzjlusers", approverUser.getUserId().toString());
+                logger.info("审批人员工号: " + approverStaffId + ", sys_user ID: " + approverUser.getUserId());
+            } else {
+                logger.error("未找到审批人,员工号: " + approverStaffId);
+                return AjaxResult.error("未找到审批人信息,请检查审批人选择是否正确");
+            }
+
+            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);
+
+            // 发送邮件通知审批人
+            try {
+                SysMessage message = new SysMessage();
+                String email = approverUser.getEmail();
+                String username = approverUser.getNickName();
+
+                logger.info("email:" + email);
+                logger.info("username:" + username);
+
+                message.setUserId(approverUser.getUserId());
+                message.setMsgTitle("您有一条维修计划待审核");
+                message.setMsgContent("您有一条维修计划待审核,请及时处理");
+
+                // 保存系统消息
+                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());
+        }
     }
 
     /**

+ 110 - 2
master/src/main/java/com/ruoyi/project/reliability/controller/TRelMaintRecordController.java

@@ -17,9 +17,11 @@ import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.project.reliability.domain.TRelMaintRecord;
 import com.ruoyi.project.reliability.domain.TRelMaintPlan;
 import com.ruoyi.project.reliability.domain.TRelMaintMemo;
+import com.ruoyi.project.reliability.domain.TRelCompo;
 import com.ruoyi.project.reliability.service.ITRelMaintRecordService;
 import com.ruoyi.project.reliability.service.ITRelMaintPlanService;
 import com.ruoyi.project.reliability.service.ITRelMaintMemoService;
+import com.ruoyi.project.reliability.service.ITRelCompoService;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -48,6 +50,9 @@ public class TRelMaintRecordController extends BaseController
     @Autowired
     private ITRelMaintMemoService tRelMaintMemoService;
 
+    @Autowired
+    private ITRelCompoService tRelCompoService;
+
     /**
      * 查询部件维修记录列表
      */
@@ -94,12 +99,17 @@ public class TRelMaintRecordController extends BaseController
     }
 
     /**
-     * 获取部件维修记录详细信息
+     * 获取部件维修记录详细信息(用于处理时的查询,会预填充部件内容)
      */
     @GetMapping(value = "/{recordId}")
     public AjaxResult getInfo(@PathVariable("recordId") Long recordId)
     {
-        return AjaxResult.success(tRelMaintRecordService.selectTRelMaintRecordById(recordId));
+        TRelMaintRecord record = tRelMaintRecordService.selectTRelMaintRecordById(recordId);
+        if (record != null) {
+            // 预填充部件的对应内容
+            fillRecordContentFromCompo(record);
+        }
+        return AjaxResult.success(record);
     }
 
     /**
@@ -167,6 +177,17 @@ public class TRelMaintRecordController extends BaseController
             createMaintMemoFromRecord(tRelMaintRecord, memoReason, memoTime);
         }
         
+        // 如果没有创建备忘录,则更新部件的上次日期
+        // 检查是否创建了备忘录(如果创建了备忘录则不更新上次日期)
+        boolean createdMemo = result > 0 && ("2".equals(maintType) || "3".equals(maintType)) 
+            && cannotMaintOrReplace != null && cannotMaintOrReplace
+            && memoReason != null && !memoReason.isEmpty()
+            && memoTime != null;
+        
+        if (result > 0 && !createdMemo && tRelMaintRecord.getCompoId() != null) {
+            updateCompoLastDate(tRelMaintRecord, maintType);
+        }
+        
         // 更新记录后,检查该记录所属的计划是否所有记录都已完成
         if (result > 0 && tRelMaintRecord.getPlanId() != null) {
             checkAndUpdatePlanCompletionStatus(tRelMaintRecord.getPlanId());
@@ -302,6 +323,93 @@ public class TRelMaintRecordController extends BaseController
         }
     }
 
+    /**
+     * 根据部件信息预填充维修记录的内容
+     * @param record 维修记录
+     */
+    private void fillRecordContentFromCompo(TRelMaintRecord record) {
+        try {
+            if (record.getCompo() == null || record.getMaintType() == null) {
+                return;
+            }
+            
+            TRelCompo compo = record.getCompo();
+            
+            // 根据维修类型预填充对应的内容
+            if ("1".equals(record.getMaintType())) {
+                // 检查:预填充检查内容
+                if ((record.getInspectContent() == null || record.getInspectContent().isEmpty()) 
+                    && compo.getInspContent() != null && !compo.getInspContent().isEmpty()) {
+                    record.setInspectContent(compo.getInspContent());
+                }
+            } else if ("2".equals(record.getMaintType())) {
+                // 维修:预填充维修内容
+                if ((record.getMaintContent() == null || record.getMaintContent().isEmpty()) 
+                    && compo.getFixContent() != null && !compo.getFixContent().isEmpty()) {
+                    record.setMaintContent(compo.getFixContent());
+                }
+            } else if ("3".equals(record.getMaintType())) {
+                // 更换:预填充更换内容
+                if ((record.getMaintContent() == null || record.getMaintContent().isEmpty()) 
+                    && compo.getReplaceContent() != null && !compo.getReplaceContent().isEmpty()) {
+                    record.setMaintContent(compo.getReplaceContent());
+                }
+            }
+        } catch (Exception e) {
+            logger.error("预填充维修记录内容失败,recordId: " + record.getRecordId(), e);
+            // 不抛出异常,避免影响主流程
+        }
+    }
+
+    /**
+     * 更新部件的上次检查/维修/更换日期
+     * @param record 维修记录
+     * @param maintType 维修类型(1-检查,2-维修,3-更换)
+     */
+    private void updateCompoLastDate(TRelMaintRecord record, String maintType) {
+        try {
+            if (record.getCompoId() == null) {
+                return;
+            }
+            
+            // 根据 compoId 查询部件
+            Long compoId = Long.parseLong(record.getCompoId());
+            TRelCompo compo = tRelCompoService.selectTRelCompoById(compoId);
+            
+            if (compo == null) {
+                logger.warn("部件不存在,compoId: " + compoId);
+                return;
+            }
+            
+            // 根据维修类型更新对应的日期
+            if ("1".equals(maintType)) {
+                // 检查:更新上次检查日期
+                if (record.getInspectTime() != null) {
+                    compo.setLastInspDate(record.getInspectTime());
+                    tRelCompoService.updateTRelCompo(compo);
+                    logger.info("更新部件上次检查日期成功,compoId: " + compoId + ", 日期: " + record.getInspectTime());
+                }
+            } else if ("2".equals(maintType)) {
+                // 维修:更新上次维修日期
+                if (record.getMaintTime() != null) {
+                    compo.setLastFixDate(record.getMaintTime());
+                    tRelCompoService.updateTRelCompo(compo);
+                    logger.info("更新部件上次维修日期成功,compoId: " + compoId + ", 日期: " + record.getMaintTime());
+                }
+            } else if ("3".equals(maintType)) {
+                // 更换:更新上次更换日期
+                if (record.getMaintTime() != null) {
+                    compo.setLastReplaceDate(record.getMaintTime());
+                    tRelCompoService.updateTRelCompo(compo);
+                    logger.info("更新部件上次更换日期成功,compoId: " + compoId + ", 日期: " + record.getMaintTime());
+                }
+            }
+        } catch (Exception e) {
+            logger.error("更新部件上次日期失败,compoId: " + record.getCompoId(), e);
+            // 不抛出异常,避免影响主流程
+        }
+    }
+
     /**
      * 删除部件维修记录
      */

+ 3 - 3
master/src/main/java/com/ruoyi/project/reliability/domain/TRelMaintMemo.java

@@ -63,7 +63,7 @@ public class TRelMaintMemo extends BaseEntity
 
     /** 维修费用 */
     @Excel(name = "维修费用")
-    private Long maintCost;
+    private Double maintCost;
 
     /** 删除标志(0代表存在 2代表删除) */
     private Long delFlag;
@@ -201,12 +201,12 @@ public class TRelMaintMemo extends BaseEntity
     {
         return memoTime;
     }
-    public void setMaintCost(Long maintCost)
+    public void setMaintCost(Double maintCost)
     {
         this.maintCost = maintCost;
     }
 
-    public Long getMaintCost()
+    public Double getMaintCost()
     {
         return maintCost;
     }

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

@@ -80,11 +80,11 @@ public class TRelMaintRecord extends BaseEntity
 
     /** 维修费用 */
     @Excel(name = "维修费用")
-    private Long maintCost;
+    private Double maintCost;
 
     /** 维修时长 */
     @Excel(name = "维修时长")
-    private Long maintDuration;
+    private Double maintDuration;
 
     /** 工艺损失 */
     @Excel(name = "工艺损失")
@@ -383,21 +383,21 @@ public class TRelMaintRecord extends BaseEntity
     {
         return maintTime;
     }
-    public void setMaintCost(Long maintCost)
+    public void setMaintCost(Double maintCost)
     {
         this.maintCost = maintCost;
     }
 
-    public Long getMaintCost()
+    public Double getMaintCost()
     {
         return maintCost;
     }
-    public void setMaintDuration(Long maintDuration)
+    public void setMaintDuration(Double maintDuration)
     {
         this.maintDuration = maintDuration;
     }
 
-    public Long getMaintDuration()
+    public Double getMaintDuration()
     {
         return maintDuration;
     }

+ 9 - 1
master/src/main/java/com/ruoyi/project/reliability/service/ITRelMaintPlanService.java

@@ -36,7 +36,15 @@ public interface ITRelMaintPlanService
     public int insertTRelMaintPlan(TRelMaintPlan tRelMaintPlan);
 
     /**
-     * 修改设备维修计划
+     * 修改设备维修计划(同步维修记录)
+     * 
+     * @param tRelMaintPlan 设备维修计划
+     * @return 结果
+     */
+    public int updateTRelMaintPlanWithSync(TRelMaintPlan tRelMaintPlan);
+
+    /**
+     * 修改设备维修计划(不同步维修记录)
      * 
      * @param tRelMaintPlan 设备维修计划
      * @return 结果

+ 132 - 1
master/src/main/java/com/ruoyi/project/reliability/service/impl/TRelMaintPlanServiceImpl.java

@@ -1,6 +1,11 @@
 package com.ruoyi.project.reliability.service.impl;
 
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ruoyi.project.reliability.mapper.TRelMaintPlanMapper;
@@ -12,6 +17,8 @@ import com.ruoyi.project.reliability.service.ITRelMaintPlanService;
 import com.ruoyi.project.reliability.service.ITRelDeviceService;
 import com.ruoyi.project.reliability.service.ITRelMaintRecordService;
 import com.ruoyi.project.reliability.service.ITRelCompoService;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
 
 /**
  * 设备维修计划Service业务层处理
@@ -22,6 +29,8 @@ import com.ruoyi.project.reliability.service.ITRelCompoService;
 @Service
 public class TRelMaintPlanServiceImpl implements ITRelMaintPlanService
 {
+    private static final Logger logger = LoggerFactory.getLogger(TRelMaintPlanServiceImpl.class);
+
     @Autowired
     private TRelMaintPlanMapper tRelMaintPlanMapper;
 
@@ -34,6 +43,9 @@ public class TRelMaintPlanServiceImpl implements ITRelMaintPlanService
     @Autowired
     private ITRelCompoService tRelCompoService;
 
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
     /**
      * 查询设备维修计划
      *
@@ -46,6 +58,18 @@ public class TRelMaintPlanServiceImpl implements ITRelMaintPlanService
         TRelMaintPlan plan = tRelMaintPlanMapper.selectTRelMaintPlanById(planId);
         
         if (plan != null) {
+            // 根据createrCode查询创建人昵称
+            if (plan.getCreaterCode() != null) {
+                try {
+                    SysUser creater = sysUserMapper.selectUserById(Long.parseLong(plan.getCreaterCode()));
+                    if (creater != null && creater.getNickName() != null) {
+                        plan.setCreaterCode(creater.getNickName());
+                    }
+                } catch (Exception e) {
+                    logger.warn("查询创建人昵称失败,createrCode: " + plan.getCreaterCode(), e);
+                }
+            }
+            
             // 根据装置和位号查询设备信息
             if (plan.getPlant() != null && plan.getDevTag() != null) {
                 TRelDevice deviceQuery = new TRelDevice();
@@ -100,7 +124,26 @@ public class TRelMaintPlanServiceImpl implements ITRelMaintPlanService
     }
 
     /**
-     * 修改设备维修计划
+     * 修改设备维修计划(同步维修记录)
+     *
+     * @param tRelMaintPlan 设备维修计划
+     * @return 结果
+     */
+    @Override
+    public int updateTRelMaintPlanWithSync(TRelMaintPlan tRelMaintPlan)
+    {
+        // 先同步维修记录(如果有maintComponents)
+        if (tRelMaintPlan.getPlanId() != null && tRelMaintPlan.getMaintComponents() != null) {
+            syncMaintRecords(tRelMaintPlan.getPlanId(), tRelMaintPlan.getMaintComponents(), tRelMaintPlan);
+        }
+        
+        // 再更新计划本身
+        return tRelMaintPlanMapper.updateTRelMaintPlan(tRelMaintPlan);
+    }
+
+    /**
+     * 修改设备维修计划(不同步维修记录)
+     * 用于仅更新计划信息,不处理维修记录的场景
      *
      * @param tRelMaintPlan 设备维修计划
      * @return 结果
@@ -108,9 +151,97 @@ public class TRelMaintPlanServiceImpl implements ITRelMaintPlanService
     @Override
     public int updateTRelMaintPlan(TRelMaintPlan tRelMaintPlan)
     {
+        // 直接更新计划本身,不触发syncMaintRecords
         return tRelMaintPlanMapper.updateTRelMaintPlan(tRelMaintPlan);
     }
 
+    /**
+     * 同步维修记录:根据maintComponents对比实际的record,进行删除、新增或修改
+     * @param planId 计划ID
+     * @param maintComponents 前端传递的部件维修列表
+     * @param tRelMaintPlan 维修计划对象
+     */
+    private void syncMaintRecords(Long planId, List<TRelMaintRecord> maintComponents, TRelMaintPlan tRelMaintPlan) {
+        try {
+            logger.info("开始同步维修记录,计划ID: " + planId + ", 部件数量: " + maintComponents.size());
+            
+            // 查询该计划下的所有现有维修记录
+            TRelMaintRecord recordQuery = new TRelMaintRecord();
+            recordQuery.setPlanId(planId);
+            List<TRelMaintRecord> existingRecords = tRelMaintRecordService.selectTRelMaintRecordList(recordQuery);
+            
+            // 构建现有记录的Map,key为compoId
+            Map<String, TRelMaintRecord> existingMap = new HashMap<>();
+            if (existingRecords != null) {
+                for (TRelMaintRecord record : existingRecords) {
+                    existingMap.put(record.getCompoId(), record);
+                }
+            }
+            
+            // 构建前端部件的Map,key为compoId
+            Map<String, TRelMaintRecord> newMap = new HashMap<>();
+            for (TRelMaintRecord component : maintComponents) {
+                newMap.put(component.getCompoId(), component);
+            }
+            
+            // 处理新增和修改
+            for (TRelMaintRecord newComponent : maintComponents) {
+                String compoId = newComponent.getCompoId();
+                TRelMaintRecord existingRecord = existingMap.get(compoId);
+                
+                if (existingRecord == null) {
+                    // 新增:该部件在现有记录中不存在
+                    // 设置基本信息
+                    newComponent.setPlant(tRelMaintPlan.getPlant());
+                    newComponent.setDevName(tRelMaintPlan.getDevName());
+                    newComponent.setDevTag(tRelMaintPlan.getDevTag());
+                    newComponent.setPlanId(planId);
+                    newComponent.setRecordStatus(0); // 新增申请中
+                    newComponent.setDelFlag(0L);
+                    // 设置创建信息
+                    newComponent.setCreaterCode(tRelMaintPlan.getCreaterCode());
+                    newComponent.setCreatedate(new Date());
+                    tRelMaintRecordService.insertTRelMaintRecord(newComponent);
+                    logger.info("新增维修记录:compoId=" + compoId + ", 维修类型=" + newComponent.getMaintType());
+                } else if (existingRecord.getRecordStatus() != null && existingRecord.getRecordStatus() != 2) {
+                    // 修改:该部件已存在且未完成(recordStatus != 2)
+                    // 直接修改,保持原状态
+                    existingRecord.setMaintType(newComponent.getMaintType());
+                    existingRecord.setResponsible(newComponent.getResponsible());
+                    tRelMaintRecordService.updateTRelMaintRecord(existingRecord);
+                    logger.info("修改维修记录:compoId=" + compoId + ", 维修类型=" + newComponent.getMaintType());
+                }
+                // 如果recordStatus == 2(已完成)或为null,则不修改该记录
+            }
+            
+            // 处理删除:现有记录中存在但前端部件中不存在的记录
+            for (TRelMaintRecord existingRecord : existingRecords) {
+                String compoId = existingRecord.getCompoId();
+                if (!newMap.containsKey(compoId)) {
+                    // 该记录在前端部件中不存在
+                    if (existingRecord.getRecordStatus() != null) {
+                        if (existingRecord.getRecordStatus() == 0) {
+                            // 新增申请中的记录,直接物理删除
+                            tRelMaintRecordService.deleteTRelMaintRecordById(existingRecord.getRecordId());
+                            logger.info("物理删除新增申请中的维修记录:compoId=" + compoId);
+                        } else if (existingRecord.getRecordStatus() == 1) {
+                            // 待处理的记录,标记为删除申请中
+                            existingRecord.setRecordStatus(-1); // 删除申请中
+                            tRelMaintRecordService.updateTRelMaintRecord(existingRecord);
+                            logger.info("标记待处理维修记录为删除申请中:compoId=" + compoId);
+                        }
+                        // recordStatus == -1(已是删除申请中)、2(已完成)或其他状态不做任何修改
+                    }
+                }
+            }
+            
+            logger.info("完成同步维修记录");
+        } catch (Exception e) {
+            logger.error("同步维修记录失败", e);
+            // 不抛出异常,避免影响计划更新
+        }
+    }
+
     /**
      * 批量删除设备维修计划
      *

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

@@ -69,3 +69,12 @@ export function handleRelMaintPlanApprove(data) {
     data: data
   })
 }
+
+// 已通过的维修计划再次提交申请
+export function resubmitApprove(data) {
+  return request({
+    url: '/reliability/rel_maint_plan/resubmitApprove',
+    method: 'post',
+    data: data
+  })
+}

+ 4 - 4
ui/src/views/plant/EOEGorganization/index.vue

@@ -252,8 +252,8 @@ export default {
                   label: this.staffmgrList[i].name,
                   post: post,
                   secretary: [[], [], [], []],
-                  img: 'http://47.114.101.16' + process.env.VUE_APP_BASE_API + this.staffmgrList[i].photo,
-                  // img: 'https://cpms.basf-ypc.net.cn' + process.env.VUE_APP_BASE_API + this.staffmgrList[i].photo,
+                  // img: 'http://47.114.101.16' + process.env.VUE_APP_BASE_API + this.staffmgrList[i].photo,
+                  img: 'https://cpms.basf-ypc.net.cn' + process.env.VUE_APP_BASE_API + this.staffmgrList[i].photo,
                   bz1: false,
                   bz2: false,
                   bz3: false,
@@ -302,8 +302,8 @@ export default {
                   pId: this.staffmgrList[i].pId,
                   label: this.staffmgrList[i].name,
                   post: post,
-                  // img: 'https://cpms.basf-ypc.net.cn' + process.env.VUE_APP_BASE_API + this.staffmgrList[i].photo,
-                  img: 'http://47.114.101.16' + process.env.VUE_APP_BASE_API + this.staffmgrList[i].photo,
+                  img: 'https://cpms.basf-ypc.net.cn' + process.env.VUE_APP_BASE_API + this.staffmgrList[i].photo,
+                  // img: 'http://47.114.101.16' + process.env.VUE_APP_BASE_API + this.staffmgrList[i].photo,
                   bz1: false,
                   bz2: false,
                   bz3: false,

+ 6 - 6
ui/src/views/reliability/rel_compo/index.vue

@@ -186,12 +186,12 @@
           <span>{{ parseTime(scope.row.lastReplaceDate, '{y}-{m}-{d}') }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="下次维护日期" align="center" prop="nextMaintDate" width="120">
-        <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.nextMaintDate, '{y}-{m}-{d}') }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="维护类型" align="center" prop="nextMaintType" width="120" :show-overflow-tooltip="true"/>
+<!--      <el-table-column label="下次维护日期" align="center" prop="nextMaintDate" width="120">-->
+<!--        <template slot-scope="scope">-->
+<!--          <span>{{ parseTime(scope.row.nextMaintDate, '{y}-{m}-{d}') }}</span>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+<!--      <el-table-column label="维护类型" align="center" prop="nextMaintType" width="120" :show-overflow-tooltip="true"/>-->
       <el-table-column label="备注" align="center" prop="remarks" width="150" :show-overflow-tooltip="true"/>
       <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
         <template slot-scope="scope">

+ 246 - 68
ui/src/views/reliability/rel_device/detail.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="device-detail-page">
     <!-- 左侧流程图区域 -->
-    <div class="diagram-section">
+    <div class="diagram-section" :style="{flex: (activeTab === 'compo' || activeTab === 'record') ? '0 0 30%' : '1'}">
       <process-diagram
         ref="processDiagram"
         :selected-device="deviceInfo"
@@ -10,7 +10,7 @@
     </div>
 
     <!-- 右侧设备信息区域 -->
-    <div class="device-info-section">
+    <div class="device-info-section" :style="{width: (activeTab === 'compo' || activeTab === 'record') ? '70%' : '400px'}">
       <div class="info-panel">
         <div class="panel-header">
           <h3>设备信息</h3>
@@ -19,77 +19,129 @@
           </el-button>
         </div>
 
-        <div class="panel-content" v-if="deviceInfo">
-          <el-descriptions :column="1" border>
-            <el-descriptions-item label="设备名称">
-              {{ deviceInfo.devName }}
-            </el-descriptions-item>
-            <el-descriptions-item label="设备位号">
-              {{ deviceInfo.devTag }}
-            </el-descriptions-item>
-            <el-descriptions-item label="装置">
-              {{ deviceInfo.plant }}
-            </el-descriptions-item>
-            <el-descriptions-item label="位置">
-              {{ deviceInfo.devLoc }}
-            </el-descriptions-item>
-            <el-descriptions-item label="设备类型">
-              {{ deviceInfo.devType }}
-            </el-descriptions-item>
-            <el-descriptions-item label="设备描述">
-              {{ deviceInfo.devDesc }}
-            </el-descriptions-item>
-            <el-descriptions-item label="区域">
-              {{ deviceInfo.devArea }}
-            </el-descriptions-item>
-            <el-descriptions-item label="区域负责人">
-              {{ deviceInfo.areaResponsibleName || deviceInfo.areaResponsible || '-' }}
-            </el-descriptions-item>
-            <el-descriptions-item label="备注">
-              {{ deviceInfo.remarks }}
-            </el-descriptions-item>
-          </el-descriptions>
-
-          <!-- 设备照片展示 -->
-          <div class="device-photo-section" v-if="deviceInfo.devPhoto">
-            <h4 class="photo-title">设备照片</h4>
-            <div class="photo-container">
-              <el-image 
-                :src="getPhotoUrl(deviceInfo.devPhoto)"
-                :preview-src-list="[getPhotoUrl(deviceInfo.devPhoto)]"
-                fit="contain"
-                class="device-photo">
-                <div slot="error" class="image-slot">
-                  <i class="el-icon-picture-outline"></i>
-                  <p>图片加载失败</p>
-                </div>
-              </el-image>
+        <el-tabs v-if="deviceInfo" class="panel-tabs" v-model="activeTab" @tab-click="handleTabClick">
+          <!-- 设备信息标签页 -->
+          <el-tab-pane label="设备信息" name="info">
+            <el-descriptions :column="1" border>
+              <el-descriptions-item label="设备名称">
+                {{ deviceInfo.devName }}
+              </el-descriptions-item>
+              <el-descriptions-item label="设备位号">
+                {{ deviceInfo.devTag }}
+              </el-descriptions-item>
+              <el-descriptions-item label="装置">
+                {{ deviceInfo.plant }}
+              </el-descriptions-item>
+              <el-descriptions-item label="位置">
+                {{ deviceInfo.devLoc }}
+              </el-descriptions-item>
+              <el-descriptions-item label="设备类型">
+                {{ deviceInfo.devType }}
+              </el-descriptions-item>
+              <el-descriptions-item label="设备描述">
+                {{ deviceInfo.devDesc }}
+              </el-descriptions-item>
+              <el-descriptions-item label="区域">
+                {{ deviceInfo.devArea }}
+              </el-descriptions-item>
+              <el-descriptions-item label="区域负责人">
+                {{ deviceInfo.areaResponsibleName || deviceInfo.areaResponsible || '-' }}
+              </el-descriptions-item>
+              <el-descriptions-item label="备注">
+                {{ deviceInfo.remarks }}
+              </el-descriptions-item>
+            </el-descriptions>
+
+            <!-- 设备照片展示 -->
+            <div class="device-photo-section" v-if="deviceInfo.devPhoto">
+              <h4 class="photo-title">设备照片</h4>
+              <div class="photo-container">
+                <el-image
+                  :src="getPhotoUrl(deviceInfo.devPhoto)"
+                  :preview-src-list="[getPhotoUrl(deviceInfo.devPhoto)]"
+                  fit="contain"
+                  class="device-photo">
+                  <div slot="error" class="image-slot">
+                    <i class="el-icon-picture-outline"></i>
+                    <p>图片加载失败</p>
+                  </div>
+                </el-image>
+              </div>
             </div>
-          </div>
+          </el-tab-pane>
 
-          <!-- 关联部件列表 -->
-          <div class="device-compo-section" v-if="deviceInfo.compoList && deviceInfo.compoList.length > 0">
-            <h4 class="compo-title">关联部件列表 ({{ deviceInfo.compoList.length }})</h4>
+          <!-- 关联部件标签页 -->
+          <el-tab-pane label="关联部件" name="compo" v-if="deviceInfo.compoList && deviceInfo.compoList.length > 0">
             <el-table :data="deviceInfo.compoList" border size="small" style="margin-top: 10px;">
-              <el-table-column label="部件名称" prop="compoName" :show-overflow-tooltip="true"/>
-              <el-table-column label="部件型号" prop="compoModel" :show-overflow-tooltip="true"/>
-              <el-table-column label="测厚点" prop="thicknessPt" width="80" :show-overflow-tooltip="true"/>
-              <el-table-column label="照片" align="center" width="70">
+              <el-table-column label="部件名称" align="center" prop="compoName" width="120" :show-overflow-tooltip="true"/>
+              <el-table-column label="检查频率" align="center" prop="inspFreq" width="110" :show-overflow-tooltip="true">
+                <template slot-scope="scope">
+                  {{ translateFrequency(scope.row.inspFreq) }}
+                </template>
+              </el-table-column>
+              <el-table-column label="检查内容" align="center" prop="inspContent" width="180" :show-overflow-tooltip="true"/>
+              <el-table-column label="上次检查日期" align="center" prop="lastInspDate" width="120">
+                <template slot-scope="scope">
+                  <span>{{ parseTime(scope.row.lastInspDate, '{y}-{m}-{d}') }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="维修频率" align="center" prop="fixFreq" width="110" :show-overflow-tooltip="true">
+                <template slot-scope="scope">
+                  {{ translateFrequency(scope.row.fixFreq) }}
+                </template>
+              </el-table-column>
+              <el-table-column label="维修内容" align="center" prop="fixContent" width="180" :show-overflow-tooltip="true"/>
+              <el-table-column label="上次维修日期" align="center" prop="lastFixDate" width="120">
                 <template slot-scope="scope">
-                  <el-button 
-                    v-if="scope.row.compoPhoto" 
-                    size="mini" 
-                    type="text" 
-                    icon="el-icon-picture"
-                    @click="handleViewCompoPhoto(scope.row.compoPhoto)">
-                    查看
-                  </el-button>
-                  <span v-else>-</span>
+                  <span>{{ parseTime(scope.row.lastFixDate, '{y}-{m}-{d}') }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="更换频率" align="center" prop="replaceFreq" width="110" :show-overflow-tooltip="true">
+                <template slot-scope="scope">
+                  {{ translateFrequency(scope.row.replaceFreq) }}
+                </template>
+              </el-table-column>
+              <el-table-column label="更换内容" align="center" prop="replaceContent" width="180" :show-overflow-tooltip="true"/>
+              <el-table-column label="上次更换日期" align="center" prop="lastReplaceDate" width="120">
+                <template slot-scope="scope">
+                  <span>{{ parseTime(scope.row.lastReplaceDate, '{y}-{m}-{d}') }}</span>
                 </template>
               </el-table-column>
             </el-table>
-          </div>
-        </div>
+          </el-tab-pane>
+
+          <!-- 维修记录标签页 -->
+          <el-tab-pane label="维修记录" name="record">
+            <el-table v-loading="maintRecordLoading" :data="maintRecordList" border size="small" :height="clientHeight" style="margin-top: 10px; width: 100%;">
+              <el-table-column label="部件名称" align="center" prop="compoName" width="120" :show-overflow-tooltip="true"/>
+              <el-table-column label="维修类型" align="center" width="100">
+                <template slot-scope="scope">
+                  <span v-if="scope.row.maintType === '1'">检查</span>
+                  <span v-else-if="scope.row.maintType === '2'">维修</span>
+                  <span v-else-if="scope.row.maintType === '3'">更换</span>
+                  <span v-else>{{ scope.row.maintType || '-' }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="责任人" align="center" width="100" :show-overflow-tooltip="true">
+                <template slot-scope="scope">
+                  <span>{{ getStaffNameById(scope.row.responsible) || '-' }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="检查内容" align="center" prop="inspectContent" width="150" :show-overflow-tooltip="true"/>
+              <el-table-column label="检查时间" align="center" prop="inspectTime" width="120">
+                <template slot-scope="scope">
+                  <span>{{ parseTime(scope.row.inspectTime, '{y}-{m}-{d}') }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="维修内容" align="center" prop="maintContent" width="150" :show-overflow-tooltip="true"/>
+              <el-table-column label="维修时间" align="center" prop="maintTime" width="120">
+                <template slot-scope="scope">
+                  <span>{{ parseTime(scope.row.maintTime, '{y}-{m}-{d}') }}</span>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-tab-pane>
+        </el-tabs>
 
         <div class="panel-content" v-else>
           <el-empty description="请点击流程图中的设备查看详情"></el-empty>
@@ -102,6 +154,8 @@
 <script>
 import ProcessDiagram from './process-diagram.vue'
 import { getRel_device } from "@/api/reliability/rel_device";
+import { listRel_maint_record } from "@/api/reliability/rel_maint_record";
+import { listStaffmgrAll } from "@/api/plant/staffmgr";
 
 export default {
   name: 'DeviceDetail',
@@ -111,7 +165,12 @@ export default {
   data() {
     return {
       deviceInfo: null,
-      deviceId: null
+      deviceId: null,
+      activeTab: 'info',
+      maintRecordList: [],
+      maintRecordLoading: false,
+      clientHeight: 0,
+      staffOptions: []
     }
   },
   created() {
@@ -120,6 +179,14 @@ export default {
     if (this.deviceId) {
       this.loadDeviceInfo();
     }
+    // 加载员工列表
+    this.loadStaffList();
+  },
+  mounted() {
+    // 设置表格高度对应屏幕高度
+    this.$nextTick(() => {
+      this.clientHeight = document.body.clientHeight - 250;
+    });
   },
   methods: {
     // 加载设备信息
@@ -135,6 +202,9 @@ export default {
               this.$refs.processDiagram.highlightDevice(this.deviceInfo.devTag || this.deviceInfo.devName);
             }
           });
+
+          // 同时加载维修记录
+          this.loadMaintRecords();
         }
       } catch (error) {
         console.error('加载设备信息失败:', error);
@@ -183,7 +253,93 @@ export default {
           center: true
         }
       );
-    }
+    },
+
+    // 处理 tab 切换
+    handleTabClick(tab) {
+      this.activeTab = tab.name;
+    },
+
+    // 加载维修记录
+    async loadMaintRecords() {
+      try {
+        this.maintRecordLoading = true;
+        const response = await listRel_maint_record({
+          devId: this.deviceId,
+          recordStatus: '2',  // 只查询已完成的维修记录
+          pageNum: 1,
+          pageSize: 1000
+        });
+        this.maintRecordList = response.rows || [];
+      } catch (error) {
+        console.error('加载维修记录失败:', error);
+        this.$message.error('加载维修记录失败');
+      } finally {
+        this.maintRecordLoading = false;
+      }
+    },
+
+    // 获取维修状态标签类型
+    getRecordStatusTagType(status) {
+      const statusMap = {
+        '-1': 'danger',    // 删除申请中
+        '0': 'info',       // 新增申请中
+        '1': 'warning',    // 待完成
+        '2': 'success'     // 已完成
+      };
+      return statusMap[status] || 'info';
+    },
+
+    // 获取维修状态文本
+    getRecordStatusText(status) {
+      const statusMap = {
+        '-1': '删除申请中',
+        '0': '新增申请中',
+        '1': '待完成',
+        '2': '已完成'
+      };
+      return statusMap[status] || '-';
+    },
+
+    // 转换频率显示
+    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;
+    },
+
+    // 加载员工列表
+    loadStaffList() {
+      listStaffmgrAll().then(response => {
+        this.staffOptions = response.rows || response.data || [];
+      }).catch(error => {
+        console.error('加载员工数据失败:', error);
+      });
+    },
+
+    // 根据员工ID获取姓名
+    getStaffNameById(staffid) {
+      if (!staffid) return '';
+      const staff = this.staffOptions.find(s => s.staffid === staffid);
+      return staff ? staff.name : '';
+    },
+
   }
 }
 </script>
@@ -199,6 +355,7 @@ export default {
   flex: 1;
   position: relative;
   overflow: hidden;
+  transition: flex 0.3s ease-in-out;
 }
 
 .device-info-section {
@@ -207,6 +364,7 @@ export default {
   border-left: 1px solid #e5e7eb;
   display: flex;
   flex-direction: column;
+  transition: width 0.3s ease-in-out;
 }
 
 .info-panel {
@@ -237,6 +395,26 @@ export default {
   overflow-y: auto;
 }
 
+.panel-tabs {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+}
+
+.panel-tabs /deep/ .el-tabs__content {
+  flex: 1;
+  overflow: hidden;
+  padding: 0;
+}
+
+.panel-tabs /deep/ .el-tab-pane {
+  padding: 20px;
+}
+
+.panel-tabs /deep/ .el-table {
+  width: 100%;
+}
+
 .device-photo-section {
   margin-top: 20px;
   padding-top: 20px;

+ 64 - 2
ui/src/views/reliability/rel_device/index.vue

@@ -161,8 +161,15 @@
         </template>
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remarks" width="150" :show-overflow-tooltip="true"/>
-      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+      <el-table-column label="操作" align="center" fixed="right" width="180" class-name="small-padding fixed-width">
         <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-plus"
+            @click="handleAddPlan(scope.row)"
+            v-hasPermi="['reliability:rel_maint_plan:add']"
+          >新计划</el-button>
           <el-button
             size="mini"
             type="text"
@@ -286,6 +293,15 @@
           <img :src="previewPhotoUrl" alt="设备照片" style="width: 100%; height: auto;">
         </div>
       </el-dialog>
+
+      <!-- 维修计划表单对话框 -->
+      <maint-plan-form
+        :visible.sync="maintPlanFormOpen"
+        :title="maintPlanFormTitle"
+        :form="maintPlanFormData"
+        @submit="handleMaintPlanFormSubmit"
+        @cancel="handleMaintPlanFormCancel"
+      />
   </div>
 </template>
 
@@ -296,10 +312,11 @@ import { listStaffmgrAll } from "@/api/plant/staffmgr";
 import { getToken } from "@/utils/auth";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import MaintPlanForm from "@/views/reliability/rel_maint_plan/MaintPlanForm.vue";
 
 export default {
   name: "Rel_device",
-  components: { Treeselect },
+  components: { Treeselect, MaintPlanForm },
   data() {
     return {
       // 遮罩层
@@ -356,6 +373,10 @@ export default {
       // 图片预览相关
       photoPreviewVisible: false,
       previewPhotoUrl: '',
+      // 维修计划表单相关
+      maintPlanFormOpen: false,
+      maintPlanFormTitle: "",
+      maintPlanFormData: {},
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -651,6 +672,47 @@ export default {
         }
       },
 
+      /** 新增维修计划按钮操作 */
+      handleAddPlan(row) {
+        // 初始化维修计划表单数据,预填设备信息
+        this.maintPlanFormData = {
+          planId: null,
+          devId: row.devId,
+          plant: row.plant,
+          devName: row.devName,
+          devTag: row.devTag,
+          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,
+          maintComponents: []
+        };
+        this.maintPlanFormTitle = "添加设备维修计划";
+        this.maintPlanFormOpen = true;
+      },
+
+      /** 维修计划表单提交 */
+      handleMaintPlanFormSubmit(formData) {
+        // 这里可以处理维修计划表单提交后的逻辑
+        // 例如刷新列表等
+        this.getList();
+      },
+
+      /** 维修计划表单取消 */
+      handleMaintPlanFormCancel() {
+        this.maintPlanFormOpen = false;
+        this.maintPlanFormData = {};
+      },
+
       /** 根据人员ID获取人员姓名 */
       getStaffName(staffId) {
         if (!staffId) return '-';

+ 4 - 59
ui/src/views/reliability/rel_device/process-diagram.vue

@@ -3,9 +3,6 @@
 	  <!-- 工具栏 -->
 	  <div class="toolbar">
 		<button @click="resetView" class="tool-btn">重置视图</button>
-		<button @click="zoomIn" class="tool-btn">放大</button>
-		<button @click="zoomOut" class="tool-btn">缩小</button>
-		<span class="zoom-info">缩放: {{ scalePercentage }}%</span>
 	  </div>
 
 	  <!-- 左侧 SVG 区域 -->
@@ -96,11 +93,6 @@
       selectedDevice: {
         type: Object,
         default: null
-      },
-      // SVG文件路径
-      svgPath: {
-        type: String,
-        default: ''
       }
     },
     data() {
@@ -110,7 +102,6 @@
         // vue-draggable-resizable 相关
         svgPosition: { x: 0, y: 0 },
         svgSize: { width: 1200, height: 900 },
-        scale: 1,
         loading: true,
 
         // 当前悬停/选中的形状
@@ -154,12 +145,7 @@
           top: '20px',
           zIndex: 1000
         }
-      },
-
-      // 计算缩放百分比
-      scalePercentage() {
-        return Math.round(this.scale * 100);
-      },
+      }
     },
 
     methods: {
@@ -282,28 +268,6 @@
       resetView() {
         this.svgPosition = { x: 0, y: 0 };
         this.svgSize = { width: 1200, height: 900 };
-        this.scale = 1;
-      },
-
-      // 缩放功能
-      zoomIn() {
-        const newScale = Math.min(5, this.scale + 0.2);
-        const scaleRatio = newScale / this.scale;
-        this.scale = newScale;
-
-        // 调整尺寸以保持视觉中心
-        this.svgSize.width = this.svgSize.width * scaleRatio;
-        this.svgSize.height = this.svgSize.height * scaleRatio;
-      },
-
-      zoomOut() {
-        const newScale = Math.max(0.1, this.scale - 0.2);
-        const scaleRatio = newScale / this.scale;
-        this.scale = newScale;
-
-        // 调整尺寸以保持视觉中心
-        this.svgSize.width = Math.max(800, this.svgSize.width * scaleRatio);
-        this.svgSize.height = Math.max(600, this.svgSize.height * scaleRatio);
       },
 
       // 保存元素的原始样式
@@ -386,18 +350,6 @@
         this.hoverShape = null;
       },
 
-      // 清除选择
-      clearSelection() {
-        this.selectedShape = null;
-        if (this.$refs.svgObject?.contentDocument) {
-          const svgDoc = this.$refs.svgObject.contentDocument;
-          svgDoc.querySelectorAll(".selected").forEach((el) => {
-            el.classList.remove("selected");
-            this.clearSelectedEffect(el);
-          });
-        }
-      },
-
       // 获取状态样式
       getStatusStyle(status) {
         const baseStyle = "padding: 4px 8px; border-radius: 4px; font-size: 12px; font-weight: 600; text-align: center; display: inline-block; min-width: 60px;";
@@ -491,14 +443,13 @@
     },
 
     mounted() {
-      // 设置初始光标样式和尺寸
+      // 设置初始 SVG 尺寸
       this.$nextTick(() => {
         if (this.$refs.svgContainer) {
           const containerRect = this.$refs.svgContainer.getBoundingClientRect();
-          // 设置初始 SVG 尺寸为容器尺寸的 95%,最小1200x900
           this.svgSize = {
-            width: Math.max(1200, Math.max(containerRect.width * 0.95, 1200)),
-            height: Math.max(900, Math.max(containerRect.height * 0.95, 900))
+            width: Math.max(1200, containerRect.width * 0.95),
+            height: Math.max(900, containerRect.height * 0.95)
           };
         }
       });
@@ -540,12 +491,6 @@
 	background: #2563eb;
   }
 
-  .zoom-info {
-	font-size: 14px;
-	color: #6b7280;
-	margin-left: auto;
-  }
-
   /* 主内容区域 */
   .svg-page > div:not(.toolbar) {
 	display: flex;

+ 83 - 52
ui/src/views/reliability/rel_maint_plan/MaintPlanForm.vue

@@ -60,8 +60,8 @@
                 <el-option
                   v-for="staff in staffOptions"
                   :key="staff.staffid"
-                  :label="staff.name"
-                  :value="staff.name">
+                  :label="`${staff.name} (${staff.staffid})`"
+                  :value="staff.staffid">
                 </el-option>
                 <div v-if="staffOptions.length === 0" style="padding: 10px; text-align: center; color: #909399;">
                   暂无人员数据
@@ -76,12 +76,13 @@
                 placeholder="请选择审批人"
                 style="width: 100%"
                 clearable
-                filterable>
+                filterable
+                :disabled="!!formData.planId">
                 <el-option
                   v-for="staff in staffOptions"
                   :key="staff.staffid"
-                  :label="staff.name"
-                  :value="staff.name">
+                  :label="`${staff.name} (${staff.staffid})`"
+                  :value="staff.staffid">
                 </el-option>
                 <div v-if="staffOptions.length === 0" style="padding: 10px; text-align: center; color: #909399;">
                   暂无人员数据
@@ -155,14 +156,18 @@
           </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>
+              <el-checkbox
+                v-model="scope.row.needMaint"
+                :disabled="scope.row.recordStatus === 2 || scope.row.recordStatus === '2'"
+                @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"
+                :disabled="!scope.row.needMaint || scope.row.recordStatus === 2 || scope.row.recordStatus === '2'"
                 @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>
@@ -177,24 +182,37 @@
                 v-model="scope.row.maintResponsible"
                 :placeholder="getResponsiblePlaceholder(scope.row.maintType)"
                 style="width: 100%"
-                :disabled="!scope.row.needMaint"
+                :disabled="!scope.row.needMaint || scope.row.recordStatus === 2 || scope.row.recordStatus === '2'"
                 clearable
                 filterable>
                 <el-option
                   v-for="staff in staffOptions"
                   :key="staff.staffid"
-                  :label="staff.name"
-                  :value="staff.name">
+                  :label="`${staff.name} (${staff.staffid})`"
+                  :value="staff.staffid">
                 </el-option>
               </el-select>
             </template>
           </el-table-column>
+          <el-table-column label="维修状态" width="100" align="center">
+            <template slot-scope="scope">
+              <el-tag
+                v-if="scope.row.recordStatus !== undefined && scope.row.recordStatus !== null"
+                :type="getRecordStatusTagType(scope.row.recordStatus)"
+                size="small"
+              >
+                {{ getRecordStatusText(scope.row.recordStatus) }}
+              </el-tag>
+              <span v-else>-</span>
+            </template>
+          </el-table-column>
         </el-table>
       </div>
     </el-form>
     <div slot="footer" class="dialog-footer">
       <el-button type="primary" @click="handleSubmit" v-if="!formData.planId">提交申请</el-button>
-      <el-button type="primary" @click="handleSubmit" v-else>确 定</el-button>
+      <el-button type="primary" @click="handleSubmit" v-else-if="formData.approvalStatus !== '1'">确 定</el-button>
+      <el-button type="primary" @click="handleSubmit" v-else>再次提交申请</el-button>
       <el-button @click="handleCancel">取 消</el-button>
     </div>
   </el-dialog>
@@ -287,23 +305,20 @@ export default {
               this.loadCompoList(this.selectedDevice.devTag);
             }
           } else if (this.formData.devId) {
+            // 当从外部传入 devId 时,需要加载设备信息并添加到 deviceOptions
             this.loadDeviceInfo(this.formData.devId);
+            getRel_device(this.formData.devId).then(response => {
+              // 确保 deviceOptions 中包含该设备,以便下拉框能正确显示
+              const deviceExists = this.deviceOptions.find(d => d.devId === this.formData.devId);
+              if (!deviceExists) {
+                this.deviceOptions = [response.data];
+              }
+            });
           }
 
           const convertIdsToNames = () => {
-            if (this.formData.approver && this.staffOptions.length > 0) {
-              const staff = this.staffOptions.find(s => s.staffid === this.formData.approver);
-              if (staff) {
-                this.formData.approver = staff.name;
-              }
-            }
-
-            if (this.formData.responsible && typeof this.formData.responsible !== 'string' && this.staffOptions.length > 0) {
-              const staff = this.staffOptions.find(s => s.staffid === this.formData.responsible);
-              if (staff) {
-                this.formData.responsible = staff.name;
-              }
-            }
+            // 审批人和责任人都已经是staffId,无需转换,直接使用
+            // 显示时通过 el-option 的 label 显示"名称 (员工号)"格式
           };
 
           if (this.staffOptions.length > 0) {
@@ -434,12 +449,10 @@ export default {
       getRel_device(devId).then(response => {
         this.selectedDevice = response.data;
 
-        // 修改模式下,将当前设备添加到deviceOptions中,以便下拉框显示
-        if (this.formData.planId && devId) {
-          const deviceExists = this.deviceOptions.find(d => d.devId === devId);
-          if (!deviceExists) {
-            this.deviceOptions = [response.data];
-          }
+        // 将当前设备添加到deviceOptions中,以便下拉框显示
+        const deviceExists = this.deviceOptions.find(d => d.devId === devId);
+        if (!deviceExists) {
+          this.deviceOptions = [response.data];
         }
 
         // 自动填充设备负责人(areaResponsible),如果还没有设置责任人
@@ -463,6 +476,7 @@ export default {
         needMaint: false,
         maintType: '',
         maintResponsible: '',
+        recordStatus: null,
         checkFreq: compo.inspFreq || '',
         lastCheckDate: compo.lastInspDate || '',
         maintFreq: compo.fixFreq || '',
@@ -514,17 +528,27 @@ export default {
           const record = maintRecords.find(r => r.compoId == compo.compoId);
 
           if (record) {
-            compo.needMaint = true;
-            compo.maintType = record.maintType;
+            compo.recordStatus = record.recordStatus;
 
-            if (record.responsible && this.staffOptions.length > 0) {
-              const staff = this.staffOptions.find(s => s.staffid === record.responsible);
-              compo.maintResponsible = staff ? staff.name : '';
+            // 如果recordStatus为-1(删除申请中),则不勾选维修
+            if (record.recordStatus === -1 || record.recordStatus === '-1') {
+              compo.needMaint = false;
+              compo.maintType = '';
+              compo.maintResponsible = '';
             } else {
-              if (compo.maintType === '1') {
-                compo.maintResponsible = compo.inspectorName || '';
-              } else if (compo.maintType === '2' || compo.maintType === '3') {
-                compo.maintResponsible = compo.fixerName || '';
+              compo.needMaint = true;
+              compo.maintType = record.maintType;
+
+              // 责任人存储staffId
+              if (record.responsible) {
+                compo.maintResponsible = record.responsible;
+              } else {
+                // 没有记录的responsible,根据维修类型使用默认值
+                if (compo.maintType === '1') {
+                  compo.maintResponsible = compo.inspector || '';
+                } else if (compo.maintType === '2' || compo.maintType === '3') {
+                  compo.maintResponsible = compo.fixer || '';
+                }
               }
             }
           }
@@ -554,9 +578,9 @@ export default {
     /** 维修形式改变 */
     handleMaintTypeChange(compo) {
       if (compo.maintType === '1') {
-        compo.maintResponsible = compo.inspectorName || '';
+        compo.maintResponsible = compo.inspector || '';
       } else if (compo.maintType === '2' || compo.maintType === '3') {
-        compo.maintResponsible = compo.fixerName || '';
+        compo.maintResponsible = compo.fixer || '';
       } else {
         compo.maintResponsible = '';
       }
@@ -600,6 +624,22 @@ export default {
     parseTime(time, pattern) {
       return formatTime(time, pattern);
     },
+    /** 获取维修状态文本 */
+    getRecordStatusText(status) {
+      if (status === -1 || status === '-1') return '删除申请中';
+      if (status === 0 || status === '0') return '新增申请中';
+      if (status === 1 || status === '1') return '待完成';
+      if (status === 2 || status === '2') return '已完成';
+      return status != null ? status : '-';
+    },
+    /** 获取维修状态标签类型 */
+    getRecordStatusTagType(status) {
+      if (status === -1 || status === '-1') return 'danger';
+      if (status === 0 || status === '0') return 'warning';
+      if (status === 1 || status === '1') return 'info';
+      if (status === 2 || status === '2') return 'success';
+      return '';
+    },
     /** 提交表单 */
     handleSubmit() {
       this.$refs.form.validate(valid => {
@@ -611,7 +651,7 @@ export default {
                 compoId: compo.compoId,
                 compoName: compo.compoName,
                 maintType: compo.maintType,
-                responsible: this.getStaffIdByName(compo.maintResponsible),
+                responsible: compo.maintResponsible,
                 inspectContent: '',
                 maintContent: '',
                 maintResult: '',
@@ -625,16 +665,7 @@ export default {
             this.formData.maintComponents = maintComponents;
           }
 
-          if (this.formData.approver) {
-            this.formData.approver = this.getStaffIdByName(this.formData.approver);
-          }
-
-          if (this.formData.responsible && typeof this.formData.responsible === 'string') {
-            const staffId = this.getStaffIdByName(this.formData.responsible);
-            if (staffId) {
-              this.formData.responsible = staffId;
-            }
-          }
+          // 审批人和责任人都已经是staffId格式,无需转换
 
           this.$emit('submit', this.formData);
         }

+ 22 - 49
ui/src/views/reliability/rel_maint_plan/index.vue

@@ -67,26 +67,16 @@
           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-col :span="1.5">
         <el-button
           type="danger"
           icon="el-icon-delete"
           size="mini"
-          :disabled="multiple"
+          :disabled="!canDelete"
           @click="handleDelete"
           v-hasPermi="['reliability:rel_maint_plan:remove']"
         >删除</el-button>
-      </el-col>
+      </el-col> -->
 <!--      <el-col :span="1.5">-->
 <!--        <el-button-->
 <!--          type="warning"-->
@@ -152,7 +142,7 @@
             v-hasPermi="['reliability:rel_maint_plan:edit']"
           >修改</el-button>
           <el-button
-            v-if="scope.row.approvalStatus !== '0'"
+            v-if="scope.row.approvalStatus === '-1' && scope.row.completionStatus === '0'"
             size="mini"
             type="text"
             icon="el-icon-delete"
@@ -187,40 +177,11 @@
       @close="handleDetailClose"
     />
       <!-- 用户导入对话框 -->
-      <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_maint_plan, getRel_maint_plan, delRel_maint_plan, addRel_maint_plan, updateRel_maint_plan, exportRel_maint_plan, importTemplate, submitApprove, resubmitApprove} from "@/api/reliability/rel_maint_plan";
 import { listRel_maint_record } from "@/api/reliability/rel_maint_record";
 import { treeselect } from "@/api/system/dept";
 import { getToken } from "@/utils/auth";
@@ -436,11 +397,23 @@ export default {
     handleFormSubmit(formData) {
       if (formData.planId != null) {
         // 修改模式
-        updateRel_maint_plan(formData).then(response => {
-          this.msgSuccess("修改成功");
-          this.open = false;
-          this.getList();
-        });
+        if (formData.approvalStatus === "1") {
+          // 已通过的计划 - 再次提交申请
+          resubmitApprove(formData).then(response => {
+            this.msgSuccess("维修计划再次提交申请成功");
+            this.open = false;
+            this.getList();
+          }).catch(error => {
+            this.msgError("再次提交失败:" + (error.message || "未知错误"));
+          });
+        } else {
+          // 其他状态 - 直接修改
+          updateRel_maint_plan(formData).then(response => {
+            this.msgSuccess("修改成功");
+            this.open = false;
+            this.getList();
+          });
+        }
       } else {
         // 新增模式 - 提交申请
         submitApprove(formData).then(response => {

+ 31 - 1
ui/src/views/reliability/rel_maint_record/index.vue

@@ -121,6 +121,20 @@
           <span>{{ getStaffNameById(scope.row.responsible) || '-' }}</span>
         </template>
       </el-table-column>
+      <el-table-column label="维修计划" align="center" width="120">
+        <template slot-scope="scope">
+          <el-link
+            v-if="scope.row.maintPlan && scope.row.maintPlan.planTime && scope.row.maintPlan.planId"
+            type="primary"
+            :underline="false"
+            style="font-size: 14px;"
+            @click="handleViewPlan(scope.row.maintPlan.planId)">
+            {{ parseTime(scope.row.maintPlan.planTime, '{y}-{m}-{d}') }}
+            <i class="el-icon-view" style="margin-right: 4px;"></i>
+          </el-link>
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
       <el-table-column label="维修状态" align="center" width="150">
         <template slot-scope="scope">
           <el-tag :type="getRecordStatusTagType(scope.row.recordStatus)" size="small">
@@ -305,6 +319,13 @@
       </div>
       </el-dialog>
 
+    <!-- 维修计划详情对话框 -->
+    <maint-plan-detail
+      :visible.sync="planDetailVisible"
+      :plan-id="planDetailId"
+      @close="planDetailVisible = false"
+    />
+
     <!-- 查看备忘录详情对话框 -->
     <el-dialog title="备忘录详情" :visible.sync="memoDialogVisible" width="700px" append-to-body>
       <el-descriptions :column="2" border v-if="memoDetail">
@@ -374,10 +395,11 @@ import { listStaffmgrAll } from "@/api/plant/staffmgr";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import Editor from '@/components/Editor';
+import MaintPlanDetail from "@/views/reliability/rel_maint_plan/MaintPlanDetail";
 
 export default {
   name: "Rel_maint_record",
-  components: { Treeselect },
+  components: { Treeselect, MaintPlanDetail },
   // components: { Editor },
   data() {
     return {
@@ -455,6 +477,9 @@ export default {
       // 备忘录对话框
       memoDialogVisible: false,
       memoDetail: null,
+      // 维修计划详情对话框
+      planDetailVisible: false,
+      planDetailId: null,
       // 所有人员选项
       staffOptions: []
     };
@@ -533,6 +558,11 @@ export default {
         this.memoDialogVisible = true;
       }
     },
+    /** 查看维修计划详情 */
+    handleViewPlan(planId) {
+      this.planDetailId = planId;
+      this.planDetailVisible = true;
+    },
     // 取消按钮
     cancel() {
       this.open = false;

+ 8 - 5
ui/src/views/reliability/rel_maint_record/myRecord.vue

@@ -116,21 +116,21 @@
           <span v-else>-</span>
         </template>
       </el-table-column>
-      <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="maintDept" :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="inspectContent" :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="maintDept" :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="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"/>
@@ -288,6 +288,9 @@
             </el-form-item>
           </template>
           <template v-else>
+            <el-form-item label="维修部门" prop="maintDept">
+              <el-input v-model="processForm.maintDept" placeholder="请输入维修部门" />
+            </el-form-item>
             <el-form-item label="维修内容" prop="maintContent">
               <el-input v-model="processForm.maintContent" type="textarea" :rows="5" placeholder="请输入维修内容" />
             </el-form-item>