浏览代码

feat(api): 能量沙盘门禁改家庭级判据 - 任一成员做过五维自检即解锁 (sandbox-gate)

- UnlockGateService 新增 hasFamilySelfCheck(familyId):查 family 内任一用户的自检记录,不依赖 unlock_gates 种子配置
- EnergyController.sandbox 个人视角改用家庭级判据 + selfCheckGateOrFallback 内置兜底 gate(无种子时前端 GateLock 也能渲染引导按钮)
- getUserUnlockStatus 个人沙盘锁定标志同步家庭级,与 /api/energy/sandbox 一致

Ultraworked with [Sisyphus](https://github.com/OhMyOpenCode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
E2E Test Bot 1 月之前
父节点
当前提交
06607fd384

+ 22 - 5
cfc-backend/src/main/java/com/etotem/cfc/controller/EnergyController.java

@@ -81,13 +81,12 @@ public class EnergyController {
             return Result.success(result);
         }
 
-        // 个人沙盘(默认):需通过 SELF_CHECK 关卡
-        boolean personalPassed = unlockGateService.isPersonalSelfCheckPassed(userId);
-        if (!personalPassed) {
-            UnlockGate gate = unlockGateService.getGateByType("SELF_CHECK");
+        // 个人沙盘(默认):家庭级判据 —— 任一成员做过五维自检(书稿"测量先行")
+        boolean familySelfCheckPassed = unlockGateService.hasFamilySelfCheck(user.getFamilyId());
+        if (!familySelfCheckPassed) {
             result.put("locked", true);
             result.put("view", "personal");
-            result.put("gate", gate != null ? gateToMap(gate) : null);
+            result.put("gate", selfCheckGateOrFallback());
             return Result.success(result);
         }
 
@@ -116,6 +115,24 @@ public class EnergyController {
         return m;
     }
 
+    /**
+     * 返回 SELF_CHECK 关卡信息:优先取配置的 unlock_gates,无种子配置时返回内置默认
+     * (保证前端 GateLock 始终能渲染引导按钮,不依赖管理端种子数据)
+     */
+    private Map<String, Object> selfCheckGateOrFallback() {
+        UnlockGate gate = unlockGateService.getGateByType("SELF_CHECK");
+        if (gate != null) {
+            return gateToMap(gate);
+        }
+        Map<String, Object> m = new HashMap<>();
+        m.put("id", null);
+        m.put("gateType", "SELF_CHECK");
+        m.put("name", "五维基础能量检测");
+        m.put("description", "检查家庭的能量维度值,解锁能量沙盘");
+        m.put("icon", "📊");
+        return m;
+    }
+
     /**
      * 获取孩子五维能量概览
      */

+ 17 - 2
cfc-backend/src/main/java/com/etotem/cfc/service/UnlockGateService.java

@@ -141,6 +141,21 @@ public class UnlockGateService {
         return count >= 1;
     }
 
+    /**
+     * 家庭级判据:family 内任一成员做过五维自检(首页能量沙盘解锁条件,书稿"测量先行")
+     * 不依赖 unlock_gates 种子配置,直接查 five_dimension_self_checks
+     */
+    public boolean hasFamilySelfCheck(Long familyId) {
+        if (familyId == null) return false;
+        List<User> familyUsers = userMapper.selectList(
+                new LambdaQueryWrapper<User>().eq(User::getFamilyId, familyId));
+        if (familyUsers.isEmpty()) return false;
+        List<Long> userIds = familyUsers.stream().map(User::getId).collect(Collectors.toList());
+        long count = selfCheckMapper.selectCount(
+                new LambdaQueryWrapper<FiveDimensionSelfCheck>().in(FiveDimensionSelfCheck::getUserId, userIds));
+        return count >= 1;
+    }
+
     // ========== 当前锁定关卡 ==========
 
     /**
@@ -334,8 +349,8 @@ public class UnlockGateService {
             return dto;
         }
 
-        // 有家庭
-        boolean personalPassed = isPersonalSelfCheckPassed(userId);
+        // 有家庭:个人沙盘门禁与 /api/energy/sandbox 保持一致 —— 家庭级判据(任一成员做过自检)
+        boolean personalPassed = hasFamilySelfCheck(familyId);
         dto.setPersonalSandboxLocked(!personalPassed);
 
         // 全家沙盘