| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- diff --git a/pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/cockpit/CockpitWorkOrderReadController.java b/pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/cockpit/CockpitWorkOrderReadController.java
- index f85f8df3..8464ba77 100644
- --- a/pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/cockpit/CockpitWorkOrderReadController.java
- +++ b/pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/cockpit/CockpitWorkOrderReadController.java
- @@ -4,6 +4,7 @@ import com.zksy.cockpit.foundation.CockpitDeviceNotFoundException;
- import com.zksy.cockpit.foundation.CockpitErrorPayload;
- import com.zksy.cockpit.foundation.CockpitInvalidRequestException;
- import com.zksy.cockpit.foundation.CockpitReadException;
- +import com.zksy.cockpit.workorder.CockpitWorkOrderListResponse;
- import com.zksy.cockpit.workorder.CockpitWorkOrderReadResponse;
- import com.zksy.cockpit.workorder.CockpitWorkOrderReadService;
- import com.zksy.cockpit.workorder.CockpitWorkOrderTimelineResponse;
- @@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestHeader;
- +import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
- import org.springframework.web.util.UriUtils;
-
- @@ -62,6 +64,31 @@ public class CockpitWorkOrderReadController {
- return ResponseEntity.ok(AjaxResult.success(response));
- }
-
- + /**
- + * 全量工单分页(票 65:报警效率面板的「当前工单列表」)。
- + *
- + * <p>为什么单开一个路径而不是复用 `/equipments/{code}/work-orders`:报警族的工单跨设备,
- + * 面板要的是「当前所有工单」;实测该设备维度能查到 7 张工单,而
- + * `handling-efficiency` 的 linkedWorkOrderCount=0 —— 两者粒度不同,不能互相代替。
- + *
- + * <p>路径挂在 `/api/cockpit/v1/**` 下:免鉴权白名单只按**路径前缀**放行
- + * (`SecurityConfig: antMatchers(GET, "/api/cockpit/v1/**").permitAll()`),
- + * 运营侧 `/api/ops/**` 需要登录态,驾驶舱不能直接用。
- + *
- + * <p>三个查询参数都可缺省:`page` 默认 1、`pageSize` 默认 10(上限 100)、
- + * `stateCode` 缺省不筛。夹取在 service,控制器不做第二套校验。
- + */
- + @GetMapping("/api/cockpit/v1/work-orders")
- + public ResponseEntity<AjaxResult> workOrderList(
- + @RequestParam(value = "page", required = false) Integer page,
- + @RequestParam(value = "pageSize", required = false) Integer pageSize,
- + @RequestParam(value = "stateCode", required = false) Integer stateCode,
- + @RequestHeader(value = REQUEST_ID_HEADER, required = false) String requestId) {
- + CockpitWorkOrderListResponse response = workOrderService.loadAll(
- + resolveRequestId(requestId), page, pageSize, stateCode);
- + return ResponseEntity.ok(AjaxResult.success(response));
- + }
- +
- @ExceptionHandler(CockpitInvalidRequestException.class)
- public ResponseEntity<AjaxResult> handleInvalidRequest(HttpServletRequest request) {
- return error(HttpStatus.BAD_REQUEST, workOrderService.invalidRequest(
- diff --git a/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/BusinessCockpitWorkOrderReadAdapter.java b/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/BusinessCockpitWorkOrderReadAdapter.java
- index dc285df6..ecb14d4c 100644
- --- a/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/BusinessCockpitWorkOrderReadAdapter.java
- +++ b/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/BusinessCockpitWorkOrderReadAdapter.java
- @@ -76,6 +76,45 @@ public class BusinessCockpitWorkOrderReadAdapter implements CockpitWorkOrderRead
- .collect(Collectors.toList());
- }
-
- + /**
- + * 全量工单分页(票 65:报警效率面板的「当前工单列表」)。
- + *
- + * <p>与设备维度同一条读取路径,只是**不加 device_id 约束**:报警族的工单在库里
- + * 本就跨设备存在(实测该端点 24 条报警事件在 handling-efficiency 里
- + * linkedWorkOrderCount=0,但设备维度能查到 7 张工单),所以「当前工单」只能是全量口径。
- + *
- + * <p>三个刻意的取舍:
- + * <ul>
- + * <li>{@code total} 走 {@code count(wrapper)} 独立查询,不由本页条数反推(票 61 纪律);</li>
- + * <li>排序与设备维度一致(创建时间倒序)——两个入口返回同一张表时顺序必须相同;</li>
- + * <li>关联解析仍走 {@link #toAlarmSummary}:全量列表里「是否关联报警」逐张如实标,
- + * 不因为换了个查询入口就一律标 true/false。</li>
- + * </ul>
- + */
- + @Override
- + public CockpitWorkOrderListSnapshot loadAll(Integer stateCode, int limit, int offset) {
- + LambdaQueryWrapper<WorkOrder> wrapper = new LambdaQueryWrapper<>();
- + if (stateCode != null) {
- + wrapper.eq(WorkOrder::getOrderStatus, stateCode);
- + }
- + long total = workOrderService.count(wrapper);
- + List<WorkOrder> orders = total <= offset
- + ? Collections.emptyList()
- + : workOrderService.list(wrapper
- + .orderByDesc(WorkOrder::getCreateTime)
- + .last("LIMIT " + limit + " OFFSET " + offset));
- + // 空页时不再打一次 association 查询:alarmsByOrderId 对空集合本来就早退,但显式一点更省一次调用栈。
- + List<CockpitWorkOrderSummary> summaries = orders.isEmpty()
- + ? Collections.emptyList()
- + : toAlarmSummaries(orders);
- + return new CockpitWorkOrderListSnapshot(
- + summaries,
- + (int) total,
- + limit <= 0 ? 1 : (offset / limit) + 1,
- + limit,
- + stateCode);
- + }
- +
- /**
- * 按对外报警标识解析报警:先按 {@code alarm_no}(真实单号),再退回主键 {@code id}。
- *
- diff --git a/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderReadAdapter.java b/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderReadAdapter.java
- index b461d3f2..3df39ccc 100644
- --- a/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderReadAdapter.java
- +++ b/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderReadAdapter.java
- @@ -6,4 +6,17 @@ public interface CockpitWorkOrderReadAdapter {
- CockpitWorkOrderReadSnapshot loadByEvent(String eventSource, String eventCode);
-
- CockpitWorkOrderTimelineSnapshot loadTimeline(String workOrderCode);
- -}
- \ No newline at end of file
- +
- + /**
- + * 全量工单分页(票 65:报警效率面板要列「当前工单列表」,不按设备也不按事件筛)。
- + *
- + * <p>与设备维度共用同一条读取路径(运营侧 {@code WorkOrderService})与同一份
- + * {@link CockpitWorkOrderSummary} 映射,区别只在不加 {@code device_id} 约束。
- + * 排序口径与设备维度一致(创建时间倒序),前端才能稳定翻页。
- + *
- + * @param stateCode 工单状态码 0–7;{@code null} 表示不筛
- + * @param limit 本页条数(调用方已夹到合法区间)
- + * @param offset 偏移量,{@code (page-1)*limit}
- + */
- + CockpitWorkOrderListSnapshot loadAll(Integer stateCode, int limit, int offset);
- +}
- diff --git a/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderReadService.java b/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderReadService.java
- index e898dba3..40d7acd4 100644
- --- a/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderReadService.java
- +++ b/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderReadService.java
- @@ -18,6 +18,12 @@ import java.util.List;
- public class CockpitWorkOrderReadService {
- private static final List<String> VALID_EVENT_SOURCES = Arrays.asList("ALARM", "WARNING");
-
- + /** 全量工单列表的默认页大小(与驾驶舱其它列表端点一致)。 */
- + private static final int DEFAULT_PAGE_SIZE = 10;
- +
- + /** 单次最多取多少张:防一个 pageSize 把全库拉下来。 */
- + private static final int MAX_PAGE_SIZE = 100;
- +
- private final CockpitWorkOrderReadAdapter adapter;
- private final Clock clock;
-
- @@ -64,6 +70,44 @@ public class CockpitWorkOrderReadService {
- return error(requestId, CockpitErrorCategory.INVALID_REQUEST, "工单查询参数不合法");
- }
-
- + /**
- + * 全量工单分页(票 65:报警效率面板的「当前工单列表」,不按设备也不按事件)。
- + *
- + * <p>翻页参数在这里**夹到合法区间**,不信任入参直接下到 SQL 的 LIMIT/OFFSET:
- + * 非法页码轻则返回错页、重则合成语法错误的 SQL。夹取后回显实际生效值,
- + * 前端据此纠偏(与票 61「越界页码夹回」同一条纪律,只是这次发生在服务端入口)。
- + *
- + * @param page 页码 1 起(null/越界 → 1)
- + * @param pageSize 每页条数(null/越界 → 10;上限 100,避免一次拉全库)
- + * @param stateCode 工单状态码 0–7(null 或越界 → 不筛)
- + */
- + public CockpitWorkOrderListResponse loadAll(
- + String requestId,
- + Integer page,
- + Integer pageSize,
- + Integer stateCode) {
- + int safePage = page == null || page < 1 ? 1 : page;
- + int safeSize = pageSize == null || pageSize < 1 ? DEFAULT_PAGE_SIZE : Math.min(pageSize, MAX_PAGE_SIZE);
- + Integer safeState = stateCode != null && stateCode >= 0 && stateCode <= 7 ? stateCode : null;
- + CockpitWorkOrderListSnapshot snapshot = adapter.loadAll(
- + safeState, safeSize, (safePage - 1) * safeSize);
- + if (snapshot == null) {
- + throw new CockpitReadException("work order list unavailable");
- + }
- + List<CockpitWorkOrderSummary> workOrders = snapshot.getWorkOrders() == null
- + ? new ArrayList<>() : snapshot.getWorkOrders();
- + boolean empty = workOrders.isEmpty();
- + return new CockpitWorkOrderListResponse(
- + requestId,
- + "v1",
- + true,
- + empty ? "EMPTY" : "READY",
- + empty ? "NO_WORK_ORDERS" : "READY",
- + CockpitWorkOrderStateDictionary.states(),
- + workOrders,
- + new CockpitWorkOrderListResponse.Pagination(safePage, safeSize, snapshot.getTotal()));
- + }
- +
- public CockpitErrorPayload notFound(String requestId) {
- return error(requestId, CockpitErrorCategory.NOT_FOUND, "工单或关联对象不存在");
- }
- diff --git a/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/EmptyCockpitWorkOrderReadAdapter.java b/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/EmptyCockpitWorkOrderReadAdapter.java
- index 7f8a694d..85ef228a 100644
- --- a/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/EmptyCockpitWorkOrderReadAdapter.java
- +++ b/pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/EmptyCockpitWorkOrderReadAdapter.java
- @@ -18,4 +18,9 @@ public class EmptyCockpitWorkOrderReadAdapter implements CockpitWorkOrderReadAda
- public CockpitWorkOrderTimelineSnapshot loadTimeline(String workOrderCode) {
- return null;
- }
- +
- + @Override
- + public CockpitWorkOrderListSnapshot loadAll(Integer stateCode, int limit, int offset) {
- + return null;
- + }
- }
- \ No newline at end of file
|