diff --git a/viewsh-module-ops/viewsh-module-ops-api/src/main/java/com/viewsh/module/ops/enums/ErrorCodeConstants.java b/viewsh-module-ops/viewsh-module-ops-api/src/main/java/com/viewsh/module/ops/enums/ErrorCodeConstants.java index 2c2359a..4d45f63 100644 --- a/viewsh-module-ops/viewsh-module-ops-api/src/main/java/com/viewsh/module/ops/enums/ErrorCodeConstants.java +++ b/viewsh-module-ops/viewsh-module-ops-api/src/main/java/com/viewsh/module/ops/enums/ErrorCodeConstants.java @@ -21,6 +21,9 @@ public interface ErrorCodeConstants { ErrorCode SECURITY_ORDER_TYPE_MISMATCH = new ErrorCode(1_020_003_001, "工单类型不匹配,期望安保工单"); ErrorCode SECURITY_AREA_USER_DUPLICATE = new ErrorCode(1_020_003_002, "该安保人员已绑定到此区域"); ErrorCode SECURITY_AREA_USER_NOT_FOUND = new ErrorCode(1_020_003_003, "绑定记录不存在"); + ErrorCode SECURITY_ASSIGNEE_NOT_BOUND_TO_AREA = new ErrorCode(1_020_003_004, "目标安保人员未绑定到工单所属区域或已停用"); + ErrorCode SECURITY_ORDER_STATUS_NOT_ALLOW_DISPATCH = new ErrorCode(1_020_003_005, "当前工单状态不允许手动派单,仅 PENDING 状态可操作"); + ErrorCode SECURITY_ORDER_PRIORITY_UPGRADE_NOT_ALLOWED = new ErrorCode(1_020_003_006, "已完成或已取消的工单不允许升级优先级"); // ========== 区域设备关联 1-020-002-000 ============ ErrorCode DEVICE_NOT_FOUND = new ErrorCode(1_020_002_000, "设备不存在"); diff --git a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/OpsOrderController.java b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/OpsOrderController.java index b183bf0..676f802 100644 --- a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/OpsOrderController.java +++ b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/OpsOrderController.java @@ -1,16 +1,13 @@ package com.viewsh.module.ops.controller.admin; -import com.viewsh.framework.apilog.core.annotation.ApiAccessLog; import com.viewsh.framework.common.pojo.CommonResult; import com.viewsh.framework.common.pojo.PageResult; import com.viewsh.framework.common.util.object.BeanUtils; import com.viewsh.module.ops.controller.admin.vo.OpsOrderAcceptReqVO; -import com.viewsh.module.ops.controller.admin.vo.OpsOrderCompleteReqVO; import com.viewsh.module.ops.controller.admin.vo.OpsOrderPauseReqVO; import com.viewsh.module.ops.controller.admin.vo.OpsOrderResumeReqVO; import com.viewsh.module.ops.service.order.dto.*; import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO; -import com.viewsh.module.ops.enums.OperatorTypeEnum; import com.viewsh.module.ops.service.order.OpsOrderService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -27,9 +24,16 @@ import static com.viewsh.framework.common.pojo.CommonResult.success; /** * 管理后台 - 通用工单 Controller *

- * 职责边界:提供所有工单类型(保洁/安保/工程/客服)通用的 CRUD、状态转换接口。 - * 保洁条线特有的业务操作(手动完单、优先级升级、时间线查询等)请使用 - * {@link com.viewsh.module.ops.controller.admin.clean.CleanWorkOrderController}。 + * 职责边界:仅提供工单查询、元数据维护、设备/人员驱动的状态操作。 + *

+ * 手动业务动作(创建/派单/完单/取消)必须通过业务条线控制器: + *

+ *

+ * 本控制器不再暴露 create/assign/complete/cancel 动作接口, + * 避免调用方绕过条线入口导致审计、校验、副作用处理不一致。 * * @author lzh */ @@ -43,31 +47,7 @@ public class OpsOrderController { @Resource private OpsOrderService opsOrderService; - @PostMapping("/create") - @Operation(summary = "创建工单") - @Parameter(name = "createReq", description = "创建请求", required = true) - @PreAuthorize("@ss.hasPermission('ops:order:create')") - public CommonResult createOrder(@Valid @RequestBody OpsOrderCreateReqDTO createReq) { - Long orderId = opsOrderService.createOrder(createReq); - return success(orderId); - } - - @PutMapping("/update") - @Operation(summary = "更新工单") - @PreAuthorize("@ss.hasPermission('ops:order:update')") - public CommonResult updateOrder(@Valid @RequestBody OpsOrderUpdateReqDTO updateReq) { - opsOrderService.updateOrder(updateReq); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除工单") - @Parameter(name = "id", description = "工单ID", required = true) - @PreAuthorize("@ss.hasPermission('ops:order:delete')") - public CommonResult deleteOrder(@RequestParam("id") Long id) { - opsOrderService.deleteOrder(id); - return success(true); - } + // ==================== 查询接口 ==================== @GetMapping("/get") @Operation(summary = "获得工单详情") @@ -86,57 +66,6 @@ public class OpsOrderController { return success(BeanUtils.toBean(pageResult, OpsOrderRespDTO.class)); } - @PostMapping("/assign") - @Operation(summary = "分配工单") - @PreAuthorize("@ss.hasPermission('ops:order:assign')") - public CommonResult assignOrder(@Valid @RequestBody OpsOrderAssignReqDTO assignReq) { - opsOrderService.assignOrder(assignReq, OperatorTypeEnum.ADMIN, null); - return success(true); - } - - @PostMapping("/accept") - @Operation(summary = "接单") - @PreAuthorize("@ss.hasPermission('ops:order:accept')") - public CommonResult acceptOrder(@Valid @RequestBody OpsOrderAcceptReqVO reqVO) { - opsOrderService.acceptOrder(reqVO.getOrderId(), reqVO.getUserId()); - return success(true); - } - - @PostMapping("/complete") - @Operation(summary = "完成工单") - @PreAuthorize("@ss.hasPermission('ops:order:complete')") - public CommonResult completeOrder(@Valid @RequestBody OpsOrderCompleteReqVO reqVO) { - OpsOrderCompleteReqDTO completeReq = new OpsOrderCompleteReqDTO(); - completeReq.setOrderId(reqVO.getOrderId()); - completeReq.setRemark(reqVO.getRemark()); - opsOrderService.completeOrder(completeReq, reqVO.getUserId()); - return success(true); - } - - @PostMapping("/pause") - @Operation(summary = "暂停工单") - @PreAuthorize("@ss.hasPermission('ops:order:pause')") - public CommonResult pauseOrder(@Valid @RequestBody OpsOrderPauseReqVO reqVO) { - opsOrderService.pauseOrder(reqVO.getOrderId(), reqVO.getUserId(), reqVO.getReason()); - return success(true); - } - - @PostMapping("/resume") - @Operation(summary = "恢复工单") - @PreAuthorize("@ss.hasPermission('ops:order:resume')") - public CommonResult resumeOrder(@Valid @RequestBody OpsOrderResumeReqVO reqVO) { - opsOrderService.resumeOrder(reqVO.getOrderId(), reqVO.getUserId()); - return success(true); - } - - @PostMapping("/cancel") - @Operation(summary = "取消工单") - @PreAuthorize("@ss.hasPermission('ops:order:cancel')") - public CommonResult cancelOrder(@Valid @RequestBody OpsOrderCancelReqDTO cancelReq) { - opsOrderService.cancelOrder(cancelReq.getId(), cancelReq.getReason(), OperatorTypeEnum.ADMIN, null); - return success(true); - } - @GetMapping("/business-logs/{orderId}") @Operation(summary = "获取工单业务日志") @Parameter(name = "orderId", description = "工单ID", required = true) @@ -146,4 +75,48 @@ public class OpsOrderController { return success(logs); } + // ==================== 元数据维护 ==================== + + @PutMapping("/update") + @Operation(summary = "更新工单") + @PreAuthorize("@ss.hasPermission('ops:order:update')") + public CommonResult updateOrder(@Valid @RequestBody OpsOrderUpdateReqDTO updateReq) { + opsOrderService.updateOrder(updateReq); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工单") + @Parameter(name = "id", description = "工单ID", required = true) + @PreAuthorize("@ss.hasPermission('ops:order:delete')") + public CommonResult deleteOrder(@RequestParam("id") Long id) { + opsOrderService.deleteOrder(id); + return success(true); + } + + // ==================== 设备/人员驱动的状态操作 ==================== + + @PostMapping("/accept") + @Operation(summary = "接单", description = "设备/人员主动接单,非管理员手动动作") + @PreAuthorize("@ss.hasPermission('ops:order:accept')") + public CommonResult acceptOrder(@Valid @RequestBody OpsOrderAcceptReqVO reqVO) { + opsOrderService.acceptOrder(reqVO.getOrderId(), reqVO.getUserId()); + return success(true); + } + + @PostMapping("/pause") + @Operation(summary = "暂停工单", description = "P0 打断等场景,非管理员手动动作") + @PreAuthorize("@ss.hasPermission('ops:order:pause')") + public CommonResult pauseOrder(@Valid @RequestBody OpsOrderPauseReqVO reqVO) { + opsOrderService.pauseOrder(reqVO.getOrderId(), reqVO.getUserId(), reqVO.getReason()); + return success(true); + } + + @PostMapping("/resume") + @Operation(summary = "恢复工单", description = "P0 完成后恢复,非管理员手动动作") + @PreAuthorize("@ss.hasPermission('ops:order:resume')") + public CommonResult resumeOrder(@Valid @RequestBody OpsOrderResumeReqVO reqVO) { + opsOrderService.resumeOrder(reqVO.getOrderId(), reqVO.getUserId()); + return success(true); + } } diff --git a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/clean/CleanWorkOrderController.java b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/clean/CleanWorkOrderController.java index 1b878d9..d81dce1 100644 --- a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/clean/CleanWorkOrderController.java +++ b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/clean/CleanWorkOrderController.java @@ -3,6 +3,9 @@ package com.viewsh.module.ops.controller.admin.clean; import com.viewsh.framework.common.pojo.CommonResult; import com.viewsh.framework.security.core.util.SecurityFrameworkUtils; import com.viewsh.module.ops.api.clean.OrderTimelineRespDTO; +import com.viewsh.module.ops.environment.service.cleanorder.dto.CleanManualCancelReqDTO; +import com.viewsh.module.ops.environment.service.cleanorder.dto.CleanManualCreateReqDTO; +import com.viewsh.module.ops.environment.service.cleanorder.dto.CleanManualDispatchReqDTO; import com.viewsh.module.ops.environment.service.cleanorder.dto.ManualCompleteOrderReqDTO; import com.viewsh.module.ops.environment.service.cleanorder.dto.UpgradePriorityReqDTO; import com.viewsh.module.ops.environment.service.badge.BadgeDeviceStatusService; @@ -69,11 +72,51 @@ public class CleanWorkOrderController { @PreAuthorize("@ss.hasPermission('ops:clean:order:upgrade')") public CommonResult upgradePriority( @Valid @RequestBody UpgradePriorityReqDTO req) { - + req.setOperatorId(SecurityFrameworkUtils.getLoginUserId()); cleanWorkOrderService.upgradePriority(req); return success(true); } + @PostMapping("/manual-upgrade-priority") + @Operation(summary = "手动升级工单优先级(规范路径)", description = "等同于 /upgrade-priority,推荐使用此路径") + @PreAuthorize("@ss.hasPermission('ops:clean:order:upgrade')") + public CommonResult manualUpgradePriority( + @Valid @RequestBody UpgradePriorityReqDTO req) { + req.setOperatorId(SecurityFrameworkUtils.getLoginUserId()); + cleanWorkOrderService.upgradePriority(req); + return success(true); + } + + @PostMapping("/manual-create") + @Operation(summary = "手动创建保洁工单") + @PreAuthorize("@ss.hasPermission('ops:clean:order:create')") + public CommonResult manualCreateOrder( + @Valid @RequestBody CleanManualCreateReqDTO req) { + req.setOperatorId(SecurityFrameworkUtils.getLoginUserId()); + Long orderId = cleanWorkOrderService.manualCreateOrder(req); + return success(orderId); + } + + @PostMapping("/manual-dispatch") + @Operation(summary = "手动派单") + @PreAuthorize("@ss.hasPermission('ops:clean:order:dispatch')") + public CommonResult manualDispatch( + @Valid @RequestBody CleanManualDispatchReqDTO req) { + req.setOperatorId(SecurityFrameworkUtils.getLoginUserId()); + cleanWorkOrderService.manualDispatch(req); + return success(true); + } + + @PostMapping("/manual-cancel") + @Operation(summary = "手动取消工单") + @PreAuthorize("@ss.hasPermission('ops:clean:order:cancel')") + public CommonResult manualCancelOrder( + @Valid @RequestBody CleanManualCancelReqDTO req) { + req.setOperatorId(SecurityFrameworkUtils.getLoginUserId()); + cleanWorkOrderService.manualCancelOrder(req); + return success(true); + } + @PostMapping("/repair-device-status") @Operation(summary = "修复工牌设备状态", description = "当设备状态残留为BUSY但关联工单已完成/取消时,修复设备状态为IDLE") @Parameter(name = "deviceId", description = "设备ID", required = true) diff --git a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/security/SecurityOrderController.java b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/security/SecurityOrderController.java index 732f311..aa8acbc 100644 --- a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/security/SecurityOrderController.java +++ b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/security/SecurityOrderController.java @@ -6,7 +6,10 @@ import com.viewsh.module.ops.controller.admin.security.vo.SecurityOrderAutoCompl import com.viewsh.module.ops.controller.admin.security.vo.SecurityOrderCompleteReqVO; import com.viewsh.module.ops.controller.admin.security.vo.SecurityOrderConfirmReqVO; import com.viewsh.module.ops.controller.admin.security.vo.SecurityOrderCreateReqVO; +import com.viewsh.module.ops.controller.admin.security.vo.SecurityOrderCancelReqVO; +import com.viewsh.module.ops.controller.admin.security.vo.SecurityOrderDispatchReqVO; import com.viewsh.module.ops.controller.admin.security.vo.SecurityOrderIdReqVO; +import com.viewsh.module.ops.controller.admin.security.vo.SecurityOrderUpgradePriorityReqVO; import com.viewsh.module.ops.security.service.securityorder.SecurityOrderCompleteReqDTO; import com.viewsh.module.ops.security.service.securityorder.SecurityOrderCreateReqDTO; import com.viewsh.module.ops.security.service.securityorder.SecurityOrderService; @@ -56,6 +59,7 @@ public class SecurityOrderController { .roiId(reqVO.getRoiId()) .imageUrl(reqVO.getImageUrl()) .sourceType(reqVO.getSourceType()) + .operatorId(SecurityFrameworkUtils.getLoginUserId()) .build(); Long orderId = securityOrderService.createSecurityOrder(dto); return success(orderId); @@ -91,6 +95,78 @@ public class SecurityOrderController { return success(true); } + @PostMapping("/dispatch") + @Operation(summary = "手动派单", description = "管理员指定安保人员进行派单,绕过自动调度") + @PreAuthorize("@ss.hasPermission('ops:security-order:dispatch')") + public CommonResult manualDispatch(@Valid @RequestBody SecurityOrderDispatchReqVO reqVO) { + securityOrderService.manualDispatch( + reqVO.getOrderId(), reqVO.getAssigneeId(), + SecurityFrameworkUtils.getLoginUserId(), reqVO.getRemark()); + return success(true); + } + + @PostMapping("/upgrade-priority") + @Operation(summary = "升级优先级", description = "管理员手动升级工单优先级,队列中的工单会重算分数") + @PreAuthorize("@ss.hasPermission('ops:security-order:update')") + public CommonResult upgradePriority(@Valid @RequestBody SecurityOrderUpgradePriorityReqVO reqVO) { + securityOrderService.upgradePriority( + reqVO.getOrderId(), reqVO.getPriority(), + SecurityFrameworkUtils.getLoginUserId()); + return success(true); + } + + @PostMapping("/manual-cancel") + @Operation(summary = "手动取消工单", description = "管理员手动取消安保工单") + @PreAuthorize("@ss.hasPermission('ops:security-order:cancel')") + public CommonResult manualCancelOrder(@Valid @RequestBody SecurityOrderCancelReqVO reqVO) { + securityOrderService.manualCancel( + reqVO.getOrderId(), reqVO.getReason(), + SecurityFrameworkUtils.getLoginUserId()); + return success(true); + } + + @PostMapping("/manual-dispatch") + @Operation(summary = "手动派单(规范路径)", description = "等同于 /dispatch,推荐使用此路径") + @PreAuthorize("@ss.hasPermission('ops:security-order:dispatch')") + public CommonResult manualDispatchNormalized(@Valid @RequestBody SecurityOrderDispatchReqVO reqVO) { + securityOrderService.manualDispatch( + reqVO.getOrderId(), reqVO.getAssigneeId(), + SecurityFrameworkUtils.getLoginUserId(), reqVO.getRemark()); + return success(true); + } + + @PostMapping("/manual-upgrade-priority") + @Operation(summary = "手动升级优先级(规范路径)", description = "等同于 /upgrade-priority,推荐使用此路径") + @PreAuthorize("@ss.hasPermission('ops:security-order:update')") + public CommonResult manualUpgradePriorityNormalized(@Valid @RequestBody SecurityOrderUpgradePriorityReqVO reqVO) { + securityOrderService.upgradePriority( + reqVO.getOrderId(), reqVO.getPriority(), + SecurityFrameworkUtils.getLoginUserId()); + return success(true); + } + + @PostMapping("/manual-create") + @Operation(summary = "手动创建安保工单(规范路径)", description = "等同于 /create,推荐使用此路径") + @PreAuthorize("@ss.hasPermission('ops:security-order:create')") + public CommonResult manualCreateOrder(@Valid @RequestBody SecurityOrderCreateReqVO reqVO) { + SecurityOrderCreateReqDTO dto = SecurityOrderCreateReqDTO.builder() + .title(reqVO.getTitle()) + .description(reqVO.getDescription()) + .priority(reqVO.getPriority()) + .areaId(reqVO.getAreaId()) + .alarmId(reqVO.getAlarmId()) + .alarmType(reqVO.getAlarmType()) + .cameraId(reqVO.getCameraId()) + .cameraName(reqVO.getCameraName()) + .roiId(reqVO.getRoiId()) + .imageUrl(reqVO.getImageUrl()) + .sourceType(reqVO.getSourceType()) + .operatorId(SecurityFrameworkUtils.getLoginUserId()) + .build(); + Long orderId = securityOrderService.createSecurityOrder(dto); + return success(orderId); + } + @PostMapping("/false-alarm") @Operation(summary = "误报标记", description = "将安保工单标记为误报并完成") @PreAuthorize("@ss.hasPermission('ops:security-order:complete')")