ソースを参照

feat(check): 添加班组执行模式支持和维修工时统计功能

- 在CheckJob实体和DTO中新增checkDeptId字段用于班组ID存储
- 在CheckStandard中新增TEAM类型的执行人方式,扩展负责人类型枚举
- 修改Mapper XML文件添加班组相关的数据库映射和查询条件
- 实现班组模式下的任务分配逻辑,支持按班组分配点检任务
- 新增维修工时统计相关VO类和导出功能
- 添加按维修人和设备维度的工时统计数据统计接口
- 实现维修工时统计的分页查询和明细查看功能
- 集成班组信息的数据库关联查询和数据显示
dazhaxie 15 時間 前
コミット
a8bbf26e7e
21 ファイル変更544 行追加11 行削除
  1. 4 0
      platform-dao/src/main/java/com/platform/dao/dto/check/CheckJobDTO.java
  2. 5 1
      platform-dao/src/main/java/com/platform/dao/dto/check/CheckStandardDTO.java
  3. 13 0
      platform-dao/src/main/java/com/platform/dao/dto/repair/RepairApplicationFormDTO.java
  4. 4 0
      platform-dao/src/main/java/com/platform/dao/entity/check/CheckJob.java
  5. 5 1
      platform-dao/src/main/java/com/platform/dao/entity/check/CheckStandard.java
  6. 5 1
      platform-dao/src/main/java/com/platform/dao/enums/CheckUserTypeEnum.java
  7. 27 0
      platform-dao/src/main/java/com/platform/dao/mapper/repair/RepairApplicationFormMapper.java
  8. 3 0
      platform-dao/src/main/java/com/platform/dao/util/TreeUtil.java
  9. 50 0
      platform-dao/src/main/java/com/platform/dao/vo/export/report/ExportRepairWorkHourSbVO.java
  10. 44 0
      platform-dao/src/main/java/com/platform/dao/vo/export/report/ExportRepairWorkHourUserVO.java
  11. 8 0
      platform-dao/src/main/java/com/platform/dao/vo/query/check/CheckJobVO.java
  12. 9 1
      platform-dao/src/main/java/com/platform/dao/vo/query/check/CheckStandardVO.java
  13. 61 0
      platform-dao/src/main/java/com/platform/dao/vo/report/RepairWorkHourReportVO.java
  14. 27 0
      platform-dao/src/main/resources/mapper/check/CheckJobMapper.xml
  15. 16 3
      platform-dao/src/main/resources/mapper/check/CheckStandardMapper.xml
  16. 94 0
      platform-dao/src/main/resources/mapper/repair/RepairApplicationFormMapper.xml
  17. 88 0
      platform-rest/src/main/java/com/platform/rest/controller/report/RepairReportController.java
  18. 30 0
      platform-service/src/main/java/com/platform/service/check/impl/CheckJobServiceImpl.java
  19. 29 0
      platform-service/src/main/java/com/platform/service/repair/RepairApplicationFormService.java
  20. 20 0
      platform-service/src/main/java/com/platform/service/repair/impl/RepairApplicationFormServiceImpl.java
  21. 2 4
      platform-service/src/main/java/com/platform/service/upms/impl/SysUserServiceImpl.java

+ 4 - 0
platform-dao/src/main/java/com/platform/dao/dto/check/CheckJobDTO.java

@@ -110,6 +110,10 @@ public class CheckJobDTO extends BaseDTO implements Serializable {
      */
     private String checkUserId;
     /**
+     * 班组ID(执行人方式为班组时使用)
+     */
+    private String checkDeptId;
+    /**
      * 设备等级
      */
     private Integer sbLevel;

+ 5 - 1
platform-dao/src/main/java/com/platform/dao/dto/check/CheckStandardDTO.java

@@ -106,10 +106,14 @@ public class CheckStandardDTO extends BaseDTO implements Serializable {
      */
     private Integer periodType;
     /**
-     * 负责人类型: 参考数据字典:1车间,2维修员,3厂商
+     * 负责人类型: 参考数据字典:1车间,2维修员,3厂商, 4班组
      */
     private Integer checkUserType;
     /**
+     * 班组ID(执行人方式为班组时使用)
+     */
+    private String checkDeptId;
+    /**
      * 上次生成时间
      */
     @Transient

+ 13 - 0
platform-dao/src/main/java/com/platform/dao/dto/repair/RepairApplicationFormDTO.java

@@ -7,6 +7,7 @@ import com.platform.dao.entity.upms.SysFile;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import javax.persistence.Id;
 import javax.persistence.Transient;
@@ -330,6 +331,18 @@ public class RepairApplicationFormDTO extends BaseDTO implements Serializable {
      */
     private LocalDateTime searchEndTime;
 
+    /**
+     * 搜索开始时间:维修开始时间(维修工时统计用)
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime searchRepairStartTime;
+
+    /**
+     * 搜索结束时间:维修开始时间(维修工时统计用)
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime searchRepairEndTime;
+
     private String secondRepairUser;
 
     private String threeRepairUser;

+ 4 - 0
platform-dao/src/main/java/com/platform/dao/entity/check/CheckJob.java

@@ -119,6 +119,10 @@ public class CheckJob implements Serializable {
      */
     private String checkUserId;
     /**
+     * 班组ID(执行人方式为班组时使用)
+     */
+    private String checkDeptId;
+    /**
      * 点检人
      */
     private String checkUserName;

+ 5 - 1
platform-dao/src/main/java/com/platform/dao/entity/check/CheckStandard.java

@@ -73,10 +73,14 @@ public class CheckStandard implements Serializable{
      */
     private Integer periodType;
     /**
-     * 负责人类型: 参考数据字典:1使用人员,2第一维修员
+     * 负责人类型: 参考数据字典:1使用人员,2第一维修员, 3指定, 4班组
      */
     private Integer checkUserType;
     /**
+     * 班组ID(执行人方式为班组时使用)
+     */
+    private String checkDeptId;
+    /**
      * 周期类型: 参考数据字典
      */
     private Integer actionType;

+ 5 - 1
platform-dao/src/main/java/com/platform/dao/enums/CheckUserTypeEnum.java

@@ -24,7 +24,11 @@ public enum CheckUserTypeEnum {
     /**
      *指定
      */
-    ZHIDING(3);
+    ZHIDING(3),
+    /**
+     * 班组
+     */
+    TEAM(4);
     private final Integer value;
 
 }

+ 27 - 0
platform-dao/src/main/java/com/platform/dao/mapper/repair/RepairApplicationFormMapper.java

@@ -4,6 +4,7 @@ import com.platform.dao.config.MyMapper;
 import com.platform.dao.dto.repair.RepairApplicationFormDTO;
 import com.platform.dao.entity.repair.RepairApplicationForm;
 import com.platform.dao.vo.repair.RepairApplicationFormVO;
+import com.platform.dao.vo.report.RepairWorkHourReportVO;
 import org.springframework.stereotype.Component;
 import java.util.List;
 
@@ -47,4 +48,30 @@ public interface RepairApplicationFormMapper extends MyMapper<RepairApplicationF
      */
     List<String> selectSbIdsWithStatus(@org.apache.ibatis.annotations.Param("sbIds") List<String> sbIds,
                                        @org.apache.ibatis.annotations.Param("status") List<Integer> status);
+
+    /**
+     * 维修工时统计:按维修人分组
+     * 统计口径:维修结束时间不为空的报修单,按维修开始时间过滤
+     *
+     * @param dto 查询条件(维修人姓名模糊、时间范围)
+     * @return 维修次数、总维修工时、平均工时、总停机修复时长
+     */
+    List<RepairWorkHourReportVO> statisticsWorkHourByUser(RepairApplicationFormDTO dto);
+
+    /**
+     * 维修工时统计:按设备分组
+     * 统计口径:维修结束时间不为空的报修单,按维修开始时间过滤
+     *
+     * @param dto 查询条件(设备名称/编号模糊、时间范围)
+     * @return 维修次数、总维修工时、平均工时、总停机修复时长
+     */
+    List<RepairWorkHourReportVO> statisticsWorkHourBySb(RepairApplicationFormDTO dto);
+
+    /**
+     * 维修工时统计明细:某维修人或某设备已完成维修的报修单列表
+     *
+     * @param dto 查询条件(维修人主维修人精确匹配、设备、时间范围)
+     * @return 报修单列表
+     */
+    List<RepairApplicationFormVO> selectWorkHourDetail(RepairApplicationFormDTO dto);
 }

+ 3 - 0
platform-dao/src/main/java/com/platform/dao/util/TreeUtil.java

@@ -235,6 +235,7 @@ public class TreeUtil {
             node.setKey(dept.getDeptId());
             node.setParentId(dept.getParentId());
             node.setTitle(dept.getName());
+            node.setValue(dept.getDeptId());
             Boolean closeDept = dept.getCloseDept();
             node.setClazz(closeDept != null && closeDept ? "tree-title-close-dept-future" : null);
             node.setItem(dept);
@@ -277,6 +278,7 @@ public class TreeUtil {
             node.setKey(dept.getDeptId());
             node.setParentId(dept.getParentId());
             node.setTitle(dept.getName());
+            node.setValue(dept.getDeptId());
             trees.add(node);
         });
         return TreeUtil.buildByLoopWithoutRoot(trees);
@@ -296,6 +298,7 @@ public class TreeUtil {
             node.setKey(dept.getDeptId());
             node.setParentId(dept.getParentId());
             node.setTitle(dept.getName());
+            node.setValue(dept.getDeptId());
             node.setItem(dept);
             trees.add(node);
         });

+ 50 - 0
platform-dao/src/main/java/com/platform/dao/vo/export/report/ExportRepairWorkHourSbVO.java

@@ -0,0 +1,50 @@
+package com.platform.dao.vo.export.report;
+
+import com.platform.office.annotation.Excel;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @Description 维修工时统计-按设备统计导出VO
+ */
+@Data
+@Accessors(chain = true)
+public class ExportRepairWorkHourSbVO implements Serializable {
+    /**
+     * 设备编号
+     */
+    @Excel(name = "设备编号", orderNum = "1")
+    private String sbNo;
+
+    /**
+     * 设备名称
+     */
+    @Excel(name = "设备名称", orderNum = "2")
+    private String sbName;
+
+    /**
+     * 维修次数
+     */
+    @Excel(name = "维修次数", orderNum = "3")
+    private Integer num;
+
+    /**
+     * 总维修工时(小时)
+     */
+    @Excel(name = "总维修工时(小时)", orderNum = "4")
+    private Double totalRepairHours;
+
+    /**
+     * 平均工时(小时)
+     */
+    @Excel(name = "平均工时(小时)", orderNum = "5")
+    private Double avgRepairHours;
+
+    /**
+     * 总停机修复时长(小时)
+     */
+    @Excel(name = "总停机修复时长(小时)", orderNum = "6")
+    private Double totalDealHours;
+}

+ 44 - 0
platform-dao/src/main/java/com/platform/dao/vo/export/report/ExportRepairWorkHourUserVO.java

@@ -0,0 +1,44 @@
+package com.platform.dao.vo.export.report;
+
+import com.platform.office.annotation.Excel;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @Description 维修工时统计-按维修人统计导出VO
+ */
+@Data
+@Accessors(chain = true)
+public class ExportRepairWorkHourUserVO implements Serializable {
+    /**
+     * 维修人
+     */
+    @Excel(name = "维修人", orderNum = "1")
+    private String repairUserName;
+
+    /**
+     * 维修次数
+     */
+    @Excel(name = "维修次数", orderNum = "2")
+    private Integer num;
+
+    /**
+     * 总维修工时(小时)
+     */
+    @Excel(name = "总维修工时(小时)", orderNum = "3")
+    private Double totalRepairHours;
+
+    /**
+     * 平均工时(小时)
+     */
+    @Excel(name = "平均工时(小时)", orderNum = "4")
+    private Double avgRepairHours;
+
+    /**
+     * 总停机修复时长(小时)
+     */
+    @Excel(name = "总停机修复时长(小时)", orderNum = "5")
+    private Double totalDealHours;
+}

+ 8 - 0
platform-dao/src/main/java/com/platform/dao/vo/query/check/CheckJobVO.java

@@ -128,6 +128,14 @@ public class CheckJobVO implements Serializable{
      */
     private String checkUserName;
     /**
+     * 班组ID(执行人方式为班组时使用)
+     */
+    private String checkDeptId;
+    /**
+     * 班组名称
+     */
+    private String checkDeptName;
+    /**
      * 任务开始时间
      */
     private LocalDate startTime;

+ 9 - 1
platform-dao/src/main/java/com/platform/dao/vo/query/check/CheckStandardVO.java

@@ -94,10 +94,18 @@ public class CheckStandardVO extends BaseVO implements Serializable{
      */
     private Integer actionType;
     /**
-     * 负责人类型: 参考数据字典:1车间,2维修员,3厂商
+     * 负责人类型: 参考数据字典:1车间,2维修员,3厂商, 4班组
      */
     private Integer checkUserType;
     /**
+     * 班组ID(执行人方式为班组时使用)
+     */
+    private String checkDeptId;
+    /**
+     * 班组名称
+     */
+    private String checkDeptName;
+    /**
      * 检查类型: 1-点检 2-巡检
      */
     private Integer type;

+ 61 - 0
platform-dao/src/main/java/com/platform/dao/vo/report/RepairWorkHourReportVO.java

@@ -0,0 +1,61 @@
+package com.platform.dao.vo.report;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @Description 维修工时统计报表
+ * 按维修人/按设备统计维修次数、维修工时(报修单维修完成的数据)
+ */
+@Data
+@Accessors(chain = true)
+public class RepairWorkHourReportVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 维修人id
+     */
+    private String repairUserId;
+
+    /**
+     * 维修人姓名
+     */
+    private String repairUserName;
+
+    /**
+     * 设备id
+     */
+    private String sbId;
+
+    /**
+     * 设备编号
+     */
+    private String sbNo;
+
+    /**
+     * 设备名称
+     */
+    private String sbName;
+
+    /**
+     * 维修次数
+     */
+    private Integer num;
+
+    /**
+     * 总维修工时(小时)
+     */
+    private Double totalRepairHours;
+
+    /**
+     * 平均工时(小时)
+     */
+    private Double avgRepairHours;
+
+    /**
+     * 总停机修复时长(小时)
+     */
+    private Double totalDealHours;
+}

+ 27 - 0
platform-dao/src/main/resources/mapper/check/CheckJobMapper.xml

@@ -25,6 +25,7 @@
         <result column="status" property="status"/>
         <result column="sb_status" property="sbStatus"/>
         <result column="check_user_id" property="checkUserId"/>
+        <result column="check_dept_id" property="checkDeptId"/>
         <result column="created_user_id" property="createdUserId"/>
         <result column="update_user_id" property="updateUserId"/>
         <result column="created_user_name" property="createdUserName"/>
@@ -50,6 +51,7 @@
         <result column="periodType" property="periodType"/>
         <result column="positionId" property="positionId"/>
         <result column="positionName" property="positionName"/>
+        <result column="checkDeptName" property="checkDeptName"/>
 
         <collection property="requirementList" ofType="com.platform.dao.entity.check.CheckRequirement">
             <id column="requirement_id" property="id" />
@@ -79,6 +81,7 @@
                                      checkjob.sb_status,
                                      checkjob.receive_overtime,
                                      checkjob.check_user_id,
+                                     checkjob.check_dept_id,
                                      checkjob.created_user_id,
                                      checkjob.update_user_id,
                                      checkjob.created_user_name,
@@ -94,6 +97,7 @@
                                      checkjob.start_time,
                                      checkjob.type,
                                      checkjob.check_user_id,
+                                     checkjob.check_dept_id,
                                      checkjob.end_time,
                                      checkjob.actual_start_time,
                                      checkjob.actual_end_time,
@@ -232,6 +236,9 @@
         <if test="checkUserId != null and checkUserId != ''">
             and checkjob.check_user_id = #{checkUserId}
         </if>
+        <if test="checkDeptId != null and checkDeptId != ''">
+            and checkjob.check_dept_id = #{checkDeptId}
+        </if>
         <if test="type != null and type != ''">
             and checkjob.type = #{type}
         </if>
@@ -408,6 +415,9 @@
         <if test="checkUserId != null and checkUserId != ''">
             and checkjob_inner.check_user_id = #{checkUserId}
         </if>
+        <if test="checkDeptId != null and checkDeptId != ''">
+            and checkjob_inner.check_dept_id = #{checkDeptId}
+        </if>
         <if test="type != null and type != ''">
             and checkjob_inner.type = #{type}
         </if>
@@ -476,6 +486,7 @@
         checkjob.status as status,
         checkjob.sb_status as sb_status,
         checkjob.check_user_id as check_user_id,
+        checkjob.check_dept_id as check_dept_id,
         checkjob.created_user_id as created_user_id,
         checkjob.update_user_id as update_user_id,
         checkjob.created_user_name as created_user_name,
@@ -488,6 +499,7 @@
         checkjob.receive_overtime as receive_overtime,
         checkjob.con_task as con_task,
         u.real_name as checkUserName,
+        dept.name as checkDeptName,
         sbinfo.name as sbName,
         sbinfo.no as sbNo,
         sbinfo.level as sbLevel,
@@ -515,6 +527,7 @@
         left join t_part_info partinfo on partinfo.id = checkjob.part_id
         left join t_check_standard standard on standard.id = checkjob.standard_id
         left join t_sys_user u on checkjob.check_user_id = u.user_id
+        left join t_sys_dept dept on checkjob.check_dept_id = dept.dept_id
         left join t_sb_position position on position.id = sbinfo.position_id
         left join t_check_standard_requirement csr on csr.standard_id = standard.id
         left join t_check_requirement cr on cr.id = csr.requirement_id
@@ -570,6 +583,7 @@
         checkjob.status as status,
         checkjob.sb_status as sb_status,
         checkjob.check_user_id as check_user_id,
+        checkjob.check_dept_id as check_dept_id,
         checkjob.created_user_id as created_user_id,
         checkjob.update_user_id as update_user_id,
         checkjob.created_user_name as created_user_name,
@@ -582,6 +596,7 @@
         checkjob.receive_overtime as receive_overtime,
         checkjob.con_task as con_task,
         u.real_name as checkUserName,
+        dept.name as checkDeptName,
         sbinfo.name as sbName,
         sbinfo.no as sbNo,
         sbinfo.level as sbLevel,
@@ -610,6 +625,7 @@
         left join t_part_info partinfo on partinfo.id = checkjob.part_id
         left join t_check_standard standard on standard.id = checkjob.standard_id
         left join t_sys_user u on checkjob.check_user_id = u.user_id
+        left join t_sys_dept dept on checkjob.check_dept_id = dept.dept_id
         left join t_sb_position position on position.id = sbinfo.position_id
         <!-- 关联保养要求表 -->
         left join t_check_standard_requirement csr on csr.standard_id = standard.id
@@ -667,6 +683,7 @@
                checkjob.status as status,
                checkjob.sb_status as sb_status,
                checkjob.check_user_id as check_user_id,
+               checkjob.check_dept_id as check_dept_id,
                checkjob.created_user_id as created_user_id,
                checkjob.update_user_id as update_user_id,
                checkjob.created_user_name as created_user_name,
@@ -679,6 +696,7 @@
                checkjob.receive_overtime as receive_overtime,
                checkjob.con_task as con_task,
                u.real_name as       checkUserName,
+               dept.name as checkDeptName,
                sbinfo.name          sbName,
                sbinfo.no            sbNo,
                sbinfo.level         sbLevel,
@@ -694,6 +712,7 @@
                  left join t_part_info partinfo on partinfo.id = checkjob.part_id
                  left join t_check_standard standard on standard.id = checkjob.standard_id
                  left join t_sys_user u on checkjob.check_user_id = u.user_id
+                 left join t_sys_dept dept on checkjob.check_dept_id = dept.dept_id
         where checkjob.id = #{id}
     </select>
 
@@ -730,6 +749,7 @@
         checkjob.status as status,
         checkjob.sb_status as sb_status,
         checkjob.check_user_id as check_user_id,
+        checkjob.check_dept_id as check_dept_id,
         checkjob.created_user_id as created_user_id,
         checkjob.update_user_id as update_user_id,
         checkjob.created_user_name as created_user_name,
@@ -793,6 +813,7 @@
         checkjob.status as status,
         checkjob.sb_status as sb_status,
         checkjob.check_user_id as check_user_id,
+        checkjob.check_dept_id as check_dept_id,
         checkjob.created_user_id as created_user_id,
         checkjob.update_user_id as update_user_id,
         checkjob.created_user_name as created_user_name,
@@ -850,6 +871,7 @@
         checkjob.status as status,
         checkjob.sb_status as sb_status,
         checkjob.check_user_id as check_user_id,
+        checkjob.check_dept_id as check_dept_id,
         checkjob.created_user_id as created_user_id,
         checkjob.update_user_id as update_user_id,
         checkjob.created_user_name as created_user_name,
@@ -862,6 +884,7 @@
         checkjob.receive_overtime as receive_overtime,
         checkjob.con_task as con_task,
         u.real_name as checkUserName,
+        dept.name as checkDeptName,
         sbinfo.name as sbName,
         sbinfo.no as sbNo,
         sbinfo.level as sbLevel,
@@ -889,6 +912,7 @@
         left join t_part_info partinfo on partinfo.id = checkjob.part_id
         left join t_check_standard standard on standard.id = checkjob.standard_id
         left join t_sys_user u on checkjob.check_user_id = u.user_id
+        left join t_sys_dept dept on checkjob.check_dept_id = dept.dept_id
         left join t_sb_position position on position.id = sbinfo.position_id
         left join t_check_standard_requirement csr on csr.standard_id = standard.id
         left join t_check_requirement cr on cr.id = csr.requirement_id
@@ -930,6 +954,7 @@
         checkjob.status as status,
         checkjob.sb_status as sb_status,
         checkjob.check_user_id as check_user_id,
+        checkjob.check_dept_id as check_dept_id,
         checkjob.created_user_id as created_user_id,
         checkjob.update_user_id as update_user_id,
         checkjob.created_user_name as created_user_name,
@@ -942,6 +967,7 @@
         checkjob.receive_overtime as receive_overtime,
         checkjob.con_task as con_task,
         u.real_name as checkUserName,
+        dept.name as checkDeptName,
         sbinfo.name as sbName,
         sbinfo.no as sbNo,
         sbinfo.level as sbLevel,
@@ -969,6 +995,7 @@
         left join t_part_info partinfo on partinfo.id = checkjob.part_id
         left join t_check_standard standard on standard.id = checkjob.standard_id
         left join t_sys_user u on checkjob.check_user_id = u.user_id
+        left join t_sys_dept dept on checkjob.check_dept_id = dept.dept_id
         left join t_sb_position position on position.id = sbinfo.position_id
         left join t_check_standard_requirement csr on csr.standard_id = standard.id
         left join t_check_requirement cr on cr.id = csr.requirement_id and cr.status = 1

+ 16 - 3
platform-dao/src/main/resources/mapper/check/CheckStandardMapper.xml

@@ -26,6 +26,7 @@
         <result column="created_user_name" property="createdUserName" />
         <result column="update_user_name" property="updateUserName" />
         <result column="check_user_id" property="checkUserId" />
+        <result column="check_dept_id" property="checkDeptId" />
         <result column="created_time" property="createdTime" />
         <result column="update_time" property="updateTime" />
 
@@ -55,6 +56,7 @@
                                      checkstandard.standard_hours,
                                      checkstandard.real_hours,
                                      checkstandard.check_user_id,
+                                     checkstandard.check_dept_id,
                                      checkstandard.name,
  checkstandard.level,
                                      checkstandard.no,
@@ -83,7 +85,7 @@ checkstandard.last_date,
     cs.last_date, cs.next_date, cs.period_type, cs.check_user_type, cs.action_type,
     cs.enable, cs.requirement, cs.part, cs.standard_hours, cs.real_hours,
     cs.remark, cs.created_user_id, cs.update_user_id, cs.created_user_name,
-    cs.update_user_name, cs.check_user_id, cs.created_time, cs.update_time,
+    cs.update_user_name, cs.check_user_id, cs.check_dept_id, cs.created_time, cs.update_time,
     cr.id as requirement_id, cr.std_name, cr.scope, cr.type as requirement_type,
     cr.method ,cr.sb_type ,
     cr.remark as requirement_remark, cr.created_user_name as requirement_created_user_name,
@@ -122,6 +124,7 @@ checkstandard.last_date,
                                      checkstandard.standard_hours,
                                      checkstandard.real_hours,
                                      checkstandard.check_user_id,
+                                     checkstandard.check_dept_id,
                                      checkstandard.name,checkstandard.level,
 checkstandard.sort,
                                      checkstandard.no,
@@ -177,6 +180,9 @@ checkstandard.last_date,
         <if test="checkUserType != null">
             and checkstandard.check_user_type = #{checkUserType}
         </if>
+        <if test="checkDeptId != null and checkDeptId != ''">
+            and checkstandard.check_dept_id = #{checkDeptId}
+        </if>
         <if test="actionType != null">
             and checkstandard.action_type = #{actionType}
         </if>
@@ -228,10 +234,12 @@ checkstandard.last_date,
         select checkstandard.*, sbInfo.name as sbName, sbInfo.no as sbNo,
         sbInfo.level as sbLevel,
         sbInfo.repair_user as repairUser,
-        partInfo.name as partName
+        partInfo.name as partName,
+        dept.name as checkDeptName
         from t_check_standard as checkstandard
         LEFT JOIN t_sb_info sbInfo on checkstandard.sb_id = sbInfo.id
         LEFT JOIN t_part_info partInfo on checkstandard.part = partInfo.id
+        LEFT JOIN t_sys_dept dept on checkstandard.check_dept_id = dept.dept_id
         <where>
             <include refid="List_Condition"/>
             <if test="sbName != null and sbName != ''">
@@ -284,11 +292,13 @@ checkstandard.last_date,
         select checkstandard.*, sbInfo.name as sbName, sbInfo.no as sbNo,
         sbInfo.level as sbLevel,
         sbInfo.repair_user as repairUser,
-        partInfo.name as partName
+        partInfo.name as partName,
+        dept.name as checkDeptName
         from t_check_standard as checkstandard
         inner join t_check_job job on job.standard_id = checkstandard.id
         LEFT JOIN t_sb_info sbInfo on checkstandard.sb_id = sbInfo.id
         LEFT JOIN t_part_info partInfo on checkstandard.part = partInfo.id
+        LEFT JOIN t_sys_dept dept on checkstandard.check_dept_id = dept.dept_id
         <where>
             <include refid="List_Condition"/>
             <if test="sbName != null and sbName != ''">
@@ -373,6 +383,9 @@ checkstandard.last_date,
                 <if test="item.checkUserType != null">
                      check_user_type = #{item.checkUserType},
                 </if>
+                <if test="item.checkDeptId != null">
+                     check_dept_id = #{item.checkDeptId},
+                </if>
                 <if test="item.lastDate != null">
                      last_date = #{item.lastDate},
                 </if>

+ 94 - 0
platform-dao/src/main/resources/mapper/repair/RepairApplicationFormMapper.xml

@@ -172,4 +172,98 @@
             </if>
         </where>
     </select>
+
+    <!-- 维修工时统计:按维修人分组,统计维修结束时间不为空的报修单 -->
+    <select id="statisticsWorkHourByUser" parameterType="com.platform.dao.dto.repair.RepairApplicationFormDTO"
+            resultType="com.platform.dao.vo.report.RepairWorkHourReportVO">
+        select application.repair_user_id as repairUserId,
+        user2.real_name as repairUserName,
+        count(1) as num,
+        IFNULL(sum(application.repair_minutes), 0) as totalRepairHours,
+        IFNULL(avg(application.repair_minutes), 0) as avgRepairHours,
+        IFNULL(sum(application.deal_minutes), 0) as totalDealHours
+        from t_repair_application_form application
+        left join t_sys_user user2 on application.repair_user_id = user2.user_id
+        <where>
+            application.repair_end_time is not null
+            and application.repair_user_id is not null and application.repair_user_id != ''
+            <if test="repairUserId != null and repairUserId != ''">
+                and application.repair_user_id = #{repairUserId}
+            </if>
+            <if test="repairUserName != null and repairUserName != ''">
+                and user2.real_name like concat('%',#{repairUserName},'%')
+            </if>
+            <if test="searchRepairStartTime != null">
+                and application.repair_start_time <![CDATA[ >= ]]> #{searchRepairStartTime}
+            </if>
+            <if test="searchRepairEndTime != null">
+                and application.repair_start_time <![CDATA[ <= ]]> #{searchRepairEndTime}
+            </if>
+        </where>
+        group by application.repair_user_id
+        order by totalRepairHours desc
+    </select>
+
+    <!-- 维修工时统计:按设备分组,统计维修结束时间不为空的报修单 -->
+    <select id="statisticsWorkHourBySb" parameterType="com.platform.dao.dto.repair.RepairApplicationFormDTO"
+            resultType="com.platform.dao.vo.report.RepairWorkHourReportVO">
+        select application.sb_id as sbId,
+        sb.no as sbNo,
+        sb.name as sbName,
+        count(1) as num,
+        IFNULL(sum(application.repair_minutes), 0) as totalRepairHours,
+        IFNULL(avg(application.repair_minutes), 0) as avgRepairHours,
+        IFNULL(sum(application.deal_minutes), 0) as totalDealHours
+        from t_repair_application_form application
+        left join t_sb_info sb on application.sb_id = sb.id
+        <where>
+            application.repair_end_time is not null
+            and application.sb_id is not null and application.sb_id != ''
+            <if test="sbId != null and sbId != ''">
+                and application.sb_id = #{sbId}
+            </if>
+            <if test="keyword != null and keyword != ''">
+                and (sb.name like concat('%',#{keyword},'%') or sb.no like concat('%',#{keyword},'%'))
+            </if>
+            <if test="searchRepairStartTime != null">
+                and application.repair_start_time <![CDATA[ >= ]]> #{searchRepairStartTime}
+            </if>
+            <if test="searchRepairEndTime != null">
+                and application.repair_start_time <![CDATA[ <= ]]> #{searchRepairEndTime}
+            </if>
+        </where>
+        group by application.sb_id
+        order by totalRepairHours desc
+    </select>
+
+    <!-- 维修工时统计明细:某维修人或某设备已完成维修的报修单列表 -->
+    <select id="selectWorkHourDetail" parameterType="com.platform.dao.dto.repair.RepairApplicationFormDTO"
+            resultType="com.platform.dao.vo.repair.RepairApplicationFormVO">
+        select
+        <include refid="Base_Column_List"/>
+        from t_repair_application_form application
+        left join t_sys_user user on application.user_id = user.user_id
+        left join t_sys_user user2 on application.repair_user_id = user2.user_id
+        left join t_sys_user user3 on application.check_user_id = user3.user_id
+        left join t_sb_info sb on application.sb_id = sb.id
+        left join t_part_info part on application.part_id = part.id
+        left join t_error_type error on application.repair_error_type_id = error.id
+        left join t_sys_dept dept on application.dept_id = dept.dept_id
+        <where>
+            application.repair_end_time is not null
+            <if test="repairUserId != null and repairUserId != ''">
+                and application.repair_user_id = #{repairUserId}
+            </if>
+            <if test="sbId != null and sbId != ''">
+                and application.sb_id = #{sbId}
+            </if>
+            <if test="searchRepairStartTime != null">
+                and application.repair_start_time <![CDATA[ >= ]]> #{searchRepairStartTime}
+            </if>
+            <if test="searchRepairEndTime != null">
+                and application.repair_start_time <![CDATA[ <= ]]> #{searchRepairEndTime}
+            </if>
+        </where>
+        order by application.repair_start_time desc
+    </select>
 </mapper>

+ 88 - 0
platform-rest/src/main/java/com/platform/rest/controller/report/RepairReportController.java

@@ -3,6 +3,7 @@ package com.platform.rest.controller.report;
 import cn.hutool.core.collection.CollectionUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.platform.common.bean.AbstractPageResultBean;
 import com.platform.common.exception.BusinessException;
 import com.platform.common.util.BeanConverterUtil;
 import com.platform.common.util.DateUtils;
@@ -14,6 +15,8 @@ import com.platform.dao.entity.repair.RepairApplicationForm;
 import com.platform.dao.entity.repair.RepairFee;
 import com.platform.dao.util.ExcelUtil;
 import com.platform.dao.vo.export.check.ExportCheckJobVO;
+import com.platform.dao.vo.export.report.ExportRepairWorkHourSbVO;
+import com.platform.dao.vo.export.report.ExportRepairWorkHourUserVO;
 import com.platform.dao.vo.export.repair.ExportRepairApplicationFormVO;
 import com.platform.dao.vo.export.repair.ExportRepairFeeVO;
 import com.platform.dao.vo.query.check.CheckJobVO;
@@ -433,4 +436,89 @@ public class RepairReportController {
             }
         }
     }
+
+    /**
+     * 维修工时统计:按维修人分页统计(已完成维修的工单)
+     * 统计口径:维修结束时间不为空,按维修开始时间过滤,仅统计主维修人
+     *
+     * @param dto      查询条件(维修人姓名模糊、维修开始时间范围)
+     * @param pageNum  页码
+     * @param pageSize 每页条数
+     * @return R
+     */
+    @GetMapping("/workhour/user")
+    @SysLog("维修工时统计-按维修人")
+    public R<AbstractPageResultBean<RepairWorkHourReportVO>> statisticsWorkHourByUser(RepairApplicationFormDTO dto,
+            @RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "20") int pageSize) {
+        return new R<>(repairApplicationFormService.statisticsWorkHourByUser(dto, pageNum, pageSize));
+    }
+
+    /**
+     * 维修工时统计:按设备分页统计(已完成维修的工单)
+     * 统计口径:维修结束时间不为空,按维修开始时间过滤,仅统计主维修人
+     *
+     * @param dto      查询条件(设备名称/编号模糊、维修开始时间范围)
+     * @param pageNum  页码
+     * @param pageSize 每页条数
+     * @return R
+     */
+    @GetMapping("/workhour/sb")
+    @SysLog("维修工时统计-按设备")
+    public R<AbstractPageResultBean<RepairWorkHourReportVO>> statisticsWorkHourBySb(RepairApplicationFormDTO dto,
+            @RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "20") int pageSize) {
+        return new R<>(repairApplicationFormService.statisticsWorkHourBySb(dto, pageNum, pageSize));
+    }
+
+    /**
+     * 维修工时统计明细:某维修人或某设备已完成维修的报修单列表(不分页,用于弹窗展示与导出)
+     *
+     * @param dto 查询条件(维修人主维修人精确匹配、设备、维修开始时间范围)
+     * @return R
+     */
+    @GetMapping("/workhour/detail")
+    @SysLog("维修工时统计-明细")
+    public R<List<RepairApplicationFormVO>> getWorkHourDetail(RepairApplicationFormDTO dto) {
+        return new R<>(repairApplicationFormService.getWorkHourDetail(dto));
+    }
+
+    /**
+     * 维修工时统计导出:按维修人
+     *
+     * @param dto 查询条件(维修人姓名模糊、维修开始时间范围)
+     */
+    @GetMapping("/workhour/export/user")
+    @SysLog("维修工时统计-按维修人导出")
+    public void exportWorkHourUser(HttpServletResponse response, RepairApplicationFormDTO dto) {
+        List<RepairWorkHourReportVO> list = repairApplicationFormService.statisticsWorkHourByUser(dto, 1, Integer.MAX_VALUE)
+                .getRows();
+        ExcelUtil.exportResponseDict(response, ExportRepairWorkHourUserVO.class,
+                BeanConverterUtil.copyListProperties(list, ExportRepairWorkHourUserVO.class), "维修工时统计-按维修人");
+    }
+
+    /**
+     * 维修工时统计导出:按设备
+     *
+     * @param dto 查询条件(设备名称/编号模糊、维修开始时间范围)
+     */
+    @GetMapping("/workhour/export/sb")
+    @SysLog("维修工时统计-按设备导出")
+    public void exportWorkHourSb(HttpServletResponse response, RepairApplicationFormDTO dto) {
+        List<RepairWorkHourReportVO> list = repairApplicationFormService.statisticsWorkHourBySb(dto, 1, Integer.MAX_VALUE)
+                .getRows();
+        ExcelUtil.exportResponseDict(response, ExportRepairWorkHourSbVO.class,
+                BeanConverterUtil.copyListProperties(list, ExportRepairWorkHourSbVO.class), "维修工时统计-按设备");
+    }
+
+    /**
+     * 维修工时统计明细导出:某维修人或某设备已完成维修的报修单列表
+     *
+     * @param dto 查询条件(维修人主维修人精确匹配、设备、维修开始时间范围)
+     */
+    @GetMapping("/workhour/export/detail")
+    @SysLog("维修工时统计-明细导出")
+    public void exportWorkHourDetail(HttpServletResponse response, RepairApplicationFormDTO dto) {
+        List<RepairApplicationFormVO> list = repairApplicationFormService.getWorkHourDetail(dto);
+        ExcelUtil.exportResponseDict(response, ExportRepairApplicationFormVO.class,
+                BeanConverterUtil.copyListProperties(list, ExportRepairApplicationFormVO.class), "维修工时统计-明细");
+    }
 }

+ 30 - 0
platform-service/src/main/java/com/platform/service/check/impl/CheckJobServiceImpl.java

@@ -1029,6 +1029,10 @@ public class CheckJobServiceImpl extends BaseServiceImpl<CheckJobMapper, CheckJo
                             checkJob.setCheckUserId(sbInfo.getRepairUser());
                         } else if (standard.getCheckUserType().equals(CheckUserTypeEnum.ZHIDING.getValue())) {
                             checkJob.setCheckUserId(sbInfo.getRepairUser());
+                        } else if (standard.getCheckUserType().equals(CheckUserTypeEnum.TEAM.getValue())) {
+                            // 班组模式:设置班组ID,不指定具体执行人
+                            checkJob.setCheckDeptId(standard.getCheckDeptId());
+                            checkJob.setCheckUserId(null);
                         }
                     }
                     checkJob.setStandardHours(standard.getStandardHours());
@@ -2544,6 +2548,10 @@ public class CheckJobServiceImpl extends BaseServiceImpl<CheckJobMapper, CheckJo
                             checkJob.setCheckUserId(sbInfo.getRepairUser());
                         } else if (standard.getCheckUserType().equals(CheckUserTypeEnum.ZHIDING.getValue())) {
                             checkJob.setCheckUserId(sbInfo.getRepairUser());
+                        } else if (standard.getCheckUserType().equals(CheckUserTypeEnum.TEAM.getValue())) {
+                            // 班组模式:设置班组ID,不指定具体执行人
+                            checkJob.setCheckDeptId(standard.getCheckDeptId());
+                            checkJob.setCheckUserId(null);
                         }
                     }
                     checkJob.setStandardHours(standard.getStandardHours());
@@ -2632,6 +2640,10 @@ public class CheckJobServiceImpl extends BaseServiceImpl<CheckJobMapper, CheckJo
                         checkJob.setCheckUserId(sbInfo.getRepairUser());
                     } else if (standard.getCheckUserType().equals(CheckUserTypeEnum.ZHIDING.getValue())) {
                         checkJob.setCheckUserId(sbInfo.getRepairUser());
+                    } else if (standard.getCheckUserType().equals(CheckUserTypeEnum.TEAM.getValue())) {
+                        // 班组模式:设置班组ID,不指定具体执行人
+                        checkJob.setCheckDeptId(standard.getCheckDeptId());
+                        checkJob.setCheckUserId(null);
                     }
                 }
                 checkJob.setStandardHours(standard.getStandardHours());
@@ -2687,6 +2699,13 @@ public class CheckJobServiceImpl extends BaseServiceImpl<CheckJobMapper, CheckJo
         List<CheckJob> jobList = new ArrayList<>();
         int generatedCount = 0;
 
+        // 查询设备信息,用于设置任务负责人
+        SbInfo sbInfo = sbInfoService.getModelById(sbId);
+        if (sbInfo == null) {
+            log.warn("设备 {} 不存在,跳过生成保养任务", sbId);
+            return;
+        }
+
         for (CheckStandard standard : standardList) {
             // 查询该标准是否已有未完成的任务
             Weekend<CheckJob> jobWeekend = new Weekend<>(CheckJob.class);
@@ -2718,6 +2737,17 @@ public class CheckJobServiceImpl extends BaseServiceImpl<CheckJobMapper, CheckJo
             checkJob.setCreatedTime(LocalDateTime.now());
             checkJob.setUpdateTime(LocalDateTime.now());
 
+            // 根据执行人方式设置任务负责人
+            if (standard.getCheckUserType() != null && standard.getCheckUserType().equals(CheckUserTypeEnum.TEAM.getValue())) {
+                // 班组模式:设置班组ID,不指定具体执行人
+                checkJob.setCheckDeptId(standard.getCheckDeptId());
+                checkJob.setCheckUserId(null);
+            } else if (standard.getCheckUserType() != null && standard.getCheckUserType().equals(CheckUserTypeEnum.USE_USER.getValue())) {
+                checkJob.setCheckUserId(sbInfo.getSaveUser());
+            } else if (standard.getCheckUserType() != null && standard.getCheckUserType().equals(CheckUserTypeEnum.REPAIR_USER.getValue())) {
+                checkJob.setCheckUserId(sbInfo.getRepairUser());
+            }
+
             // 设置开始时间和结束时间
             LocalDate startDate = LocalDate.now();
             checkJob.setStartTime(startDate);

+ 29 - 0
platform-service/src/main/java/com/platform/service/repair/RepairApplicationFormService.java

@@ -7,6 +7,7 @@ import com.platform.dao.vo.repair.RepairApplicationFormVO;
 import com.platform.dao.vo.report.RepairReport24VO;
 import com.platform.dao.vo.report.RepairReportMttr;
 import com.platform.dao.vo.report.RepairSbInfoReport;
+import com.platform.dao.vo.report.RepairWorkHourReportVO;
 import com.platform.service.base.IBaseService;
 
 import java.time.LocalDate;
@@ -137,4 +138,32 @@ public interface RepairApplicationFormService extends IBaseService<RepairApplica
      * @param record
      */
     void transferReject(RepairApplicationFormDTO record);
+
+    /**
+     * 维修工时统计:按维修人分页统计(已完成维修的工单)
+     *
+     * @param model    查询条件(维修人姓名模糊、维修开始时间范围)
+     * @param pageNum  页码
+     * @param pageSize 每页条数
+     * @return 分页统计结果
+     */
+    MyVOPage<RepairWorkHourReportVO> statisticsWorkHourByUser(RepairApplicationFormDTO model, int pageNum, int pageSize);
+
+    /**
+     * 维修工时统计:按设备分页统计(已完成维修的工单)
+     *
+     * @param model    查询条件(设备名称/编号模糊、维修开始时间范围)
+     * @param pageNum  页码
+     * @param pageSize 每页条数
+     * @return 分页统计结果
+     */
+    MyVOPage<RepairWorkHourReportVO> statisticsWorkHourBySb(RepairApplicationFormDTO model, int pageNum, int pageSize);
+
+    /**
+     * 维修工时统计明细:某维修人或某设备已完成维修的报修单列表
+     *
+     * @param model 查询条件(维修人主维修人精确匹配、设备、维修开始时间范围)
+     * @return 报修单列表
+     */
+    List<RepairApplicationFormVO> getWorkHourDetail(RepairApplicationFormDTO model);
 }

+ 20 - 0
platform-service/src/main/java/com/platform/service/repair/impl/RepairApplicationFormServiceImpl.java

@@ -33,6 +33,7 @@ import com.platform.dao.vo.repair.RepairApplicationFormVO;
 import com.platform.dao.vo.report.RepairReport24VO;
 import com.platform.dao.vo.report.RepairReportMttr;
 import com.platform.dao.vo.report.RepairSbInfoReport;
+import com.platform.dao.vo.report.RepairWorkHourReportVO;
 import com.platform.dao.vo.sb.SbInfoVO;
 import com.platform.service.base.impl.BaseServiceImpl;
 import com.platform.service.event.WorkplaceBacklogEvent;
@@ -1765,4 +1766,23 @@ public class RepairApplicationFormServiceImpl
         w.weekendCriteria().andIn(SysUser::getIdentityType, identities);
         return userMapper.selectByExample(w);
     }
+
+    @Override
+    public MyVOPage<RepairWorkHourReportVO> statisticsWorkHourByUser(RepairApplicationFormDTO model, int pageNum,
+            int pageSize) {
+        PageHelper.startPage(pageNum, pageSize);
+        return new MyVOPage<>(mapper.statisticsWorkHourByUser(model));
+    }
+
+    @Override
+    public MyVOPage<RepairWorkHourReportVO> statisticsWorkHourBySb(RepairApplicationFormDTO model, int pageNum,
+            int pageSize) {
+        PageHelper.startPage(pageNum, pageSize);
+        return new MyVOPage<>(mapper.statisticsWorkHourBySb(model));
+    }
+
+    @Override
+    public List<RepairApplicationFormVO> getWorkHourDetail(RepairApplicationFormDTO model) {
+        return mapper.selectWorkHourDetail(model);
+    }
 }

+ 2 - 4
platform-service/src/main/java/com/platform/service/upms/impl/SysUserServiceImpl.java

@@ -321,10 +321,8 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser,
         userInfoDTO.setDeptId(myDeptVo == null ? null : myDeptVo.getDeptId());
         userInfoDTO.setDeptName(myDeptVo == null ? null : myDeptVo.getDeptName());
         SysDeptVO deptVO = UserUtil.getUserNatureDeptAllowNull(DeptNatureEnum.XIANG_MU_BU, userInfo);
-        if (deptVO == null) {
-            throw new BusinessException("用户部门配置错误,当前用户所属部门的上层未找到项目部,请联系管理员检查部门结构配置,用户ID:" + userInfoDTO.getUserId());
-        }
-        userInfoDTO.setProjectId(deptVO.getDeptId());
+        // 优先取项目部层级;若用户不属于项目部体系(如管理层挂在分公司/集团下),则使用用户直接所属部门
+        userInfoDTO.setProjectId(deptVO != null ? deptVO.getDeptId() : userInfoDTO.getDeptId());
         deptVO = UserUtil.getUserNatureDeptAllowNull(DeptNatureEnum.FEN_GONG_SI, userInfo);
         userInfoDTO.setCompanyId(deptVO == null ? null : deptVO.getDeptId());
         deptVO = activitiBusinessService.getRegionDept(userInfoDTO.getDeptId());