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/IntegrationWechatService.java | 325 ++++++++++++++++++++++++++++++++++++------------------
1 files changed, 217 insertions(+), 108 deletions(-)
diff --git a/backend/src/main/java/com/sinata/appointment/service/IntegrationWechatService.java b/backend/src/main/java/com/sinata/appointment/service/IntegrationWechatService.java
index 4b111c0..940cdec 100644
--- a/backend/src/main/java/com/sinata/appointment/service/IntegrationWechatService.java
+++ b/backend/src/main/java/com/sinata/appointment/service/IntegrationWechatService.java
@@ -6,11 +6,13 @@
import com.sinata.appointment.constants.ApprovalNodeCode;
import com.sinata.appointment.constants.ApprovalTaskStatus;
import com.sinata.appointment.entity.ApprovalTask;
+import com.sinata.appointment.entity.AppointmentVisitor;
import com.sinata.appointment.entity.AppointmentOrder;
import com.sinata.appointment.entity.BizVisitReason;
import com.sinata.appointment.entity.MpUser;
import com.sinata.appointment.integration.WechatMiniGateway;
import com.sinata.appointment.mapper.ApprovalTaskMapper;
+import com.sinata.appointment.mapper.AppointmentVisitorMapper;
import com.sinata.appointment.mapper.BizVisitReasonMapper;
import com.sinata.appointment.mapper.MpUserMapper;
import java.time.LocalDate;
@@ -19,6 +21,7 @@
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@@ -31,127 +34,191 @@
public class IntegrationWechatService {
private static final String APPROVAL_RESULT_TEMPLATE_ID =
- "4FQovCBNFM7rth42AWHTusHajO788eT9VpplSN4ZG2s";
+ "rIJpfN51_q818RTpJAqTe5ssTwWCHnxDM5rpq64uuKM";
private static final String NOTICE_RESULT_TEMPLATE_ID =
- "GC1S3T2qHCbz8ow130u7elRczuqW6Z8q54mKRCYE-xo";
+ "Wip0ODJgybZpeFpcvev_0GK1wQXEqZw-LHOjS-UyDLw";
private static final String APPROVAL_RESULT_PAGE = "pages/record/index";
private static final String APPROVAL_TODO_TEMPLATE_ID =
- "BX49OBHvRcoYiCw0ZLqx04BiWQ9KaEQwuVth_Lh_M2A";
+ "QlNwG99WXWztRDgtlLcE0fHxfY2VwaX8PRMrwGpEync";
private static final String APPROVAL_TODO_PAGE = "pages/reviewList/index";
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final DateTimeFormatter TEMPLATE_TIME_FORMATTER =
+ DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
private final WechatMiniGateway wechatMiniGateway;
private final MpUserMapper mpUserMapper;
private final ApprovalTaskMapper approvalTaskMapper;
+ private final AppointmentVisitorMapper appointmentVisitorMapper;
private final BizVisitReasonMapper bizVisitReasonMapper;
+ @Async
public void notifyApprovalFinalResult(AppointmentOrder order, boolean approved) {
- if (order == null || order.getSubmitterId() == null) {
- return;
- }
- MpUser submitter =
- mpUserMapper.selectOne(
- new LambdaQueryWrapper<MpUser>()
- .eq(MpUser::getDelFlag, 0)
- .eq(MpUser::getId, order.getSubmitterId())
- .last("limit 1"));
- if (submitter == null || !StringUtils.hasText(submitter.getOpenId())) {
- log.info(
- "Skip mini subscribe notify, submitter not found or openId empty. submitterId={} orderNo={}",
- order.getSubmitterId(),
- order.getOrderNo());
- return;
- }
- Map<String, String> templateData = new LinkedHashMap<>();
- templateData.put("thing1", approved ? "审核通过" : "审核未通过");
- templateData.put("thing2", abbreviate(resolveSubmitterName(submitter), 20));
- templateData.put("time3", buildVisitTimeText(order));
- templateData.put("thing4", abbreviate(buildVisitReasonText(order), 20));
- wechatMiniGateway.sendSubscribeMessage(
- submitter.getOpenId(), APPROVAL_RESULT_TEMPLATE_ID, APPROVAL_RESULT_PAGE, templateData);
- log.info(
- "Mini subscribe notify sent submitterId={} orderNo={} result={}",
- order.getSubmitterId(),
- order.getOrderNo(),
- approved ? AppointmentOrderStatus.APPROVED : AppointmentOrderStatus.REJECTED);
- }
-
- public void notifyApprovalNoticeUsers(
- AppointmentOrder order, boolean approved, java.util.Collection<MpUser> noticeUsers, int visitorCount) {
- if (order == null || noticeUsers == null || noticeUsers.isEmpty()) {
- return;
- }
- Map<String, String> templateData = new LinkedHashMap<>();
- templateData.put("thing6", buildVisitorCountText(visitorCount));
- templateData.put("time18", buildVisitTimeText(order));
- templateData.put("thing20", abbreviate(buildNoticeBusinessTypeText(order, approved), 20));
- for (MpUser noticeUser : noticeUsers) {
- if (noticeUser == null || !StringUtils.hasText(noticeUser.getOpenId())) {
- continue;
+ try {
+ if (order == null || order.getSubmitterId() == null) {
+ log.info("Mini subscribe final result skipped, order or submitter empty. orderId={}",
+ order == null ? null : order.getId());
+ return;
}
- wechatMiniGateway.sendSubscribeMessage(
- noticeUser.getOpenId(), NOTICE_RESULT_TEMPLATE_ID, APPROVAL_RESULT_PAGE, templateData);
- log.info(
- "Mini subscribe notice sent noticeUserId={} orderNo={} result={}",
- noticeUser.getId(),
- order.getOrderNo(),
- approved ? AppointmentOrderStatus.APPROVED : AppointmentOrderStatus.REJECTED);
- }
- }
-
- public void notifyCurrentApprovers(AppointmentOrder order, Long instanceId) {
- if (order == null || instanceId == null) {
- return;
- }
- java.util.List<ApprovalTask> pendingTasks =
- approvalTaskMapper.selectList(
- new LambdaQueryWrapper<ApprovalTask>()
- .eq(ApprovalTask::getDelFlag, 0)
- .eq(ApprovalTask::getInstanceId, instanceId)
- .eq(ApprovalTask::getTaskStatus, ApprovalTaskStatus.PENDING)
- .orderByAsc(ApprovalTask::getId));
- if (pendingTasks.isEmpty()) {
- return;
- }
- java.util.LinkedHashMap<Long, java.util.LinkedHashSet<String>> userNodeNames = new java.util.LinkedHashMap<>();
- for (ApprovalTask task : pendingTasks) {
- if (task.getAssigneeUserId() == null) {
- continue;
- }
- userNodeNames.computeIfAbsent(task.getAssigneeUserId(), key -> new java.util.LinkedHashSet<>());
- userNodeNames.get(task.getAssigneeUserId()).add(resolveNodeName(task.getNodeCode()));
- }
- if (userNodeNames.isEmpty()) {
- return;
- }
- java.util.List<MpUser> users =
- mpUserMapper.selectList(
- new LambdaQueryWrapper<MpUser>()
- .eq(MpUser::getDelFlag, 0)
- .in(MpUser::getId, userNodeNames.keySet()));
- java.util.Map<Long, MpUser> userMap = new java.util.LinkedHashMap<>();
- for (MpUser user : users) {
- userMap.putIfAbsent(user.getId(), user);
- }
- for (java.util.Map.Entry<Long, java.util.LinkedHashSet<String>> entry : userNodeNames.entrySet()) {
- MpUser user = userMap.get(entry.getKey());
- if (user == null || !StringUtils.hasText(user.getOpenId())) {
- continue;
+ MpUser submitter =
+ mpUserMapper.selectOne(
+ new LambdaQueryWrapper<MpUser>()
+ .eq(MpUser::getDelFlag, 0)
+ .eq(MpUser::getId, order.getSubmitterId())
+ .last("limit 1"));
+ if (submitter == null || !StringUtils.hasText(submitter.getOpenId())) {
+ log.info(
+ "Mini subscribe final result skipped, submitter not found or openId empty. submitterId={} orderNo={}",
+ order.getSubmitterId(),
+ order.getOrderNo());
+ return;
}
Map<String, String> templateData = new LinkedHashMap<>();
- templateData.put("thing1", abbreviate(buildTodoTaskName(order), 20));
- templateData.put("thing3", abbreviate(String.join("、", entry.getValue()), 20));
+ templateData.put("phrase4", approved ? "通过" : "未通过");
+ templateData.put("time2", buildVisitTemplateTimeValue(order));
+ templateData.put("thing5", approved ? "预约审核通过" : "预约审核未通过");
wechatMiniGateway.sendSubscribeMessage(
- user.getOpenId(), APPROVAL_TODO_TEMPLATE_ID, APPROVAL_TODO_PAGE, templateData);
+ submitter.getOpenId(), APPROVAL_RESULT_TEMPLATE_ID, APPROVAL_RESULT_PAGE, templateData);
log.info(
- "Mini subscribe todo notify sent approverId={} orderNo={} stages={}",
- user.getId(),
+ "Mini subscribe final result success. submitterId={} orderNo={} result={}",
+ order.getSubmitterId(),
order.getOrderNo(),
- entry.getValue());
+ approved ? AppointmentOrderStatus.APPROVED : AppointmentOrderStatus.REJECTED);
+ } catch (Exception ex) {
+ log.warn("Mini subscribe final result failed. orderId={} orderNo={}",
+ order == null ? null : order.getId(), order == null ? null : order.getOrderNo(), ex);
+ }
+ }
+
+ @Async
+ public void notifyApprovalNoticeUsers(
+ AppointmentOrder order, boolean approved, java.util.Collection<MpUser> noticeUsers, int visitorCount) {
+ try {
+ if (order == null || noticeUsers == null || noticeUsers.isEmpty()) {
+ log.info("Mini subscribe notice skipped, order or notice users empty. orderId={}",
+ order == null ? null : order.getId());
+ return;
+ }
+ Map<String, String> templateData = new LinkedHashMap<>();
+ MpUser submitter = loadSubmitter(order);
+ templateData.put("name1", abbreviate(resolveSubmitterName(submitter), 10));
+ templateData.put("number36", buildVisitorCountNumber(visitorCount));
+ templateData.put("date3", buildVisitTemplateTimeValue(order));
+ int successCount = 0;
+ int skippedCount = 0;
+ int failedCount = 0;
+ for (MpUser noticeUser : noticeUsers) {
+ if (noticeUser == null || !StringUtils.hasText(noticeUser.getOpenId())) {
+ skippedCount++;
+ continue;
+ }
+ try {
+ wechatMiniGateway.sendSubscribeMessage(
+ noticeUser.getOpenId(), NOTICE_RESULT_TEMPLATE_ID, APPROVAL_RESULT_PAGE, templateData);
+ successCount++;
+ log.info(
+ "Mini subscribe notice success. noticeUserId={} orderNo={} result={}",
+ noticeUser.getId(),
+ order.getOrderNo(),
+ approved ? AppointmentOrderStatus.APPROVED : AppointmentOrderStatus.REJECTED);
+ } catch (Exception ex) {
+ failedCount++;
+ log.warn("Mini subscribe notice failed. noticeUserId={} orderId={} orderNo={}",
+ noticeUser.getId(), order.getId(), order.getOrderNo(), ex);
+ }
+ }
+ log.info("Mini subscribe notice completed. orderId={} orderNo={} success={} skipped={} failed={}",
+ order.getId(), order.getOrderNo(), successCount, skippedCount, failedCount);
+ } catch (Exception ex) {
+ log.warn("Mini subscribe notice batch failed. orderId={} orderNo={}",
+ order == null ? null : order.getId(), order == null ? null : order.getOrderNo(), ex);
+ }
+ }
+
+ @Async
+ public void notifyCurrentApprovers(AppointmentOrder order, Long instanceId) {
+ try {
+ if (order == null || instanceId == null) {
+ log.info("Mini subscribe todo skipped, order or instance empty. orderId={} instanceId={}",
+ order == null ? null : order.getId(), instanceId);
+ return;
+ }
+ java.util.List<ApprovalTask> pendingTasks =
+ approvalTaskMapper.selectList(
+ new LambdaQueryWrapper<ApprovalTask>()
+ .eq(ApprovalTask::getDelFlag, 0)
+ .eq(ApprovalTask::getInstanceId, instanceId)
+ .eq(ApprovalTask::getTaskStatus, ApprovalTaskStatus.PENDING)
+ .orderByAsc(ApprovalTask::getId));
+ if (pendingTasks.isEmpty()) {
+ log.info("Mini subscribe todo skipped, no pending tasks. orderId={} instanceId={}",
+ order.getId(), instanceId);
+ return;
+ }
+ java.util.LinkedHashMap<Long, java.util.LinkedHashSet<String>> userNodeNames =
+ new java.util.LinkedHashMap<>();
+ for (ApprovalTask task : pendingTasks) {
+ if (task.getAssigneeUserId() == null) {
+ continue;
+ }
+ userNodeNames.computeIfAbsent(task.getAssigneeUserId(), key -> new java.util.LinkedHashSet<>());
+ userNodeNames.get(task.getAssigneeUserId()).add(resolveNodeName(task.getNodeCode()));
+ }
+ if (userNodeNames.isEmpty()) {
+ log.info("Mini subscribe todo skipped, no assignee users. orderId={} instanceId={}",
+ order.getId(), instanceId);
+ return;
+ }
+ java.util.List<MpUser> users =
+ mpUserMapper.selectList(
+ new LambdaQueryWrapper<MpUser>()
+ .eq(MpUser::getDelFlag, 0)
+ .in(MpUser::getId, userNodeNames.keySet()));
+ java.util.Map<Long, MpUser> userMap = new java.util.LinkedHashMap<>();
+ for (MpUser user : users) {
+ userMap.putIfAbsent(user.getId(), user);
+ }
+ int successCount = 0;
+ int skippedCount = 0;
+ int failedCount = 0;
+ for (java.util.Map.Entry<Long, java.util.LinkedHashSet<String>> entry : userNodeNames.entrySet()) {
+ MpUser user = userMap.get(entry.getKey());
+ if (user == null || !StringUtils.hasText(user.getOpenId())) {
+ skippedCount++;
+ continue;
+ }
+ Map<String, String> templateData = new LinkedHashMap<>();
+ MpUser submitter = loadSubmitter(order);
+ templateData.put("name1", abbreviate(resolveSubmitterName(submitter), 10));
+ templateData.put("number15", buildVisitorCountNumber(countVisitors(order)));
+ templateData.put("time16", buildVisitTemplateTimeValue(order));
+ templateData.put("thing5", abbreviate(buildVisitReasonText(order), 20));
+ try {
+ wechatMiniGateway.sendSubscribeMessage(
+ user.getOpenId(), APPROVAL_TODO_TEMPLATE_ID, APPROVAL_TODO_PAGE, templateData);
+ successCount++;
+ log.info(
+ "Mini subscribe todo success. approverId={} orderNo={} stages={}",
+ user.getId(),
+ order.getOrderNo(),
+ entry.getValue());
+ } catch (Exception ex) {
+ failedCount++;
+ log.warn("Mini subscribe todo failed. approverId={} orderId={} orderNo={} stages={}",
+ user.getId(), order.getId(), order.getOrderNo(), entry.getValue(), ex);
+ }
+ }
+ log.info("Mini subscribe todo completed. orderId={} orderNo={} success={} skipped={} failed={}",
+ order.getId(), order.getOrderNo(), successCount, skippedCount, failedCount);
+ } catch (Exception ex) {
+ log.warn("Mini subscribe todo batch failed. orderId={} instanceId={}",
+ order == null ? null : order.getId(), instanceId, ex);
}
}
private String resolveSubmitterName(MpUser submitter) {
+ if (submitter == null) {
+ return "预约人";
+ }
if (StringUtils.hasText(submitter.getNickName())) {
return submitter.getNickName().trim();
}
@@ -159,6 +226,17 @@
return submitter.getMobile().trim();
}
return "预约人";
+ }
+
+ private MpUser loadSubmitter(AppointmentOrder order) {
+ if (order == null || order.getSubmitterId() == null) {
+ return null;
+ }
+ return mpUserMapper.selectOne(
+ new LambdaQueryWrapper<MpUser>()
+ .eq(MpUser::getDelFlag, 0)
+ .eq(MpUser::getId, order.getSubmitterId())
+ .last("limit 1"));
}
private String buildVisitTimeText(AppointmentOrder order) {
@@ -179,14 +257,32 @@
};
}
+ private String buildVisitTemplateTimeValue(AppointmentOrder order) {
+ LocalDate start = order.getVisitStartDate();
+ LocalDate end = order.getVisitEndDate();
+ if (start == null && end == null) {
+ return "2099-12-31 00:00";
+ }
+ if (start == null) {
+ start = end;
+ }
+ if (end == null) {
+ end = start;
+ }
+ return switch (safeTrim(order.getVisitTimeMode())) {
+ case "MULTI" -> start.atTime(0, 0).format(TEMPLATE_TIME_FORMATTER);
+ default -> start.atTime(resolveTemplateHour(order.getVisitTimeSlot()), 0)
+ .format(TEMPLATE_TIME_FORMATTER);
+ };
+ }
+
private String buildVisitReasonText(AppointmentOrder order) {
String reasonCode = safeTrim(order.getVisitReasonCode());
if (!StringUtils.hasText(reasonCode)) {
return "拜访";
}
if (AppointmentBizConstants.VISIT_REASON_OTHER.equalsIgnoreCase(reasonCode)) {
- String other = safeTrim(order.getVisitReasonOther());
- return StringUtils.hasText(other) ? other : "其他";
+ return "其他";
}
BizVisitReason reason =
bizVisitReasonMapper.selectOne(
@@ -200,16 +296,20 @@
return reasonCode;
}
- private String buildVisitorCountText(int visitorCount) {
- return Math.max(visitorCount, 0) + "人";
+ private String buildVisitorCountNumber(int visitorCount) {
+ return String.valueOf(Math.max(visitorCount, 0));
}
- private String buildNoticeBusinessTypeText(AppointmentOrder order, boolean approved) {
- String reason = buildVisitReasonText(order);
- if (!StringUtils.hasText(reason)) {
- return approved ? "预约通过" : "预约驳回";
+ private int countVisitors(AppointmentOrder order) {
+ if (order == null || order.getId() == null) {
+ return 0;
}
- return reason;
+ Long count =
+ appointmentVisitorMapper.selectCount(
+ new LambdaQueryWrapper<AppointmentVisitor>()
+ .eq(AppointmentVisitor::getDelFlag, 0)
+ .eq(AppointmentVisitor::getOrderId, order.getId()));
+ return count == null ? 0 : count.intValue();
}
private String buildTodoTaskName(AppointmentOrder order) {
@@ -239,6 +339,15 @@
};
}
+ private int resolveTemplateHour(String slot) {
+ return switch (safeTrim(slot)) {
+ case "AM" -> 9;
+ case "PM" -> 14;
+ case "ALL_DAY" -> 9;
+ default -> 9;
+ };
+ }
+
private String formatDate(LocalDate date) {
return date.format(DATE_FORMATTER);
}
--
Gitblit v1.7.1