From e45e74e5ae207f7642be9a88ed99b593de89fb3b Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期三, 24 六月 2026 16:54:46 +0800
Subject: [PATCH] 1.0

---
 backend/src/main/java/com/sinata/appointment/service/AppointmentApplicationService.java |  175 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 145 insertions(+), 30 deletions(-)

diff --git a/backend/src/main/java/com/sinata/appointment/service/AppointmentApplicationService.java b/backend/src/main/java/com/sinata/appointment/service/AppointmentApplicationService.java
index 8de75bd..d87666c 100644
--- a/backend/src/main/java/com/sinata/appointment/service/AppointmentApplicationService.java
+++ b/backend/src/main/java/com/sinata/appointment/service/AppointmentApplicationService.java
@@ -21,6 +21,7 @@
 import com.sinata.appointment.entity.BizVisitReason;
 import com.sinata.appointment.entity.MpUser;
 import com.sinata.appointment.entity.MpVisitor;
+import com.sinata.appointment.entity.MpPassAccessArea;
 import com.sinata.appointment.entity.SysDept;
 import com.sinata.appointment.exception.BizException;
 import com.sinata.appointment.constants.BizErrorCode;
@@ -32,6 +33,7 @@
 import com.sinata.appointment.mapper.BizVisitReasonMapper;
 import com.sinata.appointment.mapper.MpUserMapper;
 import com.sinata.appointment.mapper.MpVisitorMapper;
+import com.sinata.appointment.mapper.MpPassAccessAreaMapper;
 import com.sinata.appointment.mapper.SysDeptMapper;
 import com.sinata.appointment.util.MobileMaskUtil;
 import com.sinata.appointment.util.SensitiveDataUtil;
@@ -71,6 +73,7 @@
     private final BizVisitReasonMapper bizVisitReasonMapper;
     private final MpUserMapper mpUserMapper;
     private final MpVisitorMapper mpVisitorMapper;
+    private final MpPassAccessAreaMapper mpPassAccessAreaMapper;
     private final SysDeptMapper sysDeptMapper;
     private final ObjectMapper objectMapper;
 
@@ -79,6 +82,7 @@
             long size,
             String visitedUserName,
             Long visitedDeptId,
+            Long accessAreaId,
             String accessArea,
             String localUnit,
             LocalDate visitDateStart,
@@ -87,12 +91,14 @@
             String approvalStatus,
             String visitorKeyword,
             String visitReasonCode) {
+        List<Long> accessAreaIds = resolveAccessAreaFilterIds(accessAreaId);
         Page<AppointmentOrder> orderPage = new Page<>(Math.max(1L, page), Math.max(1L, size));
         IPage<AppointmentOrder> pagedOrders =
                 appointmentOrderMapper.pageAdminOrders(
                         orderPage,
                         trimToNull(visitedUserName),
                         visitedDeptId,
+                        accessAreaIds,
                         trimToNull(accessArea),
                         trimToNull(localUnit),
                         visitDateStart,
@@ -107,6 +113,7 @@
     public byte[] exportExcel(
             String visitedUserName,
             Long visitedDeptId,
+            Long accessAreaId,
             String accessArea,
             String localUnit,
             LocalDate visitDateStart,
@@ -115,6 +122,7 @@
             String approvalStatus,
             String visitorKeyword,
             String visitReasonCode) {
+        List<Long> accessAreaIds = resolveAccessAreaFilterIds(accessAreaId);
         long pageNo = 1L;
         long pageSize = 200L;
         List<AppointmentAdminExportRow> rows = new ArrayList<>();
@@ -125,6 +133,7 @@
                             orderPage,
                             trimToNull(visitedUserName),
                             visitedDeptId,
+                            accessAreaIds,
                             trimToNull(accessArea),
                             trimToNull(localUnit),
                             visitDateStart,
@@ -174,6 +183,7 @@
         Map<Long, MpVisitor> visitorMap = loadVisitorMap(visitorRows);
         Map<Long, String> plateMap = loadVisitorPlateMap(id);
         ApprovalInstance approvalInstance = loadLatestInstance(id);
+        MpUser submitter = loadSubmitter(order.getSubmitterId());
 
         AppointmentAdminDetailVo vo = new AppointmentAdminDetailVo();
         vo.setId(order.getId());
@@ -186,6 +196,9 @@
         vo.setLocalUnitText(defaultText(buildJsonNameText(order.getPassLocalUnitNames())));
         vo.setPlateNoText(defaultText(loadOrderPlateText(id)));
         vo.setVisitReasonText(defaultText(buildVisitReasonText(order, reasonNameMap)));
+        vo.setVisitReasonOther(defaultText(trimToNull(order.getVisitReasonOther())));
+        vo.setVisitTimeMode(trimToNull(order.getVisitTimeMode()));
+        vo.setVisitTimeSlot(trimToNull(order.getVisitTimeSlot()));
         vo.setVisitStartText(defaultText(resolveVisitStartText(order)));
         vo.setVisitEndText(defaultText(resolveVisitEndText(order)));
         String displayStatusCode = resolveDisplayStatus(order);
@@ -194,6 +207,9 @@
         String approvalStatusCode = resolveApprovalStatusCode(order, approvalInstance);
         vo.setApprovalStatusCode(approvalStatusCode);
         vo.setApprovalStatusText(resolveApprovalStatusText(approvalStatusCode));
+        vo.setSubmitterName(defaultText(resolveSubmitterName(submitter)));
+        vo.setSubmitterMobile(defaultText(trimToNull(submitter == null ? null : submitter.getMobile())));
+        vo.setSubmitTime(order.getCreateTime() == null ? "-" : order.getCreateTime().format(DATE_TIME_FORMATTER));
         vo.setVisitors(buildDetailVisitors(visitorRows, visitorMap, plateMap));
         return vo;
     }
@@ -216,6 +232,8 @@
             return page;
         }
         AdminPageData pageData = loadAdminPageData(orders);
+        List<Long> orderIds = orders.stream().map(AppointmentOrder::getId).filter(Objects::nonNull).toList();
+        Map<Long, String> orderPlateTextMap = loadOrderPlateTextMap(orderIds);
         List<AppointmentAdminListVo> records = new ArrayList<>();
         for (AppointmentOrder order : orders) {
             records.add(
@@ -224,7 +242,8 @@
                             pageData.deptNameMap().get(order.getVisitedDeptId()),
                             pageData.reasonNameMap(),
                             pageData.visitorRowsMap().get(order.getId()),
-                            pageData.approvalInstanceMap().get(order.getId())));
+                            pageData.approvalInstanceMap().get(order.getId()),
+                            orderPlateTextMap.get(order.getId())));
         }
         page.setRecords(records);
         return page;
@@ -257,6 +276,19 @@
                                 .eq(MpVisitor::getDelFlag, 0)
                                 .in(MpVisitor::getId, visitorIds));
         return visitors.stream().collect(Collectors.toMap(MpVisitor::getId, v -> v, (a, b) -> a, LinkedHashMap::new));
+    }
+
+    private MpUser loadSubmitter(Long submitterId) {
+        if (submitterId == null) {
+            return null;
+        }
+        List<MpUser> rows =
+                mpUserMapper.selectList(
+                        new LambdaQueryWrapper<MpUser>()
+                                .eq(MpUser::getDelFlag, 0)
+                                .eq(MpUser::getId, submitterId)
+                                .last("limit 1"));
+        return rows.isEmpty() ? null : rows.get(0);
     }
 
     private Map<Long, String> loadVisitorPlateMap(Long orderId) {
@@ -309,6 +341,34 @@
                 .map(String::trim)
                 .distinct()
                 .collect(Collectors.joining("、"));
+    }
+
+    private Map<Long, String> loadOrderPlateTextMap(List<Long> orderIds) {
+        if (orderIds == null || orderIds.isEmpty()) {
+            return Map.of();
+        }
+        List<AppointmentVehicle> rows =
+                appointmentVehicleMapper.selectList(
+                        new LambdaQueryWrapper<AppointmentVehicle>()
+                                .eq(AppointmentVehicle::getDelFlag, 0)
+                                .in(AppointmentVehicle::getOrderId, orderIds)
+                                .orderByAsc(AppointmentVehicle::getId));
+        if (rows == null || rows.isEmpty()) {
+            return Map.of();
+        }
+        Map<Long, LinkedHashSet<String>> grouped = new LinkedHashMap<>();
+        for (AppointmentVehicle row : rows) {
+            if (row.getOrderId() == null || !StringUtils.hasText(row.getPlateNo())) {
+                continue;
+            }
+            grouped.computeIfAbsent(row.getOrderId(), key -> new LinkedHashSet<>());
+            grouped.get(row.getOrderId()).add(row.getPlateNo().trim());
+        }
+        Map<Long, String> result = new LinkedHashMap<>();
+        for (Map.Entry<Long, LinkedHashSet<String>> entry : grouped.entrySet()) {
+            result.put(entry.getKey(), String.join("、", entry.getValue()));
+        }
+        return result;
     }
 
     private Map<Long, List<AppointmentVisitor>> loadVisitorRows(List<Long> orderIds) {
@@ -399,7 +459,8 @@
             String deptName,
             Map<String, String> reasonNameMap,
             List<AppointmentVisitor> visitorRows,
-            ApprovalInstance approvalInstance) {
+            ApprovalInstance approvalInstance,
+            String orderPlateText) {
         AppointmentAdminListVo vo = new AppointmentAdminListVo();
         vo.setId(order.getId());
         vo.setUuid(order.getUuid());
@@ -409,8 +470,9 @@
         vo.setVisitedDeptName(defaultText(trimToNull(deptName)));
         vo.setAccessAreaText(defaultText(buildJsonNameText(order.getPassAccessAreaNames())));
         vo.setLocalUnitText(defaultText(buildJsonNameText(order.getPassLocalUnitNames())));
-        vo.setPlateNoText(defaultText(joinUniqueTexts(visitorRows, AppointmentVisitor::getPlateNo)));
+        vo.setPlateNoText(defaultText(firstNonBlank(orderPlateText, joinUniqueTexts(visitorRows, AppointmentVisitor::getPlateNo), null)));
         vo.setVisitReasonText(defaultText(buildVisitReasonText(order, reasonNameMap)));
+        vo.setVisitReasonOther(defaultText(trimToNull(order.getVisitReasonOther())));
         vo.setVisitTimeText(defaultText(buildVisitTimeText(order)));
         vo.setVisitorNamesText(defaultText(joinUniqueTexts(visitorRows, AppointmentVisitor::getName)));
         vo.setStatus(order.getStatus());
@@ -446,25 +508,25 @@
 
         List<AppointmentAdminExportRow> result = new ArrayList<>();
         for (AppointmentOrder order : orders) {
+            List<AppointmentVisitor> visitors = visitorRowsMap.get(order.getId());
             AppointmentAdminListVo summary =
                     toAdminListVo(
                             order,
                             null,
                             reasonNameMap,
-                            visitorRowsMap.get(order.getId()),
-                            approvalInstanceMap.get(order.getId()));
+                            visitors,
+                            approvalInstanceMap.get(order.getId()),
+                            loadOrderPlateText(order.getId()));
             Map<String, String> nodeApproverNames =
                     approvalNameMap.getOrDefault(order.getId(), Map.of());
             MpUser submitter = submitterMap.get(order.getSubmitterId());
-            List<AppointmentVisitor> visitors = visitorRowsMap.get(order.getId());
+            Map<Long, String> orderPlateMap = visitorPlateMap.getOrDefault(order.getId(), Map.of());
             if (visitors == null || visitors.isEmpty()) {
-                result.add(buildExportRow(summary, order, null, null, Map.of(), nodeApproverNames, submitter));
+                result.add(buildExportRow(summary, order, null, visitorMap, orderPlateMap, nodeApproverNames, submitter));
                 continue;
             }
-            Map<Long, String> orderPlateMap = visitorPlateMap.getOrDefault(order.getId(), Map.of());
             for (AppointmentVisitor visitorRow : visitors) {
-                MpVisitor visitor = visitorMap.get(visitorRow.getMpVisitorId());
-                result.add(buildExportRow(summary, order, visitorRow, visitor, orderPlateMap, nodeApproverNames, submitter));
+                result.add(buildExportRow(summary, order, visitorRow, visitorMap, orderPlateMap, nodeApproverNames, submitter));
             }
         }
         return result;
@@ -474,7 +536,7 @@
             AppointmentAdminListVo summary,
             AppointmentOrder order,
             AppointmentVisitor visitorRow,
-            MpVisitor visitor,
+            Map<Long, MpVisitor> visitorMap,
             Map<Long, String> orderPlateMap,
             Map<String, String> nodeApproverNames,
             MpUser submitter) {
@@ -483,31 +545,36 @@
         row.setVisitedUserName(summary.getVisitedUserName());
         row.setAccessAreaText(summary.getAccessAreaText());
         row.setLocalUnitText(summary.getLocalUnitText());
-        row.setPlateNoText(
-                defaultText(
-                        firstNonBlank(
-                                visitorRow == null ? null : visitorRow.getPlateNo(),
-                                visitorRow == null ? null : orderPlateMap.get(visitorRow.getMpVisitorId()),
-                                summary.getPlateNoText())));
+        row.setPlateNoText(defaultText(summary.getPlateNoText()));
         row.setVisitReasonText(summary.getVisitReasonText());
+        row.setVisitReasonOther(summary.getVisitReasonOther());
         row.setVisitTimeText(summary.getVisitTimeText());
         row.setDisplayStatusText(summary.getDisplayStatusText());
-        row.setVisitorLabel(defaultText(visitorRow == null ? null : trimToNull(visitorRow.getName())));
-        row.setVisitorName(
-                defaultText(
+        MpVisitor visitor = visitorRow == null ? null : visitorMap.get(visitorRow.getMpVisitorId());
+        String visitorName =
+                trimToNull(
                         firstNonBlank(
                                 visitorRow == null ? null : visitorRow.getName(),
                                 visitor == null ? null : visitor.getVisitorName(),
-                                null)));
-        row.setIdCardText(defaultText(resolveIdCardMasked(visitorRow, visitor)));
+                                null));
+        row.setVisitorLabel(defaultText(visitorName));
+        row.setVisitorName(defaultText(visitorName));
+        row.setIdCardText(defaultText(trimToNull(resolveIdCardMasked(visitorRow, visitor))));
         row.setMobileText(
                 defaultText(
-                        MobileMaskUtil.mask(
-                                firstNonBlank(
-                                        visitorRow == null ? null : visitorRow.getMobile(),
-                                        visitor == null ? null : visitor.getVisitorMobile(),
-                                        null))));
-        row.setCompanyName(defaultText(visitor == null ? null : trimToNull(visitor.getVisitorCompany())));
+                        trimToNull(
+                                MobileMaskUtil.mask(
+                                        firstNonBlank(
+                                                visitorRow == null ? null : visitorRow.getMobile(),
+                                                visitor == null ? null : visitor.getVisitorMobile(),
+                                                null)))));
+        row.setCompanyName(defaultText(trimToNull(visitor == null ? null : visitor.getVisitorCompany())));
+        if (visitorRow != null && visitorRow.getMpVisitorId() != null) {
+            String visitorPlateText = trimToNull(orderPlateMap.get(visitorRow.getMpVisitorId()));
+            if (StringUtils.hasText(visitorPlateText)) {
+                row.setPlateNoText(visitorPlateText);
+            }
+        }
         row.setHandlerApproverNames(defaultText(nodeApproverNames.get(ApprovalNodeCode.LEVEL1_HANDLER)));
         row.setDeptLeaderApproverNames(defaultText(nodeApproverNames.get(ApprovalNodeCode.LEVEL2_DEPT_LEADER)));
         row.setVisitDeptApproverNames(defaultText(nodeApproverNames.get(ApprovalNodeCode.LEVEL4_VISIT_DEPT)));
@@ -723,8 +790,7 @@
             return null;
         }
         if ("OTHER".equalsIgnoreCase(code)) {
-            String other = trimToNull(row.getVisitReasonOther());
-            return StringUtils.hasText(other) ? "其他-" + other : "其他";
+            return "其他";
         }
         String reasonName = reasonNameMap.get(code);
         return StringUtils.hasText(reasonName) ? reasonName : code;
@@ -861,8 +927,50 @@
         return StringUtils.hasText(trimmed) ? trimmed : null;
     }
 
+    private List<Long> resolveAccessAreaFilterIds(Long accessAreaId) {
+        if (accessAreaId == null) {
+            return List.of();
+        }
+        List<MpPassAccessArea> allRows =
+                mpPassAccessAreaMapper.selectList(
+                        new LambdaQueryWrapper<MpPassAccessArea>()
+                                .eq(MpPassAccessArea::getDelFlag, 0));
+        if (allRows == null || allRows.isEmpty()) {
+            return List.of(accessAreaId);
+        }
+        Map<Long, List<Long>> childrenByPid = new LinkedHashMap<>();
+        for (MpPassAccessArea row : allRows) {
+            if (row.getId() == null) {
+                continue;
+            }
+            Long pid = row.getPid() == null ? 0L : row.getPid();
+            childrenByPid.computeIfAbsent(pid, key -> new ArrayList<>()).add(row.getId());
+        }
+        LinkedHashSet<Long> idSet = new LinkedHashSet<>();
+        ArrayList<Long> queue = new ArrayList<>();
+        queue.add(accessAreaId);
+        for (int i = 0; i < queue.size(); i++) {
+            Long current = queue.get(i);
+            if (current == null || !idSet.add(current)) {
+                continue;
+            }
+            List<Long> children = childrenByPid.get(current);
+            if (children != null && !children.isEmpty()) {
+                queue.addAll(children);
+            }
+        }
+        return idSet.isEmpty() ? List.of(accessAreaId) : new ArrayList<>(idSet);
+    }
+
     private static String defaultText(String value) {
         return StringUtils.hasText(value) ? value : "-";
+    }
+
+    private String resolveSubmitterName(MpUser submitter) {
+        if (submitter == null) {
+            return null;
+        }
+        return firstNonBlank(submitter.getNickName(), submitter.getMobile());
     }
 
     @SafeVarargs
@@ -883,4 +991,11 @@
             Map<Long, ApprovalInstance> approvalInstanceMap,
             Map<Long, String> deptNameMap,
             Map<String, String> reasonNameMap) {}
+
+    private enum VisitorFieldType {
+        NAME,
+        ID_CARD,
+        MOBILE,
+        COMPANY
+    }
 }

--
Gitblit v1.7.1