package jnpf.message.service; import jnpf.base.UserInfo; import jnpf.exception.DataException; import jnpf.message.entity.MessageReceiveEntity; import jnpf.message.entity.MessageTemplateConfigEntity; import jnpf.message.mapper.DmsUpgradeMessageMapper; import jnpf.message.model.DmsUpgradeMessage; import jnpf.message.util.PushMessageUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.web.util.HtmlUtils; import java.util.*; /** DMS专属可靠站内信分支;不改变其他消息的发送行为。 */ @Slf4j @Service @RequiredArgsConstructor public class DmsUpgradeMessageService { private final DmsUpgradeMessageMapper mapper; @Transactional(rollbackFor = Exception.class) public boolean send(DmsUpgradeMessage request) { if (request == null || blank(request.getTenantId()) || blank(request.getTaskId()) || request.getToUserIds() == null || request.getToUserIds().isEmpty() || request.getToUserIds().stream().anyMatch(DmsUpgradeMessageService::blank)) throw new DataException("升版通知缺少事件或接收人"); List templates = mapper.templates(request.getTenantId()); if (templates.size() != 1) throw new DataException("请配置唯一且启用的站内信模板 dmsTemplateUpgrade"); MessageTemplateConfigEntity template = templates.get(0); if (blank(template.getTitle()) || blank(template.getContent())) throw new DataException("升版消息模板标题或正文为空"); String title = render(template.getTitle(), request.getParameters(), false); String content = render(template.getContent(), request.getParameters(), true); Map inserted = new LinkedHashMap<>(); for (String user : new LinkedHashSet<>(request.getToUserIds())) { if (mapper.claimDelivery(request.getTenantId(), request.getTaskId(), user) == 0) continue; MessageReceiveEntity message = new MessageReceiveEntity(); message.setId(UUID.randomUUID().toString().replace("-", "")); message.setUserId(user); message.setTitle(title); message.setBodyText(content); message.setType(3); message.setIsRead(0); message.setCreatorUserId(request.getActorId()); message.setCreatorTime(new Date()); if (mapper.insertMessage(message, request.getTenantId()) != 1) throw new DataException("站内信保存失败"); inserted.put(user, message); } UserInfo actor = new UserInfo(); actor.setTenantId(request.getTenantId()); actor.setUserId(request.getActorId()); // 事务提交即为可靠送达;WebSocket仅刷新在线界面,不把离线或推送失败误判为丢消息。 if (!inserted.isEmpty()) TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { try { PushMessageUtil.pushMessage(inserted, actor, 3); } catch (RuntimeException error) { log.warn("升版站内信已保存,在线推送刷新失败", error); } } }); return true; } static String render(String template, Map values, boolean html) { java.util.regex.Matcher matcher = java.util.regex.Pattern.compile("\\{@([A-Za-z][A-Za-z0-9]*)}").matcher(template); StringBuffer result = new StringBuffer(); while (matcher.find()) { String value = values == null ? null : values.get(matcher.group(1)); if (value == null) throw new DataException("升版消息模板包含未知参数:" + matcher.group(1)); matcher.appendReplacement(result, java.util.regex.Matcher.quoteReplacement(html ? HtmlUtils.htmlEscape(value) : value)); } matcher.appendTail(result); return result.toString(); } private static boolean blank(String value) { return value == null || value.isBlank(); } }