统一系统时间输出并优化任务列表查询

This commit is contained in:
andy
2026-07-08 15:15:42 +08:00
parent 936a5921b0
commit 8a196f14ed
20 changed files with 308 additions and 79 deletions

View File

@@ -0,0 +1,24 @@
package cn.nianxx.thhotel.platform.common.time;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
/**
* UTC 时间格式工具。数据库中的业务时间点统一按 UTC LocalDateTime 保存API 出口统一补 UTC offset。
*/
public final class UtcTimeFormatter {
private UtcTimeFormatter() {
}
/**
* 将数据库 UTC LocalDateTime 转为带 UTC offset 的结构化时间。
*/
public static OffsetDateTime toUtcOffsetDateTime(LocalDateTime value) {
if (value == null) {
return null;
}
return value.atOffset(ZoneOffset.UTC);
}
}

View File

@@ -28,6 +28,7 @@ import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.HexFormat;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@@ -70,6 +71,25 @@ public class MybatisSourceMessageInboxRepository implements SourceMessageInboxRe
return Optional.ofNullable(inboxMapper.selectById(id)).map(this::toSnapshot);
}
/**
* 批量读取 Inbox 安全快照,只读取 Inbox 索引表字段,不访问正文、媒体或 payload 表。
*/
@Override
public List<SourceMessageInboxSnapshot> findByIds(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
return List.of();
}
List<Long> safeIds = ids.stream().filter(Objects::nonNull).distinct().toList();
if (safeIds.isEmpty()) {
return List.of();
}
return inboxMapper.selectList(Wrappers.<SourceMessageInboxEntity>lambdaQuery()
.in(SourceMessageInboxEntity::getId, safeIds))
.stream()
.map(this::toSnapshot)
.toList();
}
/**
* 根据 SourceMessage 幂等键读取已有记录,用于重复投递判断。
*/

View File

@@ -20,6 +20,11 @@ public interface SourceMessageInboxRepository {
*/
Optional<SourceMessageInboxSnapshot> findById(Long id);
/**
* 按内部 SourceMessage ID 批量查询 Inbox 安全快照,供列表类接口预取摘要。
*/
List<SourceMessageInboxSnapshot> findByIds(List<Long> ids);
/**
* 按酒店、来源、渠道、外部邮件 ID 查询幂等记录。
*/

View File

@@ -35,4 +35,12 @@ public interface SourceMessageQueryService {
* @return 存在时返回安全摘要,不存在时为空
*/
Optional<SourceMessageSummaryResponse> getSummary(Long inboxId);
/**
* 按内部 SourceMessage ID 批量读取安全摘要,供业务列表避免逐条查询。
*
* @param inboxIds 内部 SourceMessage Inbox ID 列表
* @return 匹配到的安全摘要列表不返回正文、HTML、附件 URL 或 payload
*/
List<SourceMessageSummaryResponse> getSummariesByIds(List<Long> inboxIds);
}

View File

@@ -1,14 +1,12 @@
package cn.nianxx.thhotel.platform.message.service.impl;
import cn.nianxx.thhotel.platform.common.time.UtcTimeFormatter;
import cn.nianxx.thhotel.platform.message.common.dto.SourceMessageInboxSnapshot;
import cn.nianxx.thhotel.platform.message.common.dto.SourceMessageSummaryResponse;
import cn.nianxx.thhotel.platform.message.common.request.SourceMessageQueryRequest;
import cn.nianxx.thhotel.platform.message.common.result.SourceMessagePageResult;
import cn.nianxx.thhotel.platform.message.repository.SourceMessageInboxRepository;
import cn.nianxx.thhotel.platform.message.service.SourceMessageQueryService;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Service;
@@ -61,6 +59,19 @@ public class SourceMessageQueryServiceImpl implements SourceMessageQueryService
return inboxRepository.findById(inboxId).map(this::toSummary);
}
/**
* 批量读取 SourceMessage 安全摘要,用于业务列表预取主题等摘要字段,避免逐条查询。
*/
@Override
public List<SourceMessageSummaryResponse> getSummariesByIds(List<Long> inboxIds) {
if (inboxIds == null || inboxIds.isEmpty()) {
return List.of();
}
return inboxRepository.findByIds(inboxIds).stream()
.map(this::toSummary)
.toList();
}
/**
* 规范化页码,缺失或非法页码统一回到第一页。
*/
@@ -94,21 +105,11 @@ public class SourceMessageQueryServiceImpl implements SourceMessageQueryService
snapshot.externalConversationId(),
snapshot.captureStatus(),
snapshot.duplicatePayloadChanged(),
toOffsetDateTime(snapshot.receivedAt()),
toOffsetDateTime(snapshot.sourceSentAt()),
UtcTimeFormatter.toUtcOffsetDateTime(snapshot.receivedAt()),
UtcTimeFormatter.toUtcOffsetDateTime(snapshot.sourceSentAt()),
snapshot.senderSummary(),
snapshot.subject(),
snapshot.safeSnippet()
);
}
/**
* 将数据库 UTC 时间转换为带 UTC offset 的 API 时间字段。
*/
private OffsetDateTime toOffsetDateTime(LocalDateTime value) {
if (value == null) {
return null;
}
return value.atOffset(ZoneOffset.UTC);
}
}