|
|
@@ -244,6 +244,43 @@ public class FamilyMemberService {
|
|
|
new LambdaQueryWrapper<FamilyMember>()
|
|
|
.eq(FamilyMember::getFamilyId, familyId)
|
|
|
.ne(FamilyMember::getStatus, "recycled"));
|
|
|
+ // 兜底去重:同一 userId 多条记录只保留一条记录
|
|
|
+ // 优先 status=active + userId 非空,其次 updated_at 最新
|
|
|
+ // userId 为 null 的孤儿记录保持原样
|
|
|
+ if (familyMembers != null && !familyMembers.isEmpty()) {
|
|
|
+ Map<Long, List<FamilyMember>> userIdGroups = new java.util.HashMap<>();
|
|
|
+ List<FamilyMember> orphans = new ArrayList<>();
|
|
|
+ for (FamilyMember fm : familyMembers) {
|
|
|
+ if (fm.getUserId() == null) {
|
|
|
+ orphans.add(fm);
|
|
|
+ } else {
|
|
|
+ userIdGroups.computeIfAbsent(fm.getUserId(), k -> new ArrayList<>()).add(fm);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<FamilyMember> deduped = new ArrayList<>();
|
|
|
+ deduped.addAll(orphans);
|
|
|
+ for (List<FamilyMember> group : userIdGroups.values()) {
|
|
|
+ if (group.size() == 1) {
|
|
|
+ deduped.add(group.get(0));
|
|
|
+ } else {
|
|
|
+ // status=active 优先,其次 updated_at 最新
|
|
|
+ FamilyMember winner = group.stream()
|
|
|
+ .max((a, b) -> {
|
|
|
+ boolean aActive = "active".equals(a.getStatus());
|
|
|
+ boolean bActive = "active".equals(b.getStatus());
|
|
|
+ if (aActive && !bActive) return -1;
|
|
|
+ if (!aActive && bActive) return 1;
|
|
|
+ if (a.getUpdatedAt() != null && b.getUpdatedAt() != null) {
|
|
|
+ return b.getUpdatedAt().compareTo(a.getUpdatedAt());
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ })
|
|
|
+ .orElse(group.get(0));
|
|
|
+ deduped.add(winner);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ familyMembers = deduped;
|
|
|
+ }
|
|
|
|
|
|
// 查找当前查看者在 family_members 中的记录(用于计算视角标签)
|
|
|
FamilyMember viewerMember = null;
|
|
|
@@ -305,6 +342,14 @@ public class FamilyMemberService {
|
|
|
vo.setIntimacyScore(fm.getIntimacyScore());
|
|
|
vo.setCommunicationScore(fm.getCommunicationScore());
|
|
|
vo.setIsSelf(viewerMember != null && viewerMember.getId().equals(fm.getId()));
|
|
|
+ // 设置 memberType:userId 非空且关联 User 有 openid -> 'login';否则 -> 'local'
|
|
|
+ if (fm.getUserId() != null) {
|
|
|
+ User memberUser = userMapper.selectById(fm.getUserId());
|
|
|
+ String openid = memberUser != null ? memberUser.getOpenid() : null;
|
|
|
+ vo.setMemberType(openid != null && !openid.isEmpty() ? "login" : "local");
|
|
|
+ } else {
|
|
|
+ vo.setMemberType("local");
|
|
|
+ }
|
|
|
// 设置 isSwitchable:仅无 openid 的不可登录成员可被切换(可登录成员不允许切换视角)
|
|
|
if (fm.getUserId() != null) {
|
|
|
User memberUser = userMapper.selectById(fm.getUserId());
|