From c4db0a4526f61758272c92396aa788d84f098102 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期二, 21 四月 2026 17:04:30 +0800
Subject: [PATCH] 风险规避

---
 backend/src/main/java/com/sinata/appointment/service/MiniAppointmentApplicationService.java |  261 ++++++++++++++++++++-------------------------------
 1 files changed, 104 insertions(+), 157 deletions(-)

diff --git a/backend/src/main/java/com/sinata/appointment/service/MiniAppointmentApplicationService.java b/backend/src/main/java/com/sinata/appointment/service/MiniAppointmentApplicationService.java
index 4cf442b..344c06b 100644
--- a/backend/src/main/java/com/sinata/appointment/service/MiniAppointmentApplicationService.java
+++ b/backend/src/main/java/com/sinata/appointment/service/MiniAppointmentApplicationService.java
@@ -15,6 +15,7 @@
 import com.sinata.appointment.constants.SystemSettingKeys;
 import com.sinata.appointment.dto.MiniAppointmentCreateRequest;
 import com.sinata.appointment.dto.MiniAppointmentListVo;
+import com.sinata.appointment.dto.MiniApprovalHistoryRow;
 import com.sinata.appointment.dto.MiniAppointmentVehicleItemRequest;
 import com.sinata.appointment.dto.MiniApprovalDetailVisitorVo;
 import com.sinata.appointment.dto.MiniMyAppointmentDetailVo;
@@ -67,6 +68,8 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
+import org.springframework.context.ApplicationEventPublisher;
+import com.sinata.appointment.service.event.AppointmentApprovedEvent;
 
 @Service
 @RequiredArgsConstructor
@@ -96,6 +99,7 @@
     private final PostApprovalOrchestrationService postApprovalOrchestrationService;
     private final ApprovalFlowViewApplicationService approvalFlowViewApplicationService;
     private final ObjectMapper objectMapper;
+    private final ApplicationEventPublisher applicationEventPublisher;
 
     @Transactional(rollbackFor = Exception.class)
     public Long create(MiniAppointmentCreateRequest req) {
@@ -179,11 +183,11 @@
 
         List<String> chain = approvalEngineService.resolveEnabledNodeChain(order);
         if (chain.isEmpty()) {
-            postApprovalOrchestrationService.onOrderFullyApproved(appointmentOrderMapper.selectById(order.getId()));
+            applicationEventPublisher.publishEvent(new AppointmentApprovedEvent(order.getId()));
         } else {
             ApprovalInstance inst = approvalEngineService.startFlow(order);
             if (inst == null) {
-                postApprovalOrchestrationService.onOrderFullyApproved(appointmentOrderMapper.selectById(order.getId()));
+                applicationEventPublisher.publishEvent(new AppointmentApprovedEvent(order.getId()));
             }
         }
         return order.getId();
@@ -222,190 +226,94 @@
     public IPage<MiniAppointmentListVo> pageMine(
             long page, long size, String status, String visitedUserNameKeyword, LocalDate visitDate) {
         MpUser current = miniAuthApplicationService.currentMpUser();
-        LambdaQueryWrapper<ApprovalTask> tq =
-                new LambdaQueryWrapper<ApprovalTask>()
-                        .eq(ApprovalTask::getDelFlag, 0)
-                        .eq(ApprovalTask::getAssigneeUserId, current.getId())
-                        .in(
-                                ApprovalTask::getTaskStatus,
-                                ApprovalTaskStatus.APPROVED,
-                                ApprovalTaskStatus.REJECTED)
-                        .orderByDesc(ApprovalTask::getUpdateTime)
-                        .orderByDesc(ApprovalTask::getId);
-        if (StringUtils.hasText(status)) {
-            tq.eq(ApprovalTask::getTaskStatus, status.trim());
+        Page<MiniApprovalHistoryRow> rowPage = new Page<>(Math.max(1L, page), Math.max(1L, size));
+        IPage<MiniApprovalHistoryRow> pagedRows =
+                approvalTaskMapper.pageMiniApprovalHistory(
+                        rowPage,
+                        current.getId(),
+                        trimToNull(status),
+                        trimToNull(visitedUserNameKeyword),
+                        visitDate);
+        Page<MiniAppointmentListVo> result =
+                new Page<>(pagedRows.getCurrent(), pagedRows.getSize(), pagedRows.getTotal());
+        List<MiniApprovalHistoryRow> rows = pagedRows.getRecords();
+        if (rows == null || rows.isEmpty()) {
+            result.setRecords(List.of());
+            return result;
         }
-        List<ApprovalTask> tasks = approvalTaskMapper.selectList(tq);
-        if (tasks.isEmpty()) {
-            return new Page<>(page, size);
-        }
-
-        java.util.LinkedHashMap<Long, ApprovalTask> latestTaskByOrder = new java.util.LinkedHashMap<>();
-        for (ApprovalTask task : tasks) {
-            ApprovalInstance inst = approvalInstanceMapper.selectById(task.getInstanceId());
-            if (inst == null || (inst.getDelFlag() != null && inst.getDelFlag() == 1) || inst.getOrderId() == null) {
-                continue;
-            }
-            latestTaskByOrder.putIfAbsent(inst.getOrderId(), task);
-        }
-        if (latestTaskByOrder.isEmpty()) {
-            return new Page<>(page, size);
-        }
-
-        List<AppointmentOrder> orders =
-                appointmentOrderMapper.selectList(
-                        new LambdaQueryWrapper<AppointmentOrder>()
-                                .eq(AppointmentOrder::getDelFlag, 0)
-                                .in(AppointmentOrder::getId, latestTaskByOrder.keySet()));
-        java.util.Map<Long, AppointmentOrder> orderMap =
-                orders.stream().collect(java.util.stream.Collectors.toMap(AppointmentOrder::getId, x -> x, (a, b) -> a));
-
-        List<MiniAppointmentListVo> all = new java.util.ArrayList<>();
-        for (var e : latestTaskByOrder.entrySet()) {
-            AppointmentOrder order = orderMap.get(e.getKey());
-            if (order == null) {
-                continue;
-            }
-            if (StringUtils.hasText(visitedUserNameKeyword)) {
-                if (!StringUtils.hasText(order.getVisitedUserName())
-                        || !order.getVisitedUserName().contains(visitedUserNameKeyword.trim())) {
-                    continue;
-                }
-            }
-            if (visitDate != null) {
-                if (order.getVisitStartDate() == null
-                        || order.getVisitEndDate() == null
-                        || visitDate.isBefore(order.getVisitStartDate())
-                        || visitDate.isAfter(order.getVisitEndDate())) {
-                    continue;
-                }
-            }
+        List<AppointmentOrder> orders = rows.stream().map(this::toOrderSnapshot).toList();
+        Map<Long, String> deptNameMap = loadDeptNameMap(orders);
+        Map<String, String> reasonNameMap = loadReasonNameMap(orders);
+        List<MiniAppointmentListVo> records = new ArrayList<>();
+        for (MiniApprovalHistoryRow row : rows) {
+            AppointmentOrder order = toOrderSnapshot(row);
             MiniAppointmentListVo vo = toListVo(order);
-            vo.setStatus(e.getValue().getTaskStatus());
-            all.add(vo);
+            vo.setStatus(row.getTaskStatus());
+            vo.setVisitedDeptName(deptNameMap.get(order.getVisitedDeptId()));
+            vo.setVisitedUserDisplay(buildVisitedUserDisplay(order.getVisitedUserName(), vo.getVisitedDeptName()));
+            vo.setVisitTimeText(buildVisitTimeText(order));
+            vo.setVisitReasonText(buildVisitReasonText(order, reasonNameMap));
+            vo.setAccessAreaText(buildAccessAreaText(order.getPassAccessAreaNames()));
+            records.add(vo);
         }
-        return slicePage(page, size, all);
+        result.setRecords(records);
+        return result;
     }
 
     public IPage<MiniVisitRecordListVo> pageVisitRecords(
             long page, long size, String visitorNameKeyword, LocalDate visitDate) {
         MpUser current = miniAuthApplicationService.currentMpUser();
-        List<AppointmentOrder> orders =
-                appointmentOrderMapper.selectList(
-                        new LambdaQueryWrapper<AppointmentOrder>()
-                                .eq(AppointmentOrder::getDelFlag, 0)
-                                .eq(AppointmentOrder::getStatus, AppointmentOrderStatus.APPROVED)
-                                .eq(AppointmentOrder::getVisitedUserId, current.getId()));
-        if (orders.isEmpty()) {
-            return new Page<>(page, size);
+        Page<AppointmentOrder> orderPage = new Page<>(Math.max(1L, page), Math.max(1L, size));
+        IPage<AppointmentOrder> pagedOrders =
+                appointmentOrderMapper.pageMiniVisitRecords(
+                        orderPage, current.getId(), trimToNull(visitorNameKeyword), visitDate);
+        Page<MiniVisitRecordListVo> result =
+                new Page<>(pagedOrders.getCurrent(), pagedOrders.getSize(), pagedOrders.getTotal());
+        List<AppointmentOrder> orders = pagedOrders.getRecords();
+        if (orders == null || orders.isEmpty()) {
+            result.setRecords(List.of());
+            return result;
         }
-        List<Long> orderIds = orders.stream().map(AppointmentOrder::getId).filter(Objects::nonNull).toList();
-        List<AppointmentVisitor> visitors =
-                appointmentVisitorMapper.selectList(
-                        new LambdaQueryWrapper<AppointmentVisitor>()
-                                .eq(AppointmentVisitor::getDelFlag, 0)
-                                .in(AppointmentVisitor::getOrderId, orderIds)
-                                .orderByAsc(AppointmentVisitor::getId));
-        Map<Long, List<String>> visitorNamesMap = new java.util.LinkedHashMap<>();
-        for (AppointmentVisitor row : visitors) {
-            visitorNamesMap.computeIfAbsent(row.getOrderId(), k -> new java.util.ArrayList<>());
-            if (StringUtils.hasText(row.getName())) {
-                visitorNamesMap.get(row.getOrderId()).add(row.getName().trim());
-            }
-        }
-
-        List<MiniVisitRecordListVo> rows = new java.util.ArrayList<>();
+        Map<Long, List<String>> visitorNamesMap = loadVisitorNamesMap(orders.stream().map(AppointmentOrder::getId).toList());
+        List<MiniVisitRecordListVo> records = new ArrayList<>();
         for (AppointmentOrder order : orders) {
-            List<String> names = visitorNamesMap.getOrDefault(order.getId(), List.of());
-            if (StringUtils.hasText(visitorNameKeyword)) {
-                String kw = visitorNameKeyword.trim();
-                boolean hit = false;
-                for (String n : names) {
-                    if (n.contains(kw)) {
-                        hit = true;
-                        break;
-                    }
-                }
-                if (!hit) {
-                    continue;
-                }
-            }
-            if (visitDate != null) {
-                if (order.getVisitStartDate() == null
-                        || order.getVisitEndDate() == null
-                        || visitDate.isBefore(order.getVisitStartDate())
-                        || visitDate.isAfter(order.getVisitEndDate())) {
-                    continue;
-                }
-            }
             MiniVisitRecordListVo vo = new MiniVisitRecordListVo();
             vo.setOrderId(order.getId());
             vo.setOrderNo(order.getOrderNo());
-            vo.setVisitorNames(names);
+            vo.setVisitorNames(visitorNamesMap.getOrDefault(order.getId(), List.of()));
             vo.setVisitStartDate(order.getVisitStartDate());
             vo.setVisitEndDate(order.getVisitEndDate());
             vo.setVisitTimeMode(order.getVisitTimeMode());
             vo.setVisitTimeSlot(order.getVisitTimeSlot());
             vo.setCreateTime(order.getCreateTime());
-            rows.add(vo);
+            records.add(vo);
         }
-
-        rows.sort(
-                java.util.Comparator
-                        .comparing(
-                                MiniVisitRecordListVo::getVisitEndDate,
-                                java.util.Comparator.nullsLast(java.util.Comparator.naturalOrder()))
-                        .reversed()
-                        .thenComparing(
-                                this::singleDaySlotSortWeight,
-                                java.util.Comparator.reverseOrder())
-                        .thenComparing(
-                                MiniVisitRecordListVo::getCreateTime,
-                                java.util.Comparator.nullsLast(java.util.Comparator.reverseOrder())));
-        return slicePageVisitRecord(page, size, rows);
+        result.setRecords(records);
+        return result;
     }
 
     public IPage<MiniAppointmentListVo> pageMyOrders(
             long page, long size, String status, String keyword) {
         MpUser current = miniAuthApplicationService.currentMpUser();
-        List<AppointmentOrder> orders =
-                appointmentOrderMapper.selectList(
-                        new LambdaQueryWrapper<AppointmentOrder>()
-                                .eq(AppointmentOrder::getDelFlag, 0)
-                                .eq(AppointmentOrder::getSubmitterId, current.getId())
-                                .orderByDesc(AppointmentOrder::getCreateTime)
-                                .orderByDesc(AppointmentOrder::getId));
-        if (orders.isEmpty()) {
-            return new Page<>(page, size);
+        Page<AppointmentOrder> orderPage = new Page<>(Math.max(1L, page), Math.max(1L, size));
+        IPage<AppointmentOrder> pagedOrders =
+                appointmentOrderMapper.pageMiniMyOrders(
+                        orderPage, current.getId(), trimToNull(status), trimToNull(keyword));
+        Page<MiniAppointmentListVo> result =
+                new Page<>(pagedOrders.getCurrent(), pagedOrders.getSize(), pagedOrders.getTotal());
+        List<AppointmentOrder> orders = pagedOrders.getRecords();
+        if (orders == null || orders.isEmpty()) {
+            result.setRecords(List.of());
+            return result;
         }
-
         Map<Long, String> deptNameMap = loadDeptNameMap(orders);
         Map<String, String> reasonNameMap = loadReasonNameMap(orders);
-        String normalizedKeyword = trimToNull(keyword);
-        String normalizedStatus = trimToNull(status);
-        List<MiniAppointmentListVo> rows = new ArrayList<>();
+        List<MiniAppointmentListVo> records = new ArrayList<>();
         for (AppointmentOrder order : orders) {
-            MiniAppointmentListVo vo = toMyOrderListVo(order, deptNameMap, reasonNameMap);
-            if (StringUtils.hasText(normalizedStatus)
-                    && !Objects.equals(normalizedStatus, vo.getDisplayStatus())) {
-                continue;
-            }
-            if (StringUtils.hasText(normalizedKeyword)
-                    && !containsIgnoreCase(vo.getVisitedUserDisplay(), normalizedKeyword)
-                    && !containsIgnoreCase(vo.getVisitReasonText(), normalizedKeyword)) {
-                continue;
-            }
-            rows.add(vo);
+            records.add(toMyOrderListVo(order, deptNameMap, reasonNameMap));
         }
-
-        rows.sort(
-                Comparator.comparing(
-                                MiniAppointmentListVo::getCreateTime,
-                                Comparator.nullsLast(Comparator.reverseOrder()))
-                        .thenComparing(
-                                MiniAppointmentListVo::getId,
-                                Comparator.nullsLast(Comparator.reverseOrder())));
-        return slicePage(page, size, rows);
+        result.setRecords(records);
+        return result;
     }
 
     public List<MiniMyVisitorCodeOrderVo> listMyVisitorCodes() {
@@ -809,6 +717,25 @@
         return vo;
     }
 
+    private AppointmentOrder toOrderSnapshot(MiniApprovalHistoryRow row) {
+        AppointmentOrder order = new AppointmentOrder();
+        order.setId(row.getId());
+        order.setUuid(row.getUuid());
+        order.setOrderNo(row.getOrderNo());
+        order.setVisitedUserName(row.getVisitedUserName());
+        order.setVisitedDeptId(row.getVisitedDeptId());
+        order.setVisitStartDate(row.getVisitStartDate());
+        order.setVisitEndDate(row.getVisitEndDate());
+        order.setVisitReasonCode(row.getVisitReasonCode());
+        order.setVisitReasonOther(row.getVisitReasonOther());
+        order.setVisitTimeMode(row.getVisitTimeMode());
+        order.setVisitTimeSlot(row.getVisitTimeSlot());
+        order.setPassAccessAreaNames(row.getPassAccessAreaNames());
+        order.setStatus(row.getStatus());
+        order.setCreateTime(row.getCreateTime());
+        return order;
+    }
+
     private Map<Long, String> loadDeptNameMap(List<AppointmentOrder> orders) {
         Set<Long> deptIds =
                 orders.stream()
@@ -852,6 +779,26 @@
                                 LinkedHashMap::new));
     }
 
+    private Map<Long, List<String>> loadVisitorNamesMap(List<Long> orderIds) {
+        if (orderIds == null || orderIds.isEmpty()) {
+            return Map.of();
+        }
+        List<AppointmentVisitor> visitors =
+                appointmentVisitorMapper.selectList(
+                        new LambdaQueryWrapper<AppointmentVisitor>()
+                                .eq(AppointmentVisitor::getDelFlag, 0)
+                                .in(AppointmentVisitor::getOrderId, orderIds)
+                                .orderByAsc(AppointmentVisitor::getId));
+        Map<Long, List<String>> result = new LinkedHashMap<>();
+        for (AppointmentVisitor row : visitors) {
+            result.computeIfAbsent(row.getOrderId(), k -> new ArrayList<>());
+            if (StringUtils.hasText(row.getName())) {
+                result.get(row.getOrderId()).add(row.getName().trim());
+            }
+        }
+        return result;
+    }
+
     private String buildVisitedUserDisplay(String userName, String deptName) {
         String name = trimToNull(userName);
         String dept = trimToNull(deptName);

--
Gitblit v1.7.1