Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/master'

Kazerin 1 nedēļu atpakaļ
vecāks
revīzija
fb42789213
16 mainītis faili ar 250 papildinājumiem un 39 dzēšanām
  1. 31 4
      pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/gasbasic/BusinessWorkOrderController.java
  2. 3 3
      pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/manhole/WorkOrderController.java
  3. 2 1
      pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/warning/EarlyWarningController.java
  4. 10 4
      pipe-network-service/zksy-system/src/main/java/com/zksy/base/domain/WorkOrder.java
  5. 16 3
      pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/BusinessWorkOrderService.java
  6. 2 2
      pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/WorkOrderService.java
  7. 108 9
      pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/impl/BusinessWorkOrderServiceImpl.java
  8. 48 3
      pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/impl/WorkOrderServiceImpl.java
  9. 1 1
      pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/mapper/EarlyWarningMapper.java
  10. 1 1
      pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/service/EarlyWarningService.java
  11. 2 2
      pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/service/impl/EarlyWarningServiceImpl.java
  12. 6 0
      pipe-network-service/zksy-system/src/main/java/com/zksy/manhole/dto/in/WorkOrderAddInDTO.java
  13. 4 0
      pipe-network-service/zksy-system/src/main/java/com/zksy/manhole/dto/in/WorkOrderOperInDTO.java
  14. 3 2
      pipe-network-service/zksy-system/src/main/resources/mapper/WorkOrderMapper.xml
  15. 3 0
      pipe-network-service/zksy-system/src/main/resources/mapper/warning/EarlyWarningMapper.xml
  16. 10 4
      zk-api-service/src/main/java/com/zksy/api/domain/WorkOrder.java

+ 31 - 4
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/gasbasic/BusinessWorkOrderController.java

@@ -31,7 +31,7 @@ public class BusinessWorkOrderController extends BaseController {
 
     @GetMapping("/list")
     @ApiOperation("查询工单列表(equipmentType:gas-燃气 drainage-排水,为空默认燃气)")
-    public AjaxResult list(Integer orderType, Integer orderLevel, Integer orderStatus, String deviceCode, String keyword, String equipmentType, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {
+    public AjaxResult list(Integer orderType, Integer orderLevel, String orderStatus, String deviceCode, String keyword, String equipmentType, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {
 
         IPage<WorkOrder> page = businessWorkOrderService.selectWorkOrderList(orderType, orderLevel, orderStatus, deviceCode, keyword, equipmentType, pageNum, pageSize);
 
@@ -43,6 +43,16 @@ public class BusinessWorkOrderController extends BaseController {
         return AjaxResult.success(data);
     }
 
+    @PostMapping("/add")
+    @ApiOperation("手动新增工单(故障维修/日常巡检/设备保养)")
+    public AjaxResult add(@RequestBody WorkOrder workOrder) {
+        if (workOrder.getOrderDesc() == null || workOrder.getOrderDesc().isEmpty()) {
+            return AjaxResult.error("工单描述不能为空");
+        }
+        Long orderId = businessWorkOrderService.createWorkOrder(workOrder);
+        return AjaxResult.success("工单创建成功", orderId);
+    }
+
     @GetMapping("/{orderId}")
     @ApiOperation("查询工单详情(含操作日志)")
     public AjaxResult detail(@PathVariable Long orderId) {
@@ -108,20 +118,25 @@ public class BusinessWorkOrderController extends BaseController {
         Long orderId = Long.valueOf(body.get("orderId").toString());
         String handleResult = body.get("handleResult") != null ? body.get("handleResult").toString() : "";
         String solution = body.get("solution") != null ? body.get("solution").toString() : "";
+        String maintenanceBeforeImg = body.get("maintenanceBeforeImg") != null ? body.get("maintenanceBeforeImg").toString() : "";
         Long userId = SecurityUtils.getUserId();
         String userName = SecurityUtils.getUsername();
 
-        businessWorkOrderService.processOrder(orderId, handleResult, solution, userId, userName);
+        businessWorkOrderService.processOrder(orderId, handleResult, solution, maintenanceBeforeImg, userId, userName);
         return AjaxResult.success("处理完成");
     }
 
     @PutMapping("/complete")
     @ApiOperation("完成/提交验收")
-    public AjaxResult complete(@RequestParam Long orderId, @RequestParam String result) {
+    public AjaxResult complete(@RequestBody Map<String, Object> body) {
+        Long orderId = Long.valueOf(body.get("orderId").toString());
+        String result = body.get("result") != null ? body.get("result").toString() : "";
+        String maintenanceAfterImg = body.get("maintenanceAfterImg") != null
+                ? body.get("maintenanceAfterImg").toString() : "";
         Long userId = SecurityUtils.getUserId();
         String userName = SecurityUtils.getUsername();
 
-        businessWorkOrderService.completeOrder(orderId, result, userId, userName);
+        businessWorkOrderService.completeOrder(orderId, result, maintenanceAfterImg, userId, userName);
         return AjaxResult.success("提交验收成功");
     }
 
@@ -160,6 +175,18 @@ public class BusinessWorkOrderController extends BaseController {
         return AjaxResult.success("工单创建成功", orderId);
     }
 
+    @PutMapping("/reject")
+    @ApiOperation("驳回工单(待派单/待接单 -> 已驳回)")
+    public AjaxResult reject(@RequestBody Map<String, Object> body) {
+        Long orderId = Long.valueOf(body.get("orderId").toString());
+        String reason = body.get("reason") != null ? body.get("reason").toString() : "";
+        Long userId = SecurityUtils.getUserId();
+        String userName = SecurityUtils.getUsername();
+
+        businessWorkOrderService.rejectOrder(orderId, reason, userId, userName);
+        return AjaxResult.success("驳回成功");
+    }
+
     @DeleteMapping("/{orderId}")
     @ApiOperation("取消工单")
     public AjaxResult cancel(@PathVariable Long orderId) {

+ 3 - 3
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/manhole/WorkOrderController.java

@@ -131,9 +131,9 @@ public class WorkOrderController extends BaseController
     @PostMapping(value = "/addWorkOrder")
     @ApiOperation(value = "新增工单")
     public AjaxResult addWorkOrder(@RequestBody WorkOrderAddInDTO inDTO) {
-        boolean result = workOrderService.addWorkOrder(inDTO);
-        return result ? AjaxResult.success("新增成功", result)
-                : AjaxResult.error("新增失败", result);
+        Long orderId = workOrderService.addWorkOrder(inDTO);
+        return orderId != null ? AjaxResult.success("新增成功", orderId)
+                : AjaxResult.error("新增失败");
     }
 
     /**

+ 2 - 1
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/warning/EarlyWarningController.java

@@ -262,11 +262,12 @@ List<String> alarmIds = alarmIdsJson != null && !alarmIdsJson.isEmpty()
             @ApiParam("状态") @RequestParam(required = false) String status,
             @ApiParam("预警位置") @RequestParam(required = false) String location,
             @ApiParam("发布人") @RequestParam(required = false) String publisher,
+            @ApiParam("排除发布人(如:系统自动)") @RequestParam(required = false) String excludePublisher,
             @ApiParam("权属单位") @RequestParam(required = false) String ownershipUnit,
             @ApiParam("开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
             @ApiParam("结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
         Page<?> page = new Page<>(pageNum, pageSize);
-        IPage<Map<String, Object>> result = earlyWarningService.searchWarnings(page, warningName, warningNo, warningType, warningLevel, status, location, publisher, ownershipUnit, startTime, endTime);
+        IPage<Map<String, Object>> result = earlyWarningService.searchWarnings(page, warningName, warningNo, warningType, warningLevel, status, location, publisher, ownershipUnit, startTime, endTime, excludePublisher);
         return AjaxResult.success(result);
     }
 

+ 10 - 4
pipe-network-service/zksy-system/src/main/java/com/zksy/base/domain/WorkOrder.java

@@ -162,10 +162,16 @@ public class WorkOrder implements Serializable {
     private String repairResult;
 
     /**
-     * 工单图片(多个图片用逗号分隔)
+     * 维修前图片 URL,多个图片使用逗号分隔
      */
-    @ApiModelProperty(value = "工单图片,多个用逗号分隔")
-    private String workImage;
+    @ApiModelProperty(value = "维修前图片 URL")
+    private String maintenanceBeforeImg;
+
+    /**
+     * 维修后图片 URL,多个图片使用逗号分隔
+     */
+    @ApiModelProperty(value = "维修后图片 URL")
+    private String maintenanceAfterImg;
 
     /**
      * 验收人ID
@@ -193,4 +199,4 @@ public class WorkOrder implements Serializable {
     @ApiModelProperty(value = "更新时间")
     @JsonFormat(locale = "zh",pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
     private Date updateTime;
-}
+}

+ 16 - 3
pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/BusinessWorkOrderService.java

@@ -18,7 +18,7 @@ public interface BusinessWorkOrderService extends IService<WorkOrder> {
      * @param equipmentType 设备类型:gas-燃气 drainage-排水,为空查询全部
      */
     IPage<WorkOrder> selectWorkOrderList(Integer orderType, Integer orderLevel,
-                                         Integer orderStatus, String deviceCode,
+                                         String orderStatus, String deviceCode,
                                          String keyword, String equipmentType,
                                          Integer pageNum, Integer pageSize);
 
@@ -50,18 +50,24 @@ public interface BusinessWorkOrderService extends IService<WorkOrder> {
     /**
      * 处理
      */
-    boolean processOrder(Long orderId, String handleResult, String solution, Long operUserId, String operUserName);
+    boolean processOrder(Long orderId, String handleResult, String solution, String maintenanceBeforeImg, Long operUserId, String operUserName);
 
     /**
      * 完成/提交验收
      */
-    boolean completeOrder(Long orderId, String result, Long operUserId, String operUserName);
+    boolean completeOrder(Long orderId, String result, String maintenanceAfterImg, Long operUserId, String operUserName);
 
     /**
      * 取消工单
      */
     boolean cancelOrder(Long orderId, Long operUserId, String operUserName);
 
+    /**
+     * 驳回工单(待派单/待接单 -> 已驳回)
+     * @param reason 驳回原因
+     */
+    boolean rejectOrder(Long orderId, String reason, Long operUserId, String operUserName);
+
     /**
      * 验收通过/结案(status 5→6),同步联动隐患状态为"已整改"
      */
@@ -80,4 +86,11 @@ public interface BusinessWorkOrderService extends IService<WorkOrder> {
      */
     Long createWorkOrderFromHazard(String hazardId, String hazardNo, String hazardDesc, String equipmentId,
                                     String hazardLevel, String hazardImages, Date planFinishTime);
+
+    /**
+     * 手动新增工单(故障维修/日常巡检/设备保养)
+     * @param workOrder 工单信息(orderType/orderLevel/orderDesc/deviceId/deviceCode/planFinishTime)
+     * @return 工单ID
+     */
+    Long createWorkOrder(WorkOrder workOrder);
 }

+ 2 - 2
pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/WorkOrderService.java

@@ -23,9 +23,9 @@ public interface WorkOrderService extends IService<WorkOrder> {
     /**
      * 新增工单
      * @param inDTO
-     * @return
+     * @return 工单ID(新增成功返回 orderId,失败返回 null)
      */
-    boolean addWorkOrder(WorkOrderAddInDTO inDTO);
+    Long addWorkOrder(WorkOrderAddInDTO inDTO);
 
     /**
      * 经办工单分页查询(处理中:待接单、已接单、处理中、待验收)

+ 108 - 9
pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/impl/BusinessWorkOrderServiceImpl.java

@@ -48,10 +48,10 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
     private EquipmentStatusMapper equipmentStatusMapper;
 
     @Override
-    public IPage<WorkOrder> selectWorkOrderList(Integer orderType, Integer orderLevel, Integer orderStatus, String deviceCode, String keyword, String equipmentType, Integer pageNum, Integer pageSize) {
+    public IPage<WorkOrder> selectWorkOrderList(Integer orderType, Integer orderLevel, String orderStatus, String deviceCode, String keyword, String equipmentType, Integer pageNum, Integer pageSize) {
         Page<WorkOrder> page = new Page<>(pageNum, pageSize);
         LambdaQueryWrapper<WorkOrder> wrapper = new LambdaQueryWrapper<>();
-        // 按设备类型过滤工单:gas-燃气(父类别ID=3),drainage-排水(typeId为drainage的顶级分类)
+        // 按设备类型过滤工单:gas-燃气(父类别ID=3),drainage-排水(typeId为drainage的顶级分类),water-供水;为空查询全部设备工单
         if (StringUtils.isNotEmpty(equipmentType)) {
             if ("gas".equals(equipmentType)) {
                 wrapper.inSql(WorkOrder::getDeviceId, "SELECT eb.equipment_id FROM app_user.equipment_base eb " + "INNER JOIN app_user.equipment_type et ON eb.equipment_type_id = et.id " + "WHERE et.parent_type_id = '3'");
@@ -62,13 +62,23 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
                 // 供水:顶级类型名称为“供水”的分类及其全部子类型
                 wrapper.inSql(WorkOrder::getDeviceId, "SELECT eb.equipment_id FROM app_user.equipment_base eb " + "INNER JOIN app_user.equipment_type et ON eb.equipment_type_id = et.id " + "WHERE et.id IN (SELECT id FROM app_user.equipment_type WHERE type_name = '供水' AND parent_type_id = '0' " + "UNION SELECT id FROM app_user.equipment_type WHERE parent_type_id = (SELECT id FROM app_user.equipment_type WHERE type_name = '供水' AND parent_type_id = '0'))");
             }
-        } else {
-            // 默认只查询燃气设备类工单(兼容旧逻辑)
-            wrapper.inSql(WorkOrder::getDeviceId, "SELECT eb.equipment_id FROM app_user.equipment_base eb " + "INNER JOIN app_user.equipment_type et ON eb.equipment_type_id = et.id " + "WHERE et.parent_type_id = '3'");
         }
         if (orderType != null) wrapper.eq(WorkOrder::getOrderType, orderType);
         if (orderLevel != null) wrapper.eq(WorkOrder::getOrderLevel, orderLevel);
-        if (orderStatus != null) wrapper.eq(WorkOrder::getOrderStatus, orderStatus);
+        // orderStatus 支持逗号分隔多值,如 1,2,3
+        if (StringUtils.isNotEmpty(orderStatus)) {
+            if (orderStatus.contains(",")) {
+                List<Integer> statusList = Arrays.stream(orderStatus.split(","))
+                        .filter(StringUtils::isNumeric)
+                        .map(Integer::valueOf)
+                        .collect(Collectors.toList());
+                if (!statusList.isEmpty()) {
+                    wrapper.in(WorkOrder::getOrderStatus, statusList);
+                }
+            } else {
+                wrapper.eq(WorkOrder::getOrderStatus, Integer.valueOf(orderStatus));
+            }
+        }
         if (StringUtils.isNotEmpty(deviceCode)) wrapper.eq(WorkOrder::getDeviceCode, deviceCode);
         if (StringUtils.isNotEmpty(keyword)) {
             wrapper.and(w -> w.like(WorkOrder::getOrderNo, keyword).or().like(WorkOrder::getDeviceCode, keyword).or().like(WorkOrder::getOrderDesc, keyword));
@@ -182,7 +192,7 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean processOrder(Long orderId, String handleResult, String solution, Long operUserId, String operUserName) {
+    public boolean processOrder(Long orderId, String handleResult, String solution, String maintenanceBeforeImg, Long operUserId, String operUserName) {
         WorkOrder order = this.getById(orderId);
         if (order == null) throw new ServiceException("工单不存在");
         if (!Arrays.asList(3, 4).contains(order.getOrderStatus())) throw new ServiceException("当前工单状态不允许处理");
@@ -191,6 +201,9 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
         entity.setOrderId(orderId);
         entity.setOrderStatus(4);
         entity.setRepairResult(solution);
+        if (StringUtils.isNotBlank(maintenanceBeforeImg)) {
+            entity.setMaintenanceBeforeImg(maintenanceBeforeImg);
+        }
         this.updateById(entity);
 
         // 工单处理中 → 同步隐患状态为"整改中"
@@ -209,7 +222,7 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean completeOrder(Long orderId, String result, Long operUserId, String operUserName) {
+    public boolean completeOrder(Long orderId, String result, String maintenanceAfterImg, Long operUserId, String operUserName) {
         WorkOrder order = this.getById(orderId);
         if (order == null) throw new ServiceException("工单不存在");
         if (order.getOrderStatus() != 4)
@@ -219,6 +232,9 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
         entity.setOrderId(orderId);
         entity.setOrderStatus(5);
         entity.setRepairResult(result);
+        if (StringUtils.isNotBlank(maintenanceAfterImg)) {
+            entity.setMaintenanceAfterImg(maintenanceAfterImg);
+        }
         this.updateById(entity);
 
         WorkOrderLog logEntry = new WorkOrderLog();
@@ -235,6 +251,9 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createWorkOrderFromHazard(String hazardId, String hazardNo, String hazardDesc, String equipmentId, String hazardLevel, String hazardImages, Date planFinishTime) {
+        // 同一设备存在进行中工单(状态非 6 已结案/7 已驳回)时禁止重复建单
+        checkDeviceOrderConflict(equipmentId);
+
         // 隐患等级映射到工单优先级:0-重大→紧急(1) 1-较大→一般(2) 2-一般→一般(2) 3-轻微→低(3)
         Integer orderLevel;
         if ("0".equals(hazardLevel)) {
@@ -261,7 +280,10 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
         workOrder.setOrderLevel(orderLevel);
         workOrder.setOrderDesc(hazardDesc);
         workOrder.setOrderStatus(1); // 待派单
-        workOrder.setWorkImage(hazardImages);
+        // 隐患图片作为维修前图片(如有)
+        if (StringUtils.isNotEmpty(hazardImages)) {
+            workOrder.setMaintenanceBeforeImg(hazardImages);
+        }
         workOrder.setPlanFinishTime(planFinishTime);
         workOrder.setCreateTime(new Date());
         this.save(workOrder);
@@ -278,6 +300,59 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
         return workOrder.getOrderId();
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createWorkOrder(WorkOrder workOrder) {
+        // 同一设备存在进行中工单(状态非 6 已结案/7 已驳回)时禁止重复建单
+        checkDeviceOrderConflict(workOrder.getDeviceId());
+
+        if (workOrder.getOrderType() == null) {
+            workOrder.setOrderType(1);
+        }
+        if (workOrder.getOrderLevel() == null) {
+            workOrder.setOrderLevel(2);
+        }
+        workOrder.setOrderNo(generateOrderNo());
+        // 设备ID存在但未填设备编码时自动补全
+        if (StringUtils.isNotEmpty(workOrder.getDeviceId()) && StringUtils.isEmpty(workOrder.getDeviceCode())) {
+            EquipmentBase equipment = equipmentBaseMapper.selectById(workOrder.getDeviceId());
+            if (equipment != null) {
+                workOrder.setDeviceCode(equipment.getEquipmentCode());
+            }
+        }
+        workOrder.setOrderStatus(1); // 待派单
+        workOrder.setCreateTime(new Date());
+        this.save(workOrder);
+
+        // 写入操作日志
+        WorkOrderLog logEntry = new WorkOrderLog();
+        logEntry.setOrderId(workOrder.getOrderId());
+        logEntry.setOperType(1);
+        logEntry.setOperDesc("手动创建工单");
+        logEntry.setOperTime(new Date());
+        workOrderLogMapper.insert(logEntry);
+
+        log.info("手动创建工单成功,工单ID={},类型={}", workOrder.getOrderId(), workOrder.getOrderType());
+        return workOrder.getOrderId();
+    }
+
+    /**
+     * 校验设备是否存在进行中工单(状态 1-5/8/9),存在则禁止再次创建工单
+     * 业务规则:同一设备同一时间只能有一个进行中的工单,结案(6)或驳回(7)后方可再次创建
+     */
+    private void checkDeviceOrderConflict(String deviceId) {
+        if (StringUtils.isEmpty(deviceId)) {
+            return;
+        }
+        Long count = this.lambdaQuery()
+                .eq(WorkOrder::getDeviceId, deviceId)
+                .notIn(WorkOrder::getOrderStatus, 6, 7)
+                .count();
+        if (count > 0) {
+            throw new ServiceException("该设备已有处理中的工单,需结案或驳回后才能创建新工单");
+        }
+    }
+
     /**
      * 生成工单编号:WO-yyyyMMddHHmmssSSS
      */
@@ -308,6 +383,30 @@ public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, W
         return true;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean rejectOrder(Long orderId, String reason, Long operUserId, String operUserName) {
+        WorkOrder order = this.getById(orderId);
+        if (order == null) throw new ServiceException("工单不存在");
+        // 仅待派单/待接单可驳回,已流转的工单请使用取消
+        if (!Arrays.asList(1, 2).contains(order.getOrderStatus())) throw new ServiceException("当前工单状态不允许驳回");
+
+        WorkOrder entity = new WorkOrder();
+        entity.setOrderId(orderId);
+        entity.setOrderStatus(7);
+        this.updateById(entity);
+
+        WorkOrderLog logEntry = new WorkOrderLog();
+        logEntry.setOrderId(orderId);
+        logEntry.setOperType(7);
+        logEntry.setOperDesc("驳回工单,原因:" + (reason != null ? reason : ""));
+        logEntry.setOperUserId(operUserId);
+        logEntry.setOperUserName(operUserName);
+        logEntry.setOperTime(new Date());
+        workOrderLogMapper.insert(logEntry);
+        return true;
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean closeOrder(Long orderId, String result, Long operUserId, String operUserName) {

+ 48 - 3
pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/impl/WorkOrderServiceImpl.java

@@ -8,6 +8,8 @@ import com.zksy.base.domain.CaseInfo;
 import com.zksy.base.domain.EquipmentBase;
 import com.zksy.base.domain.WorkOrder;
 import com.zksy.base.domain.WorkOrderLog;
+import com.zksy.base.warning.domain.EarlyWarning;
+import com.zksy.base.warning.service.EarlyWarningService;
 import com.zksy.base.mapper.CaseInfoMapper;
 import com.zksy.base.mapper.EquipmentBaseMapper;
 import com.zksy.base.mapper.WorkOrderLogMapper;
@@ -56,6 +58,9 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
     @Autowired
     private EquipmentBaseMapper equipmentBaseMapper;
 
+    @Autowired
+    private EarlyWarningService earlyWarningService;
+
     /**
      * 查询窨井类型设备ID列表(equipment_type_id: 9=排水窨井, 10=供水窨井)
      */
@@ -105,11 +110,21 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
     /**
      * 新增工单
      * @param inDTO
-     * @return
+     * @return 工单ID(新增成功返回 orderId,失败返回 null)
      */
     @Override
-    public boolean addWorkOrder(WorkOrderAddInDTO inDTO) {
+    public Long addWorkOrder(WorkOrderAddInDTO inDTO) {
         log.info("新增工单-入参:{}", inDTO);
+        // 同一设备存在进行中工单(状态非 6 已结案/7 已驳回)时禁止重复建单
+        if (inDTO.getDeviceId() != null) {
+            Long count = this.lambdaQuery()
+                    .eq(WorkOrder::getDeviceId, inDTO.getDeviceId())
+                    .notIn(WorkOrder::getOrderStatus, 6, 7)
+                    .count();
+            if (count > 0) {
+                throw new ServiceException("该设备已有处理中的工单,需结案或驳回后才能创建新工单");
+            }
+        }
         WorkOrder workOrder = BeanUtil.copyProperties(inDTO, WorkOrder.class);
         workOrder.setOrderNo(generateOrderNo());
         // 初始状态:1-待派单
@@ -128,6 +143,13 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
                 workOrder.setDeviceCode(equipmentBase.getEquipmentCode());
             }
         }
+        // 设置维修前后图片(如果 DTO 中有传递)
+        if (inDTO.getMaintenanceBeforeImg() != null) {
+            workOrder.setMaintenanceBeforeImg(inDTO.getMaintenanceBeforeImg());
+        }
+        if (inDTO.getMaintenanceAfterImg() != null) {
+            workOrder.setMaintenanceAfterImg(inDTO.getMaintenanceAfterImg());
+        }
         this.save(workOrder);
         WorkOrderLog workOrderLog = new WorkOrderLog();
         workOrderLog.setOrderId(workOrder.getOrderId());
@@ -139,7 +161,9 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
             workOrderLog.setOperUserId(loginUser.getUserId());
             workOrderLog.setOperUserName(loginUser.getUser().getNickName());
         }
-        return workOrderLogMapper.insert(workOrderLog) > 0;
+        workOrderLogMapper.insert(workOrderLog);
+        // 返回工单ID,供后续派单使用
+        return workOrder.getOrderId();
     }
 
     /**
@@ -253,10 +277,16 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
         } else if(inDTO.getOperType() == 4){
             //4-开始维修
             entity.setOrderStatus(4);
+            if (StringUtils.isNotBlank(inDTO.getMaintenanceBeforeImg())) {
+                entity.setMaintenanceBeforeImg(inDTO.getMaintenanceBeforeImg());
+            }
         } else if(inDTO.getOperType() == 5){
             //5-提交验收
             entity.setOrderStatus(5);
             entity.setVerifyUser(workOrder.getDispatchUser());
+            if (StringUtils.isNotBlank(inDTO.getMaintenanceAfterImg())) {
+                entity.setMaintenanceAfterImg(inDTO.getMaintenanceAfterImg());
+            }
         } else if(inDTO.getOperType() == 6){
             //6-验收通过
             entity.setOrderStatus(6);
@@ -273,6 +303,21 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
                     caseInfoMapper.updateById(caseEntity);
                 }
             }
+            // 若工单关联了预警(alarmId 对应 early_warning 记录),验收通过时自动解除预警
+            if(workOrder.getAlarmId() != null){
+                try {
+                    EarlyWarning warning = earlyWarningService.getById(workOrder.getAlarmId());
+                    if(warning != null){
+                        earlyWarningService.resolveWarning(warning.getWarningId(),
+                                "工单验收通过(" + workOrder.getOrderNo() + "),预警已解除");
+                        log.info("工单验收通过,自动解除预警: orderNo={}, warningId={}",
+                                workOrder.getOrderNo(), workOrder.getAlarmId());
+                    }
+                } catch (Exception e) {
+                    log.warn("工单验收通过后解除预警失败: orderNo={}, warningId={}",
+                            workOrder.getOrderNo(), workOrder.getAlarmId(), e);
+                }
+            }
         } else if(inDTO.getOperType() == 7){
             //7-驳回工单
             entity.setOrderStatus(7);

+ 1 - 1
pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/mapper/EarlyWarningMapper.java

@@ -16,7 +16,7 @@ public interface EarlyWarningMapper extends BaseMapper<EarlyWarning> {
 
     IPage<Map<String, Object>> selectWarningList(Page<?> page, @Param("warningName") String warningName, @Param("warningType") String warningType, @Param("warningLevel") String warningLevel, @Param("status") String status);
 
-    IPage<Map<String, Object>> searchWarnings(Page<?> page, @Param("warningName") String warningName, @Param("warningNo") String warningNo, @Param("warningType") String warningType, @Param("warningLevel") String warningLevel, @Param("status") String status, @Param("location") String location, @Param("publisher") String publisher, @Param("ownershipUnit") String ownershipUnit, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
+    IPage<Map<String, Object>> searchWarnings(Page<?> page, @Param("warningName") String warningName, @Param("warningNo") String warningNo, @Param("warningType") String warningType, @Param("warningLevel") String warningLevel, @Param("status") String status, @Param("location") String location, @Param("publisher") String publisher, @Param("ownershipUnit") String ownershipUnit, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("excludePublisher") String excludePublisher);
 
     IPage<Map<String, Object>> selectTodoList(Page<?> page, @Param("userId") String userId, @Param("todoType") String todoType, @Param("warningName") String warningName);
 

+ 1 - 1
pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/service/EarlyWarningService.java

@@ -16,7 +16,7 @@ public interface EarlyWarningService extends IService<EarlyWarning> {
 
     IPage<Map<String, Object>> getWarningList(Page<?> page, String warningName, String warningType, String warningLevel, String status);
 
-    IPage<Map<String, Object>> searchWarnings(Page<?> page, String warningName, String warningNo, String warningType, String warningLevel, String status, String location, String publisher, String ownershipUnit, LocalDateTime startTime, LocalDateTime endTime);
+    IPage<Map<String, Object>> searchWarnings(Page<?> page, String warningName, String warningNo, String warningType, String warningLevel, String status, String location, String publisher, String ownershipUnit, LocalDateTime startTime, LocalDateTime endTime, String excludePublisher);
 
     IPage<Map<String, Object>> getTodoList(Page<?> page, String userName, String todoType, String warningName);
 

+ 2 - 2
pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/service/impl/EarlyWarningServiceImpl.java

@@ -45,8 +45,8 @@ public class EarlyWarningServiceImpl extends ServiceImpl<EarlyWarningMapper, Ear
     }
 
     @Override
-    public IPage<Map<String, Object>> searchWarnings(Page<?> page, String warningName, String warningNo, String warningType, String warningLevel, String status, String location, String publisher, String ownershipUnit, LocalDateTime startTime, LocalDateTime endTime) {
-        return earlyWarningMapper.searchWarnings(page, warningName, warningNo, warningType, warningLevel, status, location, publisher, ownershipUnit, startTime, endTime);
+    public IPage<Map<String, Object>> searchWarnings(Page<?> page, String warningName, String warningNo, String warningType, String warningLevel, String status, String location, String publisher, String ownershipUnit, LocalDateTime startTime, LocalDateTime endTime, String excludePublisher) {
+        return earlyWarningMapper.searchWarnings(page, warningName, warningNo, warningType, warningLevel, status, location, publisher, ownershipUnit, startTime, endTime, excludePublisher);
     }
 
     @Override

+ 6 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/manhole/dto/in/WorkOrderAddInDTO.java

@@ -42,4 +42,10 @@ public class WorkOrderAddInDTO implements Serializable {
     @ApiModelProperty(value = "计划完成时间")
     @JsonFormat(locale = "zh", pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date planFinishTime;
+
+    @ApiModelProperty(value = "维修前图片 URL")
+    private String maintenanceBeforeImg;
+
+    @ApiModelProperty(value = "维修后图片 URL")
+    private String maintenanceAfterImg;
 }

+ 4 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/manhole/dto/in/WorkOrderOperInDTO.java

@@ -39,4 +39,8 @@ public class WorkOrderOperInDTO implements Serializable {
     @ApiModelProperty(value = "延期截止时间(操作类型为 8-申请延期 时,必填)")
     @JsonFormat(locale = "zh",pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
     private Date delayedDeadline;
+
+    private String maintenanceBeforeImg;
+
+    private String maintenanceAfterImg;
 }

+ 3 - 2
pipe-network-service/zksy-system/src/main/resources/mapper/WorkOrderMapper.xml

@@ -25,7 +25,8 @@
             <result property="planFinishTime" column="plan_finish_time" jdbcType="TIMESTAMP"/>
             <result property="realFinishTime" column="real_finish_time" jdbcType="TIMESTAMP"/>
             <result property="repairResult" column="repair_result" jdbcType="VARCHAR"/>
-            <result property="workImage" column="work_image" jdbcType="VARCHAR"/>
+            <result property="maintenanceBeforeImg" column="maintenance_before_img" jdbcType="VARCHAR"/>
+            <result property="maintenanceAfterImg" column="maintenance_after_img" jdbcType="VARCHAR"/>
             <result property="verifyUser" column="verify_user" jdbcType="BIGINT"/>
             <result property="verifyTime" column="verify_time" jdbcType="TIMESTAMP"/>
             <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
@@ -39,7 +40,7 @@
         order_desc,dept_id,dispatch_user,
         dispatch_time,receive_user,order_status,
         delayed_reason,delayed_deadline,plan_finish_time,
-        real_finish_time,repair_result,work_image,verify_user,
+        real_finish_time,repair_result,maintenance_before_img,maintenance_after_img,verify_user,
         verify_time,create_time,update_time
     </sql>
 </mapper>

+ 3 - 0
pipe-network-service/zksy-system/src/main/resources/mapper/warning/EarlyWarningMapper.xml

@@ -439,6 +439,9 @@
             <if test="publisher != null and publisher != ''">
                 AND w.publisher LIKE CONCAT('%', #{publisher}, '%')
             </if>
+            <if test="excludePublisher != null and excludePublisher != ''">
+                AND (w.publisher IS NULL OR w.publisher NOT LIKE CONCAT('%', #{excludePublisher}, '%'))
+            </if>
             <if test="ownershipUnit != null and ownershipUnit != ''">
                 AND w.ownership_unit LIKE CONCAT('%', #{ownershipUnit}, '%')
             </if>

+ 10 - 4
zk-api-service/src/main/java/com/zksy/api/domain/WorkOrder.java

@@ -150,10 +150,16 @@ public class WorkOrder implements Serializable {
     private String repairResult;
 
     /**
-     * 工单图片(多个图片用逗号分隔)
+     * 维修前图片 URL,多个图片使用逗号分隔
      */
-    @ApiModelProperty(value = "工单图片,多个用逗号分隔")
-    private String workImage;
+    @ApiModelProperty(value = "维修前图片 URL")
+    private String maintenanceBeforeImg;
+
+    /**
+     * 维修后图片 URL,多个图片使用逗号分隔
+     */
+    @ApiModelProperty(value = "维修后图片 URL")
+    private String maintenanceAfterImg;
 
     /**
      * 验收人ID
@@ -181,4 +187,4 @@ public class WorkOrder implements Serializable {
     @ApiModelProperty(value = "更新时间")
     @JsonFormat(locale = "zh",pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
     private Date updateTime;
-}
+}