Просмотр исходного кода

feat(backend): 关系pairwise接口(以成员为中心) + VO补齐沟通评分+isSelf

Sisyphus 2 месяцев назад
Родитель
Сommit
05fbd985ce

+ 23 - 1
cfc-backend/src/main/java/com/etotem/cfc/controller/family/RelationshipQualityController.java

@@ -1,6 +1,7 @@
 package com.etotem.cfc.controller.family;
 
 import com.etotem.cfc.common.Result;
+import com.etotem.cfc.dto.FamilyMemberVO;
 import com.etotem.cfc.dto.HealthAlertVO;
 import com.etotem.cfc.dto.MilestoneVO;
 import com.etotem.cfc.dto.RelationshipScoreVO;
@@ -87,7 +88,7 @@ public class RelationshipQualityController {
         return Result.success(milestones);
     }
 
-    /**
+/**
      * 解析请求中的家庭ID:优先请求体中的familyId,其次request attribute,最后回退用户所属家庭
      */
     private Long getFamilyIdFromRequest(Long userId, Map<String, Object> body, Long familyId) {
@@ -105,4 +106,25 @@ public class RelationshipQualityController {
         }
         return null;
     }
+
+    @Operation(summary = "获取以指定成员为中心的所有成员关系(pairwise)")
+    @PostMapping("/pairwise")
+    public Result<List<FamilyMemberVO>> getPairwise(@RequestBody Map<String, Object> body,
+                                                    @RequestAttribute("userId") Long userId) {
+        if (userId == null) {
+            return Result.error("请先登录");
+        }
+        Long centerMemberId = body.get("centerMemberId") != null
+                ? Long.valueOf(body.get("centerMemberId").toString()) : null;
+        if (centerMemberId == null) {
+            return Result.error("centerMemberId不能为空");
+        }
+        Long familyId = getFamilyIdFromRequest(userId, body, null);
+        try {
+            List<FamilyMemberVO> members = relationshipQualityService.getPairwiseRelationships(centerMemberId, familyId);
+            return Result.success(members);
+        } catch (RuntimeException e) {
+            return Result.error(e.getMessage());
+        }
+    }
 }

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/dto/FamilyMemberVO.java

@@ -64,6 +64,9 @@ public class FamilyMemberVO {
     /** 亲密度分数 */
     private java.math.BigDecimal intimacyScore;
 
+    /** 沟通质量分数 */
+    private java.math.BigDecimal communicationScore;
+
     /** 最近互动时间 */
     private java.util.Date lastInteractionAt;
 

+ 2 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyMemberService.java

@@ -241,6 +241,8 @@ public class FamilyMemberService {
             vo.setIsSpouse(fm.getIsSpouse());
             vo.setTrustScore(fm.getTrustScore());
             vo.setIntimacyScore(fm.getIntimacyScore());
+            vo.setCommunicationScore(fm.getCommunicationScore());
+            vo.setIsSelf(viewerMember != null && viewerMember.getId().equals(fm.getId()));
             vo.setLastInteractionAt(fm.getLastInteractionAt());
             vo.setStreakDays(fm.getStreakDays());
             result.add(vo);

+ 69 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/RelationshipQualityService.java

@@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.etotem.cfc.dto.HealthAlertVO;
 import com.etotem.cfc.dto.MilestoneVO;
 import com.etotem.cfc.dto.RelationshipScoreVO;
+import com.etotem.cfc.dto.FamilyMemberVO;
 import com.etotem.cfc.entity.FamilyMember;
 import com.etotem.cfc.entity.FamilyMemberAttributes;
+import com.etotem.cfc.entity.FamilyRelationship;
 import com.etotem.cfc.mapper.FamilyMemberAttributesMapper;
 import com.etotem.cfc.mapper.FamilyMemberMapper;
 import org.slf4j.Logger;
@@ -18,7 +20,9 @@ import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @Service
 public class RelationshipQualityService {
@@ -31,6 +35,9 @@ public class RelationshipQualityService {
     @Resource
     private FamilyMemberAttributesMapper familyMemberAttributesMapper;
 
+    @Resource
+    private FamilyRelationshipService familyRelationshipService;
+
     private static final String TYPE_BIRTHDAY = "birthday";
 
     /**
@@ -214,4 +221,66 @@ public class RelationshipQualityService {
         }
         return "parent";
     }
+
+    /**
+     * 获取以指定成员为中心的所有成员关系(关系类型 + 三项评分)
+     */
+    public List<FamilyMemberVO> getPairwiseRelationships(Long centerMemberId, Long familyId) {
+        List<FamilyMemberVO> result = new ArrayList<>();
+        FamilyMember center = familyMemberMapper.selectById(centerMemberId);
+        if (center == null || (familyId != null && !familyId.equals(center.getFamilyId()))) {
+            throw new RuntimeException("成员不存在或不属于该家庭");
+        }
+        if (familyId == null) {
+            familyId = center.getFamilyId();
+        }
+
+        List<FamilyMember> members = familyMemberMapper.selectList(
+                new LambdaQueryWrapper<FamilyMember>().eq(FamilyMember::getFamilyId, familyId));
+
+        // 中心成员 → 各成员的关系行(评分与关系类型来源)
+        List<FamilyRelationship> rels = familyRelationshipService.getRelationsForMember(centerMemberId);
+        Map<Long, FamilyRelationship> relMap = new HashMap<>();
+        for (FamilyRelationship rel : rels) {
+            relMap.put(rel.getToMemberId(), rel);
+        }
+
+        for (FamilyMember fm : members) {
+            FamilyMemberVO vo = new FamilyMemberVO();
+            vo.setId(fm.getId());
+            vo.setSource("family_member");
+            vo.setUserId(fm.getUserId());
+            vo.setNickname(fm.getNickname());
+            vo.setPhone(fm.getPhone());
+            vo.setAvatar(fm.getAvatar());
+            vo.setGender(fm.getGender());
+            vo.setGeneration(fm.getGeneration());
+            vo.setEffectiveRole(computeEffectiveRole(fm));
+            vo.setRoleLabel(computeEffectiveRole(fm));
+            vo.setIsSelf(centerMemberId.equals(fm.getId()));
+            vo.setAge(fm.getAge());
+
+            FamilyRelationship rel = relMap.get(fm.getId());
+            if (rel != null) {
+                vo.setGenerationValue(rel.getGenerationValue());
+                String label = rel.getRelationshipKey() != null && !rel.getRelationshipKey().isEmpty()
+                        ? rel.getRelationshipKey()
+                        : familyRelationshipService.computeRelationshipLabel(rel.getGenerationValue(), fm.getGender());
+                vo.setRelativeLabel(label);
+                vo.setRelationship(label);
+                vo.setTrustScore(rel.getTrustScore());
+                vo.setIntimacyScore(rel.getIntimacyScore());
+                vo.setCommunicationScore(rel.getCommunicationScore());
+            } else if (centerMemberId.equals(fm.getId())) {
+                vo.setRelationship("我");
+                vo.setRelativeLabel("我");
+            } else {
+                vo.setTrustScore(BigDecimal.ZERO);
+                vo.setIntimacyScore(BigDecimal.ZERO);
+                vo.setCommunicationScore(BigDecimal.ZERO);
+            }
+            result.add(vo);
+        }
+        return result;
+    }
 }