fix(archive&generation): 修复时区和员工ID解析问题

1. 统一将时间计算改为使用上海时区,避免UTC零点导致中国时区上午消息被遗漏
2. 新增用户ID数组解析逻辑,支持处理格式为JSON数组的员工ID字段
3. 过滤外部用户ID,避免将外部账号关联到客户联系人中
This commit is contained in:
jqb 2026-07-23 14:57:48 +08:00
parent 26fadbe307
commit 8975e69aab
2 changed files with 44 additions and 9 deletions

View File

@ -164,8 +164,13 @@ public class ArchiveContactService {
// 更新关联员工列表 // 更新关联员工列表
String oppositeStaff = "INTERNAL".equals(message.getFromRole()) ? fromUser : message.getToUser(); String oppositeStaff = "INTERNAL".equals(message.getFromRole()) ? fromUser : message.getToUser();
if (oppositeStaff != null && !oppositeStaff.isEmpty() && !isExternalUserId(oppositeStaff)) { if (oppositeStaff != null && !oppositeStaff.isEmpty()) {
updateCustomerStaffIds(existing, oppositeStaff); // to_user 可能存的是 JSON 数组(如 ["LiRong"]),需解析后逐个提取真实员工ID
for (String staffId : parsePossibleUserIds(oppositeStaff)) {
if (!isExternalUserId(staffId)) {
updateCustomerStaffIds(existing, staffId);
}
}
} }
customerMapper.updateById(existing); customerMapper.updateById(existing);
@ -328,6 +333,29 @@ public class ArchiveContactService {
return userId != null && (userId.startsWith("wm") || userId.startsWith("wo")); return userId != null && (userId.startsWith("wm") || userId.startsWith("wo"));
} }
/**
* 解析可能为 JSON 数组的用户ID字段(如 ["DengHan"]),返回逐个ID列表
*/
private List<String> parsePossibleUserIds(String fieldValue) {
if (fieldValue.startsWith("[") && fieldValue.endsWith("]")) {
try {
List<String> ids = JsonUtils.fromJsonList(fieldValue, String.class);
if (ids != null) {
return ids.stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
}
} catch (Exception e) {
log.debug("解析userId JSON数组失败: {}", fieldValue);
}
// 回退:去掉括号引号后按单值处理
return Collections.singletonList(fieldValue.replaceAll("[\\[\\]\"]", "").trim());
}
return Collections.singletonList(fieldValue);
}
/** /**
* 全量扫描历史消息,补全 staff/customer 记录 * 全量扫描历史消息,补全 staff/customer 记录
*/ */
@ -539,14 +567,19 @@ public class ArchiveContactService {
try { try {
List<String> parsed = JsonUtils.fromJsonList(rawId, String.class); List<String> parsed = JsonUtils.fromJsonList(rawId, String.class);
if (parsed != null) { if (parsed != null) {
staffIdSet.addAll(parsed.stream().filter(s -> s != null && !s.isEmpty()).collect(Collectors.toList())); staffIdSet.addAll(parsed.stream()
.filter(s -> s != null && !s.isEmpty() && !isExternalUserId(s))
.collect(Collectors.toList()));
continue; continue;
} }
} catch (Exception e) { } catch (Exception e) {
log.debug("解析员工ID JSON 数组失败: {}", rawId); log.debug("解析员工ID JSON 数组失败: {}", rawId);
} }
staffIdSet.add(rawId.replaceAll("[\\[\\]\"]", "").trim()); String fallback = rawId.replaceAll("[\\[\\]\"]", "").trim();
} else { if (!fallback.isEmpty() && !isExternalUserId(fallback)) {
staffIdSet.add(fallback);
}
} else if (!isExternalUserId(rawId)) {
staffIdSet.add(rawId); staffIdSet.add(rawId);
} }
} }

View File

@ -38,6 +38,8 @@ import java.util.stream.Collectors;
@RequestMapping("/api/v1/generation") @RequestMapping("/api/v1/generation")
public class GenerationController { public class GenerationController {
private static final ZoneId SHANGHAI_ZONE = ZoneId.of("Asia/Shanghai");
@Autowired @Autowired
private QianwenClient qianwenClient; private QianwenClient qianwenClient;
@ -216,7 +218,7 @@ public class GenerationController {
List<ArchiveMessage> messages; List<ArchiveMessage> messages;
boolean isGroupChat = roomid != null && !roomid.isEmpty(); boolean isGroupChat = roomid != null && !roomid.isEmpty();
// 查最近 今 天,避免今天没聊天就找不到记录 // 查今天(按上海时区),避免 UTC 零点导致中国时区上午消息被漏掉
long startTime = getTodayStartTime(); long startTime = getTodayStartTime();
long endTime = getTodayEndTime(); long endTime = getTodayEndTime();
//// 指定日期:2026-05-22 todo 测试需要 //// 指定日期:2026-05-22 todo 测试需要
@ -259,15 +261,15 @@ public class GenerationController {
} }
private long getTodayStartTime() { private long getTodayStartTime() {
return java.time.LocalDate.now().atStartOfDay(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli(); return java.time.LocalDate.now().atStartOfDay(SHANGHAI_ZONE).toInstant().toEpochMilli();
} }
private long getTodayEndTime() { private long getTodayEndTime() {
return java.time.LocalDate.now().plusDays(1).atStartOfDay(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli() - 1; return java.time.LocalDate.now().plusDays(1).atStartOfDay(SHANGHAI_ZONE).toInstant().toEpochMilli() - 1;
} }
private long get7DaysAgoStartTime() { private long get7DaysAgoStartTime() {
return java.time.LocalDate.now().minusDays(7).atStartOfDay(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli(); return java.time.LocalDate.now().minusDays(7).atStartOfDay(SHANGHAI_ZONE).toInstant().toEpochMilli();
} }
/** /**