From 700f9d0da314a4ea701fe9f68d305b67d72ec5fb Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期三, 08 七月 2026 15:08:37 +0800
Subject: [PATCH] 各类修复fix
---
backend/src/main/java/com/sinata/appointment/service/MiniAppointmentApplicationService.java | 666 +++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 474 insertions(+), 192 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..6006207 100644
--- a/backend/src/main/java/com/sinata/appointment/service/MiniAppointmentApplicationService.java
+++ b/backend/src/main/java/com/sinata/appointment/service/MiniAppointmentApplicationService.java
@@ -14,12 +14,15 @@
import com.sinata.appointment.constants.QrcodeTicketStatus;
import com.sinata.appointment.constants.SystemSettingKeys;
import com.sinata.appointment.dto.MiniAppointmentCreateRequest;
+import com.sinata.appointment.dto.MiniAppointmentCreateResultVo;
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;
import com.sinata.appointment.dto.MiniMyVisitorCodeOrderVo;
import com.sinata.appointment.dto.MiniMyVisitorCodeTicketVo;
+import com.sinata.appointment.dto.MiniSharedAppointmentDetailVo;
import com.sinata.appointment.dto.MiniVisitRecordListVo;
import com.sinata.appointment.dto.ApprovalFlowNodeVo;
import com.sinata.appointment.entity.AppointmentOrder;
@@ -63,11 +66,16 @@
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
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;
+import com.sinata.appointment.service.event.AppointmentApproversNotifyEvent;
+@Slf4j
@Service
@RequiredArgsConstructor
public class MiniAppointmentApplicationService {
@@ -95,10 +103,13 @@
private final ApprovalEngineService approvalEngineService;
private final PostApprovalOrchestrationService postApprovalOrchestrationService;
private final ApprovalFlowViewApplicationService approvalFlowViewApplicationService;
+ private final SensitiveWordFilterService sensitiveWordFilterService;
+ private final IntegrationHikvisionService integrationHikvisionService;
private final ObjectMapper objectMapper;
+ private final ApplicationEventPublisher applicationEventPublisher;
@Transactional(rollbackFor = Exception.class)
- public Long create(MiniAppointmentCreateRequest req) {
+ public MiniAppointmentCreateResultVo create(MiniAppointmentCreateRequest req) {
MpUser current = miniAuthApplicationService.currentMpUser();
FieldRequiredContext required = loadFieldRequiredContext();
MpUser visited = loadVisitedUser(req.getVisitedUserId());
@@ -140,7 +151,7 @@
order.setVisitedUserName(StringUtils.hasText(visited.getNickName()) ? visited.getNickName() : "员工");
order.setVisitedDeptId(visited.getDeptId());
order.setVisitReasonCode(req.getVisitReasonCode().trim());
- order.setVisitReasonOther(trimToNull(req.getVisitReasonOther()));
+ order.setVisitReasonOther(sensitiveWordFilterService.filter(trimToNull(req.getVisitReasonOther())));
order.setVisitorOrg(resolveVisitorOrg(visitorMap.values()));
order.setVisitTimeMode(mode);
order.setVisitTimeSlot(
@@ -152,6 +163,7 @@
order.setPersonEntryFlag(personEntry);
order.setVehicleEntryFlag(vehicleEntry);
order.setSubmitterId(current.getId());
+ order.setSubmitterVisibleFlag(1);
order.setHolidayFlag(holidayFlag);
order.setStatus(AppointmentOrderStatus.PENDING_APPROVAL);
appointmentOrderMapper.insert(order);
@@ -179,14 +191,20 @@
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()));
+ } else {
+ applicationEventPublisher.publishEvent(
+ new AppointmentApproversNotifyEvent(order.getId(), inst.getId()));
}
}
- return order.getId();
+ MiniAppointmentCreateResultVo result = new MiniAppointmentCreateResultVo();
+ result.setId(order.getId());
+ result.setUuid(order.getUuid());
+ return result;
}
@Transactional(rollbackFor = Exception.class)
@@ -210,7 +228,7 @@
ApprovalInstance latestInst = loadLatestInstanceByOrderId(order.getId());
if (latestInst != null
&& ApprovalInstanceStatus.IN_PROGRESS.equals(latestInst.getStatus())) {
- approvalEngineService.rejectInstance(latestInst, CANCEL_REASON_BY_SUBMITTER);
+ approvalEngineService.cancelInstance(latestInst, CANCEL_REASON_BY_SUBMITTER);
}
order.setStatus(AppointmentOrderStatus.CANCELLED);
@@ -219,193 +237,130 @@
expireUnusedTicketsByOrderId(order.getId());
}
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteMyOrderRecord(Long orderId, String uuid) {
+ if (orderId == null || orderId <= 0) {
+ throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "预约单不存在");
+ }
+ MpUser current = miniAuthApplicationService.currentMpUser();
+ AppointmentOrder order = appointmentOrderMapper.selectById(orderId);
+ if (order == null || (order.getDelFlag() != null && order.getDelFlag() == 1)) {
+ throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "预约单不存在");
+ }
+ UuidAssert.match(order, uuid);
+ if (!Objects.equals(order.getSubmitterId(), current.getId())) {
+ throw new BizException(BizErrorCode.AUTH_FORBIDDEN, "仅预约发起人可删除");
+ }
+ if (!isDeletableStatus(order.getStatus(), resolveDisplayStatus(order))) {
+ throw new BizException(BizErrorCode.ORDER_STATE_INVALID, "当前状态不可删除");
+ }
+ order.setSubmitterVisibleFlag(0);
+ appointmentOrderMapper.updateById(order);
+ }
+
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<Long> orderIds = orders.stream().map(AppointmentOrder::getId).filter(Objects::nonNull).toList();
+ Map<Long, String> visitorDisplayMap = loadVisitorDisplayMapByOrderIds(orderIds);
+ Map<Long, String> plateTextMap = loadPlateTextMapByOrderIds(orderIds);
+ 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()));
+ vo.setVisitorDisplayText(visitorDisplayMap.get(order.getId()));
+ vo.setPlateNoText(plateTextMap.get(order.getId()));
+ 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) {
+ long page, long size, boolean futureOnly, 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(), futureOnly, 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;
}
+ Map<String, String> reasonNameMap = loadReasonNameMap(orders);
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());
+ Map<Long, String> visitorDisplayMap = loadVisitorDisplayMapByOrderIds(orderIds);
+ Map<Long, String> plateTextMap = loadPlateTextMapByOrderIds(orderIds);
+ 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.setVisitorDisplayText(visitorDisplayMap.get(order.getId()));
+ vo.setPlateNoText(plateTextMap.get(order.getId()));
+ vo.setVisitReasonText(buildVisitReasonText(order, reasonNameMap));
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() {
@@ -418,15 +373,81 @@
.eq(AppointmentOrder::getStatus, AppointmentOrderStatus.APPROVED)
.orderByDesc(AppointmentOrder::getVisitStartDate)
.orderByDesc(AppointmentOrder::getId));
+ return buildVisitorCodeOrders(orders, true);
+ }
+
+ public MiniSharedAppointmentDetailVo detailSharedOrder(String uuid) {
+ AppointmentOrder order = loadApprovedOrderByUuid(uuid);
+ String deptName = loadDeptName(order.getVisitedDeptId());
+ MiniSharedAppointmentDetailVo vo = new MiniSharedAppointmentDetailVo();
+ vo.setOrderId(order.getId());
+ vo.setOrderUuid(order.getUuid());
+ vo.setVisitedUserDisplay(buildVisitedUserDisplay(order.getVisitedUserName(), deptName));
+ vo.setAccessAreaText(buildAccessAreaText(order.getPassAccessAreaNames()));
+ vo.setVisitTimeText(buildVisitTimeText(order));
+ return vo;
+ }
+
+ public MiniMyVisitorCodeOrderVo getSharedVisitorCodes(String uuid) {
+ AppointmentOrder order = loadApprovedOrderByUuid(uuid);
+ List<MiniMyVisitorCodeOrderVo> rows = buildVisitorCodeOrders(List.of(order), false);
+ if (rows.isEmpty()) {
+ MiniMyVisitorCodeOrderVo vo = new MiniMyVisitorCodeOrderVo();
+ vo.setOrderId(order.getId());
+ vo.setOrderUuid(order.getUuid());
+ vo.setVisitedUserDisplay(buildVisitedUserDisplay(order.getVisitedUserName(), loadDeptName(order.getVisitedDeptId())));
+ vo.setAccessAreaText(buildAccessAreaText(order.getPassAccessAreaNames()));
+ vo.setVisitTimeText(buildVisitTimeText(order));
+ vo.setQrCodes(List.of());
+ return vo;
+ }
+ return rows.get(0);
+ }
+
+ public MiniMyVisitorCodeOrderVo getSharedVisitorCodeByTicketUuid(String ticketUuid) {
+ QrcodeTicket ticket = loadTicketByUuid(ticketUuid);
+ AppointmentOrder order = loadApprovedOrderById(ticket.getOrderId());
+ String deptName = loadDeptName(order.getVisitedDeptId());
+
+ MiniMyVisitorCodeOrderVo vo = new MiniMyVisitorCodeOrderVo();
+ vo.setOrderId(order.getId());
+ vo.setOrderUuid(order.getUuid());
+ vo.setVisitedUserDisplay(buildVisitedUserDisplay(order.getVisitedUserName(), deptName));
+ vo.setAccessAreaText(buildAccessAreaText(order.getPassAccessAreaNames()));
+ vo.setVisitTimeText(buildVisitTimeText(order));
+ vo.setValidStartTime(ticket.getGenerateTime());
+ vo.setValidEndTime(ticket.getExpireTime());
+
+ if (!QrcodeTicketStatus.UNUSED.equals(ticket.getTicketStatus())) {
+ vo.setQrCodes(List.of());
+ return vo;
+ }
+
+ Map<Long, MpVisitor> visitorMap =
+ loadMpVisitorMap(
+ ticket.getMpVisitorId() == null
+ ? Set.of()
+ : Set.of(ticket.getMpVisitorId()));
+ List<AppointmentVisitor> orderVisitors =
+ loadOrderVisitorRows(List.of(order.getId())).getOrDefault(order.getId(), List.of());
+ vo.setQrCodes(List.of(toMyVisitorCodeTicketVo(ticket, orderVisitors, visitorMap)));
+ return vo;
+ }
+
+ private List<MiniMyVisitorCodeOrderVo> buildVisitorCodeOrders(
+ List<AppointmentOrder> orders, boolean futureOnly) {
if (orders.isEmpty()) {
return List.of();
}
- LocalDateTime now = LocalDateTime.now();
- List<AppointmentOrder> eligibleOrders =
- orders.stream()
- .filter(order -> resolveVisitStartAt(order).isAfter(now))
- .toList();
+ List<AppointmentOrder> eligibleOrders = orders;
+ if (futureOnly) {
+ LocalDateTime now = LocalDateTime.now();
+ eligibleOrders =
+ orders.stream()
+ .filter(order -> resolveVisitStartAt(order).isAfter(now))
+ .toList();
+ }
if (eligibleOrders.isEmpty()) {
return List.of();
}
@@ -479,31 +500,82 @@
return result;
}
+ private AppointmentOrder loadApprovedOrderByUuid(String uuid) {
+ String normalizedUuid = trimToNull(uuid);
+ if (!StringUtils.hasText(normalizedUuid)) {
+ throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "预约单不存在");
+ }
+ AppointmentOrder order =
+ appointmentOrderMapper.selectOne(
+ new LambdaQueryWrapper<AppointmentOrder>()
+ .eq(AppointmentOrder::getDelFlag, 0)
+ .eq(AppointmentOrder::getUuid, normalizedUuid)
+ .eq(AppointmentOrder::getStatus, AppointmentOrderStatus.APPROVED)
+ .last("limit 1"));
+ if (order == null) {
+ throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "预约单不存在");
+ }
+ return order;
+ }
+
+ private AppointmentOrder loadApprovedOrderById(Long orderId) {
+ if (orderId == null || orderId <= 0) {
+ throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "预约单不存在");
+ }
+ AppointmentOrder order =
+ appointmentOrderMapper.selectOne(
+ new LambdaQueryWrapper<AppointmentOrder>()
+ .eq(AppointmentOrder::getDelFlag, 0)
+ .eq(AppointmentOrder::getId, orderId)
+ .eq(AppointmentOrder::getStatus, AppointmentOrderStatus.APPROVED)
+ .last("limit 1"));
+ if (order == null) {
+ throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "预约单不存在");
+ }
+ return order;
+ }
+
+ private QrcodeTicket loadTicketByUuid(String ticketUuid) {
+ String normalizedTicketUuid = trimToNull(ticketUuid);
+ if (!StringUtils.hasText(normalizedTicketUuid)) {
+ throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "访客码不存在");
+ }
+ QrcodeTicket ticket =
+ qrcodeTicketMapper.selectOne(
+ new LambdaQueryWrapper<QrcodeTicket>()
+ .eq(QrcodeTicket::getDelFlag, 0)
+ .eq(QrcodeTicket::getUuid, normalizedTicketUuid)
+ .last("limit 1"));
+ if (ticket == null) {
+ throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "访客码不存在");
+ }
+ return ticket;
+ }
+
public MiniMyAppointmentDetailVo detailMyOrder(Long orderId, String uuid) {
if (orderId == null || orderId <= 0) {
throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "预约单不存在");
}
MpUser current = miniAuthApplicationService.currentMpUser();
- AppointmentOrder order = appointmentOrderMapper.selectById(orderId);
- if (order == null || (order.getDelFlag() != null && order.getDelFlag() == 1)) {
+ AppointmentOrder order = appointmentOrderMapper.selectMiniVisibleOrderById(orderId, current.getId());
+ if (order == null) {
throw new BizException(BizErrorCode.ORDER_NOT_FOUND, "预约单不存在");
}
UuidAssert.match(order, uuid);
- if (!Objects.equals(order.getSubmitterId(), current.getId())) {
- throw new BizException(BizErrorCode.AUTH_FORBIDDEN, "无权查看该预约详情");
- }
String deptName = loadDeptName(order.getVisitedDeptId());
String reasonName = loadReasonName(order.getVisitReasonCode());
+ String displayStatus = resolveDisplayStatus(order);
MiniMyAppointmentDetailVo vo = new MiniMyAppointmentDetailVo();
vo.setOrderId(order.getId());
vo.setOrderUuid(order.getUuid());
vo.setOrderNo(order.getOrderNo());
vo.setStatus(order.getStatus());
- vo.setDisplayStatus(resolveDisplayStatus(order));
+ vo.setDisplayStatus(displayStatus);
vo.setStatusText(resolveOrderStatusText(order));
vo.setCancelable(isCancelableStatus(order.getStatus()));
+ vo.setDeletable(isDeletableStatus(order.getStatus(), displayStatus));
vo.setVisitedUserId(order.getVisitedUserId());
vo.setVisitedUserName(order.getVisitedUserName());
vo.setVisitedDeptName(deptName);
@@ -511,9 +583,19 @@
vo.setAccessAreaText(buildAccessAreaText(order.getPassAccessAreaNames()));
vo.setVisitTypeText(buildVisitTypeText(order));
vo.setVisitReasonText(buildVisitReasonText(order, reasonName == null ? Map.of() : Map.of(trimToNull(order.getVisitReasonCode()), reasonName)));
+ vo.setVisitReasonCode(order.getVisitReasonCode());
+ vo.setVisitReasonOther(order.getVisitReasonOther());
vo.setVisitTimeText(buildVisitTimeText(order));
+ vo.setVisitTimeMode(order.getVisitTimeMode());
+ vo.setVisitTimeSlot(order.getVisitTimeSlot());
+ vo.setVisitStartDate(order.getVisitStartDate());
+ vo.setVisitEndDate(order.getVisitEndDate());
+ vo.setPersonEntry(order.getPersonEntryFlag() == null || Boolean.TRUE.equals(order.getPersonEntryFlag()));
+ vo.setVehicleEntry(Boolean.TRUE.equals(order.getVehicleEntryFlag()));
vo.setCreateTime(order.getCreateTime());
vo.setVisitors(loadOrderVisitors(order.getId()));
+ vo.setRebookVisitors(loadRebookVisitors(order.getId()));
+ vo.setRebookVehicles(loadRebookVehicles(order.getId()));
List<ApprovalFlowNodeVo> flowTree = approvalFlowViewApplicationService.treeByOrderId(order.getId());
vo.setFlowTree(flowTree == null ? List.of() : flowTree);
return vo;
@@ -538,14 +620,14 @@
if (!StringUtils.hasText(c)) {
throw new BizException(BizErrorCode.AUTH_INVALID_CREDENTIALS, "拜访事由不能为空");
}
+ String txt = trimToNull(other);
+ if (!StringUtils.hasText(txt)) {
+ throw new BizException(BizErrorCode.AUTH_INVALID_CREDENTIALS, "请输入事由说明");
+ }
+ if (txt.length() > 15) {
+ throw new BizException(BizErrorCode.AUTH_INVALID_CREDENTIALS, "事由说明不能超过15个字");
+ }
if (AppointmentBizConstants.VISIT_REASON_OTHER.equalsIgnoreCase(c)) {
- String txt = trimToNull(other);
- if (!StringUtils.hasText(txt)) {
- throw new BizException(BizErrorCode.AUTH_INVALID_CREDENTIALS, "选择其他时须填写自定义内容");
- }
- if (txt.length() > 255) {
- throw new BizException(BizErrorCode.AUTH_INVALID_CREDENTIALS, "自定义内容不能超过255字");
- }
return;
}
Long cnt =
@@ -790,6 +872,7 @@
vo.setVisitStartDate(row.getVisitStartDate());
vo.setVisitEndDate(row.getVisitEndDate());
vo.setVisitReasonCode(row.getVisitReasonCode());
+ vo.setVisitReasonOther(row.getVisitReasonOther());
vo.setCreateTime(row.getCreateTime());
return vo;
}
@@ -807,6 +890,25 @@
vo.setVisitReasonText(buildVisitReasonText(row, reasonNameMap));
vo.setAccessAreaText(buildAccessAreaText(row.getPassAccessAreaNames()));
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) {
@@ -852,6 +954,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);
@@ -862,6 +984,92 @@
return name;
}
return StringUtils.hasText(dept) ? dept : "-";
+ }
+
+ private Map<Long, String> loadVisitorDisplayMapByOrderIds(List<Long> orderIds) {
+ if (orderIds == null || orderIds.isEmpty()) {
+ return Map.of();
+ }
+ List<AppointmentVisitor> rows =
+ appointmentVisitorMapper.selectList(
+ new LambdaQueryWrapper<AppointmentVisitor>()
+ .eq(AppointmentVisitor::getDelFlag, 0)
+ .in(AppointmentVisitor::getOrderId, orderIds)
+ .orderByAsc(AppointmentVisitor::getId));
+ Set<Long> visitorIds =
+ rows.stream()
+ .map(AppointmentVisitor::getMpVisitorId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ Map<Long, String> companyMap = loadMpVisitorCompanyMap(visitorIds);
+ Map<Long, List<String>> grouped = new LinkedHashMap<>();
+ for (AppointmentVisitor row : rows) {
+ if (row.getOrderId() == null) {
+ continue;
+ }
+ String name = trimToNull(row.getName());
+ if (!StringUtils.hasText(name)) {
+ continue;
+ }
+ String company = companyMap.get(row.getMpVisitorId());
+ String display = StringUtils.hasText(company) ? name + "(" + company + ")" : name;
+ grouped.computeIfAbsent(row.getOrderId(), key -> new ArrayList<>()).add(display);
+ }
+ Map<Long, String> result = new LinkedHashMap<>();
+ for (Map.Entry<Long, List<String>> entry : grouped.entrySet()) {
+ String text = entry.getValue().stream().distinct().collect(Collectors.joining("、"));
+ if (StringUtils.hasText(text)) {
+ result.put(entry.getKey(), text);
+ }
+ }
+ return result;
+ }
+
+ private Map<Long, String> loadMpVisitorCompanyMap(Set<Long> visitorIds) {
+ if (visitorIds == null || visitorIds.isEmpty()) {
+ return Map.of();
+ }
+ List<MpVisitor> rows =
+ mpVisitorMapper.selectList(
+ new LambdaQueryWrapper<MpVisitor>()
+ .eq(MpVisitor::getDelFlag, 0)
+ .in(MpVisitor::getId, visitorIds));
+ Map<Long, String> result = new LinkedHashMap<>();
+ for (MpVisitor row : rows) {
+ result.put(row.getId(), trimToNull(row.getVisitorCompany()));
+ }
+ return result;
+ }
+
+ private Map<Long, String> loadPlateTextMapByOrderIds(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));
+ Map<Long, List<String>> grouped = new LinkedHashMap<>();
+ for (AppointmentVehicle row : rows) {
+ if (row.getOrderId() == null) {
+ continue;
+ }
+ String plateNo = trimToNull(row.getPlateNo());
+ if (!StringUtils.hasText(plateNo)) {
+ continue;
+ }
+ grouped.computeIfAbsent(row.getOrderId(), key -> new ArrayList<>()).add(plateNo);
+ }
+ Map<Long, String> result = new LinkedHashMap<>();
+ for (Map.Entry<Long, List<String>> entry : grouped.entrySet()) {
+ String text = entry.getValue().stream().distinct().collect(Collectors.joining("、"));
+ if (StringUtils.hasText(text)) {
+ result.put(entry.getKey(), text);
+ }
+ }
+ return result;
}
private String resolveOrderStatusText(AppointmentOrder row) {
@@ -895,12 +1103,19 @@
return DISPLAY_STATUS_INVALID;
}
+ private boolean isDeletableStatus(String status, String displayStatus) {
+ if (AppointmentOrderStatus.CANCELLED.equals(status)) {
+ return true;
+ }
+ return DISPLAY_STATUS_INVALID.equals(displayStatus);
+ }
+
private String buildVisitTimeText(AppointmentOrder row) {
if (AppointmentBizConstants.TIME_MODE_SINGLE.equals(row.getVisitTimeMode())) {
String slotLabel = switch (trimToNull(row.getVisitTimeSlot())) {
- case AppointmentBizConstants.TIME_SLOT_ALL_DAY -> "全天";
- case AppointmentBizConstants.TIME_SLOT_AM -> "上午";
- case AppointmentBizConstants.TIME_SLOT_PM -> "下午";
+ case AppointmentBizConstants.TIME_SLOT_ALL_DAY -> "00:00-23:59";
+ case AppointmentBizConstants.TIME_SLOT_AM -> "00:00-11:59";
+ case AppointmentBizConstants.TIME_SLOT_PM -> "12:00-23:59";
default -> "";
};
if (row.getVisitStartDate() == null) {
@@ -920,12 +1135,12 @@
}
private String buildVisitReasonText(AppointmentOrder row, Map<String, String> reasonNameMap) {
- if (AppointmentBizConstants.VISIT_REASON_OTHER.equalsIgnoreCase(trimToNull(row.getVisitReasonCode()))) {
- String other = trimToNull(row.getVisitReasonOther());
- return StringUtils.hasText(other) ? "其他-" + other : "其他";
+ String code = trimToNull(row.getVisitReasonCode());
+ if (AppointmentBizConstants.VISIT_REASON_OTHER.equalsIgnoreCase(code)) {
+ return "其他";
}
- String reasonName = reasonNameMap.get(trimToNull(row.getVisitReasonCode()));
- return StringUtils.hasText(reasonName) ? reasonName : trimToNull(row.getVisitReasonCode());
+ String reasonName = reasonNameMap.get(code);
+ return StringUtils.hasText(reasonName) ? reasonName : code;
}
private String buildAccessAreaText(String rawJson) {
@@ -947,16 +1162,16 @@
}
private LocalDateTime resolveVisitStartAt(AppointmentOrder row) {
- LocalDate date = row.getVisitStartDate() != null ? row.getVisitStartDate() : row.getVisitEndDate();
+ LocalDate date = row.getVisitEndDate() != null ? row.getVisitEndDate() : row.getVisitStartDate();
if (date == null) {
return LocalDateTime.MIN;
}
if (!AppointmentBizConstants.TIME_MODE_SINGLE.equals(row.getVisitTimeMode())) {
- return LocalDateTime.of(date, LocalTime.MIN);
+ return LocalDateTime.of(date, LocalTime.MAX);
}
return switch (trimToNull(row.getVisitTimeSlot())) {
- case AppointmentBizConstants.TIME_SLOT_PM -> LocalDateTime.of(date, LocalTime.of(12, 0));
- default -> LocalDateTime.of(date, LocalTime.MIN);
+ case AppointmentBizConstants.TIME_SLOT_AM -> LocalDateTime.of(date, LocalTime.of(12, 0));
+ default -> LocalDateTime.of(date, LocalTime.MAX);
};
}
@@ -994,7 +1209,7 @@
vo.setTicketId(ticket.getId());
vo.setTicketUuid(ticket.getUuid());
vo.setMpVisitorId(ticket.getMpVisitorId());
- vo.setPayload(ticket.getPayload());
+ vo.setPayload(integrationHikvisionService.encryptQrcodePayload(ticket.getPayload()));
vo.setGenerateTime(ticket.getGenerateTime());
vo.setExpireTime(ticket.getExpireTime());
vo.setVisitorName(resolveVisitorName(ticket.getMpVisitorId(), orderVisitors, visitorMap));
@@ -1076,6 +1291,73 @@
return result;
}
+ private List<MiniMyAppointmentDetailVo.RebookVisitorItem> loadRebookVisitors(Long orderId) {
+ List<AppointmentVisitor> rows =
+ appointmentVisitorMapper.selectList(
+ new LambdaQueryWrapper<AppointmentVisitor>()
+ .eq(AppointmentVisitor::getDelFlag, 0)
+ .eq(AppointmentVisitor::getOrderId, orderId)
+ .orderByAsc(AppointmentVisitor::getId));
+ if (rows.isEmpty()) {
+ return List.of();
+ }
+ List<Long> visitorIds =
+ rows.stream()
+ .map(AppointmentVisitor::getMpVisitorId)
+ .filter(Objects::nonNull)
+ .toList();
+ Map<Long, MpVisitor> visitorMap = loadVisitorMap(visitorIds);
+ List<MiniMyAppointmentDetailVo.RebookVisitorItem> result = new ArrayList<>();
+ for (AppointmentVisitor row : rows) {
+ MpVisitor visitor = visitorMap.get(row.getMpVisitorId());
+ MiniMyAppointmentDetailVo.RebookVisitorItem item = new MiniMyAppointmentDetailVo.RebookVisitorItem();
+ item.setVisitorId(row.getMpVisitorId());
+ item.setVisitorUuid(visitor == null ? null : visitor.getUuid());
+ item.setName(firstNonBlank(row.getName(), visitor == null ? null : visitor.getVisitorName(), "-"));
+ item.setGender(visitor == null ? null : visitor.getGender());
+ item.setCompanyName(visitor == null ? null : trimToNull(visitor.getVisitorCompany()));
+ item.setMobileMasked(
+ MobileMaskUtil.mask(
+ firstNonBlank(
+ row.getMobile(),
+ visitor == null ? null : visitor.getVisitorMobile(),
+ null)));
+ String idCardPlain =
+ StringUtils.hasText(row.getIdCardCipher())
+ ? SensitiveDataUtil.decryptIdCard(row.getIdCardCipher())
+ : (visitor != null && StringUtils.hasText(visitor.getIdCardCipher())
+ ? SensitiveDataUtil.decryptIdCard(visitor.getIdCardCipher())
+ : null);
+ item.setIdCardMasked(
+ StringUtils.hasText(idCardPlain)
+ ? SensitiveDataUtil.maskIdCard(idCardPlain)
+ : null);
+ result.add(item);
+ }
+ return result;
+ }
+
+ private List<MiniMyAppointmentDetailVo.RebookVehicleItem> loadRebookVehicles(Long orderId) {
+ List<AppointmentVehicle> rows =
+ appointmentVehicleMapper.selectList(
+ new LambdaQueryWrapper<AppointmentVehicle>()
+ .eq(AppointmentVehicle::getDelFlag, 0)
+ .eq(AppointmentVehicle::getOrderId, orderId)
+ .orderByAsc(AppointmentVehicle::getId));
+ if (rows.isEmpty()) {
+ return List.of();
+ }
+ List<MiniMyAppointmentDetailVo.RebookVehicleItem> result = new ArrayList<>();
+ for (AppointmentVehicle row : rows) {
+ MiniMyAppointmentDetailVo.RebookVehicleItem item = new MiniMyAppointmentDetailVo.RebookVehicleItem();
+ item.setPlateNo(trimToNull(row.getPlateNo()));
+ item.setDriverVisitorId(row.getDriverVisitorId());
+ item.setDriverName(trimToNull(row.getDriverName()));
+ result.add(item);
+ }
+ return result;
+ }
+
private Map<Long, MpVisitor> loadVisitorMap(List<Long> visitorIds) {
if (visitorIds.isEmpty()) {
return Map.of();
--
Gitblit v1.7.1