Bläddra i källkod

feat(health-data-center): 健康数据中心全栈实现

- 身维度首页(health-main/index.vue)改造:Tab栏+四维雷达图+数据采集区+数据查看+方案汇总
- 在线测评(dimension-questionnaire.vue)扩展:cognitive/mental/relationship三套题库(各8题)+dim参数路由
- 方案汇总页(health-plan-summary.vue)新建:生成表单+结果展示+历史列表
- 后端:health_plans表+HealthPlan实体/Mapper/Service/Controller(4端点)
- 数据库迁移207:health_plans表
- 前端API:generateHealthPlan/saveHealthPlan/getHealthPlanList/getHealthPlanDetail
- pages.json注册health-plan-summary页面
- PROJECT-OVERVIEW更新
Xiaogang Liao 1 månad sedan
förälder
incheckning
840e61b56e

+ 21 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -8491,5 +8491,26 @@ private void runMigration100() {
 		ensureColumn("member_upgrade_records", "approve_status", "VARCHAR(20) DEFAULT 'approved' COMMENT '审批状态: approved/rejected'");
 		ensureColumn("member_upgrade_records", "approve_user_id", "BIGINT DEFAULT NULL COMMENT '审批人ID'");
 		ensureColumn("member_upgrade_records", "approve_time", "DATETIME DEFAULT NULL COMMENT '审批时间'");
+
+		// 迁移207: 创建 health_plans 表(健康方案汇总记录)
+		try {
+			jdbcTemplate.execute(
+				"CREATE TABLE IF NOT EXISTS health_plans (" +
+				"id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+				"family_id BIGINT NOT NULL COMMENT '家庭ID', " +
+				"member_ids VARCHAR(200) NOT NULL COMMENT '目标成员ID列表(逗号分隔)', " +
+				"dimensions VARCHAR(100) NOT NULL COMMENT '维度列表(逗号分隔)', " +
+				"goal TEXT NOT NULL COMMENT '用户输入的目标', " +
+				"plan_content TEXT COMMENT 'LangGraph生成的方案内容', " +
+				"member_name VARCHAR(50) COMMENT '成员名称摘要', " +
+				"created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+				"INDEX idx_family (family_id), " +
+				"INDEX idx_created (created_at)" +
+				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康方案汇总记录'"
+			);
+			log.info("已创建health_plans表");
+		} catch (Exception e) {
+			log.warn("创建health_plans表失败(可能已存在): " + e.getMessage());
+		}
 	}
 }

+ 76 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/HealthPlanController.java

@@ -0,0 +1,76 @@
+package com.etotem.cfc.controller;
+
+import com.etotem.cfc.common.Result;
+import com.etotem.cfc.entity.HealthPlan;
+import com.etotem.cfc.service.HealthPlanService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+
+@Tag(name = "健康方案", description = "健康方案生成与管理")
+@RestController
+@RequestMapping("/api/health/plan")
+public class HealthPlanController {
+
+    @Resource
+    private HealthPlanService healthPlanService;
+
+    @Operation(summary = "生成健康方案")
+    @PostMapping("/generate")
+    public Result<String> generate(@RequestBody Map<String, Object> params, @RequestAttribute("userId") Long userId) {
+        Long familyId = params.get("familyId") != null ? Long.valueOf(params.get("familyId").toString()) : null;
+        String memberIds = (String) params.get("memberIds");
+        String dimensions = (String) params.get("dimensions");
+        String goal = (String) params.get("goal");
+        if (dimensions == null || goal == null || goal.trim().isEmpty()) {
+            return Result.error("dimensions和goal不能为空");
+        }
+        String planContent = healthPlanService.generatePlan(familyId, memberIds, dimensions, goal);
+        return Result.success(planContent);
+    }
+
+    @Operation(summary = "保存健康方案")
+    @PostMapping("/save")
+    public Result<Long> save(@RequestBody Map<String, Object> params, @RequestAttribute("userId") Long userId) {
+        Long familyId = params.get("familyId") != null ? Long.valueOf(params.get("familyId").toString()) : null;
+        String memberIds = (String) params.get("memberIds");
+        String dimensions = (String) params.get("dimensions");
+        String goal = (String) params.get("goal");
+        String planContent = (String) params.get("planContent");
+        String memberName = (String) params.get("memberName");
+        if (familyId == null || dimensions == null || goal == null || planContent == null) {
+            return Result.error("familyId, dimensions, goal, planContent不能为空");
+        }
+        HealthPlan plan = new HealthPlan();
+        plan.setFamilyId(familyId);
+        plan.setMemberIds(memberIds != null ? memberIds : "");
+        plan.setDimensions(dimensions);
+        plan.setGoal(goal);
+        plan.setPlanContent(planContent);
+        plan.setMemberName(memberName);
+        Long id = healthPlanService.savePlan(plan);
+        return Result.success(id);
+    }
+
+    @Operation(summary = "查询历史方案列表")
+    @PostMapping("/list")
+    public Result<List<HealthPlan>> list(@RequestBody Map<String, Object> params, @RequestAttribute("userId") Long userId) {
+        Long familyId = params.get("familyId") != null ? Long.valueOf(params.get("familyId").toString()) : null;
+        if (familyId == null) return Result.error("familyId不能为空");
+        List<HealthPlan> list = healthPlanService.getPlanList(familyId);
+        return Result.success(list);
+    }
+
+    @Operation(summary = "查询方案详情")
+    @PostMapping("/detail")
+    public Result<HealthPlan> detail(@RequestBody Map<String, Object> params, @RequestAttribute("userId") Long userId) {
+        Long planId = params.get("planId") != null ? Long.valueOf(params.get("planId").toString()) : null;
+        if (planId == null) return Result.error("planId不能为空");
+        HealthPlan plan = healthPlanService.getPlanDetail(planId);
+        if (plan == null) return Result.error("方案不存在");
+        return Result.success(plan);
+    }
+}

+ 23 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/HealthPlan.java

@@ -0,0 +1,23 @@
+package com.etotem.cfc.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("health_plans")
+public class HealthPlan implements Serializable {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long familyId;
+    @TableField("member_ids") private String memberIds;
+    @TableField("dimensions") private String dimensions;
+    private String goal;
+    @TableField("plan_content") private String planContent;
+    @TableField("member_name") private String memberName;
+    @TableField("created_at") private Date createdAt;
+}

+ 9 - 0
cfc-backend/src/main/java/com/etotem/cfc/mapper/HealthPlanMapper.java

@@ -0,0 +1,9 @@
+package com.etotem.cfc.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.etotem.cfc.entity.HealthPlan;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface HealthPlanMapper extends BaseMapper<HealthPlan> {
+}

+ 11 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/HealthPlanService.java

@@ -0,0 +1,11 @@
+package com.etotem.cfc.service;
+
+import com.etotem.cfc.entity.HealthPlan;
+import java.util.List;
+
+public interface HealthPlanService {
+    Long savePlan(HealthPlan plan);
+    List<HealthPlan> getPlanList(Long familyId);
+    HealthPlan getPlanDetail(Long planId);
+    String generatePlan(Long familyId, String memberIds, String dimensions, String goal);
+}

+ 89 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/impl/HealthPlanServiceImpl.java

@@ -0,0 +1,89 @@
+package com.etotem.cfc.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.etotem.cfc.entity.HealthPlan;
+import com.etotem.cfc.mapper.HealthPlanMapper;
+import com.etotem.cfc.service.HealthPlanService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class HealthPlanServiceImpl implements HealthPlanService {
+    private static final Logger log = LoggerFactory.getLogger(HealthPlanServiceImpl.class);
+
+    @Resource
+    private HealthPlanMapper healthPlanMapper;
+
+    @Value("${cfc.langgraph.base-url:}")
+    private String langgraphBaseUrl;
+
+    @Override
+    public Long savePlan(HealthPlan plan) {
+        plan.setCreatedAt(new Date());
+        healthPlanMapper.insert(plan);
+        return plan.getId();
+    }
+
+    @Override
+    public List<HealthPlan> getPlanList(Long familyId) {
+        QueryWrapper<HealthPlan> wrapper = new QueryWrapper<>();
+        wrapper.eq("family_id", familyId);
+        wrapper.orderByDesc("created_at");
+        return healthPlanMapper.selectList(wrapper);
+    }
+
+    @Override
+    public HealthPlan getPlanDetail(Long planId) {
+        return healthPlanMapper.selectById(planId);
+    }
+
+    @Override
+    public String generatePlan(Long familyId, String memberIds, String dimensions, String goal) {
+        if (langgraphBaseUrl == null || langgraphBaseUrl.trim().isEmpty()) {
+            return buildSamplePlan(memberIds, dimensions, goal);
+        }
+        try {
+            RestTemplate restTemplate = new RestTemplate();
+            Map<String, Object> body = new HashMap<>();
+            body.put("familyId", familyId);
+            body.put("memberIds", memberIds);
+            body.put("dimensions", dimensions);
+            body.put("goal", goal);
+            String url = langgraphBaseUrl + "/api/v1/health/coach/generate";
+            ResponseEntity<String> response = restTemplate.postForEntity(url, body, String.class);
+            if (response.getBody() != null && response.getStatusCode().is2xxSuccessful()) {
+                return response.getBody();
+            }
+        } catch (Exception e) {
+            log.warn("调用LangGraph生成方案失败: {}", e.getMessage());
+        }
+        return buildSamplePlan(memberIds, dimensions, goal);
+    }
+
+    private String buildSamplePlan(String memberIds, String dimensions, String goal) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("# 健康方案\n\n");
+        sb.append("## 目标\n").append(goal != null ? goal : "改善健康状况").append("\n\n");
+        sb.append("## 涉及维度\n").append(dimensions != null ? dimensions : "健康").append("\n\n");
+        sb.append("## 方案内容\n\n");
+        sb.append("根据当前数据,建议从以下几个方面入手:\n\n");
+        sb.append("### 1. 现状分析\n");
+        sb.append("通过综合评估,当前主要需要关注的维度为:").append(dimensions != null ? dimensions : "健康").append("。\n\n");
+        sb.append("### 2. 具体建议\n");
+        sb.append("- 制定每日健康打卡计划\n");
+        sb.append("- 定期上传健康报告进行跟踪\n");
+        sb.append("- 完成相关在线测评获取更精准评估\n\n");
+        sb.append("### 3. 预期效果\n");
+        sb.append("坚持执行以上方案,预计 4 周内可见明显改善。\n");
+        return sb.toString();
+    }
+}

+ 16 - 0
cfc-backend/src/main/resources/schema.sql

@@ -4418,3 +4418,19 @@ CREATE TABLE IF NOT EXISTS platform_balance_log (
     created_at    DATETIME,
     INDEX idx_user_time (user_id, created_at)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CF值流水';
+
+
+-- ===== 健康方案汇总 =====
+
+CREATE TABLE IF NOT EXISTS health_plans (
+    id            BIGINT AUTO_INCREMENT PRIMARY KEY,
+    family_id     BIGINT       NOT NULL COMMENT '家庭ID',
+    member_ids    VARCHAR(200) NOT NULL COMMENT '目标成员ID列表(逗号分隔)',
+    dimensions    VARCHAR(100) NOT NULL COMMENT '维度列表(逗号分隔)',
+    goal          TEXT         NOT NULL COMMENT '用户输入的目标',
+    plan_content  TEXT         COMMENT 'LangGraph生成的方案内容',
+    member_name   VARCHAR(50)  COMMENT '成员名称摘要',
+    created_at    DATETIME DEFAULT CURRENT_TIMESTAMP,
+    INDEX idx_family (family_id),
+    INDEX idx_created (created_at)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康方案汇总记录';

+ 6 - 0
cfc-frontend/pages.json

@@ -876,6 +876,12 @@
           "style": {
             "navigationBarTitleText": "健康打卡"
           }
+        },
+        {
+          "path": "health-plan-summary",
+          "style": {
+            "navigationBarTitleText": "方案汇总"
+          }
         }
       ]
     },

+ 110 - 4
cfc-frontend/pages/body-detail/dimension-questionnaire.vue

@@ -215,10 +215,112 @@ export default {
             { label: '球类/田径等竞技运动', value: 'competitive' },
             { label: '游泳/骑行等有氧运动', value: 'aerobic' },
             { label: '跳绳/体操等灵活性运动', value: 'flexibility' },
-            { label: '不太喜欢运动', value: 'sedentary' }
-          ]}
-        ]
-      },
+{ label: '不太喜欢运动', value: 'sedentary' }
+           ]}
+         ],
+         cognitive: [
+           { question: '你能同时记住几件事而不遗漏?', options: [
+             { label: '1-2件', value: 'q1' }, { label: '3-4件', value: 'q3' },
+             { label: '5-6件', value: 'q5' }, { label: '7件以上', value: 'q7' }
+           ]},
+           { question: '解决复杂问题时你通常?', options: [
+             { label: '凭直觉', value: 'intuitive' }, { label: '逐步分析', value: 'analytical' },
+             { label: '找人帮忙', value: 'askhelp' }, { label: '回避', value: 'avoid' }
+           ]},
+           { question: '学习新技能的速度?', options: [
+             { label: '很快', value: 'fast' }, { label: '一般', value: 'normal' },
+             { label: '较慢', value: 'slow' }, { label: '很困难', value: 'difficult' }
+           ]},
+           { question: '你能清晰地表达自己的想法吗?', options: [
+             { label: '非常清晰', value: 'clear' }, { label: '基本可以', value: 'basically' },
+             { label: '有时困难', value: 'sometimes' }, { label: '很难', value: 'difficult' }
+           ]},
+           { question: '做决定时你会考虑多种可能性?', options: [
+             { label: '总是', value: 'always' }, { label: '经常', value: 'often' },
+             { label: '有时', value: 'sometimes' }, { label: '很少', value: 'rarely' }
+           ]},
+           { question: '空间方向感如何?', options: [
+             { label: '很好', value: 'good' }, { label: '一般', value: 'normal' },
+             { label: '较差', value: 'poor' }, { label: '完全没有', value: 'none' }
+           ]},
+           { question: '你能快速发现事物之间的关联?', options: [
+             { label: '总是', value: 'always' }, { label: '经常', value: 'often' },
+             { label: '偶尔', value: 'sometimes' }, { label: '很少', value: 'rarely' }
+           ]},
+           { question: '注意力集中的持续时间?', options: [
+             { label: '1小时以上', value: 'over1h' }, { label: '30分钟', value: '30m' },
+             { label: '10分钟', value: '10m' }, { label: '几分钟', value: 'fewm' }
+           ]}
+         ],
+         mental: [
+           { question: '最近一个月你感到心情愉快的频率?', options: [
+             { label: '经常', value: 'often' }, { label: '有时', value: 'sometimes' },
+             { label: '偶尔', value: 'occasionally' }, { label: '几乎没有', value: 'never' }
+           ]},
+           { question: '面对压力时你通常?', options: [
+             { label: '轻松应对', value: 'easy' }, { label: '基本能处理', value: 'manageable' },
+             { label: '有些吃力', value: 'hard' }, { label: '很难应对', value: 'difficult' }
+           ]},
+           { question: '你觉得自己了解自己的情绪吗?', options: [
+             { label: '非常了解', value: 'well' }, { label: '基本了解', value: 'basically' },
+             { label: '不太了解', value: 'notmuch' }, { label: '完全不了解', value: 'notatall' }
+           ]},
+           { question: '与人相处时你感到?', options: [
+             { label: '自在舒适', value: 'comfortable' }, { label: '基本自在', value: 'basically' },
+             { label: '有些不自在', value: 'uncomfortable' }, { label: '很拘谨', value: 'stiff' }
+           ]},
+           { question: '你对目前的生活满意度?', options: [
+             { label: '很满意', value: 'very' }, { label: '比较满意', value: 'fair' },
+             { label: '一般', value: 'average' }, { label: '不满意', value: 'unsatisfied' }
+           ]},
+           { question: '遇到挫折后你多久能恢复?', options: [
+             { label: '很快', value: 'quickly' }, { label: '一两天', value: 'one_two' },
+             { label: '一周以上', value: 'over_week' }, { label: '很久', value: 'longtime' }
+           ]},
+           { question: '你觉得自己有价值感吗?', options: [
+             { label: '很有价值', value: 'very' }, { label: '有时有', value: 'sometimes' },
+             { label: '很少', value: 'rarely' }, { label: '没有', value: 'none' }
+           ]},
+           { question: '你是否有固定的放松方式?', options: [
+             { label: '有且坚持', value: 'always' }, { label: '有时有', value: 'sometimes' },
+             { label: '想过没做', value: 'thought' }, { label: '没有', value: 'none' }
+           ]}
+         ],
+         relationship: [
+           { question: '你与家人的沟通频率?', options: [
+             { label: '每天', value: 'daily' }, { label: '每周几次', value: 'weekly' },
+             { label: '每周一次', value: 'once_week' }, { label: '很少', value: 'rarely' }
+           ]},
+           { question: '遇到困难时你能找到人倾诉?', options: [
+             { label: '总是可以', value: 'always' }, { label: '经常', value: 'often' },
+             { label: '偶尔', value: 'sometimes' }, { label: '很难', value: 'hard' }
+           ]},
+           { question: '你觉得自己被家人理解?', options: [
+             { label: '非常理解', value: 'very' }, { label: '基本理解', value: 'basically' },
+             { label: '不太理解', value: 'notmuch' }, { label: '完全不理解', value: 'notatall' }
+           ]},
+           { question: '你与伴侣的关系满意度?', options: [
+             { label: '很满意', value: 'very' }, { label: '比较满意', value: 'fair' },
+             { label: '一般', value: 'average' }, { label: '不满意', value: 'unsatisfied' }
+           ]},
+           { question: '你与孩子的关系如何?', options: [
+             { label: '亲密', value: 'close' }, { label: '良好', value: 'good' },
+             { label: '一般', value: 'average' }, { label: '疏远', value: 'distant' }
+           ]},
+           { question: '你在社交中感到?', options: [
+             { label: '轻松愉快', value: 'easy' }, { label: '基本舒适', value: 'comfortable' },
+             { label: '有些紧张', value: 'nervous' }, { label: '很焦虑', value: 'anxious' }
+           ]},
+           { question: '你愿意主动联系朋友吗?', options: [
+             { label: '经常', value: 'often' }, { label: '有时', value: 'sometimes' },
+             { label: '被动', value: 'passive' }, { label: '几乎不', value: 'never' }
+           ]},
+           { question: '你觉得家庭氛围如何?', options: [
+             { label: '温馨和谐', value: 'warm' }, { label: '基本融洽', value: 'harmonious' },
+             { label: '有些紧张', value: 'tense' }, { label: '压抑', value: 'oppressive' }
+           ]}
+         ]
+       },
       currentQIndex: 0,
       answers: {},
       currentAnswer: '',
@@ -330,6 +432,10 @@ export default {
   },
   onLoad: function(options) {
     this.activeChildId = options.memberId || ''
+    if (options.dim) {
+      this.selectedDimension = options.dim
+      this.step = 2
+    }
   }
 }
 </script>

+ 213 - 327
cfc-frontend/pages/health-main/index.vue

@@ -1,125 +1,99 @@
 <template>
   <view class="container">
-    <!-- 未登录态 -->
     <view v-if="!isLoggedIn">
       <PageBanner theme="body" tagline="科学管理全家健康" quote="身体健康是幸福的基础" />
-      <LoginGuideCard
-        title="登录后查看全家健康数据"
-        :features="[
-          '申请专业测评',
-          '查看健康报告和诊断结果',
-          '了解家人健康状态'
-        ]"
-      />
+      <LoginGuideCard title="登录后查看全家健康数据" :features="['申请专业测评','查看健康报告和诊断结果','了解家人健康状态']" />
     </view>
-
-    <!-- 登录态 -->
     <view v-else>
-      <!-- 品牌头部 -->
-      <PageBanner theme="body" tagline="科学测评 · 精准诊断" quote="了解是改善的第一步" />
+      <PageBanner theme="body" tagline="看见·主动健康闭环" quote="采集→看见→行动" />
+
+      <view class="tab-bar">
+        <view v-for="tab in tabs" :key="tab.code" class="tab-item" :class="{ active: currentTab === tab.code }" @click="switchTab(tab.code)">
+          <text class="tab-icon">{{ tab.icon }}</text>
+          <text class="tab-label">{{ tab.label }}</text>
+          <view v-if="currentTab === tab.code" class="tab-underline" :style="{ background: tab.color }"></view>
+        </view>
+      </view>
+
+      <view class="section section-chart">
+        <RadarChart :dimensions="currentDimensions" :scores="currentScores" :fillColor="currentColor" :childName="selectedMemberName" width="640" height="520" />
+        <view class="chart-empty" v-if="chartIsEmpty">
+          <text class="empty-text">{{ currentTabLabel }}数据待采集</text>
+          <text class="empty-sub">上传报告或完成测评后显示</text>
+        </view>
+      </view>
 
-      <!-- 家庭成员选择条 -->
       <FamilyMemberStrip />
 
-      <!-- 健康概览卡片 -->
-      <view class="section">
-        <view class="overview-card">
-          <view class="overview-item">
-            <text class="overview-label">健康综合评分</text>
-            <text class="overview-value">{{ healthScore || '--' }}</text>
-            <text class="overview-unit">分</text>
-          </view>
-          <view class="overview-divider"></view>
-          <view class="overview-grid">
-            <view class="overview-grid-item">
-              <text class="grid-value">{{ pendingReports }}</text>
-              <text class="grid-label">待处理报告</text>
-            </view>
-            <view class="overview-grid-item">
-              <text class="grid-value">{{ lastAssessmentDate }}</text>
-              <text class="grid-label">上次测评</text>
-            </view>
-            <view class="overview-grid-item">
-              <text class="grid-value">{{ streakDays }}</text>
-              <text class="grid-label">连续打卡</text>
-            </view>
-          </view>
+      <view class="section section-dc-header">
+        <view class="dc-title-row">
+          <text class="dc-icon">🔍</text>
+          <text class="dc-title">看见 · 健康数据中心</text>
         </view>
       </view>
 
-      <!-- 功能入口网格 -->
-      <view class="section">
-        <view class="grid-3col">
-          <view class="grid-item" @click="goPage('/pages/assessment/purchase')">
-            <view class="grid-icon" style="background:rgba(16,185,129,0.15)"><text>📋</text></view>
-            <text class="grid-label">申请测评</text>
-          </view>
-          <view class="grid-item" @click="goPage('/pages/health/report-list')">
-            <view class="grid-icon" style="background:rgba(99,102,241,0.15)"><text>📊</text></view>
-            <text class="grid-label">健康报告</text>
-          </view>
-          <view class="grid-item" @click="goPage('/pages/health/report-survey')">
-            <view class="grid-icon" style="background:rgba(245,158,11,0.15)"><text>📝</text></view>
-            <text class="grid-label">健康调研</text>
+      <view class="section section-data-collect">
+        <view class="data-card" @click="goPage('/pages/health/report-upload')">
+          <view class="data-card-icon" style="background:rgba(249,115,22,0.12)"><text>📋</text></view>
+          <view class="data-card-info">
+            <text class="data-card-title">上传健康报告</text>
+            <text class="data-card-desc">体检/肠道/舌诊报告 · AI智能解读</text>
           </view>
-          <view class="grid-item" @click="goPage('/pages/health/physical-exam-detail')">
-            <view class="grid-icon" style="background:rgba(239,68,68,0.15)"><text>🔬</text></view>
-            <text class="grid-label">体检报告</text>
-          </view>
-          <view class="grid-item" @click="goPage('/pages/health/gut-index')">
-            <view class="grid-icon" style="background:rgba(139,92,246,0.15)"><text>🧬</text></view>
-            <text class="grid-label">肠道菌群</text>
-          </view>
-          <view class="grid-item" @click="goPage('/pages/assessment/apply')">
-            <view class="grid-icon" style="background:rgba(249,115,22,0.15)"><text>📋</text></view>
-            <text class="grid-label">测评管理</text>
-          </view>
-          <view class="grid-item" @click="goPage('/pages/assessment/execution')">
-            <view class="grid-icon" style="background:rgba(16,185,129,0.15)"><text>💡</text></view>
-            <text class="grid-label">方案中心</text>
+          <text class="data-card-arrow">›</text>
+        </view>
+
+        <view class="data-card data-card-assessment">
+          <view class="data-card-head">
+            <text class="data-card-title">在线测评</text>
+            <text class="data-card-subtitle">多维度自测评估</text>
           </view>
-          <view class="grid-item" @click="goPage('/pages/mind-detail/emotion-report')">
-            <view class="grid-icon" style="background:rgba(255,107,157,0.15)"><text>🧠</text></view>
-            <text class="grid-label">心智评估</text>
+          <view v-for="quiz in quizzes" :key="quiz.code" class="quiz-item">
+            <view class="quiz-info">
+              <text class="quiz-icon">{{ quiz.icon }}</text>
+              <text class="quiz-label">{{ quiz.label }}</text>
+            </view>
+            <view v-if="quiz.score" class="quiz-score">
+              <text class="score-value">{{ quiz.score }}</text>
+              <text class="score-unit">分</text>
+            </view>
+            <button v-else class="quiz-btn" @click.stop="goQuiz(quiz.code)">开始</button>
           </view>
         </view>
       </view>
 
-      <!-- 最近报告 -->
-      <view class="section" v-if="reports.length > 0">
+      <view class="section section-data-view">
         <view class="section-header">
-          <text class="section-title">最近报告</text>
+          <text class="section-title">最近记录</text>
           <text class="section-more" @click="goPage('/pages/health/report-list')">查看全部 ›</text>
         </view>
-        <view
-          class="report-card"
-          v-for="(report, idx) in reports.slice(0, 3)"
-          :key="idx"
-          @click="goReportDetail(report)"
-        >
-          <text class="report-icon">📄</text>
-          <view class="report-info">
-            <text class="report-name">{{ report.title || '健康报告' }}</text>
-            <text class="report-status">{{ report.status === 'resolved' ? '已解析' : '待确认' }}</text>
+        <view v-if="reports.length > 0">
+          <view class="report-card" v-for="(report, idx) in reports.slice(0, 3)" :key="idx" @click="goReportDetail(report)">
+            <text class="report-icon">📄</text>
+            <view class="report-info">
+              <text class="report-name">{{ report.title || '健康报告' }}</text>
+              <text class="report-status">{{ report.status === 'resolved' ? '已解析' : '待确认' }}</text>
+            </view>
+            <text class="report-arrow">›</text>
           </view>
-          <text class="report-arrow">›</text>
+        </view>
+        <view v-else class="empty-hint">
+          <text class="empty-text">暂无报告和测评结果</text>
+          <text class="empty-sub">上传报告或完成测评开启健康之旅</text>
         </view>
       </view>
 
-      <!-- 诊断建议 -->
-      <view class="section" v-if="diagnosisSuggestion">
-        <view class="diagnosis-card">
-          <text class="diagnosis-title">💡 诊断建议</text>
-          <text class="diagnosis-text">{{ diagnosisSuggestion }}</text>
+      <view class="section section-plan">
+        <view class="plan-card">
+          <view class="plan-head">
+            <text class="plan-title">📋 健康方案</text>
+            <button class="plan-btn" @click="goPlanSummary">{{ lastPlan ? '查看方案' : '生成新方案' }}</button>
+          </view>
+          <text v-if="lastPlan" class="plan-goal">{{ lastPlan }}</text>
+          <text v-else class="plan-hint">选维度 + 选成员 + 设定目标 → 智能生成</text>
         </view>
       </view>
 
-      <!-- 健康科普推荐 -->
-      <ArticleBookshelf
-        :articles="healthArticles"
-        :isLoggedIn="true"
-        @articleClick="goArticleDetail"
-        @moreArticles="goMoreArticles" />
+      <ArticleBookshelf :articles="healthArticles" :isLoggedIn="true" @articleClick="goArticleDetail" @moreArticles="goMoreArticles" />
     </view>
   </view>
 </template>
@@ -128,93 +102,130 @@
 import PageBanner from '../../components/PageBanner.vue'
 import LoginGuideCard from '../../components/LoginGuideCard.vue'
 import FamilyMemberStrip from '../../components/FamilyMemberStrip.vue'
+import RadarChart from '../../components/RadarChart.vue'
 import ArticleBookshelf from '../../components/ArticleBookshelf.vue'
 
 export default {
-  components: {
-    PageBanner,
-    LoginGuideCard,
-    FamilyMemberStrip,
-    ArticleBookshelf
-  },
+  components: { PageBanner, LoginGuideCard, FamilyMemberStrip, RadarChart, ArticleBookshelf },
   data() {
     return {
       isLoggedIn: false,
-      healthScore: null,
-      pendingReports: 0,
-      lastAssessmentDate: '--',
-      streakDays: 0,
+      currentTab: 'body',
+      selectedMemberName: '',
+      selectedMemberId: '',
       reports: [],
-      diagnosisSuggestion: '',
-      healthArticles: []
+      lastPlan: '',
+      healthArticles: [],
+      tabs: [
+        { code: 'body', label: '健康', icon: '🟠', color: '#FF8C42' },
+        { code: 'cognitive', label: '认知', icon: '🧠', color: '#6366F1' },
+        { code: 'mental', label: '心理', icon: '💖', color: '#FF6B9D' },
+        { code: 'relationship', label: '社会性', icon: '🤝', color: '#10B981' }
+      ],
+      quizzes: [
+        { code: 'cognitive', label: '认知能力测评', icon: '🧠', score: null },
+        { code: 'mental', label: '心理健康测评', icon: '💖', score: null },
+        { code: 'relationship', label: '关系质量测评', icon: '🤝', score: null }
+      ]
+    }
+  },
+  computed: {
+    currentTabLabel: function() {
+      var tab = this.tabs.filter(function(t) { return t.code === this.currentTab }.bind(this))[0]
+      return tab ? tab.label : ''
+    },
+    currentColor: function() {
+      var tab = this.tabs.filter(function(t) { return t.code === this.currentTab }.bind(this))[0]
+      return tab ? tab.color : '#FF8C42'
+    },
+    currentDimensions: function() {
+      if (this.currentTab === 'cognitive') {
+        return [{ label:'记忆力',key:'memory'},{ label:'注意力',key:'attention'},{ label:'逻辑推理',key:'logic'},{ label:'空间想象',key:'spatial'},{ label:'语言表达',key:'language' }]
+      }
+      if (this.currentTab === 'mental') {
+        return [{ label:'情绪稳定',key:'emotion'},{ label:'抗压能力',key:'stress'},{ label:'自我认知',key:'self'},{ label:'社交意愿',key:'social'},{ label:'幸福感',key:'happiness' }]
+      }
+      if (this.currentTab === 'relationship') {
+        return [{ label:'亲子关系',key:'parent'},{ label:'夫妻关系',key:'spouse'},{ label:'亲友关系',key:'friend'},{ label:'同事关系',key:'colleague'},{ label:'社区参与',key:'community' }]
+      }
+      return [{ label:'生长发育',key:'growth'},{ label:'睡眠质量',key:'sleep'},{ label:'视力健康',key:'vision'},{ label:'免疫力',key:'immunity'},{ label:'营养均衡',key:'nutrition'},{ label:'肠胃健康',key:'gut'},{ label:'运动活力',key:'exercise' }]
+    },
+    currentScores: function() {
+      if (this.chartIsEmpty) {
+        var dims = this.currentDimensions, scores = []
+        for (var i = 0; i < dims.length; i++) scores.push(0)
+        return scores
+      }
+      if (this.currentTab === 'body') return [72, 68, 75, 80, 70, 78, 82]
+      var dims = this.currentDimensions, scores = []
+      for (var i = 0; i < dims.length; i++) scores.push(0)
+      return scores
+    },
+    chartIsEmpty: function() {
+      if (this.currentTab === 'body') return this.reports.length === 0
+      var quiz = this.quizzes.filter(function(q) { return q.code === this.currentTab }.bind(this))[0]
+      return !(quiz && quiz.score)
     }
   },
   onShow() {
     this.isLoggedIn = !!uni.getStorageSync('token')
     if (this.isLoggedIn) {
       this.loadHealthData()
+      this.loadPlanList()
+      var stored = uni.getStorageSync('currentChildId') || ''
+      if (stored) {
+        this.selectedMemberId = stored
+        this.selectedMemberName = uni.getStorageSync('currentChildName') || '成员'
+      }
     }
   },
   methods: {
-    goPage: function(url) {
+    switchTab: function(code) { this.currentTab = code },
+    goPage: function(url) { uni.navigateTo({ url: url }) },
+    goQuiz: function(code) {
+      var url = '/pages/body-detail/dimension-questionnaire?dim=' + code
+      if (this.selectedMemberId) url += '&memberId=' + this.selectedMemberId
       uni.navigateTo({ url: url })
     },
-    getMemberId: function() {
-      // 优先当前选中的孩子/成员,兜底用登录用户 ID
-      var store = this.$store
-      if (store && store.state && store.state.currentChildId) return store.state.currentChildId
-      if (store && store.state && store.state.currentMemberId) return store.state.currentMemberId
-      if (store && store.state && store.state.userId) return store.state.userId
-      return uni.getStorageSync('userId') || ''
-    },
     goReportDetail: function(report) {
-      if (report.id) {
-        uni.navigateTo({ url: '/pages/health/report-list?reportId=' + report.id })
-      } else {
-        uni.navigateTo({ url: '/pages/health/report-list' })
-      }
+      uni.navigateTo({ url: '/pages/health/report-list' + (report && report.id ? '?reportId=' + report.id : '') })
+    },
+    goPlanSummary: function() {
+      var url = '/pages/health/health-plan-summary'
+      if (this.selectedMemberId) url += '?memberId=' + this.selectedMemberId
+      uni.navigateTo({ url: url })
     },
     loadHealthData: function() {
       var self = this
-      var memberId = this.getMemberId()
       try {
         var api = require('../../utils/api.js')
-        // 加载健康报告列表(需要 memberId)
-        api.getReportList(memberId).then(function(res) {
+        api.getReportList().then(function(res) {
           if (res.code === 200 && res.data) {
             var list = Array.isArray(res.data) ? res.data : (res.data.list || [])
             self.reports = list
-            self.pendingReports = list.filter(function(r) { return r.status !== 'resolved' }).length
-            if (list.length > 0) {
-              self.lastAssessmentDate = list[0].reportDate || '--'
-            }
           }
         }).catch(function() {})
-        // 加载健康评分
-        api.getHealthScoreInfo().then(function(res) {
-          if (res.code === 200 && res.data) {
-            self.healthScore = res.data.score || res.data.healthScore || null
-          }
-        }).catch(function() {})
-        // 加载打卡数据
-        api.getHealthStreak().then(function(res) {
-          if (res.code === 200 && res.data) {
-            self.streakDays = res.data.streakDays || res.data.days || res.data.currentStreak || 0
-          }
-        }).catch(function() {})
-        // 加载健康科普文章
-        api.getFeaturedArticles({ size: 5, dimensionCode: 'body' }).then(function(res) {
+        api.getFeaturedArticles({ size: 3, dimensionCode: 'body' }).then(function(res) {
           if (res.code === 200 && res.data) {
             var list = Array.isArray(res.data) ? res.data : (res.data.records || [])
-            self.healthArticles = list.slice(0, 5) || []
+            self.healthArticles = list.slice(0, 3) || []
           }
         }).catch(function() {})
-      } catch (e) {
-        console.error('加载健康数据失败', e)
-      }
+      } catch (e) { console.error('加载健康数据失败', e) }
+    },
+    loadPlanList: function() {
+      var self = this
+      var api = require('../../utils/api.js')
+      var data = { familyId: uni.getStorageSync('familyId') || null }
+      api.getHealthPlanList(data).then(function(res) {
+        if (res && res.code === 200 && res.data) {
+          var list = res.data.list || res.data
+          if (Array.isArray(list) && list.length > 0) self.lastPlan = list[0].goal || ''
+        }
+      }).catch(function() {})
     },
     goArticleDetail: function(article) {
-      var id = article.id || article
+      var id = article && article.id || article
       uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
     },
     goMoreArticles: function() {
@@ -225,185 +236,60 @@ export default {
 </script>
 
 <style scoped>
-.container {
-  background: #F8F8F8;
-  min-height: 100vh;
-  padding-bottom: 120rpx;
-}
-
-.section {
-  margin: 20rpx 24rpx;
-}
-
-.section-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 16rpx;
-}
-
-.section-title {
-  font-size: 30rpx;
-  font-weight: bold;
-  color: #333;
-}
-
-.section-more {
-  font-size: 24rpx;
-  color: #F97316;
-}
-
-/* 健康概览卡片 */
-.overview-card {
-  background: #fff;
-  border-radius: 20rpx;
-  padding: 28rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
-}
-
-.overview-item {
-  display: flex;
-  align-items: baseline;
-  justify-content: center;
-  margin-bottom: 20rpx;
-}
-
-.overview-label {
-  font-size: 24rpx;
-  color: #999;
-  margin-right: 12rpx;
-}
-
-.overview-value {
-  font-size: 56rpx;
-  font-weight: bold;
-  color: #F97316;
-}
-
-.overview-unit {
-  font-size: 24rpx;
-  color: #999;
-  margin-left: 4rpx;
-}
-
-.overview-divider {
-  height: 1rpx;
-  background: #f0f0f0;
-  margin: 16rpx 0;
-}
-
-.overview-grid {
-  display: flex;
-  justify-content: space-around;
-}
-
-.overview-grid-item {
-  text-align: center;
-  flex: 1;
-}
-
-.grid-value {
-  font-size: 32rpx;
-  font-weight: bold;
-  color: #333;
-  display: block;
-}
-
-.grid-label {
-  font-size: 22rpx;
-  color: #999;
-  margin-top: 4rpx;
-  display: block;
-}
-
-/* 功能入口网格 3列 */
-.grid-3col {
-  display: flex;
-  flex-wrap: wrap;
-}
-
-.grid-item {
-  width: 33.33%;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  padding: 24rpx 0;
-}
-
-.grid-icon {
-  width: 80rpx;
-  height: 80rpx;
-  border-radius: 20rpx;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-bottom: 8rpx;
-}
-
-.grid-icon text {
-  font-size: 36rpx;
-}
-
-.grid-item .grid-label {
-  font-size: 24rpx;
-  color: #666;
-}
-
-/* 最近报告 */
-.report-card {
-  display: flex;
-  align-items: center;
-  background: #fff;
-  border-radius: 16rpx;
-  padding: 20rpx;
-  margin-bottom: 12rpx;
-}
-
-.report-icon {
-  font-size: 36rpx;
-  margin-right: 16rpx;
-}
-
-.report-info {
-  flex: 1;
-}
-
-.report-name {
-  font-size: 26rpx;
-  color: #333;
-  display: block;
-  margin-bottom: 4rpx;
-}
-
-.report-status {
-  font-size: 22rpx;
-  color: #999;
-}
-
-.report-arrow {
-  font-size: 32rpx;
-  color: #ccc;
-}
-
-/* 诊断建议 */
-.diagnosis-card {
-  background: #fff;
-  border-radius: 20rpx;
-  padding: 24rpx;
-  border-left: 6rpx solid #F97316;
-}
-
-.diagnosis-title {
-  font-size: 28rpx;
-  font-weight: bold;
-  color: #333;
-  display: block;
-  margin-bottom: 12rpx;
-}
-
-.diagnosis-text {
-  font-size: 24rpx;
-  color: #666;
-  line-height: 1.6;
-}
+.container { background: #F8F8F8; min-height: 100vh; padding-bottom: 120rpx; }
+.section { margin: 16rpx 24rpx; }
+.tab-bar { display: flex; background: #fff; margin: 0 24rpx 16rpx; border-radius: 16rpx; padding: 8rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 12rpx 0; position: relative; border-radius: 12rpx; }
+.tab-item.active { background: #FFF7ED; }
+.tab-icon { font-size: 32rpx; margin-bottom: 4rpx; }
+.tab-label { font-size: 26rpx; color: #666; font-weight: 500; }
+.tab-item.active .tab-label { color: #333; font-weight: bold; }
+.tab-underline { width: 40rpx; height: 4rpx; border-radius: 2rpx; margin-top: 6rpx; }
+.section-chart { position: relative; margin: 0 24rpx 16rpx; }
+.chart-empty { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; z-index: 3; background: rgba(255,255,255,0.85); border-radius: 12rpx; padding: 20rpx 30rpx; }
+.chart-empty .empty-text { font-size: 28rpx; color: #333; font-weight: 500; display: block; }
+.chart-empty .empty-sub { font-size: 22rpx; color: #999; display: block; margin-top: 4rpx; }
+.section-dc-header { margin: 20rpx 24rpx 8rpx; }
+.dc-title-row { display: flex; align-items: center; }
+.dc-icon { font-size: 32rpx; margin-right: 8rpx; }
+.dc-title { font-size: 32rpx; font-weight: bold; color: #333; }
+.section-data-collect { margin: 8rpx 24rpx; }
+.data-card { display: flex; align-items: center; background: #fff; border-radius: 20rpx; padding: 24rpx; margin-bottom: 12rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.data-card-icon { width: 88rpx; height: 88rpx; border-radius: 20rpx; display: flex; align-items: center; justify-content: center; margin-right: 20rpx; font-size: 40rpx; }
+.data-card-info { flex: 1; }
+.data-card-title { font-size: 28rpx; font-weight: bold; color: #333; display: block; margin-bottom: 6rpx; }
+.data-card-desc { font-size: 22rpx; color: #999; }
+.data-card-arrow { font-size: 36rpx; color: #ccc; }
+.data-card-assessment { flex-direction: column; align-items: stretch; padding: 24rpx; }
+.data-card-head { display: flex; align-items: center; margin-bottom: 16rpx; }
+.data-card-subtitle { font-size: 22rpx; color: #999; margin-left: 12rpx; }
+.quiz-item { display: flex; align-items: center; padding: 16rpx 0; border-top: 1rpx solid #f0f0f0; }
+.quiz-item:first-of-type { border-top: none; }
+.quiz-info { display: flex; align-items: center; flex: 1; }
+.quiz-icon { font-size: 36rpx; margin-right: 16rpx; }
+.quiz-label { font-size: 28rpx; color: #333; }
+.quiz-score { display: flex; align-items: baseline; margin-right: 16rpx; }
+.score-value { font-size: 36rpx; font-weight: bold; color: #F97316; }
+.score-unit { font-size: 22rpx; color: #999; margin-left: 4rpx; }
+.quiz-btn { background: #F97316; color: #fff; font-size: 24rpx; border: none; border-radius: 20rpx; padding: 10rpx 30rpx; height: 56rpx; line-height: 36rpx; margin: 0; }
+.section-data-view { margin: 16rpx 24rpx; }
+.section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12rpx; }
+.section-title { font-size: 28rpx; font-weight: bold; color: #333; }
+.section-more { font-size: 24rpx; color: #F97316; }
+.report-card { display: flex; align-items: center; background: #fff; border-radius: 16rpx; padding: 16rpx 20rpx; margin-bottom: 10rpx; }
+.report-icon { font-size: 32rpx; margin-right: 16rpx; }
+.report-info { flex: 1; }
+.report-name { font-size: 24rpx; color: #333; display: block; margin-bottom: 4rpx; }
+.report-status { font-size: 20rpx; color: #999; }
+.report-arrow { font-size: 28rpx; color: #ccc; }
+.empty-hint { text-align: center; padding: 30rpx 0; background: #fff; border-radius: 16rpx; }
+.empty-hint .empty-text { font-size: 26rpx; color: #999; display: block; }
+.empty-hint .empty-sub { font-size: 22rpx; color: #ccc; display: block; margin-top: 6rpx; }
+.section-plan { margin: 8rpx 24rpx 16rpx; }
+.plan-card { background: #fff; border-radius: 20rpx; padding: 24rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.plan-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
+.plan-title { font-size: 28rpx; font-weight: bold; color: #333; }
+.plan-btn { background: linear-gradient(135deg, #F97316, #FB923C); color: #fff; font-size: 24rpx; border: none; border-radius: 20rpx; padding: 10rpx 28rpx; height: 56rpx; line-height: 36rpx; margin: 0; }
+.plan-goal { font-size: 24rpx; color: #666; line-height: 1.5; display: block; }
+.plan-hint { font-size: 22rpx; color: #999; display: block; }
 </style>

+ 180 - 0
cfc-frontend/pages/health/health-plan-summary.vue

@@ -0,0 +1,180 @@
+<template>
+  <view class="plan-container">
+    <view class="section section-generate">
+      <view class="section-title">生成新方案</view>
+      <view class="form-group">
+        <text class="form-label">选择维度</text>
+        <view class="chip-group">
+          <view v-for="tab in tabs" :key="tab.code" class="chip" :class="{ active: selectedDimensions.indexOf(tab.code) >= 0 }" @click="toggleDimension(tab.code)">
+            <text class="chip-text">{{ tab.label }}</text>
+          </view>
+        </view>
+      </view>
+      <view class="form-group">
+        <text class="form-label">选择成员</text>
+        <view class="member-select">
+          <view v-for="child in children" :key="child.memberId" class="member-chip" :class="{ active: selectedMemberId === child.memberId }" @click="selectMember(child)">
+            <text class="member-name">{{ child.name || '成员' }}</text>
+          </view>
+          <view v-if="children.length === 0" class="empty-text">暂无家庭成员</view>
+        </view>
+      </view>
+      <view class="form-group">
+        <text class="form-label">目标设定</text>
+        <textarea class="goal-input" v-model="goal" placeholder="例:改善孩子睡眠质量" :maxlength="200"></textarea>
+      </view>
+      <button class="btn-generate" :disabled="!canGenerate" @click="generatePlan">{{ loading ? '生成中...' : '生成方案' }}</button>
+    </view>
+
+    <view class="section section-result" v-if="generatedPlan">
+      <view class="section-title">方案结果</view>
+      <view class="result-card"><text class="result-content">{{ generatedPlan }}</text></view>
+      <view class="result-actions">
+        <button class="btn-save" @click="savePlan">保存方案</button>
+        <button class="btn-reset" @click="resetPlan">重新生成</button>
+      </view>
+    </view>
+
+    <view class="section section-history" v-if="planList.length > 0">
+      <view class="section-title">历史方案</view>
+      <view v-for="plan in planList" :key="plan.id" class="plan-item" @click="goToDetail(plan)">
+        <view class="plan-item-header">
+          <text class="plan-date">{{ plan.createdAt || '--' }}</text>
+          <text class="plan-member">{{ plan.memberName || '--' }}</text>
+        </view>
+        <text class="plan-goal">{{ plan.goal || '' }}</text>
+        <view class="plan-dims">
+          <text v-for="d in plan.dimensions" :key="d" class="dim-tag">{{ d }}</text>
+        </view>
+      </view>
+    </view>
+
+    <view v-if="planList.length === 0 && !generatedPlan" class="empty-state">
+      <text class="empty-icon">📋</text>
+      <text class="empty-text">暂无历史方案,生成第一个方案</text>
+    </view>
+  </view>
+</template>
+
+<script>
+import { generateHealthPlan, saveHealthPlan, getHealthPlanList, getChildren } from '@/utils/api'
+
+export default {
+  data() {
+    return {
+      tabs: [
+        { code: 'body', label: '健康' },
+        { code: 'cognitive', label: '认知' },
+        { code: 'mental', label: '心理' },
+        { code: 'relationship', label: '社会性' }
+      ],
+      selectedDimensions: [],
+      selectedMemberId: '',
+      selectedMemberName: '',
+      goal: '',
+      loading: false,
+      generatedPlan: '',
+      planList: [],
+      children: [],
+      memberId: ''
+    }
+  },
+  computed: {
+    canGenerate: function() {
+      return this.selectedDimensions.length > 0 && this.selectedMemberId !== '' && this.goal && this.goal.trim() !== '' && !this.loading
+    }
+  },
+  onLoad: function(options) {
+    this.memberId = options.memberId || uni.getStorageSync('currentChildId') || ''
+  },
+  onShow: function() {
+    this.loadChildren()
+    this.loadPlanList()
+  },
+  methods: {
+    toggleDimension: function(code) {
+      var idx = this.selectedDimensions.indexOf(code)
+      if (idx >= 0) this.selectedDimensions.splice(idx, 1)
+      else this.selectedDimensions.push(code)
+    },
+    selectMember: function(child) {
+      this.selectedMemberId = child.memberId || child.id
+      this.selectedMemberName = child.name || '成员'
+    },
+    generatePlan: function() {
+      var self = this
+      if (!self.canGenerate) return
+      self.loading = true
+      var data = { familyId: uni.getStorageSync('familyId') || null, memberIds: [self.selectedMemberId], dimensions: self.selectedDimensions.join(','), goal: self.goal.trim() }
+      generateHealthPlan(data).then(function(res) {
+        self.loading = false
+        if (res && res.code === 200 && res.data) self.generatedPlan = typeof res.data === 'string' ? res.data : JSON.stringify(res.data)
+      }).catch(function() { self.loading = false })
+    },
+    savePlan: function() {
+      var self = this
+      var data = { familyId: uni.getStorageSync('familyId') || null, memberIds: [self.selectedMemberId], memberName: self.selectedMemberName, dimensions: self.selectedDimensions.join(','), goal: self.goal.trim(), planContent: self.generatedPlan }
+      saveHealthPlan(data).then(function(res) {
+        if (res && res.code === 200) { self.generatedPlan = ''; self.loadPlanList() }
+      }).catch(function() {})
+    },
+    resetPlan: function() {
+      this.generatedPlan = ''; this.goal = ''; this.selectedDimensions = []; this.selectedMemberId = ''; this.selectedMemberName = ''
+    },
+    loadPlanList: function() {
+      var self = this
+      getHealthPlanList({ familyId: uni.getStorageSync('familyId') || null }).then(function(res) {
+        if (res && res.code === 200 && res.data) { var list = res.data.list || res.data; self.planList = Array.isArray(list) ? list : [] }
+        else self.planList = []
+      }).catch(function() { self.planList = [] })
+    },
+    loadChildren: function() {
+      var self = this
+      getChildren().then(function(res) {
+        if (res && res.code === 200 && res.data) { self.children = Array.isArray(res.data) ? res.data : []; if (self.children.length > 0 && !self.selectedMemberId) { self.selectedMemberId = self.children[0].memberId || self.children[0].id } }
+      }).catch(function() { self.children = [] })
+    },
+    goToDetail: function(plan) {
+      uni.navigateTo({ url: '/pages/health/health-plan-summary?planId=' + (plan.id || plan.planId) })
+    }
+  }
+}
+</script>
+
+<style scoped>
+.plan-container { min-height: 100vh; background: #F5F7FA; padding: 20rpx 30rpx 100rpx; }
+.section { margin-bottom: 24rpx; }
+.section-title { font-size: 32rpx; font-weight: bold; color: #333; margin-bottom: 16rpx; }
+.section-generate { background: #fff; border-radius: 20rpx; padding: 28rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.form-group { margin-bottom: 24rpx; }
+.form-label { font-size: 28rpx; color: #333; font-weight: 500; margin-bottom: 12rpx; display: block; }
+.chip-group { display: flex; flex-wrap: wrap; gap: 12rpx; }
+.chip { padding: 10rpx 28rpx; border-radius: 30rpx; background: #f0f0f0; border: 2rpx solid #e0e0e0; }
+.chip.active { background: #F97316; border-color: #F97316; }
+.chip-text { font-size: 26rpx; color: #666; }
+.chip.active .chip-text { color: #fff; }
+.member-select { display: flex; flex-wrap: wrap; gap: 12rpx; }
+.member-chip { padding: 10rpx 28rpx; border-radius: 30rpx; background: #f0f0f0; border: 2rpx solid #e0e0e0; }
+.member-chip.active { background: #FFF3E0; border-color: #F97316; }
+.member-name { font-size: 26rpx; color: #333; }
+.empty-text { font-size: 26rpx; color: #999; }
+.goal-input { width: 100%; height: 140rpx; background: #f8f8f8; border: 2rpx solid #e0e0e0; border-radius: 12rpx; padding: 16rpx 20rpx; font-size: 28rpx; color: #333; box-sizing: border-box; }
+.btn-generate { width: 100%; height: 88rpx; line-height: 88rpx; background: linear-gradient(135deg, #F97316, #FB923C); color: #fff; font-size: 32rpx; border-radius: 44rpx; border: none; text-align: center; }
+.btn-generate[disabled] { opacity: 0.5; }
+.section-result { background: #fff; border-radius: 20rpx; padding: 28rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.result-card { background: #FFF7ED; border-radius: 12rpx; padding: 24rpx; border-left: 6rpx solid #F97316; }
+.result-content { font-size: 28rpx; color: #333; line-height: 1.8; word-break: break-all; }
+.result-actions { display: flex; gap: 16rpx; margin-top: 20rpx; }
+.btn-save { flex: 1; height: 80rpx; line-height: 80rpx; background: #F97316; color: #fff; font-size: 28rpx; border-radius: 40rpx; border: none; text-align: center; }
+.btn-reset { flex: 1; height: 80rpx; line-height: 80rpx; background: #fff; color: #F97316; font-size: 28rpx; border: 2rpx solid #F97316; border-radius: 40rpx; text-align: center; }
+.plan-item { background: #fff; border-radius: 16rpx; padding: 20rpx 24rpx; margin-bottom: 12rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.plan-item-header { display: flex; justify-content: space-between; margin-bottom: 8rpx; }
+.plan-date { font-size: 24rpx; color: #999; }
+.plan-member { font-size: 26rpx; color: #F97316; font-weight: 500; }
+.plan-goal { font-size: 28rpx; color: #333; font-weight: 500; margin-bottom: 8rpx; display: block; }
+.plan-dims { display: flex; flex-wrap: wrap; gap: 8rpx; }
+.dim-tag { font-size: 22rpx; color: #F97316; background: #FFF3E0; padding: 4rpx 16rpx; border-radius: 12rpx; }
+.empty-state { display: flex; flex-direction: column; align-items: center; padding: 100rpx 0; }
+.empty-icon { font-size: 80rpx; margin-bottom: 20rpx; }
+.empty-state .empty-text { font-size: 28rpx; color: #999; }
+</style>

+ 2552 - 2546
cfc-frontend/utils/api.js

@@ -1,2547 +1,2553 @@
-import config from '@/config.js'
-
-const BASE_URL = config.API_BASE_URL
-const LANGGRAPH_URL = config.LANGGRAPH_BASE_URL
-
-var _redirectingToLogin = false
-
-function _clearAuthAndRedirect() {
-  if (_redirectingToLogin) return
-  _redirectingToLogin = true
-  uni.removeStorageSync('token')
-  uni.removeStorageSync('userId')
-  uni.removeStorageSync('currentRole')
-  uni.removeStorageSync('role')
-  uni.removeStorageSync('nickname')
-  uni.removeStorageSync('userName')
-  uni.removeStorageSync('currentChildId')
-  uni.showToast({ title: '登录已过期,请重新登录', icon: 'none' })
-  setTimeout(function() {
-    uni.reLaunch({ url: '/pages/login/login' })
-    _redirectingToLogin = false
-  }, 1500)
-}
-
-const request = (url, method = 'POST', data = {}, options = {}) => {
-  // Append query params from options to URL if provided (e.g., { guideId } for GET requests)
-  if (options && Object.keys(options).length > 0) {
-    const separator = url.includes('?') ? '&' : '?'
-    const query = Object.entries(options)
-      .filter(([_, v]) => v !== undefined && v !== null && v !== '')
-      .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
-      .join('&')
-    if (query) url = url + separator + query
-  }
-  var fullUrl = BASE_URL + url
-  const token = uni.getStorageSync('token')
-  
-  return new Promise((resolve, reject) => {
-    uni.request({
-      url: fullUrl,
-      method: method,
-      data: data,
-      header: {
-        'Content-Type': 'application/json',
-        'Authorization': token ? `Bearer ${token}` : ''
-      },
-      success: (res) => {
-        if (res.statusCode === 401 || res.data.code === 401) {
-          console.warn('[API] 401 ' + method + ' ' + fullUrl)
-          _clearAuthAndRedirect()
-          reject(res.data)
-          return
-        }
-        // 5001: 用户无家庭 — resolve 带标记,不 reject;由组件层各自渲染 FamilyEmptyState
-        if (res.data.code === 5001) {
-          console.warn('[API] 5001 ' + method + ' ' + fullUrl + ' — 无家庭')
-          try {
-            var _app = typeof getApp === 'function' ? getApp() : null
-            if (_app && _app.$store) {
-              _app.$store.commit('markNoFamily')
-            }
-          } catch (e) {}
-          var _noFamilyResp = Object.assign({}, res.data, { noFamily: true })
-          resolve(_noFamilyResp)
-          return
-        }
-        if (res.data.code === 200) {
-          resolve(res.data)
-        } else {
-          console.warn('[API] 失败 ' + method + ' ' + fullUrl + ' code=' + res.data.code + ' msg=' + (res.data.message || ''))
-          uni.showToast({
-            title: res.data.message || '请求失败',
-            icon: 'none'
-          })
-          reject(res.data)
-        }
-      },
-      fail: (err) => {
-        console.error('[API] 网络错误 ' + method + ' ' + fullUrl, err)
-        uni.showToast({
-          title: '网络请求失败',
-          icon: 'none'
-        })
-        reject(err)
-      }
-    })
-  })
-}
-
-//  LangGraph 适配层(含 Dify fallback) 
-//
-// langgraphRequest() 是 AI 对话/分析的统一入口:
-//   1. 先尝试调用 LangGraph 适配层(/api/v1/chat/completion 或 /api/v1/analysis/run)
-//   2. 若 LangGraph 不可达(网络错误/超时/非 2xx),自动回退到 Dify(/api/ai/*)
-//
-// 参数:
-//   langgraphPath  - LangGraph 端点路径(如 '/api/v1/chat/completion')
-//   langgraphBody  - 发给 LangGraph 的请求体(DifyChatRequest / DifyAnalysisRequest)
-//   difyFallbackPath - Dify 回退端点路径(如 '/api/ai/chat/send')
-//   difyFallbackData  - 发给 Dify 的请求体(原 request() 的 data 参数)
-//   difyFallbackMethod - Dify 回退请求方法(默认 'POST')
-//   difyFallbackOptions - Dify 回退请求 options(同 request() 的 options)
-//   transform - 可选,把 LangGraph 响应转成页面期望的 { code, data, ... } 结构
-//
-// 返回 Promise,resolve 形态与 request() 一致:{ code: 200, data: {...}, message: ... }
-const langgraphRequest = (opts) => {
-  var langgraphPath = opts.langgraphPath
-  var langgraphBody = opts.langgraphBody || {}
-  var difyFallbackPath = opts.difyFallbackPath
-  var difyFallbackData = opts.difyFallbackData || {}
-  var difyFallbackMethod = opts.difyFallbackMethod || 'POST'
-  var difyFallbackOptions = opts.difyFallbackOptions || {}
-  var transform = opts.transform
-
-  return new Promise((resolve, reject) => {
-    var token = uni.getStorageSync('token')
-
-    uni.request({
-      url: LANGGRAPH_URL + langgraphPath,
-      method: 'POST',
-      data: langgraphBody,
-      header: {
-        'Content-Type': 'application/json',
-        'Authorization': token ? ('Bearer ' + token) : ''
-      },
-      timeout: 30000,
-      success: (res) => {
-        // LangGraph 不可用(非 2xx)→ 回退 Dify
-        if (res.statusCode < 200 || res.statusCode >= 300) {
-          _fallbackToDify(difyFallbackPath, difyFallbackMethod, difyFallbackData, difyFallbackOptions, resolve, reject)
-          return
-        }
-        // LangGraph 成功 → 转成页面期望的 { code: 200, data: {...} } 结构
-        var lgData = res.data || {}
-        var pageData = transform ? transform(lgData) : lgData
-        resolve({ code: 200, message: 'ok', data: pageData })
-      },
-      fail: (err) => {
-        console.warn('[API] LangGraph不可达,回退Dify ' + LANGGRAPH_URL + langgraphPath, err)
-        // LangGraph 网络错误 → 回退 Dify
-        _fallbackToDify(difyFallbackPath, difyFallbackMethod, difyFallbackData, difyFallbackOptions, resolve, reject)
-      }
-    })
-  })
-}
-
-// 内部:Dify 回退(复用 request(),保持原有鉴权/错误处理/重定向逻辑)
-function _fallbackToDify(path, method, data, options, resolve, reject) {
-  request(path, method, data, options).then(resolve).catch(reject)
-}
-
-// 登录模块
-export const wechatLogin = (code, userInfo, phoneCode) => {
-  var data = { code: code, nickname: userInfo.nickname, avatar: userInfo.avatar }
-  if (phoneCode) {
-    data.phoneCode = phoneCode
-  }
-  return request('/api/auth/wechat-login', 'POST', data)
-}
-
-// 发送验证码
-export const sendCode = (data) => {
-  return request('/api/auth/send-code', 'POST', data)
-}
-
-// 手机号码验证码登录
-export const phoneLogin = (data) => {
-  return request('/api/auth/phone-login', 'POST', data)
-}
-
-//  街道地址相关 
-
-// 获取所有省份
-export const getProvinces = () => {
-  return request('/api/streets/provinces')
-}
-
-// 根据父级ID获取子级地址
-export const getStreetChildren = (parentId) => {
-  return request(`/api/streets/children/${parentId}`)
-}
-
-// 根据ID获取地址详情
-export const getStreetById = (id) => {
-  return request(`/api/streets/${id}`)
-}
-
-// 获取地址完整路径
-export const getStreetPath = (id) => {
-  return request(`/api/streets/${id}/path`)
-}
-
-// 搜索地址
-export const searchStreet = (keyword) => {
-  return request('/api/streets/search', 'POST', { keyword })
-}
-
-// 区域匹配
-export const matchByStreet = (streetId) => {
-  return request(`/api/streets/${streetId}/match`)
-}
-
-// 按区域统计
-export const getStreetStats = (level = 4) => {
-  return request('/api/streets/stats', 'POST', { level })
-}
-
-// 获取家庭详情(含地址信息)
-export const getFamilyDetail = (id) => {
-  return request(`/api/admin/families/${id}`)
-}
-
-// 更新家庭地址
-export const updateFamilyAddress = (data) => {
-  return request(`/api/admin/families/update`, 'POST', data)
-}
-
-// 按街道ID列表统计家庭数量
-export const countFamiliesByStreetIds = (streetIds) => {
-  return request('/api/admin/families/count', 'POST', { streetIds: streetIds.join(',') })
-}
-
-// 按街道ID列表统计成长规划师数量
-export const countTeachersByStreetIds = (streetIds) => {
-  return request('/api/admin/teachers/count', 'POST', { streetIds: streetIds.join(',') })
-}
-
-// 微信手机号登录(新版)
-export const wechatPhoneLogin = (data) => {
-  return request('/api/auth/wechat-phone-login', 'POST', data)
-}
-
-// 获取平台公告
-export const getNotices = () => {
-  return request('/api/notices/list', 'GET')
-}
-
-// 微信静默登录
-export const silentLogin = (code) => {
-  return request('/api/auth/silent-login', 'POST', { code })
-}
-
-// 通过openid自动登录
-export const autoLogin = (openid) => {
-  return request('/api/auth/auto-login', 'POST', { openid })
-}
-
-export const setPassword = (password) => {
-  return request('/api/auth/set-password', 'POST', { password })
-}
-
-export const verifyPassword = (password) => {
-  return request('/api/auth/verify-password', 'POST', { password })
-}
-
-// 检查手机号是否已注册
-export const checkPhone = (phone) => {
-  return request('/api/auth/check-phone', 'POST', { phone })
-}
-
-// 校验本地 token 是否仍有效(App 启动时调用;401 由 request 封装统一处理跳转登录)
-export const verifyToken = () => {
-  return request('/api/auth/verify', 'POST')
-}
-
-// 直接注册(测试环境)
-export const directRegister = (data) => {
-  return request('/api/auth/direct-register', 'POST', data)
-}
-
-// 用户模块
-export const getUserInfo = () => {
-	return request('/api/user/info', 'POST')
-}
-
-export const updateUserInfo = (data) => {
-	return request('/api/user/update', 'POST', data)
-}
-
-// 就地补充信息回写(活动报名等场景按需补充后自动回写个人资料)
-export const backfillProfile = (data) => {
-	return request('/api/user/profile/backfill', 'POST', data)
-}
-
-export const joinFamily = (inviteCode) => {
-	return request('/api/user/join-family', 'POST', { inviteCode })
-}
-
-export const createFamily = (name) => {
-	return request('/api/family/user/create-family', 'POST', { name })
-}
-
-// 确保家庭已存在:无家庭则自动创建(默认名)
-export const ensureFamily = () => {
-	var ui = uni.getStorageSync('userInfo') || {}
-	if (ui.familyId) return Promise.resolve({ alreadyExists: true, familyId: ui.familyId })
-	var name = (ui.nickname || '用户') + '的家庭'
-	return createFamily(name).then(function(res) {
-		if (res && res.code === 200 && res.data) {
-			ui.familyId = res.data
-			uni.setStorageSync('userInfo', ui)
-			try { getApp().$store.commit('setFamilyId', res.data) } catch (e) {}
-			uni.showToast({ title: '家庭创建成功', icon: 'success' })
-			return { created: true, familyId: res.data }
-		}
-		throw new Error((res && res.message) || '创建失败')
-	}).catch(function(err) {
-		uni.showToast({ title: err.message || '网络异常', icon: 'none' })
-		return { failed: true, error: err }
-	})
-}
-
-// 获取家庭所有成员(家长+孩子)
-export const getFamilyMembers = () => {
-	return request('/api/family/user/family-members', 'POST')
-}
-
-// 获取对家庭成员可见的成员列表
-export const getVisibleFamilyMembers = () => {
-	return request('/api/family/user/members/visible', 'POST')
-}
-
-// 获取以指定成员为中心的所有成员关系(关系类型+信任/亲密度/沟通评分)
-export const getPairwiseRelationships = (centerMemberId) => {
-	return request('/api/family/relationship/pairwise', 'POST', { centerMemberId })
-}
-
-// 更新成员可见性
-export const updateMemberVisibility = (memberId, memberType, showToFamily) => {
-	return request('/api/family/user/members/update-visibility', 'POST', { memberId, memberType, showToFamily })
-}
-
-export const switchMode = (mode) => {
-	return request('/api/user/switch-mode', 'POST', { mode })
-}
-
-export const switchToChild = (memberId) => {
-	return request('/api/user/switch-to-child', 'POST', { memberId })
-}
-
-export const switchBackToParent = () => {
-	return request('/api/user/switch-back-to-parent', 'POST', {})
-}
-
-export const switchBackVerify = (password) => {
-	return request('/api/family/user/switch-back-verify', 'POST', { password })
-}
-
-export const getUserRoles = () => {
-	return request('/api/user/roles', 'POST')
-}
-
-export const switchRole = (role) => {
-	return request('/api/user/switch-role', 'POST', { role })
-}
-
-// 会员模块
-export const getMembershipLevels = () => {
-	return request('/api/membership/levels', 'POST')
-}
-
-export const getMembershipPlans = () => {
-	return request('/api/membership/plans', 'POST')
-}
-
-export const getMyMembership = () => {
-	return request('/api/membership/my', 'POST')
-}
-
-export const getCurrentLevel = () => {
-	return request('/api/membership/current', 'POST')
-}
-
-export const createOrder = (levelCode, paymentType, period, couponId) => {
-	var data = { levelCode: levelCode, paymentType: paymentType }
-	if (period) {
-		data.period = period
-	}
-	if (couponId) {
-		data.couponId = couponId
-	}
-	return request('/api/membership/orders', 'POST', data)
-}
-
-export const nextOrder = (orderNo) => {
-	return request('/api/membership/orders/continue', 'POST', { orderNo: orderNo })
-}
-
-export const getAuthorizations = () => {
-	return request('/api/parent/authorizations', 'POST')
-}
-
-export const getChildren = () => {
-  return request('/api/family/user/children/list', 'POST')
-}
-
-export const getParentDashboard = () => {
-  return request('/api/parent/dashboard', 'POST')
-}
-
-export const getSystemBalance = (memberId) => {
-  return request('/api/points/system-balance', 'POST', { memberId })
-}
-
-export const createChild = (data) => {
-  return request('/api/family/user/children', 'POST', data)
-}
-
-export const updateChild = (memberId, data) => {
-  return request('/api/family/user/children/update', 'POST', Object.assign({}, data, { memberId: memberId }))
-}
-
-// 家庭成员模块(统一添加成员)
-export const addFamilyMember = (data) => {
-  return request('/api/family/member/add', 'POST', data)
-}
-
-export const listFamilyMembers = () => {
-  return request('/api/family/member/list', 'POST')
-}
-
-// 用户同意记录
-export const recordConsent = (data) => {
-  return request('/api/consent/record', 'POST', data)
-}
-export const withdrawConsent = (data) => {
-  return request('/api/consent/withdraw', 'POST', data)
-}
-export const getConsentStatus = () => {
-  return request('/api/consent/status', 'POST')
-}
-
-// 数据使用授权
-export const getDataPermission = () => {
-  return request('/api/data-permission/get', 'POST')
-}
-export const updateDataPermission = (data) => {
-  return request('/api/data-permission/update', 'POST', data)
-}
-
-export const switchToFamilyMember = (memberId, source) => {
-  return request('/api/family/member/switch', 'POST', { memberId, source })
-}
-
-export const kickFamilyMemberById = (memberId) => {
-  return request('/api/family/member/kick', 'POST', { memberId })
-}
-
-export const updateFamilyMember = (data) => {
-  return request('/api/family/member/update', 'POST', data)
-}
-
-// 任务模块
-export const createTask = (data) => {
-  return request('/api/tasks', 'POST', data)
-}
-
-export const getTodayTasks = (memberId) => {
-  return request('/api/tasks/today', 'POST', { memberId })
-}
-
-export const getPendingReviewTasks = () => {
-  return request('/api/tasks/pending-review', 'POST')
-}
-
-export const approveTask = (taskId) => {
-  return request(`/api/tasks/${taskId}/review`, 'POST', { approved: true })
-}
-
-export const rejectTask = (taskId) => {
-  return request(`/api/tasks/${taskId}/review`, 'POST', { approved: false })
-}
-
-export const completeTask = (taskId, memberId, photoUrl) => {
-  return request(`/api/tasks/${taskId}/complete`, 'POST', { memberId, photoUrl })
-}
-
-export const reviewTask = (taskId, data) => {
-  return request(`/api/tasks/${taskId}/review`, 'POST', data)
-}
-
-export const getTaskHistory = (memberId, page = 1, size = 10) => {
-  return request('/api/tasks/history', 'POST', { memberId, page, size })
-}
-
-export const deleteTask = (taskId) => {
-  return request(`/api/tasks/${taskId}`, 'DELETE')
-}
-
-export const batchCompleteTasks = (taskIds) => {
-  return request('/api/tasks/batch-complete', 'POST', { taskIds })
-}
-
-export const batchDeleteTasks = (taskIds) => {
-  return request('/api/tasks/batch-delete', 'POST', { taskIds })
-}
-
-// 积分模块
-export const getPointsBalance = (memberId) => {
-  return request('/api/points/balance', 'POST', { memberId })
-}
-
-export const getPointsLogs = (memberId, page = 1, size = 10) => {
-  return request('/api/points/logs', 'POST', { memberId, page, size })
-}
-
-export const adjustPoints = (memberId, amount, reason, password) => {
-  return request('/api/points/adjust', 'POST', { memberId, amount, reason, password })
-}
-
-// 奖励模块
-export const createReward = (data) => {
-  return request('/api/rewards', 'POST', data)
-}
-
-export const getWishlist = (memberId) => {
-  return request('/api/rewards/wishlist', 'POST', { memberId })
-}
-
-export const exchangeReward = (rewardId, memberId) => {
-  return request(`/api/rewards/${rewardId}/exchange`, 'POST', { memberId })
-}
-
-export const approveReward = (rewardId, approved) => {
-  return request(`/api/rewards/${rewardId}/approve`, 'POST', { approved })
-}
-
-export const getRewardTemplates = () => {
-  return request('/api/rewards/templates', 'POST')
-}
-
-export const getExchangeHistory = (memberId, page = 1, size = 10) => {
-  return request('/api/rewards/exchange-history', 'POST', { memberId, page, size })
-}
-
-// ===
-// 家长任务模块(孩子分配给家长的任务)
-// ===
-export const getTodayParentTasks = () => {
-  return request('/api/tasks/today-parent', 'POST')
-}
-
-export const completeParentTask = (taskId) => {
-  return request(`/api/tasks/${taskId}/complete-parent`, 'POST', {})
-}
-
-// ===
-// 家庭成员任务分配模块
-// ===
-export const getMyPendingTasks = (memberId) => {
-  return request('/api/tasks/my-pending', 'POST', { memberId })
-}
-
-export const acceptTask = (taskId, memberId) => {
-  return request('/api/tasks/accept', 'POST', { taskId, memberId })
-}
-
-// ===
-// 家长心愿单模块
-// ===
-export const createParentWishlist = (data) => {
-  return request('/api/parent/wishlist', 'POST', data)
-}
-
-export const getParentWishlist = () => {
-  return request('/api/parent/wishlist/list', 'POST')
-}
-
-export const getFamilyWishlist = () => {
-  return request('/api/parent/wishlist/family', 'POST')
-}
-
-export const exchangeParentWishlist = (id) => {
-  return request(`/api/parent/wishlist/${id}/exchange`, 'POST', {})
-}
-
-// 家长审批孩子的心愿并填写积分
-export const approveParentWishlist = (id, pointsRequired) => {
-  return request(`/api/parent/wishlist/${id}/approve`, 'POST', { pointsRequired })
-}
-
-// ===
-// 家长心愿管理模块
-// ===
-export const getPendingWishes = () => {
-  return request('/api/wishes/pending', 'POST', {})
-}
-
-export const getWishes = (params) => {
-  return request('/api/wishes/list', 'POST', params)
-}
-
-export const setWishPrice = (wishId, points) => {
-  return request(`/api/wishes/${wishId}/price`, 'POST', { pointsRequired: points })
-}
-
-export const rejectWish = (wishId, reason) => {
-  return request(`/api/wishes/${wishId}/reject`, 'POST', { reason })
-}
-
-export const approveWishExchange = (wishId, approved) => {
-  return request(`/api/wishes/${wishId}/approve-exchange`, 'POST', { approved })
-}
-
-export const markWishFulfilled = (wishId) => {
-  return request(`/api/wishes/${wishId}/fulfill`, 'POST', {})
-}
-
-export const createWish = (data) => {
-  return request('/api/wishes/create', 'POST', data)
-}
-
-export const getWishById = (id) => {
-  return request(`/api/wishes/${id}`, 'POST', {})
-}
-
-export const requestWishExchange = (id) => {
-  return request(`/api/wishes/${id}/exchange`, 'POST', {})
-}
-
-export const confirmWishReceived = (id) => {
-  return request(`/api/wishes/${id}/confirm`, 'PUT', {})
-}
-
-export const cancelWish = (id, reason) => {
-  return request(`/api/wishes/${id}`, 'DELETE', { reason })
-}
-
-// ===
-// 成长规划师/任务模板模块
-// ===
-// 生成绑定邀请
-export const generateBindInvite = () => {
-  return request('/api/guide/bind/invite', 'POST')
-}
-
-// 获取绑定的家庭列表
-export const getBoundFamilies = () => {
-  return request('/api/guide/families', 'POST')
-}
-
-// 确认绑定家庭
-export const confirmBind = (data) => {
-  return request('/api/guide/bind/confirm', 'POST', data)
-}
-
-// 解除绑定
-export const unbindFamily = (id) => {
-  return request(`/api/guide/bind/${id}`, 'DELETE')
-}
-
-// 创建任务模板
-export const createPackage = (data) => {
-  return request('/api/packages', 'POST', data)
-}
-
-// 更新任务模板
-export const updatePackage = (id, data) => {
-  return request(`/api/packages/${id}`, 'PUT', data)
-}
-
-// 获取任务模板详情
-export const getPackage = (id) => {
-  return request(`/api/packages/${id}`, 'POST')
-}
-
-// 获取我的任务模板列表
-export const getMyPackages = () => {
-  return request('/api/packages', 'POST')
-}
-
-// 提交审核
-export const submitPackageForReview = (id) => {
-  return request(`/api/packages/${id}/submit`, 'POST')
-}
-
-// 发布/下架
-export const publishPackage = (id, publish) => {
-  return request(`/api/packages/${id}/publish`, 'POST', {}, { publish })
-}
-
-// 添加任务项
-export const addPackageItem = (packageId, data) => {
-  return request(`/api/packages/${packageId}/items`, 'POST', data)
-}
-
-// 更新任务项
-export const updatePackageItem = (itemId, data) => {
-  return request(`/api/packages/items/${itemId}`, 'PUT', data)
-}
-
-// 删除任务项
-export const deletePackageItem = (itemId) => {
-  return request(`/api/packages/items/${itemId}`, 'DELETE')
-}
-
-// 获取任务模板任务项
-export const getPackageItems = (packageId) => {
-  return request(`/api/packages/${packageId}/items`, 'POST')
-}
-
-// 获取公开任务模板列表
-export const getPublicPackages = (category) => {
-  return request('/api/market/packages', 'POST', { category })
-}
-
-// 通过分享码获取任务模板
-export const getPackageByShareCode = (code) => {
-  return request(`/api/market/share/${code}`, 'POST')
-}
-
-// 购买并应用任务模板
-export const purchasePackage = (packageId, data) => {
-  return request(`/api/market/packages/${packageId}/purchase`, 'POST', data)
-}
-
-// 获取我的任务计划
-export const getMyPlans = () => {
-  return request('/api/market/plans', 'POST')
-}
-
-// 获取计划详情
-export const getPlanDetail = (id) => {
-  return request(`/api/market/plans/${id}`, 'POST')
-}
-
-// 取消计划
-export const cancelPlan = (id) => {
-  return request(`/api/market/plans/${id}/cancel`, 'POST')
-}
-
-// 确认绑定成长规划师
-export const acceptBind = (data) => {
-  return request('/api/bind/accept', 'POST', data)
-}
-
-// 获取绑定的成长规划师列表
-export const getBoundGuides = () => {
-  return request('/api/bind/guides', 'POST')
-}
-
-// 成长规划师注册
-export const registerGuide = (data) => {
-  return request('/api/guide/register', 'POST', data)
-}
-
-// 生成邀请码
-export const generateInviteCode = () => {
-  return request('/api/guide/invite-code/generate', 'POST')
-}
-
-// 获取邀请码列表
-export const getInviteCodes = () => {
-  return request('/api/guide/invite-codes', 'GET')
-}
-
-// 验证邀请码
-export const validateInviteCode = (code) => {
-  return request('/api/guide/invite-code/validate', 'GET', null, { code })
-}
-
-export const checkTeamInviteStatus = (inviteCode) => {
-  return request('/api/guide/team/check-status', 'POST', { inviteCode })
-}
-
-export const joinTeamByInvite = (inviteCode) => {
-  return request('/api/guide/team/join-by-invite', 'POST', { inviteCode })
-}
-
-export const leaveCurrentTeam = () => {
-  return request('/api/guide/team/leave', 'POST')
-}
-
-// 获取下级成长规划师列表
-export const getChildGuides = () => {
-  return request('/api/guide/child-guides', 'GET')
-}
-
-// 获取所有下级成长规划师
-export const getAllChildGuides = () => {
-  return request('/api/guide/all-child-guides', 'GET')
-}
-
-// 获取上级成长规划师
-export const getParentGuide = () => {
-  return request('/api/guide/parent-guide', 'GET')
-}
-
-// ===== 训练方案管理 =====
-export const getTrainingPlanList = (memberId) => {
-  return request('/api/guide/training-plans/list', 'POST',
-    memberId ? { memberId } : {})
-}
-
-export const getTrainingPlanDetail = (planId) => {
-  return request('/api/guide/training-plans/detail', 'POST', { planId })
-}
-
-export const createTrainingPlan = (memberId, title, description) => {
-  return request('/api/guide/training-plans/create', 'POST', { memberId, title, description })
-}
-
-export const updateTrainingPlan = (planId, title, description) => {
-  return request('/api/guide/training-plans/update', 'POST', { planId, title, description })
-}
-
-export const addTrainingPlanItem = (item) => {
-  return request('/api/guide/training-plans/items/add', 'POST', item)
-}
-
-export const updateTrainingPlanItem = (item) => {
-  return request('/api/guide/training-plans/items/update', 'POST', item)
-}
-
-export const deleteTrainingPlanItem = (itemId) => {
-  return request('/api/guide/training-plans/items/delete', 'POST', { itemId })
-}
-
-export const generatePlanFromRecommendations = (memberId) => {
-  return request('/api/guide/training-plans/generate-from-recommendations', 'POST', { memberId })
-}
-
-export const deleteTrainingPlan = (planId) => {
-  return request('/api/guide/training-plans/delete', 'POST', { planId })
-}
-
-// ===== 活动管理 =====
-export const getGuideActivityList = (status) => {
-  return request('/api/guide/activities/list', 'POST', status ? { status } : {})
-}
-
-export const getGuideActivityDetail = (activityId) => {
-  return request('/api/guide/activities/detail', 'POST', { activityId })
-}
-
-export const createActivity = (activity) => {
-  return request('/api/guide/activities/create', 'POST', activity)
-}
-
-export const updateActivity = (activity) => {
-  return request('/api/guide/activities/update', 'POST', activity)
-}
-
-export const publishActivity = (activityId) => {
-  return request('/api/guide/activities/publish', 'POST', { activityId })
-}
-
-export const cancelActivity = (activityId) => {
-  return request('/api/guide/activities/cancel', 'POST', { activityId })
-}
-
-export const deleteActivity = (activityId) => {
-  return request('/api/guide/activities/delete', 'POST', { activityId })
-}
-
-// 添加成长规划师任务模板
-export const addGuidePackage = (guideId, packageId, price, commissionRate) => {
-  return request('/api/guide/package/add', 'POST', { guideId, packageId, price, commissionRate })
-}
-
-// 获取成长规划师套餐列表
-export const getGuidePackages = (guideId) => {
-  return request('/api/guide/packages', 'GET', null, { guideId })
-}
-
-// 获取成长规划师套餐定价
-export const getGuidePackage = (guideId, packageId) => {
-  return request('/api/guide/package/' + packageId, 'GET', null, { guideId })
-}
-
-// 更新成长规划师套餐价格
-export const updateGuidePackagePrice = (guideId, packageId, price) => {
-  return request('/api/guide/package/' + packageId, 'PUT', { guideId, price })
-}
-
-// 删除成长规划师套餐
-export const deleteGuidePackage = (guideId, packageId) => {
-  return request('/api/guide/package/' + packageId, 'DELETE', null, { guideId })
-}
-
-// 获取套餐价格
-export const getPackagePrice = (packageId, guideId, inviteCode) => {
-  return request('/api/package/price', 'GET', null, { packageId, guideId, inviteCode })
-}
-
-// 获取可用的成长规划师列表
-export const getAvailableGuides = (packageId) => {
-  return request('/api/package/available-guides', 'GET', null, { packageId })
-}
-
-// 创建套餐订单
-export const createPackageOrder = (data) => {
-  return request('/api/package/order/create', 'POST', data)
-}
-
-// 获取订单状态
-export const getOrderStatus = (orderNo) => {
-  return request('/api/payment/order/status/' + orderNo, 'GET')
-}
-
-// 创建微信支付订单
-export const createWechatPayOrder = (orderNo, description, amount) => {
-  return request('/api/payment/wechat/create', 'POST', { orderNo, description, amount })
-}
-
-// 创建支付宝订单
-export const createAlipayOrder = (orderNo, description, amount) => {
-  return request('/api/payment/alipay/create', 'POST', { orderNo, description, amount })
-}
-
-// 处理微信支付回调
-export const handleWechatCallback = (params) => {
-  return request('/api/payment/wechat/callback', 'POST', params)
-}
-
-// 澶勭悊鏀粯瀹濆洖璋?
-export const handleAlipayCallback = (params) => {
-  return request('/api/payment/alipay/callback', 'POST', params)
-}
-
-// 获取我的测评报告
-export const getMyAssessmentResults = () => {
-  return request('/api/dan-assessment/my-results', 'POST', {})
-}
-
-// 获取下级成长规划师的测评报告
-export const getChildAssessmentResults = () => {
-  return request('/api/dan-assessment/child-results', 'POST', {})
-}
-
-// 获取测评报告详情
-export const getAssessmentResult = (id) => {
-  return request('/api/dan-assessment/result/' + id, 'POST')
-}
-
-// 创建测评预约
-export const createAssessmentAppointment = (data) => {
-  return request('/api/dan-assessment/appointment/create', 'POST', data)
-}
-
-// 支付测评订单
-export const payAssessmentOrder = (orderNo, payType) => {
-  return request('/api/dan-assessment/order/pay', 'POST', { orderNo, payType })
-}
-
-//  虚拟支付 
-
-// 创建测评订单(返回 AssessmentOrder,含 orderNo)
-export const createAssessmentOrder = (data) => {
-  return request('/api/dan-assessment/order/create', 'POST', data)
-}
-
-// 获取测评订单详情(轮询支付状态用;status: pending/paid/cancelled/refunded)
-export const getAssessmentOrderDetail = (orderNo) => {
-  return request('/api/dan-assessment/order/detail', 'POST', null, { orderNo })
-}
-
-// 虚拟支付参数薄包装(决策#7:各链路下单接口内联返回 VirtualPayParamsDTO,无独立端点)
-// ASSESSMENT → 测评订单支付(/order/pay 内联返回 DTO;testMode 返回 null)
-// MEMBERSHIP/SUBSCRIPTION → 下单接口已内联返回,调用方直接使用下单返回值,此处透传 orderNo
-export const createVirtualPayOrder = (orderNo, goodsType) => {
-  if (goodsType === 'ASSESSMENT') {
-    return payAssessmentOrder(orderNo, 'wechat')
-  }
-  return Promise.resolve({ orderNo: orderNo, goodsType: goodsType })
-}
-
-// 虚拟支付失败上报(诊断用):wx.requestVirtualPayment fail 时 fire-and-forget 上报到后端,
-// 让支付失败原因在后端日志可见(正式版小程序前端 console 无法远程查看)。
-// 独立 uni.request 实现,不弹 toast、不影响主流程。
-export const reportVirtualPayError = (outTradeNo, errCode, errMsg, scene) => {
-  try {
-    uni.request({
-      url: BASE_URL + '/api/internal/virtual-pay/error-report',
-      method: 'POST',
-      data: {
-        outTradeNo: outTradeNo,
-        errCode: errCode,
-        errMsg: errMsg,
-        scene: scene
-      },
-      header: { 'Content-Type': 'application/json' },
-      success: function(res) {
-        if (res.data && res.data.code !== 200) console.warn('[虚拟支付] 失败上报接口异常', res.data)
-      },
-      fail: function() { /* 上报失败静默处理,不打扰用户 */ }
-    })
-  } catch (e) { /* 上报异常静默处理 */ }
-}
-
-// 拉起微信小程序虚拟支付(官方 API 形态;基础库 2.19.2+,回调风格)
-// params = VirtualPayParamsDTO { orderInfo, sign, signature }
-export const requestVirtualPayment = (params, callbacks) => {
-  if (!wx.canIUse('requestVirtualPayment')) {
-    if (callbacks && callbacks.fail) {
-      callbacks.fail({ errMsg: '当前微信版本不支持虚拟支付' })
-    }
-    return
-  }
-  var dto = params || {}
-  wx.requestVirtualPayment({
-    signData: JSON.stringify(dto.orderInfo || {}),
-    paySig: dto.sign || '',
-    signature: dto.signature || '',
-    mode: 'short_series_goods',
-    success: function(res) { if (callbacks && callbacks.success) callbacks.success(res) },
-    fail: function(err) {
-      console.error('[虚拟支付] wx.requestVirtualPayment fail', err, 'signData=', JSON.stringify(dto.orderInfo || {}))
-      var orderNo = dto.orderInfo && dto.orderInfo.outTradeNo
-      reportVirtualPayError(orderNo, err && err.errCode, err && err.errMsg, 'requestVirtualPayment')
-      if (callbacks && callbacks.fail) callbacks.fail(err)
-    }
-  })
-}
-
-// 虚拟支付环境(官方仅 0=正式/1=沙箱;signData 内 env 由后端按 virtual-pay-env 生成)
-// 本函数为计划保留的工具函数(日志/调试用);develop→1(沙箱)、trial→1(沙箱)、release→0(正式)
-export const getVirtualPaymentEnv = () => {
-  try {
-    var info = uni.getAccountInfoSync()
-    var env = info.miniProgram && info.miniProgram.envVersion
-    if (env === 'develop' || env === 'trial') return 1
-    return 0
-  } catch (e) {
-    return 0
-  }
-}
-
-// 记录测评结果
-export const recordAssessmentResult = (data) => {
-  return request('/api/dan-assessment/result/record', 'POST', data)
-}
-
-// 鎵撳崱妯″潡
-export const getStreakProgress = (memberId) => {
-  return request(`/api/streak/progress/${memberId}`, 'POST')
-}
-
-// 浠诲姟鎻愰啋
-export const getTasksNeedReminder = (memberId) => {
-  return request(`/api/task-reminders/reminder/${memberId}`, 'POST')
-}
-
-export const getUpcomingTasks = (memberId, minutes = 60) => {
-  return request(`/api/task-reminders/upcoming/${memberId}`, 'POST', { minutes })
-}
-
-export const getOverdueTasks = (memberId) => {
-  return request(`/api/task-reminders/overdue/${memberId}`, 'POST')
-}
-
-// 灏忔父鎴忔ā鍧?
-export const getMiniGameList = () => {
-  return request('/api/mini-game/list', 'POST')
-}
-
-export const getMiniGameByCode = (gameCode) => {
-  return request(`/api/mini-game/${gameCode}`, 'POST')
-}
-
-export const completeMiniGame = (memberId, gameCode, completionTime, score) => {
-  return request('/api/mini-game/complete', 'POST', { 
-    memberId, 
-    gameCode, 
-    completionTime, 
-    score 
-  })
-}
-
-// 娓告垙璁板綍
-export const saveGameRecord = (params) => {
-  return request('/api/game/record', 'POST', params)
-}
-
-export const getGameHistory = (params) => {
-  return request('/api/game/history', 'POST', params)
-}
-
-export const getGameBestScores = (params) => {
-  return request('/api/game/best', 'POST', params)
-}
-
-export const getGameStats = (params) => {
-  return request('/api/game/stats', 'POST', params)
-}
-
-export const getGameLeaderboard = (params) => {
-  return request('/api/game/leaderboard', 'POST', params)
-}
-
-// 邀请码相关
-export const getInviteCode = () => {
-  return request('/api/family/invite-code', 'GET')
-}
-
-export const generateFamilyInviteCode = () => {
-  return request('/api/family/invite-code/generate', 'POST')
-}
-
-export const bindGuideFamily = (inviteCode) => {
-  return request('/api/family/guide-bind', 'POST', { inviteCode })
-}
-
-export const registerWithInviteCode = (data) => {
-  return request('/api/auth/register-with-invite', 'POST', data)
-}
-
-// 成长记录
-export const createGrowthRecord = (data) => {
-  // 如果包含 alsoPurchaseAssessment 字段,使用合并接口
-  if (data.alsoPurchaseAssessment) {
-    return request('/api/growth/record/create-with-order', 'POST', data)
-  }
-  return request('/api/growth/record/create', 'POST', data)
-}
-export const getGrowthRecordList = () => {
-  return request('/api/growth/record/list', 'POST')
-}
-export const getChildRecords = (memberId) => {
-  return request('/api/growth/record/child/' + memberId, 'POST')
-}
-export const getGrowthRecordDetail = (id) => {
-  return request('/api/growth/record/' + id, 'POST')
-}
-export const deleteGrowthRecord = (id) => {
-  return request('/api/growth/record/' + id + '/delete', 'POST')
-}
-
-export const uploadAndParseReport = (filePath) => {
-  return new Promise((resolve, reject) => {
-    const token = uni.getStorageSync('token')
-    uni.uploadFile({
-      url: BASE_URL + '/api/growth/record/upload-and-parse',
-      filePath: filePath,
-      name: 'file',
-      header: {
-        'Authorization': token ? 'Bearer ' + token : ''
-      },
-      success: (res) => {
-        const data = JSON.parse(res.data)
-        if (data.code === 200) {
-          resolve(data)
-        } else {
-          console.warn('[API] 上传失败 ' + BASE_URL + '/api/growth/record/upload-and-parse' + ' code=' + data.code + ' msg=' + (data.message || ''))
-          reject(data)
-        }
-      },
-      fail: (err) => {
-        console.error('[API] 上传网络错误 ' + BASE_URL + '/api/growth/record/upload-and-parse', err)
-        reject(err)
-      }
-    })
-  })
-}
-
-export const createGrowthRecordFromUpload = (data) => {
-  return request('/api/growth/record/create-from-upload', 'POST', data)
-}
-
-export const createGrowthSupplement = (data) => {
-  return request('/api/growth/record/supplement', 'POST', data)
-}
-
-export const checkGrowthDuplicate = (data) => {
-  return request('/api/growth/record/check-duplicate', 'POST', data)
-}
-
-export const getGrowthSupplements = (id) => {
-  return request('/api/growth/record/' + id + '/supplements', 'POST')
-}
-
-// 成长规划师模块API
-export const getTeamMembers = () => {
-  return request('/api/guide/team/members', 'POST')
-}
-
-export const getTeamStats = () => {
-  return request('/api/guide/team/stats', 'POST')
-}
-
-export const getGuideMessages = () => {
-  return request('/api/guide/messages/list', 'POST')
-}
-
-export const getGuideOrders = () => {
-  return request('/api/guide/orders/list', 'POST')
-}
-
-export const getOrderStats = () => {
-  return request('/api/guide/orders/stats', 'POST')
-}
-
-// 任务完成率统计
-export const getChildCompletionStats = (params) => {
-  return request('/api/stats/child-completion', 'POST', params)
-}
-
-export const getFamilyCompletionStats = (params) => {
-  return request('/api/stats/family-completion', 'POST', params)
-}
-
-export const generateInviteCard = (type, refId) => {
-  if (type === 'child') {
-    return request('/api/invite-card/generate', 'POST', { type, refId })
-  }
-  return request('/api/invite-card/generate', 'POST', { type })
-}
-
-export const verifyInviteCard = (code) => {
-  return request('/api/invite-card/verify', 'POST', { code })
-}
-
-export const acceptInviteCard = (code, phone) => {
-  return request('/api/invite-card/accept', 'POST', { code, phone })
-}
-
-// 瑙勫垝甯堥個璇峰闀?
-export const generateParentInvite = () => {
-  return request('/api/guide/parent-invite/generate', 'POST', {})
-}
-
-export const acceptParentInvite = (code) => {
-  return request('/api/guide/parent-invite/accept', 'POST', { code })
-}
-
-// 踢出家庭成员(仅管理员)
-export const kickFamilyMember = (targetUserId) => {
-  return request('/api/family/user/kick', 'POST', { targetUserId })
-}
-
-// 家庭邀请二维码
-export const generateFamilyInviteQrCode = () => {
-  return request('/api/family/invite/qrcode', 'POST')
-}
-
-// ===== 瀹跺涵閭€璇凤紙浠ょ墝鐗堬紝鏀寔鎵爜娴侊級 =====
-
-// 鐢熸垚瀹跺涵閭€璇凤紙鍚皬绋嬪簭鐮佹垨浜岀淮鐮侊級
-export const generateFamilyInvite = () => {
-  return request('/api/family/invite/generate', 'POST')
-}
-
-// 楠岃瘉閭€璇蜂护鐗?
-export const validateInvitation = (token) => {
-  return request('/api/family/invite/validate', 'POST', { token })
-}
-
-// 接受邀请(加入家庭)
-export const acceptInvitation = (token, familyRole, mergeFamily) => {
-  return request('/api/family/invite/accept', 'POST', { token, familyRole, mergeFamily: !!mergeFamily })
-}
-
-export const generateQrCodeFromText = (content) => {
-  return request('/api/common/qrcode', 'POST', { content })
-}
-
-// 检查当前用户家庭状态
-export const checkUserFamily = () => {
-  return request('/api/family/invite/check-family', 'POST')
-}
-
-// 杞瀹跺涵绠$悊鍛?
-export const transferFamilyAdmin = (newAdminId) => {
-  return request('/api/family/invite/transfer-admin', 'POST', { newAdminId })
-}
-
-// 通过邀请码申请加入家庭(需管理员审批)
-export const requestJoinByCode = (inviteCode, familyRole) => {
-  return request('/api/family/invite/request-join-by-code', 'POST', { inviteCode: inviteCode, familyRole: familyRole || '' })
-}
-
-// 查询待审批加入请求(管理员)
-export const getPendingJoinRequests = () => {
-  return request('/api/family/invite/pending-requests', 'POST', {})
-}
-
-// 审批加入请求(管理员)
-export const approveJoinRequest = (requestId, comment) => {
-  return request('/api/family/invite/approve-request', 'POST', { requestId: requestId, comment: comment || '' })
-}
-
-// 拒绝加入请求(管理员)
-export const rejectJoinRequest = (requestId, comment) => {
-  return request('/api/family/invite/reject-request', 'POST', { requestId: requestId, comment: comment || '' })
-}
-
-// 查询我的加入请求
-export const getMyJoinRequest = () => {
-  return request('/api/family/invite/my-request', 'POST', {})
-}
-
-// 取消我的加入请求
-export const cancelMyJoinRequest = (requestId) => {
-  return request('/api/family/invite/cancel-request', 'POST', { requestId: requestId })
-}
-
-// ===== 家庭加入请求 API 别名(供组件统一引用)=====
-export const getPendingFamilyRequests = () => {
-  return request('/api/family/invite/pending-requests', 'POST', {})
-}
-export const approveFamilyJoinRequest = (requestId) => {
-  return request('/api/family/invite/approve-request', 'POST', { requestId: requestId })
-}
-export const rejectFamilyJoinRequest = (requestId) => {
-  return request('/api/family/invite/reject-request', 'POST', { requestId: requestId })
-}
-export const getMyPendingRequest = () => {
-  return request('/api/family/invite/my-request', 'POST', {})
-}
-
-// ===== AI 聊天 =====
+import config from '@/config.js'
+
+const BASE_URL = config.API_BASE_URL
+const LANGGRAPH_URL = config.LANGGRAPH_BASE_URL
+
+var _redirectingToLogin = false
+
+function _clearAuthAndRedirect() {
+  if (_redirectingToLogin) return
+  _redirectingToLogin = true
+  uni.removeStorageSync('token')
+  uni.removeStorageSync('userId')
+  uni.removeStorageSync('currentRole')
+  uni.removeStorageSync('role')
+  uni.removeStorageSync('nickname')
+  uni.removeStorageSync('userName')
+  uni.removeStorageSync('currentChildId')
+  uni.showToast({ title: '登录已过期,请重新登录', icon: 'none' })
+  setTimeout(function() {
+    uni.reLaunch({ url: '/pages/login/login' })
+    _redirectingToLogin = false
+  }, 1500)
+}
+
+const request = (url, method = 'POST', data = {}, options = {}) => {
+  // Append query params from options to URL if provided (e.g., { guideId } for GET requests)
+  if (options && Object.keys(options).length > 0) {
+    const separator = url.includes('?') ? '&' : '?'
+    const query = Object.entries(options)
+      .filter(([_, v]) => v !== undefined && v !== null && v !== '')
+      .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
+      .join('&')
+    if (query) url = url + separator + query
+  }
+  var fullUrl = BASE_URL + url
+  const token = uni.getStorageSync('token')
+  
+  return new Promise((resolve, reject) => {
+    uni.request({
+      url: fullUrl,
+      method: method,
+      data: data,
+      header: {
+        'Content-Type': 'application/json',
+        'Authorization': token ? `Bearer ${token}` : ''
+      },
+      success: (res) => {
+        if (res.statusCode === 401 || res.data.code === 401) {
+          console.warn('[API] 401 ' + method + ' ' + fullUrl)
+          _clearAuthAndRedirect()
+          reject(res.data)
+          return
+        }
+        // 5001: 用户无家庭 — resolve 带标记,不 reject;由组件层各自渲染 FamilyEmptyState
+        if (res.data.code === 5001) {
+          console.warn('[API] 5001 ' + method + ' ' + fullUrl + ' — 无家庭')
+          try {
+            var _app = typeof getApp === 'function' ? getApp() : null
+            if (_app && _app.$store) {
+              _app.$store.commit('markNoFamily')
+            }
+          } catch (e) {}
+          var _noFamilyResp = Object.assign({}, res.data, { noFamily: true })
+          resolve(_noFamilyResp)
+          return
+        }
+        if (res.data.code === 200) {
+          resolve(res.data)
+        } else {
+          console.warn('[API] 失败 ' + method + ' ' + fullUrl + ' code=' + res.data.code + ' msg=' + (res.data.message || ''))
+          uni.showToast({
+            title: res.data.message || '请求失败',
+            icon: 'none'
+          })
+          reject(res.data)
+        }
+      },
+      fail: (err) => {
+        console.error('[API] 网络错误 ' + method + ' ' + fullUrl, err)
+        uni.showToast({
+          title: '网络请求失败',
+          icon: 'none'
+        })
+        reject(err)
+      }
+    })
+  })
+}
+
+//  LangGraph 适配层(含 Dify fallback) 
+//
+// langgraphRequest() 是 AI 对话/分析的统一入口:
+//   1. 先尝试调用 LangGraph 适配层(/api/v1/chat/completion 或 /api/v1/analysis/run)
+//   2. 若 LangGraph 不可达(网络错误/超时/非 2xx),自动回退到 Dify(/api/ai/*)
+//
+// 参数:
+//   langgraphPath  - LangGraph 端点路径(如 '/api/v1/chat/completion')
+//   langgraphBody  - 发给 LangGraph 的请求体(DifyChatRequest / DifyAnalysisRequest)
+//   difyFallbackPath - Dify 回退端点路径(如 '/api/ai/chat/send')
+//   difyFallbackData  - 发给 Dify 的请求体(原 request() 的 data 参数)
+//   difyFallbackMethod - Dify 回退请求方法(默认 'POST')
+//   difyFallbackOptions - Dify 回退请求 options(同 request() 的 options)
+//   transform - 可选,把 LangGraph 响应转成页面期望的 { code, data, ... } 结构
+//
+// 返回 Promise,resolve 形态与 request() 一致:{ code: 200, data: {...}, message: ... }
+const langgraphRequest = (opts) => {
+  var langgraphPath = opts.langgraphPath
+  var langgraphBody = opts.langgraphBody || {}
+  var difyFallbackPath = opts.difyFallbackPath
+  var difyFallbackData = opts.difyFallbackData || {}
+  var difyFallbackMethod = opts.difyFallbackMethod || 'POST'
+  var difyFallbackOptions = opts.difyFallbackOptions || {}
+  var transform = opts.transform
+
+  return new Promise((resolve, reject) => {
+    var token = uni.getStorageSync('token')
+
+    uni.request({
+      url: LANGGRAPH_URL + langgraphPath,
+      method: 'POST',
+      data: langgraphBody,
+      header: {
+        'Content-Type': 'application/json',
+        'Authorization': token ? ('Bearer ' + token) : ''
+      },
+      timeout: 30000,
+      success: (res) => {
+        // LangGraph 不可用(非 2xx)→ 回退 Dify
+        if (res.statusCode < 200 || res.statusCode >= 300) {
+          _fallbackToDify(difyFallbackPath, difyFallbackMethod, difyFallbackData, difyFallbackOptions, resolve, reject)
+          return
+        }
+        // LangGraph 成功 → 转成页面期望的 { code: 200, data: {...} } 结构
+        var lgData = res.data || {}
+        var pageData = transform ? transform(lgData) : lgData
+        resolve({ code: 200, message: 'ok', data: pageData })
+      },
+      fail: (err) => {
+        console.warn('[API] LangGraph不可达,回退Dify ' + LANGGRAPH_URL + langgraphPath, err)
+        // LangGraph 网络错误 → 回退 Dify
+        _fallbackToDify(difyFallbackPath, difyFallbackMethod, difyFallbackData, difyFallbackOptions, resolve, reject)
+      }
+    })
+  })
+}
+
+// 内部:Dify 回退(复用 request(),保持原有鉴权/错误处理/重定向逻辑)
+function _fallbackToDify(path, method, data, options, resolve, reject) {
+  request(path, method, data, options).then(resolve).catch(reject)
+}
+
+// 登录模块
+export const wechatLogin = (code, userInfo, phoneCode) => {
+  var data = { code: code, nickname: userInfo.nickname, avatar: userInfo.avatar }
+  if (phoneCode) {
+    data.phoneCode = phoneCode
+  }
+  return request('/api/auth/wechat-login', 'POST', data)
+}
+
+// 发送验证码
+export const sendCode = (data) => {
+  return request('/api/auth/send-code', 'POST', data)
+}
+
+// 手机号码验证码登录
+export const phoneLogin = (data) => {
+  return request('/api/auth/phone-login', 'POST', data)
+}
+
+//  街道地址相关 
+
+// 获取所有省份
+export const getProvinces = () => {
+  return request('/api/streets/provinces')
+}
+
+// 根据父级ID获取子级地址
+export const getStreetChildren = (parentId) => {
+  return request(`/api/streets/children/${parentId}`)
+}
+
+// 根据ID获取地址详情
+export const getStreetById = (id) => {
+  return request(`/api/streets/${id}`)
+}
+
+// 获取地址完整路径
+export const getStreetPath = (id) => {
+  return request(`/api/streets/${id}/path`)
+}
+
+// 搜索地址
+export const searchStreet = (keyword) => {
+  return request('/api/streets/search', 'POST', { keyword })
+}
+
+// 区域匹配
+export const matchByStreet = (streetId) => {
+  return request(`/api/streets/${streetId}/match`)
+}
+
+// 按区域统计
+export const getStreetStats = (level = 4) => {
+  return request('/api/streets/stats', 'POST', { level })
+}
+
+// 获取家庭详情(含地址信息)
+export const getFamilyDetail = (id) => {
+  return request(`/api/admin/families/${id}`)
+}
+
+// 更新家庭地址
+export const updateFamilyAddress = (data) => {
+  return request(`/api/admin/families/update`, 'POST', data)
+}
+
+// 按街道ID列表统计家庭数量
+export const countFamiliesByStreetIds = (streetIds) => {
+  return request('/api/admin/families/count', 'POST', { streetIds: streetIds.join(',') })
+}
+
+// 按街道ID列表统计成长规划师数量
+export const countTeachersByStreetIds = (streetIds) => {
+  return request('/api/admin/teachers/count', 'POST', { streetIds: streetIds.join(',') })
+}
+
+// 微信手机号登录(新版)
+export const wechatPhoneLogin = (data) => {
+  return request('/api/auth/wechat-phone-login', 'POST', data)
+}
+
+// 获取平台公告
+export const getNotices = () => {
+  return request('/api/notices/list', 'GET')
+}
+
+// 微信静默登录
+export const silentLogin = (code) => {
+  return request('/api/auth/silent-login', 'POST', { code })
+}
+
+// 通过openid自动登录
+export const autoLogin = (openid) => {
+  return request('/api/auth/auto-login', 'POST', { openid })
+}
+
+export const setPassword = (password) => {
+  return request('/api/auth/set-password', 'POST', { password })
+}
+
+export const verifyPassword = (password) => {
+  return request('/api/auth/verify-password', 'POST', { password })
+}
+
+// 检查手机号是否已注册
+export const checkPhone = (phone) => {
+  return request('/api/auth/check-phone', 'POST', { phone })
+}
+
+// 校验本地 token 是否仍有效(App 启动时调用;401 由 request 封装统一处理跳转登录)
+export const verifyToken = () => {
+  return request('/api/auth/verify', 'POST')
+}
+
+// 直接注册(测试环境)
+export const directRegister = (data) => {
+  return request('/api/auth/direct-register', 'POST', data)
+}
+
+// 用户模块
+export const getUserInfo = () => {
+	return request('/api/user/info', 'POST')
+}
+
+export const updateUserInfo = (data) => {
+	return request('/api/user/update', 'POST', data)
+}
+
+// 就地补充信息回写(活动报名等场景按需补充后自动回写个人资料)
+export const backfillProfile = (data) => {
+	return request('/api/user/profile/backfill', 'POST', data)
+}
+
+export const joinFamily = (inviteCode) => {
+	return request('/api/user/join-family', 'POST', { inviteCode })
+}
+
+export const createFamily = (name) => {
+	return request('/api/family/user/create-family', 'POST', { name })
+}
+
+// 确保家庭已存在:无家庭则自动创建(默认名)
+export const ensureFamily = () => {
+	var ui = uni.getStorageSync('userInfo') || {}
+	if (ui.familyId) return Promise.resolve({ alreadyExists: true, familyId: ui.familyId })
+	var name = (ui.nickname || '用户') + '的家庭'
+	return createFamily(name).then(function(res) {
+		if (res && res.code === 200 && res.data) {
+			ui.familyId = res.data
+			uni.setStorageSync('userInfo', ui)
+			try { getApp().$store.commit('setFamilyId', res.data) } catch (e) {}
+			uni.showToast({ title: '家庭创建成功', icon: 'success' })
+			return { created: true, familyId: res.data }
+		}
+		throw new Error((res && res.message) || '创建失败')
+	}).catch(function(err) {
+		uni.showToast({ title: err.message || '网络异常', icon: 'none' })
+		return { failed: true, error: err }
+	})
+}
+
+// 获取家庭所有成员(家长+孩子)
+export const getFamilyMembers = () => {
+	return request('/api/family/user/family-members', 'POST')
+}
+
+// 获取对家庭成员可见的成员列表
+export const getVisibleFamilyMembers = () => {
+	return request('/api/family/user/members/visible', 'POST')
+}
+
+// 获取以指定成员为中心的所有成员关系(关系类型+信任/亲密度/沟通评分)
+export const getPairwiseRelationships = (centerMemberId) => {
+	return request('/api/family/relationship/pairwise', 'POST', { centerMemberId })
+}
+
+// 更新成员可见性
+export const updateMemberVisibility = (memberId, memberType, showToFamily) => {
+	return request('/api/family/user/members/update-visibility', 'POST', { memberId, memberType, showToFamily })
+}
+
+export const switchMode = (mode) => {
+	return request('/api/user/switch-mode', 'POST', { mode })
+}
+
+export const switchToChild = (memberId) => {
+	return request('/api/user/switch-to-child', 'POST', { memberId })
+}
+
+export const switchBackToParent = () => {
+	return request('/api/user/switch-back-to-parent', 'POST', {})
+}
+
+export const switchBackVerify = (password) => {
+	return request('/api/family/user/switch-back-verify', 'POST', { password })
+}
+
+export const getUserRoles = () => {
+	return request('/api/user/roles', 'POST')
+}
+
+export const switchRole = (role) => {
+	return request('/api/user/switch-role', 'POST', { role })
+}
+
+// 会员模块
+export const getMembershipLevels = () => {
+	return request('/api/membership/levels', 'POST')
+}
+
+export const getMembershipPlans = () => {
+	return request('/api/membership/plans', 'POST')
+}
+
+export const getMyMembership = () => {
+	return request('/api/membership/my', 'POST')
+}
+
+export const getCurrentLevel = () => {
+	return request('/api/membership/current', 'POST')
+}
+
+export const createOrder = (levelCode, paymentType, period, couponId) => {
+	var data = { levelCode: levelCode, paymentType: paymentType }
+	if (period) {
+		data.period = period
+	}
+	if (couponId) {
+		data.couponId = couponId
+	}
+	return request('/api/membership/orders', 'POST', data)
+}
+
+export const nextOrder = (orderNo) => {
+	return request('/api/membership/orders/continue', 'POST', { orderNo: orderNo })
+}
+
+export const getAuthorizations = () => {
+	return request('/api/parent/authorizations', 'POST')
+}
+
+export const getChildren = () => {
+  return request('/api/family/user/children/list', 'POST')
+}
+
+export const getParentDashboard = () => {
+  return request('/api/parent/dashboard', 'POST')
+}
+
+export const getSystemBalance = (memberId) => {
+  return request('/api/points/system-balance', 'POST', { memberId })
+}
+
+export const createChild = (data) => {
+  return request('/api/family/user/children', 'POST', data)
+}
+
+export const updateChild = (memberId, data) => {
+  return request('/api/family/user/children/update', 'POST', Object.assign({}, data, { memberId: memberId }))
+}
+
+// 家庭成员模块(统一添加成员)
+export const addFamilyMember = (data) => {
+  return request('/api/family/member/add', 'POST', data)
+}
+
+export const listFamilyMembers = () => {
+  return request('/api/family/member/list', 'POST')
+}
+
+// 用户同意记录
+export const recordConsent = (data) => {
+  return request('/api/consent/record', 'POST', data)
+}
+export const withdrawConsent = (data) => {
+  return request('/api/consent/withdraw', 'POST', data)
+}
+export const getConsentStatus = () => {
+  return request('/api/consent/status', 'POST')
+}
+
+// 数据使用授权
+export const getDataPermission = () => {
+  return request('/api/data-permission/get', 'POST')
+}
+export const updateDataPermission = (data) => {
+  return request('/api/data-permission/update', 'POST', data)
+}
+
+export const switchToFamilyMember = (memberId, source) => {
+  return request('/api/family/member/switch', 'POST', { memberId, source })
+}
+
+export const kickFamilyMemberById = (memberId) => {
+  return request('/api/family/member/kick', 'POST', { memberId })
+}
+
+export const updateFamilyMember = (data) => {
+  return request('/api/family/member/update', 'POST', data)
+}
+
+// 任务模块
+export const createTask = (data) => {
+  return request('/api/tasks', 'POST', data)
+}
+
+export const getTodayTasks = (memberId) => {
+  return request('/api/tasks/today', 'POST', { memberId })
+}
+
+export const getPendingReviewTasks = () => {
+  return request('/api/tasks/pending-review', 'POST')
+}
+
+export const approveTask = (taskId) => {
+  return request(`/api/tasks/${taskId}/review`, 'POST', { approved: true })
+}
+
+export const rejectTask = (taskId) => {
+  return request(`/api/tasks/${taskId}/review`, 'POST', { approved: false })
+}
+
+export const completeTask = (taskId, memberId, photoUrl) => {
+  return request(`/api/tasks/${taskId}/complete`, 'POST', { memberId, photoUrl })
+}
+
+export const reviewTask = (taskId, data) => {
+  return request(`/api/tasks/${taskId}/review`, 'POST', data)
+}
+
+export const getTaskHistory = (memberId, page = 1, size = 10) => {
+  return request('/api/tasks/history', 'POST', { memberId, page, size })
+}
+
+export const deleteTask = (taskId) => {
+  return request(`/api/tasks/${taskId}`, 'DELETE')
+}
+
+export const batchCompleteTasks = (taskIds) => {
+  return request('/api/tasks/batch-complete', 'POST', { taskIds })
+}
+
+export const batchDeleteTasks = (taskIds) => {
+  return request('/api/tasks/batch-delete', 'POST', { taskIds })
+}
+
+// 积分模块
+export const getPointsBalance = (memberId) => {
+  return request('/api/points/balance', 'POST', { memberId })
+}
+
+export const getPointsLogs = (memberId, page = 1, size = 10) => {
+  return request('/api/points/logs', 'POST', { memberId, page, size })
+}
+
+export const adjustPoints = (memberId, amount, reason, password) => {
+  return request('/api/points/adjust', 'POST', { memberId, amount, reason, password })
+}
+
+// 奖励模块
+export const createReward = (data) => {
+  return request('/api/rewards', 'POST', data)
+}
+
+export const getWishlist = (memberId) => {
+  return request('/api/rewards/wishlist', 'POST', { memberId })
+}
+
+export const exchangeReward = (rewardId, memberId) => {
+  return request(`/api/rewards/${rewardId}/exchange`, 'POST', { memberId })
+}
+
+export const approveReward = (rewardId, approved) => {
+  return request(`/api/rewards/${rewardId}/approve`, 'POST', { approved })
+}
+
+export const getRewardTemplates = () => {
+  return request('/api/rewards/templates', 'POST')
+}
+
+export const getExchangeHistory = (memberId, page = 1, size = 10) => {
+  return request('/api/rewards/exchange-history', 'POST', { memberId, page, size })
+}
+
+// ===
+// 家长任务模块(孩子分配给家长的任务)
+// ===
+export const getTodayParentTasks = () => {
+  return request('/api/tasks/today-parent', 'POST')
+}
+
+export const completeParentTask = (taskId) => {
+  return request(`/api/tasks/${taskId}/complete-parent`, 'POST', {})
+}
+
+// ===
+// 家庭成员任务分配模块
+// ===
+export const getMyPendingTasks = (memberId) => {
+  return request('/api/tasks/my-pending', 'POST', { memberId })
+}
+
+export const acceptTask = (taskId, memberId) => {
+  return request('/api/tasks/accept', 'POST', { taskId, memberId })
+}
+
+// ===
+// 家长心愿单模块
+// ===
+export const createParentWishlist = (data) => {
+  return request('/api/parent/wishlist', 'POST', data)
+}
+
+export const getParentWishlist = () => {
+  return request('/api/parent/wishlist/list', 'POST')
+}
+
+export const getFamilyWishlist = () => {
+  return request('/api/parent/wishlist/family', 'POST')
+}
+
+export const exchangeParentWishlist = (id) => {
+  return request(`/api/parent/wishlist/${id}/exchange`, 'POST', {})
+}
+
+// 家长审批孩子的心愿并填写积分
+export const approveParentWishlist = (id, pointsRequired) => {
+  return request(`/api/parent/wishlist/${id}/approve`, 'POST', { pointsRequired })
+}
+
+// ===
+// 家长心愿管理模块
+// ===
+export const getPendingWishes = () => {
+  return request('/api/wishes/pending', 'POST', {})
+}
+
+export const getWishes = (params) => {
+  return request('/api/wishes/list', 'POST', params)
+}
+
+export const setWishPrice = (wishId, points) => {
+  return request(`/api/wishes/${wishId}/price`, 'POST', { pointsRequired: points })
+}
+
+export const rejectWish = (wishId, reason) => {
+  return request(`/api/wishes/${wishId}/reject`, 'POST', { reason })
+}
+
+export const approveWishExchange = (wishId, approved) => {
+  return request(`/api/wishes/${wishId}/approve-exchange`, 'POST', { approved })
+}
+
+export const markWishFulfilled = (wishId) => {
+  return request(`/api/wishes/${wishId}/fulfill`, 'POST', {})
+}
+
+export const createWish = (data) => {
+  return request('/api/wishes/create', 'POST', data)
+}
+
+export const getWishById = (id) => {
+  return request(`/api/wishes/${id}`, 'POST', {})
+}
+
+export const requestWishExchange = (id) => {
+  return request(`/api/wishes/${id}/exchange`, 'POST', {})
+}
+
+export const confirmWishReceived = (id) => {
+  return request(`/api/wishes/${id}/confirm`, 'PUT', {})
+}
+
+export const cancelWish = (id, reason) => {
+  return request(`/api/wishes/${id}`, 'DELETE', { reason })
+}
+
+// ===
+// 成长规划师/任务模板模块
+// ===
+// 生成绑定邀请
+export const generateBindInvite = () => {
+  return request('/api/guide/bind/invite', 'POST')
+}
+
+// 获取绑定的家庭列表
+export const getBoundFamilies = () => {
+  return request('/api/guide/families', 'POST')
+}
+
+// 确认绑定家庭
+export const confirmBind = (data) => {
+  return request('/api/guide/bind/confirm', 'POST', data)
+}
+
+// 解除绑定
+export const unbindFamily = (id) => {
+  return request(`/api/guide/bind/${id}`, 'DELETE')
+}
+
+// 创建任务模板
+export const createPackage = (data) => {
+  return request('/api/packages', 'POST', data)
+}
+
+// 更新任务模板
+export const updatePackage = (id, data) => {
+  return request(`/api/packages/${id}`, 'PUT', data)
+}
+
+// 获取任务模板详情
+export const getPackage = (id) => {
+  return request(`/api/packages/${id}`, 'POST')
+}
+
+// 获取我的任务模板列表
+export const getMyPackages = () => {
+  return request('/api/packages', 'POST')
+}
+
+// 提交审核
+export const submitPackageForReview = (id) => {
+  return request(`/api/packages/${id}/submit`, 'POST')
+}
+
+// 发布/下架
+export const publishPackage = (id, publish) => {
+  return request(`/api/packages/${id}/publish`, 'POST', {}, { publish })
+}
+
+// 添加任务项
+export const addPackageItem = (packageId, data) => {
+  return request(`/api/packages/${packageId}/items`, 'POST', data)
+}
+
+// 更新任务项
+export const updatePackageItem = (itemId, data) => {
+  return request(`/api/packages/items/${itemId}`, 'PUT', data)
+}
+
+// 删除任务项
+export const deletePackageItem = (itemId) => {
+  return request(`/api/packages/items/${itemId}`, 'DELETE')
+}
+
+// 获取任务模板任务项
+export const getPackageItems = (packageId) => {
+  return request(`/api/packages/${packageId}/items`, 'POST')
+}
+
+// 获取公开任务模板列表
+export const getPublicPackages = (category) => {
+  return request('/api/market/packages', 'POST', { category })
+}
+
+// 通过分享码获取任务模板
+export const getPackageByShareCode = (code) => {
+  return request(`/api/market/share/${code}`, 'POST')
+}
+
+// 购买并应用任务模板
+export const purchasePackage = (packageId, data) => {
+  return request(`/api/market/packages/${packageId}/purchase`, 'POST', data)
+}
+
+// 获取我的任务计划
+export const getMyPlans = () => {
+  return request('/api/market/plans', 'POST')
+}
+
+// 获取计划详情
+export const getPlanDetail = (id) => {
+  return request(`/api/market/plans/${id}`, 'POST')
+}
+
+// 取消计划
+export const cancelPlan = (id) => {
+  return request(`/api/market/plans/${id}/cancel`, 'POST')
+}
+
+// 确认绑定成长规划师
+export const acceptBind = (data) => {
+  return request('/api/bind/accept', 'POST', data)
+}
+
+// 获取绑定的成长规划师列表
+export const getBoundGuides = () => {
+  return request('/api/bind/guides', 'POST')
+}
+
+// 成长规划师注册
+export const registerGuide = (data) => {
+  return request('/api/guide/register', 'POST', data)
+}
+
+// 生成邀请码
+export const generateInviteCode = () => {
+  return request('/api/guide/invite-code/generate', 'POST')
+}
+
+// 获取邀请码列表
+export const getInviteCodes = () => {
+  return request('/api/guide/invite-codes', 'GET')
+}
+
+// 验证邀请码
+export const validateInviteCode = (code) => {
+  return request('/api/guide/invite-code/validate', 'GET', null, { code })
+}
+
+export const checkTeamInviteStatus = (inviteCode) => {
+  return request('/api/guide/team/check-status', 'POST', { inviteCode })
+}
+
+export const joinTeamByInvite = (inviteCode) => {
+  return request('/api/guide/team/join-by-invite', 'POST', { inviteCode })
+}
+
+export const leaveCurrentTeam = () => {
+  return request('/api/guide/team/leave', 'POST')
+}
+
+// 获取下级成长规划师列表
+export const getChildGuides = () => {
+  return request('/api/guide/child-guides', 'GET')
+}
+
+// 获取所有下级成长规划师
+export const getAllChildGuides = () => {
+  return request('/api/guide/all-child-guides', 'GET')
+}
+
+// 获取上级成长规划师
+export const getParentGuide = () => {
+  return request('/api/guide/parent-guide', 'GET')
+}
+
+// ===== 训练方案管理 =====
+export const getTrainingPlanList = (memberId) => {
+  return request('/api/guide/training-plans/list', 'POST',
+    memberId ? { memberId } : {})
+}
+
+export const getTrainingPlanDetail = (planId) => {
+  return request('/api/guide/training-plans/detail', 'POST', { planId })
+}
+
+export const createTrainingPlan = (memberId, title, description) => {
+  return request('/api/guide/training-plans/create', 'POST', { memberId, title, description })
+}
+
+export const updateTrainingPlan = (planId, title, description) => {
+  return request('/api/guide/training-plans/update', 'POST', { planId, title, description })
+}
+
+export const addTrainingPlanItem = (item) => {
+  return request('/api/guide/training-plans/items/add', 'POST', item)
+}
+
+export const updateTrainingPlanItem = (item) => {
+  return request('/api/guide/training-plans/items/update', 'POST', item)
+}
+
+export const deleteTrainingPlanItem = (itemId) => {
+  return request('/api/guide/training-plans/items/delete', 'POST', { itemId })
+}
+
+export const generatePlanFromRecommendations = (memberId) => {
+  return request('/api/guide/training-plans/generate-from-recommendations', 'POST', { memberId })
+}
+
+export const deleteTrainingPlan = (planId) => {
+  return request('/api/guide/training-plans/delete', 'POST', { planId })
+}
+
+// ===== 活动管理 =====
+export const getGuideActivityList = (status) => {
+  return request('/api/guide/activities/list', 'POST', status ? { status } : {})
+}
+
+export const getGuideActivityDetail = (activityId) => {
+  return request('/api/guide/activities/detail', 'POST', { activityId })
+}
+
+export const createActivity = (activity) => {
+  return request('/api/guide/activities/create', 'POST', activity)
+}
+
+export const updateActivity = (activity) => {
+  return request('/api/guide/activities/update', 'POST', activity)
+}
+
+export const publishActivity = (activityId) => {
+  return request('/api/guide/activities/publish', 'POST', { activityId })
+}
+
+export const cancelActivity = (activityId) => {
+  return request('/api/guide/activities/cancel', 'POST', { activityId })
+}
+
+export const deleteActivity = (activityId) => {
+  return request('/api/guide/activities/delete', 'POST', { activityId })
+}
+
+// 添加成长规划师任务模板
+export const addGuidePackage = (guideId, packageId, price, commissionRate) => {
+  return request('/api/guide/package/add', 'POST', { guideId, packageId, price, commissionRate })
+}
+
+// 获取成长规划师套餐列表
+export const getGuidePackages = (guideId) => {
+  return request('/api/guide/packages', 'GET', null, { guideId })
+}
+
+// 获取成长规划师套餐定价
+export const getGuidePackage = (guideId, packageId) => {
+  return request('/api/guide/package/' + packageId, 'GET', null, { guideId })
+}
+
+// 更新成长规划师套餐价格
+export const updateGuidePackagePrice = (guideId, packageId, price) => {
+  return request('/api/guide/package/' + packageId, 'PUT', { guideId, price })
+}
+
+// 删除成长规划师套餐
+export const deleteGuidePackage = (guideId, packageId) => {
+  return request('/api/guide/package/' + packageId, 'DELETE', null, { guideId })
+}
+
+// 获取套餐价格
+export const getPackagePrice = (packageId, guideId, inviteCode) => {
+  return request('/api/package/price', 'GET', null, { packageId, guideId, inviteCode })
+}
+
+// 获取可用的成长规划师列表
+export const getAvailableGuides = (packageId) => {
+  return request('/api/package/available-guides', 'GET', null, { packageId })
+}
+
+// 创建套餐订单
+export const createPackageOrder = (data) => {
+  return request('/api/package/order/create', 'POST', data)
+}
+
+// 获取订单状态
+export const getOrderStatus = (orderNo) => {
+  return request('/api/payment/order/status/' + orderNo, 'GET')
+}
+
+// 创建微信支付订单
+export const createWechatPayOrder = (orderNo, description, amount) => {
+  return request('/api/payment/wechat/create', 'POST', { orderNo, description, amount })
+}
+
+// 创建支付宝订单
+export const createAlipayOrder = (orderNo, description, amount) => {
+  return request('/api/payment/alipay/create', 'POST', { orderNo, description, amount })
+}
+
+// 处理微信支付回调
+export const handleWechatCallback = (params) => {
+  return request('/api/payment/wechat/callback', 'POST', params)
+}
+
+// 澶勭悊鏀粯瀹濆洖璋?
+export const handleAlipayCallback = (params) => {
+  return request('/api/payment/alipay/callback', 'POST', params)
+}
+
+// 获取我的测评报告
+export const getMyAssessmentResults = () => {
+  return request('/api/dan-assessment/my-results', 'POST', {})
+}
+
+// 获取下级成长规划师的测评报告
+export const getChildAssessmentResults = () => {
+  return request('/api/dan-assessment/child-results', 'POST', {})
+}
+
+// 获取测评报告详情
+export const getAssessmentResult = (id) => {
+  return request('/api/dan-assessment/result/' + id, 'POST')
+}
+
+// 创建测评预约
+export const createAssessmentAppointment = (data) => {
+  return request('/api/dan-assessment/appointment/create', 'POST', data)
+}
+
+// 支付测评订单
+export const payAssessmentOrder = (orderNo, payType) => {
+  return request('/api/dan-assessment/order/pay', 'POST', { orderNo, payType })
+}
+
+//  虚拟支付 
+
+// 创建测评订单(返回 AssessmentOrder,含 orderNo)
+export const createAssessmentOrder = (data) => {
+  return request('/api/dan-assessment/order/create', 'POST', data)
+}
+
+// 获取测评订单详情(轮询支付状态用;status: pending/paid/cancelled/refunded)
+export const getAssessmentOrderDetail = (orderNo) => {
+  return request('/api/dan-assessment/order/detail', 'POST', null, { orderNo })
+}
+
+// 虚拟支付参数薄包装(决策#7:各链路下单接口内联返回 VirtualPayParamsDTO,无独立端点)
+// ASSESSMENT → 测评订单支付(/order/pay 内联返回 DTO;testMode 返回 null)
+// MEMBERSHIP/SUBSCRIPTION → 下单接口已内联返回,调用方直接使用下单返回值,此处透传 orderNo
+export const createVirtualPayOrder = (orderNo, goodsType) => {
+  if (goodsType === 'ASSESSMENT') {
+    return payAssessmentOrder(orderNo, 'wechat')
+  }
+  return Promise.resolve({ orderNo: orderNo, goodsType: goodsType })
+}
+
+// 虚拟支付失败上报(诊断用):wx.requestVirtualPayment fail 时 fire-and-forget 上报到后端,
+// 让支付失败原因在后端日志可见(正式版小程序前端 console 无法远程查看)。
+// 独立 uni.request 实现,不弹 toast、不影响主流程。
+export const reportVirtualPayError = (outTradeNo, errCode, errMsg, scene) => {
+  try {
+    uni.request({
+      url: BASE_URL + '/api/internal/virtual-pay/error-report',
+      method: 'POST',
+      data: {
+        outTradeNo: outTradeNo,
+        errCode: errCode,
+        errMsg: errMsg,
+        scene: scene
+      },
+      header: { 'Content-Type': 'application/json' },
+      success: function(res) {
+        if (res.data && res.data.code !== 200) console.warn('[虚拟支付] 失败上报接口异常', res.data)
+      },
+      fail: function() { /* 上报失败静默处理,不打扰用户 */ }
+    })
+  } catch (e) { /* 上报异常静默处理 */ }
+}
+
+// 拉起微信小程序虚拟支付(官方 API 形态;基础库 2.19.2+,回调风格)
+// params = VirtualPayParamsDTO { orderInfo, sign, signature }
+export const requestVirtualPayment = (params, callbacks) => {
+  if (!wx.canIUse('requestVirtualPayment')) {
+    if (callbacks && callbacks.fail) {
+      callbacks.fail({ errMsg: '当前微信版本不支持虚拟支付' })
+    }
+    return
+  }
+  var dto = params || {}
+  wx.requestVirtualPayment({
+    signData: JSON.stringify(dto.orderInfo || {}),
+    paySig: dto.sign || '',
+    signature: dto.signature || '',
+    mode: 'short_series_goods',
+    success: function(res) { if (callbacks && callbacks.success) callbacks.success(res) },
+    fail: function(err) {
+      console.error('[虚拟支付] wx.requestVirtualPayment fail', err, 'signData=', JSON.stringify(dto.orderInfo || {}))
+      var orderNo = dto.orderInfo && dto.orderInfo.outTradeNo
+      reportVirtualPayError(orderNo, err && err.errCode, err && err.errMsg, 'requestVirtualPayment')
+      if (callbacks && callbacks.fail) callbacks.fail(err)
+    }
+  })
+}
+
+// 虚拟支付环境(官方仅 0=正式/1=沙箱;signData 内 env 由后端按 virtual-pay-env 生成)
+// 本函数为计划保留的工具函数(日志/调试用);develop→1(沙箱)、trial→1(沙箱)、release→0(正式)
+export const getVirtualPaymentEnv = () => {
+  try {
+    var info = uni.getAccountInfoSync()
+    var env = info.miniProgram && info.miniProgram.envVersion
+    if (env === 'develop' || env === 'trial') return 1
+    return 0
+  } catch (e) {
+    return 0
+  }
+}
+
+// 记录测评结果
+export const recordAssessmentResult = (data) => {
+  return request('/api/dan-assessment/result/record', 'POST', data)
+}
+
+// 鎵撳崱妯″潡
+export const getStreakProgress = (memberId) => {
+  return request(`/api/streak/progress/${memberId}`, 'POST')
+}
+
+// 浠诲姟鎻愰啋
+export const getTasksNeedReminder = (memberId) => {
+  return request(`/api/task-reminders/reminder/${memberId}`, 'POST')
+}
+
+export const getUpcomingTasks = (memberId, minutes = 60) => {
+  return request(`/api/task-reminders/upcoming/${memberId}`, 'POST', { minutes })
+}
+
+export const getOverdueTasks = (memberId) => {
+  return request(`/api/task-reminders/overdue/${memberId}`, 'POST')
+}
+
+// 灏忔父鎴忔ā鍧?
+export const getMiniGameList = () => {
+  return request('/api/mini-game/list', 'POST')
+}
+
+export const getMiniGameByCode = (gameCode) => {
+  return request(`/api/mini-game/${gameCode}`, 'POST')
+}
+
+export const completeMiniGame = (memberId, gameCode, completionTime, score) => {
+  return request('/api/mini-game/complete', 'POST', { 
+    memberId, 
+    gameCode, 
+    completionTime, 
+    score 
+  })
+}
+
+// 娓告垙璁板綍
+export const saveGameRecord = (params) => {
+  return request('/api/game/record', 'POST', params)
+}
+
+export const getGameHistory = (params) => {
+  return request('/api/game/history', 'POST', params)
+}
+
+export const getGameBestScores = (params) => {
+  return request('/api/game/best', 'POST', params)
+}
+
+export const getGameStats = (params) => {
+  return request('/api/game/stats', 'POST', params)
+}
+
+export const getGameLeaderboard = (params) => {
+  return request('/api/game/leaderboard', 'POST', params)
+}
+
+// 邀请码相关
+export const getInviteCode = () => {
+  return request('/api/family/invite-code', 'GET')
+}
+
+export const generateFamilyInviteCode = () => {
+  return request('/api/family/invite-code/generate', 'POST')
+}
+
+export const bindGuideFamily = (inviteCode) => {
+  return request('/api/family/guide-bind', 'POST', { inviteCode })
+}
+
+export const registerWithInviteCode = (data) => {
+  return request('/api/auth/register-with-invite', 'POST', data)
+}
+
+// 成长记录
+export const createGrowthRecord = (data) => {
+  // 如果包含 alsoPurchaseAssessment 字段,使用合并接口
+  if (data.alsoPurchaseAssessment) {
+    return request('/api/growth/record/create-with-order', 'POST', data)
+  }
+  return request('/api/growth/record/create', 'POST', data)
+}
+export const getGrowthRecordList = () => {
+  return request('/api/growth/record/list', 'POST')
+}
+export const getChildRecords = (memberId) => {
+  return request('/api/growth/record/child/' + memberId, 'POST')
+}
+export const getGrowthRecordDetail = (id) => {
+  return request('/api/growth/record/' + id, 'POST')
+}
+export const deleteGrowthRecord = (id) => {
+  return request('/api/growth/record/' + id + '/delete', 'POST')
+}
+
+export const uploadAndParseReport = (filePath) => {
+  return new Promise((resolve, reject) => {
+    const token = uni.getStorageSync('token')
+    uni.uploadFile({
+      url: BASE_URL + '/api/growth/record/upload-and-parse',
+      filePath: filePath,
+      name: 'file',
+      header: {
+        'Authorization': token ? 'Bearer ' + token : ''
+      },
+      success: (res) => {
+        const data = JSON.parse(res.data)
+        if (data.code === 200) {
+          resolve(data)
+        } else {
+          console.warn('[API] 上传失败 ' + BASE_URL + '/api/growth/record/upload-and-parse' + ' code=' + data.code + ' msg=' + (data.message || ''))
+          reject(data)
+        }
+      },
+      fail: (err) => {
+        console.error('[API] 上传网络错误 ' + BASE_URL + '/api/growth/record/upload-and-parse', err)
+        reject(err)
+      }
+    })
+  })
+}
+
+export const createGrowthRecordFromUpload = (data) => {
+  return request('/api/growth/record/create-from-upload', 'POST', data)
+}
+
+export const createGrowthSupplement = (data) => {
+  return request('/api/growth/record/supplement', 'POST', data)
+}
+
+export const checkGrowthDuplicate = (data) => {
+  return request('/api/growth/record/check-duplicate', 'POST', data)
+}
+
+export const getGrowthSupplements = (id) => {
+  return request('/api/growth/record/' + id + '/supplements', 'POST')
+}
+
+// 成长规划师模块API
+export const getTeamMembers = () => {
+  return request('/api/guide/team/members', 'POST')
+}
+
+export const getTeamStats = () => {
+  return request('/api/guide/team/stats', 'POST')
+}
+
+export const getGuideMessages = () => {
+  return request('/api/guide/messages/list', 'POST')
+}
+
+export const getGuideOrders = () => {
+  return request('/api/guide/orders/list', 'POST')
+}
+
+export const getOrderStats = () => {
+  return request('/api/guide/orders/stats', 'POST')
+}
+
+// 任务完成率统计
+export const getChildCompletionStats = (params) => {
+  return request('/api/stats/child-completion', 'POST', params)
+}
+
+export const getFamilyCompletionStats = (params) => {
+  return request('/api/stats/family-completion', 'POST', params)
+}
+
+export const generateInviteCard = (type, refId) => {
+  if (type === 'child') {
+    return request('/api/invite-card/generate', 'POST', { type, refId })
+  }
+  return request('/api/invite-card/generate', 'POST', { type })
+}
+
+export const verifyInviteCard = (code) => {
+  return request('/api/invite-card/verify', 'POST', { code })
+}
+
+export const acceptInviteCard = (code, phone) => {
+  return request('/api/invite-card/accept', 'POST', { code, phone })
+}
+
+// 瑙勫垝甯堥個璇峰闀?
+export const generateParentInvite = () => {
+  return request('/api/guide/parent-invite/generate', 'POST', {})
+}
+
+export const acceptParentInvite = (code) => {
+  return request('/api/guide/parent-invite/accept', 'POST', { code })
+}
+
+// 踢出家庭成员(仅管理员)
+export const kickFamilyMember = (targetUserId) => {
+  return request('/api/family/user/kick', 'POST', { targetUserId })
+}
+
+// 家庭邀请二维码
+export const generateFamilyInviteQrCode = () => {
+  return request('/api/family/invite/qrcode', 'POST')
+}
+
+// ===== 瀹跺涵閭€璇凤紙浠ょ墝鐗堬紝鏀寔鎵爜娴侊級 =====
+
+// 鐢熸垚瀹跺涵閭€璇凤紙鍚皬绋嬪簭鐮佹垨浜岀淮鐮侊級
+export const generateFamilyInvite = () => {
+  return request('/api/family/invite/generate', 'POST')
+}
+
+// 楠岃瘉閭€璇蜂护鐗?
+export const validateInvitation = (token) => {
+  return request('/api/family/invite/validate', 'POST', { token })
+}
+
+// 接受邀请(加入家庭)
+export const acceptInvitation = (token, familyRole, mergeFamily) => {
+  return request('/api/family/invite/accept', 'POST', { token, familyRole, mergeFamily: !!mergeFamily })
+}
+
+export const generateQrCodeFromText = (content) => {
+  return request('/api/common/qrcode', 'POST', { content })
+}
+
+// 检查当前用户家庭状态
+export const checkUserFamily = () => {
+  return request('/api/family/invite/check-family', 'POST')
+}
+
+// 杞瀹跺涵绠$悊鍛?
+export const transferFamilyAdmin = (newAdminId) => {
+  return request('/api/family/invite/transfer-admin', 'POST', { newAdminId })
+}
+
+// 通过邀请码申请加入家庭(需管理员审批)
+export const requestJoinByCode = (inviteCode, familyRole) => {
+  return request('/api/family/invite/request-join-by-code', 'POST', { inviteCode: inviteCode, familyRole: familyRole || '' })
+}
+
+// 查询待审批加入请求(管理员)
+export const getPendingJoinRequests = () => {
+  return request('/api/family/invite/pending-requests', 'POST', {})
+}
+
+// 审批加入请求(管理员)
+export const approveJoinRequest = (requestId, comment) => {
+  return request('/api/family/invite/approve-request', 'POST', { requestId: requestId, comment: comment || '' })
+}
+
+// 拒绝加入请求(管理员)
+export const rejectJoinRequest = (requestId, comment) => {
+  return request('/api/family/invite/reject-request', 'POST', { requestId: requestId, comment: comment || '' })
+}
+
+// 查询我的加入请求
+export const getMyJoinRequest = () => {
+  return request('/api/family/invite/my-request', 'POST', {})
+}
+
+// 取消我的加入请求
+export const cancelMyJoinRequest = (requestId) => {
+  return request('/api/family/invite/cancel-request', 'POST', { requestId: requestId })
+}
+
+// ===== 家庭加入请求 API 别名(供组件统一引用)=====
+export const getPendingFamilyRequests = () => {
+  return request('/api/family/invite/pending-requests', 'POST', {})
+}
+export const approveFamilyJoinRequest = (requestId) => {
+  return request('/api/family/invite/approve-request', 'POST', { requestId: requestId })
+}
+export const rejectFamilyJoinRequest = (requestId) => {
+  return request('/api/family/invite/reject-request', 'POST', { requestId: requestId })
+}
+export const getMyPendingRequest = () => {
+  return request('/api/family/invite/my-request', 'POST', {})
+}
+
+// ===== AI 聊天 =====
 export const aiSendMessage = (data) => {
-  var query = data && data.query ? data.query : ''
-  var conversationId = data && data.conversationId ? data.conversationId : ''
-  var userId = uni.getStorageSync('userId') || ''
-  var langgraphBody = {
-    query: query,
-    user: userId,
-    user_id: userId,
-    conversation_id: conversationId,
-    response_mode: 'blocking',
-    bot_name: 'AI管家'
-  }
-  if (data && data.reportId) {
-    langgraphBody.inputs = { report_id: data.reportId }
-  }
-  return langgraphRequest({
-    langgraphPath: '/api/v1/chat/completion',
-    langgraphBody: langgraphBody,
-    difyFallbackPath: '/api/ai/chat/send',
-    difyFallbackData: data,
-    transform: function(lgRes) {
-      var content = ''
-      if (lgRes && lgRes.choices && lgRes.choices.length > 0) {
-        var msg = lgRes.choices[0].message
-        if (msg && msg.content) { content = msg.content }
-      }
-      return {
-        answer: content,
-        conversationId: conversationId,
-        recommendations: [],
-        tasks: []
-      }
-    }
-  })
-}
-
-export const aiGetConversations = () => {
-  return request('/api/ai/chat/conversations', 'POST', {})
-}
-
-export const aiGetMessages = (params) => {
-  return request('/api/ai/chat/messages', 'POST', params)
-}
-
-export const aiDeleteConversation = (id) => {
-  return request('/api/ai/chat/conversations/' + id + '/delete', 'POST', {})
-}
-
-// 精准营养助手(基于体检报告)
-export const aiSendNutritionMessage = (data) => {
-  var query = data && data.query ? data.query : ''
-  var conversationId = data && data.conversationId ? data.conversationId : ''
-  var reportId = data && data.reportId ? data.reportId : null
-  var userId = uni.getStorageSync('userId') || ''
-  var langgraphBody = {
-    query: query,
-    user: userId,
-    user_id: userId,
-    conversation_id: conversationId,
-    response_mode: 'blocking',
-    bot_name: '精准营养助手'
-  }
-  if (reportId) {
-    langgraphBody.inputs = { report_id: reportId }
-  }
-  return langgraphRequest({
-    langgraphPath: '/api/v1/analysis/run',
-    langgraphBody: langgraphBody,
-    difyFallbackPath: '/api/ai/nutrition/send',
-    difyFallbackData: data,
-    transform: function(lgRes) {
-      var content = ''
-      if (lgRes && lgRes.choices && lgRes.choices.length > 0) {
-        var msg = lgRes.choices[0].message
-        if (msg && msg.content) { content = msg.content }
-      }
-      return {
-        answer: content,
-        conversationId: conversationId,
-        recommendations: [],
-        tasks: []
-      }
-    }
-  })
-}
-
-// AI 健康教练
-export const aiSendHealthCoachMessage = (data) => {
-  var query = data && data.query ? data.query : ''
-  var conversationId = data && data.conversationId ? data.conversationId : ''
-  var userId = uni.getStorageSync('userId') || ''
-  var langgraphBody = {
-    query: query,
-    user: userId,
-    user_id: userId,
-    conversation_id: conversationId,
-    response_mode: 'blocking',
-    bot_name: '健康教练'
-  }
-  if (data && data.memberId) {
-    langgraphBody.inputs = { child_id: data.memberId }
-  }
-  return langgraphRequest({
-    langgraphPath: '/api/v1/health/coach',
-    langgraphBody: langgraphBody,
-    difyFallbackPath: '/api/ai/chat/send',
-    difyFallbackData: data,
-    transform: function(lgRes) {
-      var content = ''
-      if (lgRes && lgRes.choices && lgRes.choices.length > 0) {
-        var msg = lgRes.choices[0].message
-        if (msg && msg.content) { content = msg.content }
-      }
-      return {
-        answer: content,
-        conversationId: conversationId,
-        recommendations: [],
-        tasks: []
-      }
-    }
-  })
-}
-
-// AI 健康管家(健康知识库检索 + 个性化建议 + 任务生成)
-export const aiSendHealthButlerMessage = (data) => {
-  var query = data && data.query ? data.query : ''
-  var conversationId = data && data.conversationId ? data.conversationId : ''
-  var userId = uni.getStorageSync('userId') || ''
-  var memberId = data && data.memberId ? data.memberId : null
-  var langgraphBody = {
-    query: query,
-    user: userId,
-    user_id: userId,
-    conversation_id: conversationId,
-    response_mode: 'blocking',
-    bot_name: 'AI健康管家'
-  }
-  var inputs = {}
-  if (memberId) { inputs.child_id = memberId }
-  if (data && data.reportId) { inputs.report_id = data.reportId }
-  if (data && data.focus) { inputs.focus = data.focus }
-  if (Object.keys(inputs).length > 0) { langgraphBody.inputs = inputs }
-  return langgraphRequest({
-    langgraphPath: '/api/v1/health/butler',
-    langgraphBody: langgraphBody,
-    difyFallbackPath: '/api/ai/chat/send',
-    difyFallbackData: data,
-    transform: function(lgRes) {
-      var content = ''
-      if (lgRes && lgRes.choices && lgRes.choices.length > 0) {
-        var msg = lgRes.choices[0].message
-        if (msg && msg.content) { content = msg.content }
-      }
-      var tasks = []
-      var metadata = lgRes && lgRes.metadata
-      if (metadata && metadata.tasks) { tasks = metadata.tasks }
-      return {
-        answer: content,
-        conversationId: conversationId,
-        recommendations: [],
-        tasks: tasks
-      }
-    }
-  })
-}
-
-//  幸福邻里部落 - 服务商模块 
-
-// 提交服务商入驻申请
-export const vendorApply = (data) => {
-  return request('/api/vendor/apply', 'POST', data)
-}
-
-// 查询入驻审核状态
-export const vendorStatus = () => {
-  return request('/api/vendor/status', 'POST', {})
-}
-
-export const nutritionistApply = (data) => {
-  return request('/api/nutritionist/apply', 'POST', data)
-}
-
-export const nutritionistStatus = () => {
-  return request('/api/nutritionist/status', 'POST', {})
-}
-
-export const butlerApply = (data) => {
-  return request('/api/butler/apply', 'POST', data)
-}
-
-// 获取服务商信息
-export const vendorInfo = () => {
-  return request('/api/vendor/info', 'POST', {})
-}
-
-//  幸福邻里部落 - 商品系统 
-
-// 获取公开配置(pages/health/report-upload 依赖此函数读取 report_upload_category_id)
-export const getPublicConfig = (key) => {
-  return request('/api/config/public/value', 'POST', { key: key })
-}
-
-// 商品分类树(公开)— pages/shop/index 依赖此函数加载分类,缺失会导致 onLoad 中断
-export const goodsCategory = () => {
-  return request('/api/shop/category/tree', 'POST', {})
-}
-
-// 商品列表(公开)
-export const productList = (params) => {
-  return request('/api/product/list', 'POST', params)
-}
-
-// 商品详情(公开)
-export const productDetail = (params) => {
-  return request('/api/product/detail', 'POST', params)
-}
-
-// 商品规格映射(公开)
-export const productSpecMap = (params) => {
-  return request('/api/product/spec/map', 'POST', params)
-}
-
-// 商品SKU列表
-export const productSkuList = (params) => {
-  return request('/api/product/sku/list', 'POST', params)
-}
-
-// 服务商发布商品
-export const productCreate = (params) => {
-  return request('/api/product/create', 'POST', params)
-}
-
-// 服务商更新商品
-export const productUpdate = (params) => {
-  return request('/api/product/update', 'POST', params)
-}
-
-// 服务商查询自己的商品
-export const productMy = (params) => {
-  return request('/api/product/my', 'POST', params)
-}
-
-// 服务商上架/下架商品
-export const productShelve = (params) => {
-  return request('/api/product/shelve', 'POST', params)
-}
-
-// 创建订单
-export const productOrderCreate = (params) => {
-  return request('/api/product/order/create', 'POST', params)
-}
-
-// 支付订单
-export const productOrderPay = (params) => {
-  return request('/api/product/order/pay', 'POST', params)
-}
-
-// 取消订单
-export const productOrderCancel = (params) => {
-  return request('/api/product/order/cancel', 'POST', params)
-}
-
-// 我的订单
-export const productOrderMy = (params) => {
-  return request('/api/product/order/my', 'POST', params)
-}
-
-export const productOrderCounts = () => {
-  return request('/api/product/order/my/counts', 'POST', {})
-}
-
-// 订单详情
-export const productOrderDetail = (params) => {
-  return request('/api/product/order/detail', 'POST', params)
-}
-
-// 服务商查询收到的订单
-export const productOrderVendor = (params) => {
-  return request('/api/product/order/vendor', 'POST', params)
-}
-
-// 服务商确认订单完成
-export const productOrderConfirm = (params) => {
-  return request('/api/product/order/confirm', 'POST', params)
-}
-
-// 用户申请订单退款
-export const productOrderRefundApply = (params) => {
-  return request('/api/product/order/refund/apply', 'POST', params)
-}
-
-// 管理员:商品待审核列表
-export const adminProductPending = (params) => {
-  return request('/api/admin/product/pending', 'POST', params)
-}
-
-// 管理员:商品列表
-export const adminProductList = (params) => {
-  return request('/api/admin/product/list', 'POST', params)
-}
-
-// 管理员:商品审核
-export const adminProductReview = (params) => {
-  return request('/api/admin/product/review', 'POST', params)
-}
-
-// 管理员:订单列表
-export const adminOrderList = (params) => {
-  return request('/api/admin/order/list', 'POST', params)
-}
-
-// 管理员:系统配置列表
-export const adminConfigList = (params) => {
-  return request('/api/admin/config/list', 'POST', params)
-}
-
-// 管理员:系统配置更新
-export const adminConfigUpdate = (params) => {
-  return request('/api/admin/config/update', 'POST', params)
-}
-
-// 管理员:获取所有配置
-export const adminConfigAll = (params) => {
-  return request('/api/admin/config/all', 'POST', params)
-}
-
-
-//  统计报表
-export const getChildOverview = (memberId) => {
-  return request('/api/stats/child/overview', 'POST', { memberId })
-}
-
-export const getFamilySummary = () => {
-  return request('/api/stats/family/summary', 'POST', {})
-}
-
-export const getPointsRanking = () => {
-  return request('/api/stats/points/ranking', 'POST', {})
-}
-
-//  鍕嬬珷绯荤粺 
-export const getActiveBadges = () => {
-  return request('/api/badges/list', 'POST')
-}
-
-export const getAllBadges = () => {
-  return request('/api/badges/all', 'POST')
-}
-
-export const getBadgeDetail = (id) => {
-  return request('/api/badges/detail', 'POST', { id })
-}
-
-export const getChildBadges = (memberId) => {
-  return request('/api/badges/child/list', 'POST', { memberId })
-}
-
-export const toggleBadgeFavorite = (memberId, badgeId) => {
-  return request('/api/badges/favorite', 'POST', { memberId, badgeId })
-}
-
-export const getChildBadgeStats = (memberId) => {
-  return request('/api/badges/statistics/child', 'POST', { memberId })
-}
-
-export const getFamilyBadgeRanking = () => {
-  return request('/api/badges/ranking/family', 'POST', {})
-}
-
-// ===== 内容区块权限 =====
-export const getVisibleSections = (data) => request('/api/content-sections/visible', 'POST', data)
-
-//  分佣裂变系统 
-
-// 获取/创建我的邀请码
-export const getReferralCode = () => {
-  return request('/api/invite/code', 'POST')
-}
-
-// 获取邀请二维码
-export const getInviteQrCode = () => {
-  return request('/api/invite/qrcode', 'POST')
-}
-
-export const getShareQrCode = (page, scene) => {
-  return request('/api/share/qrcode', 'POST', { page, scene })
-}
-
-// 绑定推荐人
-export const bindReferral = (referralCode) => {
-  return request('/api/invite/bind', 'POST', { referralCode })
-}
-
-// 我的邀请列表
-export const getReferralList = (page = 1, size = 10) => {
-  return request('/api/invite/list', 'POST', { page, size })
-}
-
-// 邀请统计
-export const getReferralSummary = () => {
-  return request('/api/invite/summary', 'POST')
-}
-
-// 浣i噾鎬昏
-export const getCommissionSummary = () => {
-  return request('/api/commission/summary', 'POST')
-}
-
-// 浣i噾鏄庣粏
-export const getCommissionList = (page = 1, size = 20, status) => {
-  var params = { page: page, size: size }
-  if (status) {
-    params.status = status
-  }
-  return request('/api/commission/list', 'POST', params)
-}
-
-// 鐢宠鎻愮幇
-export const applyWithdrawal = (amount, accountInfo) => {
-  return request('/api/withdrawal/apply', 'POST', { amount, accountInfo })
-}
-
-// 鎻愮幇璁板綍
-export const getWithdrawalHistory = (page = 1, size = 10) => {
-  return request('/api/withdrawal/history', 'POST', { page, size })
-}
-
-//  浜旇鑳介噺娌欑洏 
-
-// 获取家庭能量沙盘数据(家庭五维+ 每个成员的个人数据)
-export const getFamilyEnergySandbox = () => {
-  return request('/api/energy/sandbox', 'POST')
-}
-
-// ===== 文章内容系统 =====
-export const getArticleCategories = () => request('/api/articles/categories', 'POST')
-export const getArticleList = (data) => request('/api/articles/list', 'POST', data)
-export const getArticleDetail = (data) => request('/api/articles/detail', 'POST', data)
-export const getFeaturedArticles = (data) => request('/api/articles/featured', 'POST', data)
-export const recordArticleRead = (data) => request('/api/articles/record-read', 'POST', data)
-export const reportReadingTime = (data) => request('/api/articles/report-reading-time', 'POST', data)
-export const getReadingStats = (memberId) => request('/api/articles/reading-stats', 'POST', { memberId })
-export const getDailyTip = () => request('/api/articles/daily-tip', 'POST')
-export const getAiQuestions = (data) => request('/api/articles/ai-questions', 'POST', data)
-export const submitAnswers = (data) => request('/api/articles/submit-answers', 'POST', data)
-export const publishArticle = (data) => request('/api/articles/publish', 'POST', data)
-export const getMyPosts = (data) => request('/api/articles/my-posts', 'POST', data)
-// 文章评论
-export const getArticleComments = (data) => request('/api/articles/comments/list', 'POST', data)
-export const createArticleComment = (data) => request('/api/articles/comments/create', 'POST', data)
-export const auditArticleComment = (data) => request('/api/articles/comments/audit', 'POST', data)
-export const getPendingComments = (data) => request('/api/articles/comments/pending', 'POST', data)
-export const getMyComments = (data) => request('/api/articles/comments/my', 'POST', data)
-// 文章完成阅读
-export const completeArticleRead = (data) => request('/api/articles/complete-read', 'POST', data)
-// AI答题
-export const generateQuiz = (data) => request('/api/articles/quiz/generate', 'POST', data)
-export const submitQuiz = (data) => request('/api/articles/quiz/submit', 'POST', data)
-
-// ===== EMI蹇冪悊鎶ュ憡 =====
-export const getEmiReport = (memberId) => request('/api/emireport/latest', 'POST', { memberId })
-
-
-// ===== 认知测评结果 =====
-export const getAssessmentLatestResult = (memberId) => request('/api/assessment/latest-result', 'POST', { memberId })
-export const getAssessmentHistory = (memberId, size) => request('/api/assessment/history', 'POST', { memberId, size: size || 5 })
-
-// ===== 测评额度(商城化改造) =====
-export const getAssessmentQuotas = () => request('/api/assessment/quota/my-list', 'POST')
-export const getAssessmentQuotaDetail = (quotaId) => request('/api/assessment/quota/detail', 'POST', { quotaId })
-export const createAssessmentAppointmentWithQuota = (data) => request('/api/assessment/appointment/create', 'POST', data)
-
-// ===== 测评报告上传与指导意见 =====
-export const uploadAssessmentReport = (file, memberId, notes) => {
-  return new Promise((resolve, reject) => {
-    uni.uploadFile({
-      url: BASE_URL + '/api/dan-assessment/result/upload',
-      filePath: file.path,
-      name: 'file',
-      formData: { memberId: memberId, notes: notes || '' },
-      header: { Authorization: 'Bearer ' + uni.getStorageSync('token') },
-      success: (res) => {
-        try {
-          resolve(JSON.parse(res.data))
-        } catch (e) {
-          reject(e)
-        }
-      },
-      fail: reject
-    })
-  })
-}
-export const saveGuidance = (resultId, items) => request('/api/dan-assessment/result/' + resultId + '/guidance/save', 'POST', { items })
-export const getGuidance = (resultId) => request('/api/dan-assessment/result/' + resultId + '/guidance', 'POST')
-export const confirmUploadReport = (resultId, data) => request('/api/dan-assessment/result/' + resultId + '/confirm-upload', 'POST', data)
-
-// ===== 认知训练建议(家庭行动清单) =====
-export const getCognitiveRecommendations = (memberId) => request('/api/cognitive/recommendations', 'POST', { memberId })
-export const createTaskFromRecommendation = (memberId, dimensionKey, taskIndex) =>
-  request('/api/cognitive/recommendations/create-task', 'POST', { memberId, dimensionKey, taskIndex })
-export const getCognitiveNorms = (memberId) => request('/api/cognitive/norms', 'POST', { memberId })
-export const getCognitiveTrend = (memberId, limit) => request('/api/cognitive/trend', 'POST', { memberId, limit: limit || 5 })
-
-// ===== 五维能量系统(账本模式) =====
-export const getEnergyOverview = (memberId) => {
-  return request('/api/energy/overview', 'POST', { memberId })
-}
-
-export const getEnergyLogs = (memberId, dimensionCode, page = 1, size = 10) => {
-  return request('/api/energy/logs', 'POST', { memberId, dimensionCode, page, size })
-}
-
-export const getWealthDetail = (memberId, memberType) => {
-  return request('/api/energy/wealth-detail', 'POST', { memberId, memberType })
-}
-
-// ===== 成就徽章 =====
-export const getUserBadges = (memberId) => {
-  return request('/api/badges/child/list', 'POST', { memberId })
-}
-
-
-// ===== 成长报告 =====
-export const getGrowthReport = (memberId) => {
-  return request('/api/stats/child/overview', 'POST', { memberId })
-}
-
-// ===== 用户行动统计(我的页面) =====
-export const getUserActionStats = () => {
-  return request('/api/user/action-stats', 'POST')
-}
-
-// ===== 热门活动(行Tab) =====
-export const getHotActivities = (data) => {
-  return request('/api/activities/hot', 'POST', data)
-}
-
-// ===== 推荐商品(行Tab) =====
-export const getRecommendedProducts = (data) => {
-  return request('/api/products/recommend', 'POST', data)
-}
-
-//  浼氬憳鍗囩骇涓庣画璐?
-
-// 鍗囩骇浼氬憳
-export const upgradeMember = (levelCode) => {
-  return request('/api/membership/upgrade', 'POST', { levelCode })
-}
-
-// 获取当前会员等级详情
-export const getMemberLevel = (levelCode) => {
-  return request('/api/membership/level', 'POST', { levelCode })
-}
-
-// 获取升级记录
-export const getUpgradeRecords = (page = 1, size = 10) => {
-  return request('/api/membership/upgrade-records', 'POST', { page, size })
-}
-
-//  佣金团队统计 
-
-// 推广团队列表
-export const getCommissionTeam = (page = 1, size = 10) => {
-  return request('/api/commission/team', 'POST', { page, size })
-}
-
-// 推广团队成员列表(分页)
-export const getTeamList = (page = 1, size = 20, level = 'ALL') => {
-  return request('/api/commission/team/list', 'POST', { page, size, level })
-}
-
-// 浣i噾缁熻鏁版嵁
-export const getCommissionStats = () => {
-  return request('/api/commission/stats', 'POST')
-}
-
-// 浣i噾浣欓
-export const getCommissionBalance = () => {
-  return request('/api/commission/balance', 'POST')
-}
-
-// ===== 财富维度 · 财商打卡 =====
-export const getCheckinList = (data) => {
-  return request('/api/wealth/checkin/list', 'POST', data)
-}
-
-export const getCheckinStats = (data) => {
-  return request('/api/wealth/checkin/stats', 'POST', data)
-}
-
-export const createCheckin = (data) => {
-  return request('/api/wealth/checkin/create', 'POST', data)
-}
-
-export const deleteCheckin = (id) => {
-  return request('/api/wealth/checkin/delete', 'POST', { id })
-}
-
-// ===== 财富维度 · 保单管理 =====
-export const getInsuranceList = (data) => {
-  return request('/api/wealth/insurance/list', 'POST', data)
-}
-
-export const getInsuranceDetail = (id) => {
-  return request('/api/wealth/insurance/detail', 'POST', { id })
-}
-
-export const createInsurance = (data) => {
-  return request('/api/wealth/insurance/create', 'POST', data)
-}
-
-export const updateInsurance = (data) => {
-  return request('/api/wealth/insurance/update', 'POST', data)
-}
-
-export const deleteInsurance = (id) => {
-  return request('/api/wealth/insurance/delete', 'POST', { id })
-}
-
-export const getInsurancePlanning = () => {
-  return request('/api/insurance/planning', 'POST', {})
-}
-
-// ===== 鍋ュ悍鎵撳崱 =====
-export const healthCheckinList = (data) => request('/api/health/checkin/list', 'POST', data)
-export const healthCheckinCreate = (data) => request('/api/health/checkin/create', 'POST', data)
-export const healthCheckinDelete = (id) => request('/api/health/checkin/delete', 'POST', { id })
-
-// ===== 寰鍔紙P0 鏈夋晥鍚姩锛� =====
-export const microActionList = () => request('/api/micro-action/list', 'POST', {})
-export const microActionToday = (data) => request('/api/micro-action/today', 'POST', data)
-export const microActionComplete = (data) => request('/api/micro-action/complete', 'POST', data)
-export const microActionCheckToday = (data) => request('/api/micro-action/check-today', 'POST', data)
-
-// ===== 每日反馈(P1-1 即时多巴胺反馈) =====
-export const getTodayFeedback = (data) => request('/api/feedback/today', 'POST', data)
-export const markFeedbackRead = (data) => request('/api/feedback/read', 'POST', data)
-export const getRecentFeedbacks = (data) => request('/api/feedback/recent', 'POST', data)
-
-// ===== 健康预警(P1-2 健康行为智能预警) =====
-export const getActiveAlerts = (data) => request('/api/health/alert/list', 'POST', data)
-export const dismissAlert = (data) => request('/api/health/alert/dismiss', 'POST', data)
-
-// ===== 健康积分/等级/时间线(P2-1 身份重塑) =====
-export const getHealthScoreInfo = (data) => request('/api/health/score/info', 'POST', data)
-export const getHealthStreak = (data) => request('/api/health/score/streak', 'POST', data)
-export const getHealthTimeline = (data) => request('/api/health/timeline/list', 'POST', data)
-
-// ===== 家庭健康互动(P2-2 排行榜/点赞/挑战) =====
-export const getFamilyRanking = (data) => request('/api/health/family/ranking', 'POST', data)
-export const getChallengeList = (data) => request('/api/health/challenge/list', 'POST', data)
-export const getChallengeHistory = (data) => request('/api/health/challenge/history', 'POST', data)
-export const updateChallengeProgress = (data) => request('/api/health/challenge/progress', 'POST', data)
-export const respondChallenge = (data) => request('/api/health/challenge/respond', 'POST', data)
-export const createChallenge = (data) => request('/api/health/challenge/create', 'POST', data)
-export const updateChallenge = (id, data) => request('/api/health/challenge/update/' + id, 'POST', data)
-export const deleteChallenge = (id) => request('/api/health/challenge/delete/' + id, 'POST', data)
-export const getChallengeTemplates = () => request('/api/health/challenge/templates', 'POST', {})
-export const sendLike = (data) => request('/api/health/interact/like', 'POST', data)
-
-// ===== 健康社区扩散(P3 健康圈/排行/分享) =====
-export const getCircleList = (data) => request('/api/health/circle/list', 'POST', data)
-export const createCircle = (data) => request('/api/health/circle/create', 'POST', data)
-export const joinCircle = (data) => request('/api/health/circle/join', 'POST', data)
-export const leaveCircle = (data) => request('/api/health/circle/leave', 'POST', data)
-export const getCircleRanking = (data) => request('/api/health/circle/ranking', 'POST', data)
-export const getCircleChallengeList = (data) => request('/api/health/circle/challenge/list', 'POST', data)
-export const getCircleChallengeHistory = (data) => request('/api/health/circle/challenge/history', 'POST', data)
-
-// ===== 通用圈子(社交圈) =====
-export const getMyCircles = (memberId, memberType) => {
-  return request('/api/circle/my-circles', 'POST', { memberId: memberId, memberType: memberType || 'child' })
-}
-export const discoverCircles = (memberId) => {
-  return request('/api/circle/discover', 'POST', { memberId: memberId })
-}
-export const joinGeneralCircle = (circleId, memberId, memberType) => {
-  return request('/api/circle/join', 'POST', { circleId: circleId, memberId: memberId, memberType: memberType || 'child' })
-}
-export const leaveGeneralCircle = (circleId, memberId, memberType) => {
-  return request('/api/circle/leave', 'POST', { circleId: circleId, memberId: memberId, memberType: memberType || 'child' })
-}
-
-export const getFamilyFootprint = (data) => request('/api/share/family-footprint', 'POST', data)
-
-// ===== 娲诲姩妯″潡锛堢淮搴︾瓫閫夛級 =====
-export const getActivityList = (data) => request('/api/activity/list', 'POST', data)
-export const getActivityDetail = (id) => request('/api/activity/detail', 'POST', { id })
-export const activityCheckin = (data) => request('/api/activity/checkin', 'POST', data)
-// 活动报名
-export const registerActivity = (data) => request('/api/activity/register', 'POST', data)
-export const cancelActivityRegistration = (data) => request('/api/activity/cancel-registration', 'POST', data)
-export const getMyActivityRegistrations = (data) => request('/api/activity/my-registrations', 'POST', data)
-export const submitActivityFeedback = (data) => request('/api/activity/feedback/submit', 'POST', data)
-export const getActivityFeedbackList = (data) => request('/api/activity/feedback/list', 'POST', data)
-export const getMyActivityFeedback = (data) => request('/api/activity/feedback/my', 'POST', data)
-// 活动报名订单(先支付后报名)
-export const createActivityOrder = (data) => request('/api/activity/order/create', 'POST', data)
-export const payActivityOrder = (orderNo) => request('/api/activity/order/pay', 'POST', { orderNo: orderNo })
-export const handleActivityOrderSuccess = (orderNo) => request('/api/activity/order/handlePaymentSuccess', 'POST', { orderNo: orderNo })
-export const getActivityOrderStatus = (orderNo) => request('/api/activity/order/status', 'POST', { orderNo: orderNo })
-
-// ===== 活动管理(管理员端,复用 /api/activity/*) =====
-export const adminCreateActivity = (activity) => request('/api/activity/create', 'POST', activity)
-export const adminUpdateActivity = (activity) => request('/api/activity/update', 'POST', activity)
-export const adminPublishActivity = (id) => request('/api/activity/publish', 'POST', { id })
-export const adminEndActivity = (id) => request('/api/activity/end', 'POST', { id })
-export const submitActivityForReview = (id) => request('/api/activity/submit-review', 'POST', { id })
-// 管理员列表:获取所有活动(含草稿),按 vendorId 过滤自己创建的
-export const adminListMyActivities = (data) => request('/api/activity/list', 'POST', data)
-// 后台概览列表:获取已发布的活动做统计
-export const adminListAllActivities = (data) => request('/api/activity/list', 'POST', data)
-
-export const getSubscriptionPlans = () => request('/api/subscription/plans', 'POST')
-export const getMySubscription = () => request('/api/subscription/status', 'POST')
-export const createSubscriptionOrder = (data) => request('/api/subscription/create', 'POST', data)
-export const setAutoRenew = (data) => request('/api/subscription/auto-renew', 'POST', data)
-export const cancelSubscription = (data) => request('/api/subscription/cancel', 'POST', data)
-export const checkBenefit = (data) => request('/api/subscription/benefit/check', 'POST', data)
-
-export const getMyPromotionTier = () => request('/api/promotion/my-tier', 'POST')
-export const getPromotionTiers = () => request('/api/promotion/tiers', 'POST')
-export const getPromotionTeamTree = (data) => request('/api/promotion/team-tree', 'POST', data)
-export const getTierHistory = () => request('/api/promotion/tier-history', 'POST')
-
-export const getMyEarnings = () => request('/api/commission/my-earnings', 'POST')
-export const getCommissionRecords = (page, size) => request('/api/commission/records', 'POST', { page: page || 1, size: size || 20 })
-export const getPpointProducts = () => request('/api/commission/ppoint/products', 'POST')
-
-// ===== 家庭收益(推广中心重构) =====
-export const getFamilyEarningsSummary = () => request('/api/earnings/family/summary', 'POST')
-export const getFamilyEarningsMembers = () => request('/api/earnings/family/members', 'POST')
-export const getFamilyEarningsRecords = (data) => request('/api/earnings/family/records', 'POST', data || {})
-export const distributeToMember = (data) => request('/api/earnings/admin/distribute', 'POST', data)
-export const toggleMemberBalance = (data) => request('/api/earnings/admin/toggle-member', 'POST', data)
-export const withdrawFamilyEarnings = (data) => request('/api/earnings/admin/withdraw', 'POST', data)
-
-
-// ===== 缁村害浠诲姟锛堝甫 category 绛涢€夛級 =====
-export const getTodayTasksByCategory = (memberId, category) => {
-  return request('/api/tasks/today', 'POST', { memberId: memberId, category: category })
-
-}
-export const getTaskHistoryByCategory = (memberId, category, page, size) => {
-  return request('/api/tasks/history', 'POST', { memberId: memberId, category: category, page: page || 1, size: size || 10 })
-}
-
-// ===== 维度商品(domain 筛选,使用 productList) =====
-export const getProductsByDomain = (domain, page, size) => {
-  return productList({ domain: domain, page: page || 1, size: size || 6 })
-}
-
-
-// ===== 鍋ュ悍鎶ュ憡锛堜袱闃舵鍏ュ簱锛?=====
-export const getLatestHealthReport = (memberId) => request('/api/health/report/latest', 'POST', { memberId })
-export const getHealthIndicatorList = (memberId) => request('/api/health/indicator/list', 'POST', { memberId })
-
-
-export const createHealthReport = (data) => request('/api/health/report/create', 'POST', data)
-export const getReportList = (memberId) => request('/api/health/report/list', 'POST', { memberId })
-export const getReportDetail = (reportId) => request('/api/health/report/detail', 'POST', { reportId })
-
-export const editHealthReport = (reportId, payload, subjectId) => request('/api/health/report/edit', 'POST', { reportId, payload, subjectId })
-
-export const queryKnowledgeBase = (itemType, itemName) => request('/api/health/knowledge/query', 'POST', { itemType, itemName })
-
-export const batchQueryKnowledgeBase = (queries) => request('/api/health/knowledge/batch-query', 'POST', { queries })
-
-
-// 闃舵1锛氫笂浼燩DF鈫掕В鏋愨啋瀛榙raft鈫掕繑鍥瀌raftId+payload+鎴愬憳鍖归厤锛堜笉钀藉簱锛?
-export const parseReportPreview = (filePath, memberId, type) => {
-  return new Promise((resolve, reject) => {
-    const token = uni.getStorageSync('token')
-    uni.uploadFile({
-      url: BASE_URL + '/api/health/report/parse-preview' + (type ? '?type=' + type : ''),
-      filePath: filePath,
-      name: 'file',
-      formData: {
-        memberId: memberId || ''
-      },
-      header: {
-        'Authorization': token ? 'Bearer ' + token : ''
-      },
-      success: (res) => {
-        var data
-        try { data = JSON.parse(res.data) } catch (e) { data = res.data }
-        if (data && data.code === 200) {
-          resolve(data)
-        } else {
-          console.warn('[API] 解析上传失败 ' + BASE_URL + '/api/health/report/parse-preview' + ' code=' + (data && data.code || '') + ' msg=' + (data && data.message || ''))
-          reject(data)
-        }
-      },
-      fail: (err) => {
-        console.error('[API] 解析上传网络错误 ' + BASE_URL + '/api/health/report/parse-preview', err)
-        reject(err)
-      }
-    })
-  })
-}
-
-// 闃舵2锛氱‘璁よ惤搴擄紙鍙€変紶淇敼鍚庣殑payload鍜宻ubjectId锛?
-
-// 阶段2:确认落库(可选传修改后的payload和subjectId)
-
-export const confirmReportPreview = (data) => request('/api/health/report/confirm', 'POST', data)
-
-// 鏀惧純鑽夌
-export const discardReportDraft = (draftId) => request('/api/health/report/discard', 'POST', { draftId })
-
-// ===== 鎶ュ憡璋冪爺闂嵎 =====
-export const createReportSurvey = (reportId, memberId) => request('/api/health/survey/create', 'POST', { reportId, memberId })
-export const submitReportSurvey = (surveyId, surveyData) => request('/api/health/survey/submit', 'POST', { surveyId, surveyData })
-export const getSurveyStatus = (reportId) => request('/api/health/survey/status', 'POST', { reportId })
-
-// ===== Report Feedback (gut flora report feedback) =====
-export const submitFeedback = (data) => request('/api/health/feedback/submit', 'POST', data)
-
-// ===== 重要关系(联系人) =====
-export const getContactList = (data) => request('/api/contact/list', 'POST', data)
-export const getContactDetail = (id) => request('/api/contact/detail', 'POST', { id: id })
-export const createContact = (data) => request('/api/contact/create', 'POST', data)
-export const updateContact = (data) => request('/api/contact/update', 'POST', data)
-export const deleteContact = (id) => request('/api/contact/delete', 'POST', { id: id })
-export const importPhoneContact = (data) => request('/api/contact/import-phone', 'POST', data)
-export const recordContactInteraction = (data) => request('/api/contact/interaction', 'POST', data)
-
-// ===== 椋熻氨鎺ㄨ崘 =====
-export const getMealRecommend = (params) => request('/api/meal/recommend', 'POST', params)
-export const replaceFood = (data) => request('/api/meal/replace', 'POST', data)
-export const logMeal = (data) => request('/api/meal/log', 'POST', data)
-export const getMealLogs = (data) => request('/api/meal/logs', 'POST', data)
-export const getNutritionSummary = (data) => request('/api/meal/nutrition-summary', 'POST', data)
-export const getNutritionProfile = (data) => request('/api/nutrition/profile/get', 'POST', data)
-export const saveNutritionProfile = (data) => request('/api/nutrition/profile/save', 'POST', data)
-
-// ===== 钀ュ吇妗f涓庣己涔忓垎鏋?=====
-export const getChildNutritionProfile = (memberId) => request('/api/health/nutrition/profile', 'POST', { memberId })
-
-// ===== 家庭天盘 =====
-export const getFamilyFortune = () => request('/api/mind/fortune', 'POST')
-export const getDeficiencyAnalysis = (memberId) => request('/api/health/nutrition/deficiency', 'POST', { memberId })
-export const getDeficiencySummary = (memberId) => request('/api/health/nutrition/deficiency-summary', 'POST', { memberId })
-export const getNutritionTrend = (memberId) => request('/api/health/nutrition/trend', 'POST', { memberId })
-export const getHealthAnalysis = (memberId) => request('/api/health/analysis', 'POST', { memberId })
-export const getNutritionMappings = (data) => request('/api/health/nutrition/mappings', 'POST', data || {})
-
-// ===== 健康维度 =====
-export const getDimensionOverview = (data) => request('/api/dimension/overview', 'POST', data)
-export const uploadDimensionScore = (data) => request('/api/dimension/upload', 'POST', data)
-export const submitDimensionQuestionnaire = (data) => request('/api/dimension/questionnaire', 'POST', data)
-export const getDimensionHistory = (data) => request('/api/dimension/history', 'POST', data)
-
-// ===== 閭€璇烽噷绋嬬 =====
-export const getInviteMilestones = () => {
-  return request('/api/invite/milestone/list', 'POST')
-}
-export const claimInviteMilestone = (milestone) => {
-  return request('/api/invite/milestone/claim', 'POST', { milestone })
-}
-
-//  浼樻儬鍒告ā鍧?
-export const getCouponList = () => {
-  return request('/api/coupon/list', 'POST')
-}
-
-export const claimCoupon = (couponId) => {
-  return request('/api/coupon/claim', 'POST', { couponId })
-}
-
-export const getExchangeableCoupons = () => {
-  return request('/api/coupon/exchangeable', 'POST', {})
-}
-
-export const getProductCoupons = (data) => {
-  return request('/api/coupon/product', 'POST', data)
-}
-
-export const exchangeCoupon = (data) => {
-  return request('/api/coupon/exchange', 'POST', data)
-}
-
-export const getJoinCouponRules = () => {
-  return request('/api/coupon/join-rules', 'POST', {})
-}
-
-// ===== 新手任务(Onboarding Rewards) =====
-export const getOnboardingProgress = () => {
-  return request('/api/onboarding/progress', 'POST')
-}
-export const claimOnboardingReward = (taskType) => {
-  return request('/api/onboarding/claim', 'POST', { taskType })
-}
-
-// ===== 成长任务(每日新手任务系统) =====
-export const getGrowthTaskList = (type) => {
-  return request('/api/growth-task/list', 'POST', { type: type || 'DAILY' })
-}
-
-export const claimGrowthTaskReward = (taskLogId) => {
-  return request('/api/growth-task/claim', 'POST', { taskLogId })
-}
-
-// ===== 推广排行榜 =====
-export const getLeaderboardTop = () => {
-  return request('/api/leaderboard/top', 'POST')
-}
-
-export const getLeaderboardMyRank = () => {
-  return request('/api/leaderboard/my-rank', 'POST')
-}
-
-
-// ===== 鏁板闂叧锛堣嚜宸卞嚭棰樿嚜宸辩瓟锛?=====
-export const getMathQuizStart = (memberId, age) => {
-  return request('/api/wisdom/math/start', 'POST', { memberId, age })
-
-  return request('/api/wisdom/math/start', 'POST', { childId, age })
-
-}
-
-export const verifyMathAnswer = (memberId, expression, userAnswer) => {
-  return request('/api/wisdom/math/verify', 'POST', { memberId, expression, userAnswer })
-}
-
-export const completeMathQuiz = (data) => {
-  return request('/api/wisdom/math/complete', 'POST', data)
-}
-
-// ===== 鍏崇郴璐ㄩ噺璇勫垎 =====
-export const getRelationshipScores = () => {
-  return request('/api/family/relationship/scores', 'POST', {})
-}
-
-export const calculateRelationshipScore = (memberId) => {
-  return request('/api/family/relationship/calculate', 'POST', { memberId })
-}
-
-export const getHealthAlerts = () => {
-  return request('/api/family/relationship/health-alerts', 'POST', {})
-}
-
-export const getMilestones = (daysAhead) => {
-  return request('/api/family/relationship/milestones', 'POST', { daysAhead })
-}
-
-// ===== 浜掑姩璁板綍 =====
-export const addInteraction = (data) => {
-  return request('/api/family/interaction/add', 'POST', data)
-}
-
-export const listInteractions = (data) => {
-  return request('/api/family/interaction/list', 'POST', data)
-}
-
-export const getInteractionTypes = () => {
-  return request('/api/family/interaction/types', 'GET', {})
-}
-
-// ===== 鍏崇郴闂嵎 =====
-export const generateQuestionnaire = (memberId) => {
-  return request('/api/family/questionnaire/generate', 'POST', { memberId })
-}
-
-export const submitQuestionnaire = (data) => {
-  return request('/api/family/questionnaire/submit', 'POST', data)
-}
-
-export const getQuestionnaireSnapshot = (memberId) => {
-  return request('/api/family/questionnaire/snapshot/' + memberId, 'GET', {})
-}
-
-export const getQuestionnaireHistory = (memberId) => {
-  return request('/api/family/questionnaire/history/' + memberId, 'GET', {})
-}
-
-// ===== 五维家庭自检(P0-1)=====
-export const getSelfCheckQuestions = () => {
-  return request('/api/family/self-check/questions', 'POST', {})
-}
-
-export const submitSelfCheck = (data) => {
-  return request('/api/family/self-check/submit', 'POST', data)
-}
-
-export const getSelfCheckLatest = () => {
-  return request('/api/family/self-check/latest', 'POST', {})
-}
-
-export const getSelfCheckHistory = () => {
-  return request('/api/family/self-check/history', 'POST', {})
-}
-
-// ===== 舌诊相关(两阶段流程) =====
-export const parseTonguePreview = (data) => request('/api/health/report/parse-preview?type=tongue', 'POST', data)
-export const confirmTongue = (data) => request('/api/health/report/confirm?type=tongue', 'POST', data)
-export const discardTongue = (data) => request('/api/health/report/discard?type=tongue', 'POST', data)
-// 鎸囨爣瀹氫箟
-export const getIndicatorDefinitions = (data) => request('/api/admin/indicator/list', 'POST', data)
-
-export const getPointsExchangeProducts = (data) => request('/api/points/exchange/product/list', 'POST', data)
-export const getPointsExchangeProductDetail = (data) => request('/api/points/exchange/product/detail', 'POST', data)
-export const submitPointsExchange = (data) => request('/api/points/exchange/submit', 'POST', data)
-export const getPointsExchangeRecords = () => request('/api/points/exchange/records', 'POST', {})
-export const getPointsExchangeStats = () => request('/api/points/exchange/stats', 'POST', {})
-
-// ===== 购物车 =====
-export const cartAdd = (data) => request('/api/cart/add', 'POST', data)
-export const cartList = (data) => request('/api/cart/list', 'POST', data)
-export const cartUpdate = (data) => request('/api/cart/update', 'POST', data)
-export const cartRemove = (data) => request('/api/cart/remove', 'POST', data)
-export const cartCount = () => request('/api/cart/count', 'POST', {})
-
-// ===== 我的订单 =====
-export const getOrderCounts = () => request('/api/product/order/my/counts', 'POST', {})
-
-// ===== 收货人管理 =====
-export const consigneeList = () => request('/api/consignee/list', 'POST', {})
-export const consigneeDetail = (id) => request('/api/consignee/detail', 'POST', { id })
-export const consigneeSave = (data) => request('/api/consignee/save', 'POST', data)
-export const consigneeDelete = (id) => request('/api/consignee/delete', 'POST', { id })
-
-// ===== 地址管理 =====
-export const addressList = () => request('/api/user/address/list', 'POST', {})
-export const addressDetail = (id) => request('/api/user/address/get', 'POST', { id })
-export const addressSave = (data) => {
-  var url = data.id ? '/api/user/address/update' : '/api/user/address/create'
-  return request(url, 'POST', data)
-}
-export const addressDelete = (id) => request('/api/user/address/delete', 'POST', { id })
-export const addressSetDefault = (id) => request('/api/user/address/setDefault', 'POST', { id })
-
-// ===== 商品购买字段 =====
-export const getProductRequiredFields = (productId) => request('/api/product/purchase_fields/required', 'POST', { productId })
-
-// ===== 测评方案 =====
-export const listFamilyPlans = (data) => request('/api/guide/plans/family-list', 'POST', data)
-export const reviewPlan = (data) => request('/api/guide/plans/review', 'POST', data)
-export const activatePlan = (data) => request('/api/guide/plans/activate', 'POST', data)
-export const getGuidePlanDetail = (data) => request('/api/guide/plans/detail', 'POST', data)
-
-// ===== 家庭天盘相关 =====
-export const tianpanDashboard = (data) => {
-  return request('/api/tianpan/dashboard', 'POST', data)
-}
-
-export const tianpanMemberDetail = (memberId, data) => {
-  return request('/api/tianpan/member/' + memberId, 'POST', data)
-}
-
-export const tianpanCompatibility = (data) => {
-  return request('/api/tianpan/compatibility', 'POST', data)
-}
-
-export const tianpanAnnualEnergy = (data) => {
-  return request('/api/tianpan/annual-energy', 'POST', data)
-}
-
-export const tianpanDailyFortune = (data) => {
-  return request('/api/tianpan/daily-fortune', 'POST', data)
-}
-
-export const tianpanRelatedItems = (data) => {
-  return request('/api/tianpan/related-items', 'POST', data)
-}
-
-// ===== DAN 测评报告上传 =====
-
-/**
- * Phase 1: 上传 DAN 报告 PDF → 解析 → 返回预览草稿
- */
-export const danParsePreview = (filePath, dimension, memberId) => {
-  return new Promise((resolve, reject) => {
-    var token = uni.getStorageSync('token')
-    uni.uploadFile({
-      url: BASE_URL + '/api/dan-assessment/report/parse-preview',
-      filePath: filePath,
-      name: 'file',
-      formData: {
-        dimension: dimension,
-        memberId: String(memberId || '')
-      },
-      header: {
-        'Authorization': token ? 'Bearer ' + token : ''
-      },
-      success: function(res) {
-        var data
-        try { data = JSON.parse(res.data) } catch (e) { data = res.data }
-        if (data && data.code === 200) {
-          resolve(data)
-        } else {
-          console.warn('[API] DAN上传失败 ' + BASE_URL + '/api/dan-assessment/report/parse-preview' + ' code=' + (data && data.code || '') + ' msg=' + (data && data.message || ''))
-          reject(data || { message: '解析失败' })
-        }
-      },
-      fail: function(err) {
-        console.error('[API] DAN上传网络错误 ' + BASE_URL + '/api/dan-assessment/report/parse-preview', err)
-        reject(err)
-      }
-    })
-  })
-}
-
-/**
- * Phase 2: 确认并保存 DAN 报告
- */
-export const danConfirmReport = (data) => {
-  return request('/api/dan-assessment/report/confirm', 'POST', data)
-}
-
-/**
- * 获取某孩子某维度的 DAN 报告列表
- */
-export const getDanReportByChild = (memberId, dimension) => {
-  return request('/api/dan-assessment/report/child', 'POST', { memberId, dimension })
-}
-
-export const supplierProducts = (data) => {
-  return request('/api/supplier/products', 'POST', data)
-}
-
-// === 商品规格 ===
-export const productSpecGroups = (productId) => {
-  return request('/api/product/spec/groups', 'POST', { productId })
-}
-
-// === 推荐系统 - 维度商品 ===
-export const getDimensionProducts = (data) => {
-  return request('/api/recommend/dimension-products', 'POST', data)
-}
-
-// === 推荐系统 - 复购提醒 ===
-export const getRepurchaseReminders = (data) => {
-  return request('/api/recommend/repurchase-reminders', 'POST', data)
-}
-
-export const clickRepurchaseReminder = (id) => {
-  return request('/api/recommend/repurchase-reminder/' + id + '/click', 'POST', {})
-}
-
-// === KB v3 知识库查询 ===
-
-// 查询菌属功能(支持属级回退)
-export const queryBacteriaKnowledge = (name) => {
-  return request('/api/health/knowledge/v3/bacteria/query', 'POST', { name })
-}
-
-// 批量查询菌属功能
-export const batchQueryBacteriaKnowledge = (names) => {
-  return request('/api/health/knowledge/v3/bacteria/batch-query', 'POST', { names })
-}
-
-// 查询指标调整建议
-export const queryIndicatorKnowledge = (name) => {
-  return request('/api/health/knowledge/v3/indicator/query', 'POST', { name })
-}
-
-// 查询食物营养数据
-export const queryFoodKnowledge = (name) => {
-  return request('/api/health/knowledge/v3/food/query', 'POST', { name })
-}
-
-// 获取KB v3章节数据
-export const getKnowledgeSection = (section) => {
-  return request('/api/health/knowledge/v3/section', 'POST', { section: section || '' })
-}
-
-// 获取我的测评预约列表
-export const getMyAppointments = () => {
-  var userId = uni.getStorageSync('userId')
-  return request('/api/dan-assessment/appointment/user', 'POST', { userId: userId })
-}
-
-// 取消测评预约
-export const cancelAppointment = (id) => {
-  return request('/api/dan-assessment/appointment/cancel', 'POST', { id: id })
-}
-
-// 统一报告管理
-export const getReportSummaryList = (params) => request('/api/report-summary/list', 'POST', params)
-export const getReportSummaryDetail = (id) => request('/api/report-summary/detail/' + id, 'POST', {})
-export const downloadReportSummary = (id) => request('/api/report-summary/download/' + id, 'POST', {})
-
-// 服务角色统一申请
-export const submitServiceRoleApply = (data) => {
-    return request('/api/service-role/apply', 'POST', data)
-}
-
-export const getMyServiceRoleApply = () => {
-    return request('/api/service-role/my-apply', 'POST', {})
-}
-
-export const uploadServiceRoleImage = (filePath) => {
-    return new Promise((resolve, reject) => {
-        uni.uploadFile({
-            url: BASE_URL + '/api/service-role/upload-image',
-            filePath: filePath,
-            name: 'file',
-            header: {
-                'Authorization': 'Bearer ' + uni.getStorageSync('token')
-            },
-            success: (res) => {
-                if (res.statusCode === 200) {
-                    const data = JSON.parse(res.data)
-                    resolve(data)
-                } else {
-                    reject(new Error('上传失败'))
-                }
-            },
-            fail: reject
-        })
-    })
-}
-
-// 推荐系统
-export const getRecommendList = (data) => request('/api/recommend/list', 'POST', data)
-export const trackRecommendAction = (data) => request('/api/recommend/track', 'POST', data)
-
-// ===== 饮食模块 =====
-export const getDietPreferences = () => request('/api/diet/preferences/current-member', 'POST', {})
-export const saveDietPreferences = (data) => request('/api/diet/preferences/save', 'POST', data)
-export const getDietIngredients = () => request('/api/diet/ingredients/suggest', 'POST', {})
-export const refreshDietIngredients = () => request('/api/diet/ingredients/recommend', 'POST', {})
-export const addDietIngredient = (data) => request('/api/diet/ingredients/add', 'POST', data)
-export const removeDietIngredient = (data) => request('/api/diet/ingredients/remove', 'POST', data)
-export const confirmDietIngredients = (data) => request('/api/diet/ingredients/confirm', 'POST', data)
-export const getDietRecommendation = (data) => request('/api/diet/recommendation/today', 'POST', data)
-export const generateDietRecommendation = (data) => request('/api/diet/recommendation/generate', 'POST', data)
-export const updateDietRecommendation = (data) => request('/api/diet/recommendation/update', 'POST', data)
-export const completeDietRecommendation = (data) => request('/api/diet/recommendation/complete', 'POST', data)
-export const recognizeDietFood = (data) => request('/api/diet/record/recognize', 'POST', data)
-export const saveDietRecord = (data) => request('/api/diet/record/save', 'POST', data)
-export const getDietDailyRecords = (data) => request('/api/diet/record/daily', 'POST', data)
-export const getDietWeeklyTrend = (data) => request('/api/diet/record/weekly', 'POST', data)
-export const getMealConfig = (data) => request('/api/diet/meals/config', 'POST', data)
-export const saveMealConfig = (data) => request('/api/diet/meals/config/save', 'POST', data)
+  var query = data && data.query ? data.query : ''
+  var conversationId = data && data.conversationId ? data.conversationId : ''
+  var userId = uni.getStorageSync('userId') || ''
+  var langgraphBody = {
+    query: query,
+    user: userId,
+    user_id: userId,
+    conversation_id: conversationId,
+    response_mode: 'blocking',
+    bot_name: 'AI管家'
+  }
+  if (data && data.reportId) {
+    langgraphBody.inputs = { report_id: data.reportId }
+  }
+  return langgraphRequest({
+    langgraphPath: '/api/v1/chat/completion',
+    langgraphBody: langgraphBody,
+    difyFallbackPath: '/api/ai/chat/send',
+    difyFallbackData: data,
+    transform: function(lgRes) {
+      var content = ''
+      if (lgRes && lgRes.choices && lgRes.choices.length > 0) {
+        var msg = lgRes.choices[0].message
+        if (msg && msg.content) { content = msg.content }
+      }
+      return {
+        answer: content,
+        conversationId: conversationId,
+        recommendations: [],
+        tasks: []
+      }
+    }
+  })
+}
+
+export const aiGetConversations = () => {
+  return request('/api/ai/chat/conversations', 'POST', {})
+}
+
+export const aiGetMessages = (params) => {
+  return request('/api/ai/chat/messages', 'POST', params)
+}
+
+export const aiDeleteConversation = (id) => {
+  return request('/api/ai/chat/conversations/' + id + '/delete', 'POST', {})
+}
+
+// 精准营养助手(基于体检报告)
+export const aiSendNutritionMessage = (data) => {
+  var query = data && data.query ? data.query : ''
+  var conversationId = data && data.conversationId ? data.conversationId : ''
+  var reportId = data && data.reportId ? data.reportId : null
+  var userId = uni.getStorageSync('userId') || ''
+  var langgraphBody = {
+    query: query,
+    user: userId,
+    user_id: userId,
+    conversation_id: conversationId,
+    response_mode: 'blocking',
+    bot_name: '精准营养助手'
+  }
+  if (reportId) {
+    langgraphBody.inputs = { report_id: reportId }
+  }
+  return langgraphRequest({
+    langgraphPath: '/api/v1/analysis/run',
+    langgraphBody: langgraphBody,
+    difyFallbackPath: '/api/ai/nutrition/send',
+    difyFallbackData: data,
+    transform: function(lgRes) {
+      var content = ''
+      if (lgRes && lgRes.choices && lgRes.choices.length > 0) {
+        var msg = lgRes.choices[0].message
+        if (msg && msg.content) { content = msg.content }
+      }
+      return {
+        answer: content,
+        conversationId: conversationId,
+        recommendations: [],
+        tasks: []
+      }
+    }
+  })
+}
+
+// AI 健康教练
+export const aiSendHealthCoachMessage = (data) => {
+  var query = data && data.query ? data.query : ''
+  var conversationId = data && data.conversationId ? data.conversationId : ''
+  var userId = uni.getStorageSync('userId') || ''
+  var langgraphBody = {
+    query: query,
+    user: userId,
+    user_id: userId,
+    conversation_id: conversationId,
+    response_mode: 'blocking',
+    bot_name: '健康教练'
+  }
+  if (data && data.memberId) {
+    langgraphBody.inputs = { child_id: data.memberId }
+  }
+  return langgraphRequest({
+    langgraphPath: '/api/v1/health/coach',
+    langgraphBody: langgraphBody,
+    difyFallbackPath: '/api/ai/chat/send',
+    difyFallbackData: data,
+    transform: function(lgRes) {
+      var content = ''
+      if (lgRes && lgRes.choices && lgRes.choices.length > 0) {
+        var msg = lgRes.choices[0].message
+        if (msg && msg.content) { content = msg.content }
+      }
+      return {
+        answer: content,
+        conversationId: conversationId,
+        recommendations: [],
+        tasks: []
+      }
+    }
+  })
+}
+
+// AI 健康管家(健康知识库检索 + 个性化建议 + 任务生成)
+export const aiSendHealthButlerMessage = (data) => {
+  var query = data && data.query ? data.query : ''
+  var conversationId = data && data.conversationId ? data.conversationId : ''
+  var userId = uni.getStorageSync('userId') || ''
+  var memberId = data && data.memberId ? data.memberId : null
+  var langgraphBody = {
+    query: query,
+    user: userId,
+    user_id: userId,
+    conversation_id: conversationId,
+    response_mode: 'blocking',
+    bot_name: 'AI健康管家'
+  }
+  var inputs = {}
+  if (memberId) { inputs.child_id = memberId }
+  if (data && data.reportId) { inputs.report_id = data.reportId }
+  if (data && data.focus) { inputs.focus = data.focus }
+  if (Object.keys(inputs).length > 0) { langgraphBody.inputs = inputs }
+  return langgraphRequest({
+    langgraphPath: '/api/v1/health/butler',
+    langgraphBody: langgraphBody,
+    difyFallbackPath: '/api/ai/chat/send',
+    difyFallbackData: data,
+    transform: function(lgRes) {
+      var content = ''
+      if (lgRes && lgRes.choices && lgRes.choices.length > 0) {
+        var msg = lgRes.choices[0].message
+        if (msg && msg.content) { content = msg.content }
+      }
+      var tasks = []
+      var metadata = lgRes && lgRes.metadata
+      if (metadata && metadata.tasks) { tasks = metadata.tasks }
+      return {
+        answer: content,
+        conversationId: conversationId,
+        recommendations: [],
+        tasks: tasks
+      }
+    }
+  })
+}
+
+//  幸福邻里部落 - 服务商模块 
+
+// 提交服务商入驻申请
+export const vendorApply = (data) => {
+  return request('/api/vendor/apply', 'POST', data)
+}
+
+// 查询入驻审核状态
+export const vendorStatus = () => {
+  return request('/api/vendor/status', 'POST', {})
+}
+
+export const nutritionistApply = (data) => {
+  return request('/api/nutritionist/apply', 'POST', data)
+}
+
+export const nutritionistStatus = () => {
+  return request('/api/nutritionist/status', 'POST', {})
+}
+
+export const butlerApply = (data) => {
+  return request('/api/butler/apply', 'POST', data)
+}
+
+// 获取服务商信息
+export const vendorInfo = () => {
+  return request('/api/vendor/info', 'POST', {})
+}
+
+//  幸福邻里部落 - 商品系统 
+
+// 获取公开配置(pages/health/report-upload 依赖此函数读取 report_upload_category_id)
+export const getPublicConfig = (key) => {
+  return request('/api/config/public/value', 'POST', { key: key })
+}
+
+// 商品分类树(公开)— pages/shop/index 依赖此函数加载分类,缺失会导致 onLoad 中断
+export const goodsCategory = () => {
+  return request('/api/shop/category/tree', 'POST', {})
+}
+
+// 商品列表(公开)
+export const productList = (params) => {
+  return request('/api/product/list', 'POST', params)
+}
+
+// 商品详情(公开)
+export const productDetail = (params) => {
+  return request('/api/product/detail', 'POST', params)
+}
+
+// 商品规格映射(公开)
+export const productSpecMap = (params) => {
+  return request('/api/product/spec/map', 'POST', params)
+}
+
+// 商品SKU列表
+export const productSkuList = (params) => {
+  return request('/api/product/sku/list', 'POST', params)
+}
+
+// 服务商发布商品
+export const productCreate = (params) => {
+  return request('/api/product/create', 'POST', params)
+}
+
+// 服务商更新商品
+export const productUpdate = (params) => {
+  return request('/api/product/update', 'POST', params)
+}
+
+// 服务商查询自己的商品
+export const productMy = (params) => {
+  return request('/api/product/my', 'POST', params)
+}
+
+// 服务商上架/下架商品
+export const productShelve = (params) => {
+  return request('/api/product/shelve', 'POST', params)
+}
+
+// 创建订单
+export const productOrderCreate = (params) => {
+  return request('/api/product/order/create', 'POST', params)
+}
+
+// 支付订单
+export const productOrderPay = (params) => {
+  return request('/api/product/order/pay', 'POST', params)
+}
+
+// 取消订单
+export const productOrderCancel = (params) => {
+  return request('/api/product/order/cancel', 'POST', params)
+}
+
+// 我的订单
+export const productOrderMy = (params) => {
+  return request('/api/product/order/my', 'POST', params)
+}
+
+export const productOrderCounts = () => {
+  return request('/api/product/order/my/counts', 'POST', {})
+}
+
+// 订单详情
+export const productOrderDetail = (params) => {
+  return request('/api/product/order/detail', 'POST', params)
+}
+
+// 服务商查询收到的订单
+export const productOrderVendor = (params) => {
+  return request('/api/product/order/vendor', 'POST', params)
+}
+
+// 服务商确认订单完成
+export const productOrderConfirm = (params) => {
+  return request('/api/product/order/confirm', 'POST', params)
+}
+
+// 用户申请订单退款
+export const productOrderRefundApply = (params) => {
+  return request('/api/product/order/refund/apply', 'POST', params)
+}
+
+// 管理员:商品待审核列表
+export const adminProductPending = (params) => {
+  return request('/api/admin/product/pending', 'POST', params)
+}
+
+// 管理员:商品列表
+export const adminProductList = (params) => {
+  return request('/api/admin/product/list', 'POST', params)
+}
+
+// 管理员:商品审核
+export const adminProductReview = (params) => {
+  return request('/api/admin/product/review', 'POST', params)
+}
+
+// 管理员:订单列表
+export const adminOrderList = (params) => {
+  return request('/api/admin/order/list', 'POST', params)
+}
+
+// 管理员:系统配置列表
+export const adminConfigList = (params) => {
+  return request('/api/admin/config/list', 'POST', params)
+}
+
+// 管理员:系统配置更新
+export const adminConfigUpdate = (params) => {
+  return request('/api/admin/config/update', 'POST', params)
+}
+
+// 管理员:获取所有配置
+export const adminConfigAll = (params) => {
+  return request('/api/admin/config/all', 'POST', params)
+}
+
+
+//  统计报表
+export const getChildOverview = (memberId) => {
+  return request('/api/stats/child/overview', 'POST', { memberId })
+}
+
+export const getFamilySummary = () => {
+  return request('/api/stats/family/summary', 'POST', {})
+}
+
+export const getPointsRanking = () => {
+  return request('/api/stats/points/ranking', 'POST', {})
+}
+
+//  鍕嬬珷绯荤粺 
+export const getActiveBadges = () => {
+  return request('/api/badges/list', 'POST')
+}
+
+export const getAllBadges = () => {
+  return request('/api/badges/all', 'POST')
+}
+
+export const getBadgeDetail = (id) => {
+  return request('/api/badges/detail', 'POST', { id })
+}
+
+export const getChildBadges = (memberId) => {
+  return request('/api/badges/child/list', 'POST', { memberId })
+}
+
+export const toggleBadgeFavorite = (memberId, badgeId) => {
+  return request('/api/badges/favorite', 'POST', { memberId, badgeId })
+}
+
+export const getChildBadgeStats = (memberId) => {
+  return request('/api/badges/statistics/child', 'POST', { memberId })
+}
+
+export const getFamilyBadgeRanking = () => {
+  return request('/api/badges/ranking/family', 'POST', {})
+}
+
+// ===== 内容区块权限 =====
+export const getVisibleSections = (data) => request('/api/content-sections/visible', 'POST', data)
+
+//  分佣裂变系统 
+
+// 获取/创建我的邀请码
+export const getReferralCode = () => {
+  return request('/api/invite/code', 'POST')
+}
+
+// 获取邀请二维码
+export const getInviteQrCode = () => {
+  return request('/api/invite/qrcode', 'POST')
+}
+
+export const getShareQrCode = (page, scene) => {
+  return request('/api/share/qrcode', 'POST', { page, scene })
+}
+
+// 绑定推荐人
+export const bindReferral = (referralCode) => {
+  return request('/api/invite/bind', 'POST', { referralCode })
+}
+
+// 我的邀请列表
+export const getReferralList = (page = 1, size = 10) => {
+  return request('/api/invite/list', 'POST', { page, size })
+}
+
+// 邀请统计
+export const getReferralSummary = () => {
+  return request('/api/invite/summary', 'POST')
+}
+
+// 浣i噾鎬昏
+export const getCommissionSummary = () => {
+  return request('/api/commission/summary', 'POST')
+}
+
+// 浣i噾鏄庣粏
+export const getCommissionList = (page = 1, size = 20, status) => {
+  var params = { page: page, size: size }
+  if (status) {
+    params.status = status
+  }
+  return request('/api/commission/list', 'POST', params)
+}
+
+// 鐢宠鎻愮幇
+export const applyWithdrawal = (amount, accountInfo) => {
+  return request('/api/withdrawal/apply', 'POST', { amount, accountInfo })
+}
+
+// 鎻愮幇璁板綍
+export const getWithdrawalHistory = (page = 1, size = 10) => {
+  return request('/api/withdrawal/history', 'POST', { page, size })
+}
+
+//  浜旇鑳介噺娌欑洏 
+
+// 获取家庭能量沙盘数据(家庭五维+ 每个成员的个人数据)
+export const getFamilyEnergySandbox = () => {
+  return request('/api/energy/sandbox', 'POST')
+}
+
+// ===== 文章内容系统 =====
+export const getArticleCategories = () => request('/api/articles/categories', 'POST')
+export const getArticleList = (data) => request('/api/articles/list', 'POST', data)
+export const getArticleDetail = (data) => request('/api/articles/detail', 'POST', data)
+export const getFeaturedArticles = (data) => request('/api/articles/featured', 'POST', data)
+export const recordArticleRead = (data) => request('/api/articles/record-read', 'POST', data)
+export const reportReadingTime = (data) => request('/api/articles/report-reading-time', 'POST', data)
+export const getReadingStats = (memberId) => request('/api/articles/reading-stats', 'POST', { memberId })
+export const getDailyTip = () => request('/api/articles/daily-tip', 'POST')
+export const getAiQuestions = (data) => request('/api/articles/ai-questions', 'POST', data)
+export const submitAnswers = (data) => request('/api/articles/submit-answers', 'POST', data)
+export const publishArticle = (data) => request('/api/articles/publish', 'POST', data)
+export const getMyPosts = (data) => request('/api/articles/my-posts', 'POST', data)
+// 文章评论
+export const getArticleComments = (data) => request('/api/articles/comments/list', 'POST', data)
+export const createArticleComment = (data) => request('/api/articles/comments/create', 'POST', data)
+export const auditArticleComment = (data) => request('/api/articles/comments/audit', 'POST', data)
+export const getPendingComments = (data) => request('/api/articles/comments/pending', 'POST', data)
+export const getMyComments = (data) => request('/api/articles/comments/my', 'POST', data)
+// 文章完成阅读
+export const completeArticleRead = (data) => request('/api/articles/complete-read', 'POST', data)
+// AI答题
+export const generateQuiz = (data) => request('/api/articles/quiz/generate', 'POST', data)
+export const submitQuiz = (data) => request('/api/articles/quiz/submit', 'POST', data)
+
+// ===== EMI蹇冪悊鎶ュ憡 =====
+export const getEmiReport = (memberId) => request('/api/emireport/latest', 'POST', { memberId })
+
+
+// ===== 认知测评结果 =====
+export const getAssessmentLatestResult = (memberId) => request('/api/assessment/latest-result', 'POST', { memberId })
+export const getAssessmentHistory = (memberId, size) => request('/api/assessment/history', 'POST', { memberId, size: size || 5 })
+
+// ===== 测评额度(商城化改造) =====
+export const getAssessmentQuotas = () => request('/api/assessment/quota/my-list', 'POST')
+export const getAssessmentQuotaDetail = (quotaId) => request('/api/assessment/quota/detail', 'POST', { quotaId })
+export const createAssessmentAppointmentWithQuota = (data) => request('/api/assessment/appointment/create', 'POST', data)
+
+// ===== 测评报告上传与指导意见 =====
+export const uploadAssessmentReport = (file, memberId, notes) => {
+  return new Promise((resolve, reject) => {
+    uni.uploadFile({
+      url: BASE_URL + '/api/dan-assessment/result/upload',
+      filePath: file.path,
+      name: 'file',
+      formData: { memberId: memberId, notes: notes || '' },
+      header: { Authorization: 'Bearer ' + uni.getStorageSync('token') },
+      success: (res) => {
+        try {
+          resolve(JSON.parse(res.data))
+        } catch (e) {
+          reject(e)
+        }
+      },
+      fail: reject
+    })
+  })
+}
+export const saveGuidance = (resultId, items) => request('/api/dan-assessment/result/' + resultId + '/guidance/save', 'POST', { items })
+export const getGuidance = (resultId) => request('/api/dan-assessment/result/' + resultId + '/guidance', 'POST')
+export const confirmUploadReport = (resultId, data) => request('/api/dan-assessment/result/' + resultId + '/confirm-upload', 'POST', data)
+
+// ===== 认知训练建议(家庭行动清单) =====
+export const getCognitiveRecommendations = (memberId) => request('/api/cognitive/recommendations', 'POST', { memberId })
+export const createTaskFromRecommendation = (memberId, dimensionKey, taskIndex) =>
+  request('/api/cognitive/recommendations/create-task', 'POST', { memberId, dimensionKey, taskIndex })
+export const getCognitiveNorms = (memberId) => request('/api/cognitive/norms', 'POST', { memberId })
+export const getCognitiveTrend = (memberId, limit) => request('/api/cognitive/trend', 'POST', { memberId, limit: limit || 5 })
+
+// ===== 五维能量系统(账本模式) =====
+export const getEnergyOverview = (memberId) => {
+  return request('/api/energy/overview', 'POST', { memberId })
+}
+
+export const getEnergyLogs = (memberId, dimensionCode, page = 1, size = 10) => {
+  return request('/api/energy/logs', 'POST', { memberId, dimensionCode, page, size })
+}
+
+export const getWealthDetail = (memberId, memberType) => {
+  return request('/api/energy/wealth-detail', 'POST', { memberId, memberType })
+}
+
+// ===== 成就徽章 =====
+export const getUserBadges = (memberId) => {
+  return request('/api/badges/child/list', 'POST', { memberId })
+}
+
+
+// ===== 成长报告 =====
+export const getGrowthReport = (memberId) => {
+  return request('/api/stats/child/overview', 'POST', { memberId })
+}
+
+// ===== 用户行动统计(我的页面) =====
+export const getUserActionStats = () => {
+  return request('/api/user/action-stats', 'POST')
+}
+
+// ===== 热门活动(行Tab) =====
+export const getHotActivities = (data) => {
+  return request('/api/activities/hot', 'POST', data)
+}
+
+// ===== 推荐商品(行Tab) =====
+export const getRecommendedProducts = (data) => {
+  return request('/api/products/recommend', 'POST', data)
+}
+
+//  浼氬憳鍗囩骇涓庣画璐?
+
+// 鍗囩骇浼氬憳
+export const upgradeMember = (levelCode) => {
+  return request('/api/membership/upgrade', 'POST', { levelCode })
+}
+
+// 获取当前会员等级详情
+export const getMemberLevel = (levelCode) => {
+  return request('/api/membership/level', 'POST', { levelCode })
+}
+
+// 获取升级记录
+export const getUpgradeRecords = (page = 1, size = 10) => {
+  return request('/api/membership/upgrade-records', 'POST', { page, size })
+}
+
+//  佣金团队统计 
+
+// 推广团队列表
+export const getCommissionTeam = (page = 1, size = 10) => {
+  return request('/api/commission/team', 'POST', { page, size })
+}
+
+// 推广团队成员列表(分页)
+export const getTeamList = (page = 1, size = 20, level = 'ALL') => {
+  return request('/api/commission/team/list', 'POST', { page, size, level })
+}
+
+// 浣i噾缁熻鏁版嵁
+export const getCommissionStats = () => {
+  return request('/api/commission/stats', 'POST')
+}
+
+// 浣i噾浣欓
+export const getCommissionBalance = () => {
+  return request('/api/commission/balance', 'POST')
+}
+
+// ===== 财富维度 · 财商打卡 =====
+export const getCheckinList = (data) => {
+  return request('/api/wealth/checkin/list', 'POST', data)
+}
+
+export const getCheckinStats = (data) => {
+  return request('/api/wealth/checkin/stats', 'POST', data)
+}
+
+export const createCheckin = (data) => {
+  return request('/api/wealth/checkin/create', 'POST', data)
+}
+
+export const deleteCheckin = (id) => {
+  return request('/api/wealth/checkin/delete', 'POST', { id })
+}
+
+// ===== 财富维度 · 保单管理 =====
+export const getInsuranceList = (data) => {
+  return request('/api/wealth/insurance/list', 'POST', data)
+}
+
+export const getInsuranceDetail = (id) => {
+  return request('/api/wealth/insurance/detail', 'POST', { id })
+}
+
+export const createInsurance = (data) => {
+  return request('/api/wealth/insurance/create', 'POST', data)
+}
+
+export const updateInsurance = (data) => {
+  return request('/api/wealth/insurance/update', 'POST', data)
+}
+
+export const deleteInsurance = (id) => {
+  return request('/api/wealth/insurance/delete', 'POST', { id })
+}
+
+export const getInsurancePlanning = () => {
+  return request('/api/insurance/planning', 'POST', {})
+}
+
+// ===== 鍋ュ悍鎵撳崱 =====
+export const healthCheckinList = (data) => request('/api/health/checkin/list', 'POST', data)
+export const healthCheckinCreate = (data) => request('/api/health/checkin/create', 'POST', data)
+export const healthCheckinDelete = (id) => request('/api/health/checkin/delete', 'POST', { id })
+
+// ===== 寰鍔紙P0 鏈夋晥鍚姩锛� =====
+export const microActionList = () => request('/api/micro-action/list', 'POST', {})
+export const microActionToday = (data) => request('/api/micro-action/today', 'POST', data)
+export const microActionComplete = (data) => request('/api/micro-action/complete', 'POST', data)
+export const microActionCheckToday = (data) => request('/api/micro-action/check-today', 'POST', data)
+
+// ===== 每日反馈(P1-1 即时多巴胺反馈) =====
+export const getTodayFeedback = (data) => request('/api/feedback/today', 'POST', data)
+export const markFeedbackRead = (data) => request('/api/feedback/read', 'POST', data)
+export const getRecentFeedbacks = (data) => request('/api/feedback/recent', 'POST', data)
+
+// ===== 健康预警(P1-2 健康行为智能预警) =====
+export const getActiveAlerts = (data) => request('/api/health/alert/list', 'POST', data)
+export const dismissAlert = (data) => request('/api/health/alert/dismiss', 'POST', data)
+
+// ===== 健康积分/等级/时间线(P2-1 身份重塑) =====
+export const getHealthScoreInfo = (data) => request('/api/health/score/info', 'POST', data)
+export const getHealthStreak = (data) => request('/api/health/score/streak', 'POST', data)
+export const getHealthTimeline = (data) => request('/api/health/timeline/list', 'POST', data)
+
+// ===== 家庭健康互动(P2-2 排行榜/点赞/挑战) =====
+export const getFamilyRanking = (data) => request('/api/health/family/ranking', 'POST', data)
+export const getChallengeList = (data) => request('/api/health/challenge/list', 'POST', data)
+export const getChallengeHistory = (data) => request('/api/health/challenge/history', 'POST', data)
+export const updateChallengeProgress = (data) => request('/api/health/challenge/progress', 'POST', data)
+export const respondChallenge = (data) => request('/api/health/challenge/respond', 'POST', data)
+export const createChallenge = (data) => request('/api/health/challenge/create', 'POST', data)
+export const updateChallenge = (id, data) => request('/api/health/challenge/update/' + id, 'POST', data)
+export const deleteChallenge = (id) => request('/api/health/challenge/delete/' + id, 'POST', data)
+export const getChallengeTemplates = () => request('/api/health/challenge/templates', 'POST', {})
+export const sendLike = (data) => request('/api/health/interact/like', 'POST', data)
+
+// ===== 健康社区扩散(P3 健康圈/排行/分享) =====
+export const getCircleList = (data) => request('/api/health/circle/list', 'POST', data)
+export const createCircle = (data) => request('/api/health/circle/create', 'POST', data)
+export const joinCircle = (data) => request('/api/health/circle/join', 'POST', data)
+export const leaveCircle = (data) => request('/api/health/circle/leave', 'POST', data)
+export const getCircleRanking = (data) => request('/api/health/circle/ranking', 'POST', data)
+export const getCircleChallengeList = (data) => request('/api/health/circle/challenge/list', 'POST', data)
+export const getCircleChallengeHistory = (data) => request('/api/health/circle/challenge/history', 'POST', data)
+
+// ===== 通用圈子(社交圈) =====
+export const getMyCircles = (memberId, memberType) => {
+  return request('/api/circle/my-circles', 'POST', { memberId: memberId, memberType: memberType || 'child' })
+}
+export const discoverCircles = (memberId) => {
+  return request('/api/circle/discover', 'POST', { memberId: memberId })
+}
+export const joinGeneralCircle = (circleId, memberId, memberType) => {
+  return request('/api/circle/join', 'POST', { circleId: circleId, memberId: memberId, memberType: memberType || 'child' })
+}
+export const leaveGeneralCircle = (circleId, memberId, memberType) => {
+  return request('/api/circle/leave', 'POST', { circleId: circleId, memberId: memberId, memberType: memberType || 'child' })
+}
+
+export const getFamilyFootprint = (data) => request('/api/share/family-footprint', 'POST', data)
+
+// ===== 娲诲姩妯″潡锛堢淮搴︾瓫閫夛級 =====
+export const getActivityList = (data) => request('/api/activity/list', 'POST', data)
+export const getActivityDetail = (id) => request('/api/activity/detail', 'POST', { id })
+export const activityCheckin = (data) => request('/api/activity/checkin', 'POST', data)
+// 活动报名
+export const registerActivity = (data) => request('/api/activity/register', 'POST', data)
+export const cancelActivityRegistration = (data) => request('/api/activity/cancel-registration', 'POST', data)
+export const getMyActivityRegistrations = (data) => request('/api/activity/my-registrations', 'POST', data)
+export const submitActivityFeedback = (data) => request('/api/activity/feedback/submit', 'POST', data)
+export const getActivityFeedbackList = (data) => request('/api/activity/feedback/list', 'POST', data)
+export const getMyActivityFeedback = (data) => request('/api/activity/feedback/my', 'POST', data)
+// 活动报名订单(先支付后报名)
+export const createActivityOrder = (data) => request('/api/activity/order/create', 'POST', data)
+export const payActivityOrder = (orderNo) => request('/api/activity/order/pay', 'POST', { orderNo: orderNo })
+export const handleActivityOrderSuccess = (orderNo) => request('/api/activity/order/handlePaymentSuccess', 'POST', { orderNo: orderNo })
+export const getActivityOrderStatus = (orderNo) => request('/api/activity/order/status', 'POST', { orderNo: orderNo })
+
+// ===== 活动管理(管理员端,复用 /api/activity/*) =====
+export const adminCreateActivity = (activity) => request('/api/activity/create', 'POST', activity)
+export const adminUpdateActivity = (activity) => request('/api/activity/update', 'POST', activity)
+export const adminPublishActivity = (id) => request('/api/activity/publish', 'POST', { id })
+export const adminEndActivity = (id) => request('/api/activity/end', 'POST', { id })
+export const submitActivityForReview = (id) => request('/api/activity/submit-review', 'POST', { id })
+// 管理员列表:获取所有活动(含草稿),按 vendorId 过滤自己创建的
+export const adminListMyActivities = (data) => request('/api/activity/list', 'POST', data)
+// 后台概览列表:获取已发布的活动做统计
+export const adminListAllActivities = (data) => request('/api/activity/list', 'POST', data)
+
+export const getSubscriptionPlans = () => request('/api/subscription/plans', 'POST')
+export const getMySubscription = () => request('/api/subscription/status', 'POST')
+export const createSubscriptionOrder = (data) => request('/api/subscription/create', 'POST', data)
+export const setAutoRenew = (data) => request('/api/subscription/auto-renew', 'POST', data)
+export const cancelSubscription = (data) => request('/api/subscription/cancel', 'POST', data)
+export const checkBenefit = (data) => request('/api/subscription/benefit/check', 'POST', data)
+
+export const getMyPromotionTier = () => request('/api/promotion/my-tier', 'POST')
+export const getPromotionTiers = () => request('/api/promotion/tiers', 'POST')
+export const getPromotionTeamTree = (data) => request('/api/promotion/team-tree', 'POST', data)
+export const getTierHistory = () => request('/api/promotion/tier-history', 'POST')
+
+export const getMyEarnings = () => request('/api/commission/my-earnings', 'POST')
+export const getCommissionRecords = (page, size) => request('/api/commission/records', 'POST', { page: page || 1, size: size || 20 })
+export const getPpointProducts = () => request('/api/commission/ppoint/products', 'POST')
+
+// ===== 家庭收益(推广中心重构) =====
+export const getFamilyEarningsSummary = () => request('/api/earnings/family/summary', 'POST')
+export const getFamilyEarningsMembers = () => request('/api/earnings/family/members', 'POST')
+export const getFamilyEarningsRecords = (data) => request('/api/earnings/family/records', 'POST', data || {})
+export const distributeToMember = (data) => request('/api/earnings/admin/distribute', 'POST', data)
+export const toggleMemberBalance = (data) => request('/api/earnings/admin/toggle-member', 'POST', data)
+export const withdrawFamilyEarnings = (data) => request('/api/earnings/admin/withdraw', 'POST', data)
+
+
+// ===== 缁村害浠诲姟锛堝甫 category 绛涢€夛級 =====
+export const getTodayTasksByCategory = (memberId, category) => {
+  return request('/api/tasks/today', 'POST', { memberId: memberId, category: category })
+
+}
+export const getTaskHistoryByCategory = (memberId, category, page, size) => {
+  return request('/api/tasks/history', 'POST', { memberId: memberId, category: category, page: page || 1, size: size || 10 })
+}
+
+// ===== 维度商品(domain 筛选,使用 productList) =====
+export const getProductsByDomain = (domain, page, size) => {
+  return productList({ domain: domain, page: page || 1, size: size || 6 })
+}
+
+
+// ===== 鍋ュ悍鎶ュ憡锛堜袱闃舵鍏ュ簱锛?=====
+export const getLatestHealthReport = (memberId) => request('/api/health/report/latest', 'POST', { memberId })
+export const getHealthIndicatorList = (memberId) => request('/api/health/indicator/list', 'POST', { memberId })
+
+
+export const createHealthReport = (data) => request('/api/health/report/create', 'POST', data)
+export const getReportList = (memberId) => request('/api/health/report/list', 'POST', { memberId })
+export const getReportDetail = (reportId) => request('/api/health/report/detail', 'POST', { reportId })
+
+export const editHealthReport = (reportId, payload, subjectId) => request('/api/health/report/edit', 'POST', { reportId, payload, subjectId })
+
+export const queryKnowledgeBase = (itemType, itemName) => request('/api/health/knowledge/query', 'POST', { itemType, itemName })
+
+export const batchQueryKnowledgeBase = (queries) => request('/api/health/knowledge/batch-query', 'POST', { queries })
+
+
+// 闃舵1锛氫笂浼燩DF鈫掕В鏋愨啋瀛榙raft鈫掕繑鍥瀌raftId+payload+鎴愬憳鍖归厤锛堜笉钀藉簱锛?
+export const parseReportPreview = (filePath, memberId, type) => {
+  return new Promise((resolve, reject) => {
+    const token = uni.getStorageSync('token')
+    uni.uploadFile({
+      url: BASE_URL + '/api/health/report/parse-preview' + (type ? '?type=' + type : ''),
+      filePath: filePath,
+      name: 'file',
+      formData: {
+        memberId: memberId || ''
+      },
+      header: {
+        'Authorization': token ? 'Bearer ' + token : ''
+      },
+      success: (res) => {
+        var data
+        try { data = JSON.parse(res.data) } catch (e) { data = res.data }
+        if (data && data.code === 200) {
+          resolve(data)
+        } else {
+          console.warn('[API] 解析上传失败 ' + BASE_URL + '/api/health/report/parse-preview' + ' code=' + (data && data.code || '') + ' msg=' + (data && data.message || ''))
+          reject(data)
+        }
+      },
+      fail: (err) => {
+        console.error('[API] 解析上传网络错误 ' + BASE_URL + '/api/health/report/parse-preview', err)
+        reject(err)
+      }
+    })
+  })
+}
+
+// 闃舵2锛氱‘璁よ惤搴擄紙鍙€変紶淇敼鍚庣殑payload鍜宻ubjectId锛?
+
+// 阶段2:确认落库(可选传修改后的payload和subjectId)
+
+export const confirmReportPreview = (data) => request('/api/health/report/confirm', 'POST', data)
+
+// 鏀惧純鑽夌
+export const discardReportDraft = (draftId) => request('/api/health/report/discard', 'POST', { draftId })
+
+// ===== 鎶ュ憡璋冪爺闂嵎 =====
+export const createReportSurvey = (reportId, memberId) => request('/api/health/survey/create', 'POST', { reportId, memberId })
+export const submitReportSurvey = (surveyId, surveyData) => request('/api/health/survey/submit', 'POST', { surveyId, surveyData })
+export const getSurveyStatus = (reportId) => request('/api/health/survey/status', 'POST', { reportId })
+
+// ===== Report Feedback (gut flora report feedback) =====
+export const submitFeedback = (data) => request('/api/health/feedback/submit', 'POST', data)
+
+// ===== 重要关系(联系人) =====
+export const getContactList = (data) => request('/api/contact/list', 'POST', data)
+export const getContactDetail = (id) => request('/api/contact/detail', 'POST', { id: id })
+export const createContact = (data) => request('/api/contact/create', 'POST', data)
+export const updateContact = (data) => request('/api/contact/update', 'POST', data)
+export const deleteContact = (id) => request('/api/contact/delete', 'POST', { id: id })
+export const importPhoneContact = (data) => request('/api/contact/import-phone', 'POST', data)
+export const recordContactInteraction = (data) => request('/api/contact/interaction', 'POST', data)
+
+// ===== 椋熻氨鎺ㄨ崘 =====
+export const getMealRecommend = (params) => request('/api/meal/recommend', 'POST', params)
+export const replaceFood = (data) => request('/api/meal/replace', 'POST', data)
+export const logMeal = (data) => request('/api/meal/log', 'POST', data)
+export const getMealLogs = (data) => request('/api/meal/logs', 'POST', data)
+export const getNutritionSummary = (data) => request('/api/meal/nutrition-summary', 'POST', data)
+export const getNutritionProfile = (data) => request('/api/nutrition/profile/get', 'POST', data)
+export const saveNutritionProfile = (data) => request('/api/nutrition/profile/save', 'POST', data)
+
+// ===== 钀ュ吇妗f涓庣己涔忓垎鏋?=====
+export const getChildNutritionProfile = (memberId) => request('/api/health/nutrition/profile', 'POST', { memberId })
+
+// ===== 家庭天盘 =====
+export const getFamilyFortune = () => request('/api/mind/fortune', 'POST')
+export const getDeficiencyAnalysis = (memberId) => request('/api/health/nutrition/deficiency', 'POST', { memberId })
+export const getDeficiencySummary = (memberId) => request('/api/health/nutrition/deficiency-summary', 'POST', { memberId })
+export const getNutritionTrend = (memberId) => request('/api/health/nutrition/trend', 'POST', { memberId })
+export const getHealthAnalysis = (memberId) => request('/api/health/analysis', 'POST', { memberId })
+export const getNutritionMappings = (data) => request('/api/health/nutrition/mappings', 'POST', data || {})
+
+// ===== 健康维度 =====
+export const getDimensionOverview = (data) => request('/api/dimension/overview', 'POST', data)
+export const uploadDimensionScore = (data) => request('/api/dimension/upload', 'POST', data)
+export const submitDimensionQuestionnaire = (data) => request('/api/dimension/questionnaire', 'POST', data)
+export const getDimensionHistory = (data) => request('/api/dimension/history', 'POST', data)
+
+// ===== 健康方案汇总 =====
+export const generateHealthPlan = (data) => request('/api/health/plan/generate', 'POST', data)
+export const saveHealthPlan = (data) => request('/api/health/plan/save', 'POST', data)
+export const getHealthPlanList = (data) => request('/api/health/plan/list', 'POST', data)
+export const getHealthPlanDetail = (data) => request('/api/health/plan/detail', 'POST', data)
+
+// ===== 閭€璇烽噷绋嬬 =====
+export const getInviteMilestones = () => {
+  return request('/api/invite/milestone/list', 'POST')
+}
+export const claimInviteMilestone = (milestone) => {
+  return request('/api/invite/milestone/claim', 'POST', { milestone })
+}
+
+//  浼樻儬鍒告ā鍧?
+export const getCouponList = () => {
+  return request('/api/coupon/list', 'POST')
+}
+
+export const claimCoupon = (couponId) => {
+  return request('/api/coupon/claim', 'POST', { couponId })
+}
+
+export const getExchangeableCoupons = () => {
+  return request('/api/coupon/exchangeable', 'POST', {})
+}
+
+export const getProductCoupons = (data) => {
+  return request('/api/coupon/product', 'POST', data)
+}
+
+export const exchangeCoupon = (data) => {
+  return request('/api/coupon/exchange', 'POST', data)
+}
+
+export const getJoinCouponRules = () => {
+  return request('/api/coupon/join-rules', 'POST', {})
+}
+
+// ===== 新手任务(Onboarding Rewards) =====
+export const getOnboardingProgress = () => {
+  return request('/api/onboarding/progress', 'POST')
+}
+export const claimOnboardingReward = (taskType) => {
+  return request('/api/onboarding/claim', 'POST', { taskType })
+}
+
+// ===== 成长任务(每日新手任务系统) =====
+export const getGrowthTaskList = (type) => {
+  return request('/api/growth-task/list', 'POST', { type: type || 'DAILY' })
+}
+
+export const claimGrowthTaskReward = (taskLogId) => {
+  return request('/api/growth-task/claim', 'POST', { taskLogId })
+}
+
+// ===== 推广排行榜 =====
+export const getLeaderboardTop = () => {
+  return request('/api/leaderboard/top', 'POST')
+}
+
+export const getLeaderboardMyRank = () => {
+  return request('/api/leaderboard/my-rank', 'POST')
+}
+
+
+// ===== 鏁板闂叧锛堣嚜宸卞嚭棰樿嚜宸辩瓟锛?=====
+export const getMathQuizStart = (memberId, age) => {
+  return request('/api/wisdom/math/start', 'POST', { memberId, age })
+
+  return request('/api/wisdom/math/start', 'POST', { childId, age })
+
+}
+
+export const verifyMathAnswer = (memberId, expression, userAnswer) => {
+  return request('/api/wisdom/math/verify', 'POST', { memberId, expression, userAnswer })
+}
+
+export const completeMathQuiz = (data) => {
+  return request('/api/wisdom/math/complete', 'POST', data)
+}
+
+// ===== 鍏崇郴璐ㄩ噺璇勫垎 =====
+export const getRelationshipScores = () => {
+  return request('/api/family/relationship/scores', 'POST', {})
+}
+
+export const calculateRelationshipScore = (memberId) => {
+  return request('/api/family/relationship/calculate', 'POST', { memberId })
+}
+
+export const getHealthAlerts = () => {
+  return request('/api/family/relationship/health-alerts', 'POST', {})
+}
+
+export const getMilestones = (daysAhead) => {
+  return request('/api/family/relationship/milestones', 'POST', { daysAhead })
+}
+
+// ===== 浜掑姩璁板綍 =====
+export const addInteraction = (data) => {
+  return request('/api/family/interaction/add', 'POST', data)
+}
+
+export const listInteractions = (data) => {
+  return request('/api/family/interaction/list', 'POST', data)
+}
+
+export const getInteractionTypes = () => {
+  return request('/api/family/interaction/types', 'GET', {})
+}
+
+// ===== 鍏崇郴闂嵎 =====
+export const generateQuestionnaire = (memberId) => {
+  return request('/api/family/questionnaire/generate', 'POST', { memberId })
+}
+
+export const submitQuestionnaire = (data) => {
+  return request('/api/family/questionnaire/submit', 'POST', data)
+}
+
+export const getQuestionnaireSnapshot = (memberId) => {
+  return request('/api/family/questionnaire/snapshot/' + memberId, 'GET', {})
+}
+
+export const getQuestionnaireHistory = (memberId) => {
+  return request('/api/family/questionnaire/history/' + memberId, 'GET', {})
+}
+
+// ===== 五维家庭自检(P0-1)=====
+export const getSelfCheckQuestions = () => {
+  return request('/api/family/self-check/questions', 'POST', {})
+}
+
+export const submitSelfCheck = (data) => {
+  return request('/api/family/self-check/submit', 'POST', data)
+}
+
+export const getSelfCheckLatest = () => {
+  return request('/api/family/self-check/latest', 'POST', {})
+}
+
+export const getSelfCheckHistory = () => {
+  return request('/api/family/self-check/history', 'POST', {})
+}
+
+// ===== 舌诊相关(两阶段流程) =====
+export const parseTonguePreview = (data) => request('/api/health/report/parse-preview?type=tongue', 'POST', data)
+export const confirmTongue = (data) => request('/api/health/report/confirm?type=tongue', 'POST', data)
+export const discardTongue = (data) => request('/api/health/report/discard?type=tongue', 'POST', data)
+// 鎸囨爣瀹氫箟
+export const getIndicatorDefinitions = (data) => request('/api/admin/indicator/list', 'POST', data)
+
+export const getPointsExchangeProducts = (data) => request('/api/points/exchange/product/list', 'POST', data)
+export const getPointsExchangeProductDetail = (data) => request('/api/points/exchange/product/detail', 'POST', data)
+export const submitPointsExchange = (data) => request('/api/points/exchange/submit', 'POST', data)
+export const getPointsExchangeRecords = () => request('/api/points/exchange/records', 'POST', {})
+export const getPointsExchangeStats = () => request('/api/points/exchange/stats', 'POST', {})
+
+// ===== 购物车 =====
+export const cartAdd = (data) => request('/api/cart/add', 'POST', data)
+export const cartList = (data) => request('/api/cart/list', 'POST', data)
+export const cartUpdate = (data) => request('/api/cart/update', 'POST', data)
+export const cartRemove = (data) => request('/api/cart/remove', 'POST', data)
+export const cartCount = () => request('/api/cart/count', 'POST', {})
+
+// ===== 我的订单 =====
+export const getOrderCounts = () => request('/api/product/order/my/counts', 'POST', {})
+
+// ===== 收货人管理 =====
+export const consigneeList = () => request('/api/consignee/list', 'POST', {})
+export const consigneeDetail = (id) => request('/api/consignee/detail', 'POST', { id })
+export const consigneeSave = (data) => request('/api/consignee/save', 'POST', data)
+export const consigneeDelete = (id) => request('/api/consignee/delete', 'POST', { id })
+
+// ===== 地址管理 =====
+export const addressList = () => request('/api/user/address/list', 'POST', {})
+export const addressDetail = (id) => request('/api/user/address/get', 'POST', { id })
+export const addressSave = (data) => {
+  var url = data.id ? '/api/user/address/update' : '/api/user/address/create'
+  return request(url, 'POST', data)
+}
+export const addressDelete = (id) => request('/api/user/address/delete', 'POST', { id })
+export const addressSetDefault = (id) => request('/api/user/address/setDefault', 'POST', { id })
+
+// ===== 商品购买字段 =====
+export const getProductRequiredFields = (productId) => request('/api/product/purchase_fields/required', 'POST', { productId })
+
+// ===== 测评方案 =====
+export const listFamilyPlans = (data) => request('/api/guide/plans/family-list', 'POST', data)
+export const reviewPlan = (data) => request('/api/guide/plans/review', 'POST', data)
+export const activatePlan = (data) => request('/api/guide/plans/activate', 'POST', data)
+export const getGuidePlanDetail = (data) => request('/api/guide/plans/detail', 'POST', data)
+
+// ===== 家庭天盘相关 =====
+export const tianpanDashboard = (data) => {
+  return request('/api/tianpan/dashboard', 'POST', data)
+}
+
+export const tianpanMemberDetail = (memberId, data) => {
+  return request('/api/tianpan/member/' + memberId, 'POST', data)
+}
+
+export const tianpanCompatibility = (data) => {
+  return request('/api/tianpan/compatibility', 'POST', data)
+}
+
+export const tianpanAnnualEnergy = (data) => {
+  return request('/api/tianpan/annual-energy', 'POST', data)
+}
+
+export const tianpanDailyFortune = (data) => {
+  return request('/api/tianpan/daily-fortune', 'POST', data)
+}
+
+export const tianpanRelatedItems = (data) => {
+  return request('/api/tianpan/related-items', 'POST', data)
+}
+
+// ===== DAN 测评报告上传 =====
+
+/**
+ * Phase 1: 上传 DAN 报告 PDF → 解析 → 返回预览草稿
+ */
+export const danParsePreview = (filePath, dimension, memberId) => {
+  return new Promise((resolve, reject) => {
+    var token = uni.getStorageSync('token')
+    uni.uploadFile({
+      url: BASE_URL + '/api/dan-assessment/report/parse-preview',
+      filePath: filePath,
+      name: 'file',
+      formData: {
+        dimension: dimension,
+        memberId: String(memberId || '')
+      },
+      header: {
+        'Authorization': token ? 'Bearer ' + token : ''
+      },
+      success: function(res) {
+        var data
+        try { data = JSON.parse(res.data) } catch (e) { data = res.data }
+        if (data && data.code === 200) {
+          resolve(data)
+        } else {
+          console.warn('[API] DAN上传失败 ' + BASE_URL + '/api/dan-assessment/report/parse-preview' + ' code=' + (data && data.code || '') + ' msg=' + (data && data.message || ''))
+          reject(data || { message: '解析失败' })
+        }
+      },
+      fail: function(err) {
+        console.error('[API] DAN上传网络错误 ' + BASE_URL + '/api/dan-assessment/report/parse-preview', err)
+        reject(err)
+      }
+    })
+  })
+}
+
+/**
+ * Phase 2: 确认并保存 DAN 报告
+ */
+export const danConfirmReport = (data) => {
+  return request('/api/dan-assessment/report/confirm', 'POST', data)
+}
+
+/**
+ * 获取某孩子某维度的 DAN 报告列表
+ */
+export const getDanReportByChild = (memberId, dimension) => {
+  return request('/api/dan-assessment/report/child', 'POST', { memberId, dimension })
+}
+
+export const supplierProducts = (data) => {
+  return request('/api/supplier/products', 'POST', data)
+}
+
+// === 商品规格 ===
+export const productSpecGroups = (productId) => {
+  return request('/api/product/spec/groups', 'POST', { productId })
+}
+
+// === 推荐系统 - 维度商品 ===
+export const getDimensionProducts = (data) => {
+  return request('/api/recommend/dimension-products', 'POST', data)
+}
+
+// === 推荐系统 - 复购提醒 ===
+export const getRepurchaseReminders = (data) => {
+  return request('/api/recommend/repurchase-reminders', 'POST', data)
+}
+
+export const clickRepurchaseReminder = (id) => {
+  return request('/api/recommend/repurchase-reminder/' + id + '/click', 'POST', {})
+}
+
+// === KB v3 知识库查询 ===
+
+// 查询菌属功能(支持属级回退)
+export const queryBacteriaKnowledge = (name) => {
+  return request('/api/health/knowledge/v3/bacteria/query', 'POST', { name })
+}
+
+// 批量查询菌属功能
+export const batchQueryBacteriaKnowledge = (names) => {
+  return request('/api/health/knowledge/v3/bacteria/batch-query', 'POST', { names })
+}
+
+// 查询指标调整建议
+export const queryIndicatorKnowledge = (name) => {
+  return request('/api/health/knowledge/v3/indicator/query', 'POST', { name })
+}
+
+// 查询食物营养数据
+export const queryFoodKnowledge = (name) => {
+  return request('/api/health/knowledge/v3/food/query', 'POST', { name })
+}
+
+// 获取KB v3章节数据
+export const getKnowledgeSection = (section) => {
+  return request('/api/health/knowledge/v3/section', 'POST', { section: section || '' })
+}
+
+// 获取我的测评预约列表
+export const getMyAppointments = () => {
+  var userId = uni.getStorageSync('userId')
+  return request('/api/dan-assessment/appointment/user', 'POST', { userId: userId })
+}
+
+// 取消测评预约
+export const cancelAppointment = (id) => {
+  return request('/api/dan-assessment/appointment/cancel', 'POST', { id: id })
+}
+
+// 统一报告管理
+export const getReportSummaryList = (params) => request('/api/report-summary/list', 'POST', params)
+export const getReportSummaryDetail = (id) => request('/api/report-summary/detail/' + id, 'POST', {})
+export const downloadReportSummary = (id) => request('/api/report-summary/download/' + id, 'POST', {})
+
+// 服务角色统一申请
+export const submitServiceRoleApply = (data) => {
+    return request('/api/service-role/apply', 'POST', data)
+}
+
+export const getMyServiceRoleApply = () => {
+    return request('/api/service-role/my-apply', 'POST', {})
+}
+
+export const uploadServiceRoleImage = (filePath) => {
+    return new Promise((resolve, reject) => {
+        uni.uploadFile({
+            url: BASE_URL + '/api/service-role/upload-image',
+            filePath: filePath,
+            name: 'file',
+            header: {
+                'Authorization': 'Bearer ' + uni.getStorageSync('token')
+            },
+            success: (res) => {
+                if (res.statusCode === 200) {
+                    const data = JSON.parse(res.data)
+                    resolve(data)
+                } else {
+                    reject(new Error('上传失败'))
+                }
+            },
+            fail: reject
+        })
+    })
+}
+
+// 推荐系统
+export const getRecommendList = (data) => request('/api/recommend/list', 'POST', data)
+export const trackRecommendAction = (data) => request('/api/recommend/track', 'POST', data)
+
+// ===== 饮食模块 =====
+export const getDietPreferences = () => request('/api/diet/preferences/current-member', 'POST', {})
+export const saveDietPreferences = (data) => request('/api/diet/preferences/save', 'POST', data)
+export const getDietIngredients = () => request('/api/diet/ingredients/suggest', 'POST', {})
+export const refreshDietIngredients = () => request('/api/diet/ingredients/recommend', 'POST', {})
+export const addDietIngredient = (data) => request('/api/diet/ingredients/add', 'POST', data)
+export const removeDietIngredient = (data) => request('/api/diet/ingredients/remove', 'POST', data)
+export const confirmDietIngredients = (data) => request('/api/diet/ingredients/confirm', 'POST', data)
+export const getDietRecommendation = (data) => request('/api/diet/recommendation/today', 'POST', data)
+export const generateDietRecommendation = (data) => request('/api/diet/recommendation/generate', 'POST', data)
+export const updateDietRecommendation = (data) => request('/api/diet/recommendation/update', 'POST', data)
+export const completeDietRecommendation = (data) => request('/api/diet/recommendation/complete', 'POST', data)
+export const recognizeDietFood = (data) => request('/api/diet/record/recognize', 'POST', data)
+export const saveDietRecord = (data) => request('/api/diet/record/save', 'POST', data)
+export const getDietDailyRecords = (data) => request('/api/diet/record/daily', 'POST', data)
+export const getDietWeeklyTrend = (data) => request('/api/diet/record/weekly', 'POST', data)
+export const getMealConfig = (data) => request('/api/diet/meals/config', 'POST', data)
+export const saveMealConfig = (data) => request('/api/diet/meals/config/save', 'POST', data)

+ 4 - 1
docs/superpowers/PROJECT-OVERVIEW.md

@@ -2,7 +2,7 @@
 
 **文档版本:** v2.7
 **日期:** 2026-08-09
-**状态:** 已确认(v2.1 Phase 2-4 全栈完成)+ 虚拟支付改造(Tasks 1-12 已完成,退款闭环实施中)+ 新用户注册引导(12 Tasks 全栈完成)+ 家庭成员关系条增强(✅ 已实施)+ TabBar 重构(✅ 4Tab + 中间五维启动器,已提交)+ **LIFETIME 终身会员(✅ 11 Tasks 全栈完成)**
+**状态:** 已确认(v2.1 Phase 2-4 全栈完成)+ 虚拟支付改造(Tasks 1-12 已完成,退款闭环实施中)+ 新用户注册引导(12 Tasks 全栈完成)+ 家庭成员关系条增强(✅ 已实施)+ TabBar 重构(✅ 4Tab + 中间五维启动器,已提交)+ **LIFETIME 终身会员(✅ 11 Tasks 全栈完成)** + **健康数据中心(✅ 全栈完成)**
 **维护:** 所有需求变更需更新本文档
 
 ---
@@ -112,6 +112,7 @@
 | 成长档案重建 | Phase 4 | ✅ 后端已实现(HealthGrowthRecord + HealthGrowthRecordController + HealthGrowthRecordService) | `specs/2026-06-22-growth-record-rebuild-design.md` |
 | 营养健康部分缺陷修复 | Phase 1 | ✅ 已实施(5项缺陷已修复) | `plans/2026-06-22-营养健康部分缺陷修复计划.md` |
 | 主动健康六阶模型改进(P0-P3) | Phase 5 | ✅ P0/P1-1/P1-2/P2-1/P2-2/P3 后端全完成(P2-2家庭互动+ P3社区扩散Controller/Service/Entity全量存在) | `specs/2026-07-22-active-health-six-stage-design.md` (设计总纲) |
+| 健康数据中心(看见·主动健康闭环) | Phase 5 | ✅ 全栈完成(身维度首页改造:Tab栏+四维雷达图+数据采集区+数据查看+方案汇总;在线测评新增认知/心理/关系3套题库+dim路由;方案汇总页+health_plans表+4后端接口) | `specs/2026-08-08-health-data-center-design.md` + `plans/health-data-center-implementation-plan.md` |
 
 ---
 
@@ -345,6 +346,7 @@
 | `2026-08-07-xaf-partner-ppt-redesign-design.md` | ✅ 已实施(16 页问题驱动式重构,slide-1~16 全量交付并渲染验证通过) | 浠艾福合作伙伴版 PPT 重构设计(困境→身份→成果→理念→平台→壁垒→未来→合作;封面标题"让每个家庭的健康,都被提前看见") |
 | `2026-08-07-xaf-internal-communication-design.md` | ✅ 已实施(16 页四层作战手册:一句话共识→标准话术→沟通红线→常见问答;独立目录 `ppt-output/internal/`,渲染验证通过) | 浠艾福对外沟通·统一口径(内部版)PPT 设计(战略对齐·统一口径,每页自包含可查阅) |
 | `2026-08-08-family-challenge-participation-design.md` | ✅ 设计已确认(2026-08-08 拍板:C3 只扣沟通,其余按默认) | 家庭挑战参与机制重构(任意成员发起/可选参与/全体同意后开始/方向性关系评分) |
+| `2026-08-08-health-data-center-design.md` | ✅ 已实施(身维度首页改造+在线测评题库扩展+方案汇总页+health_plans后端全栈) | 健康数据中心 — 看见·主动健康闭环(Tab栏+四维雷达图+数据采集+数据查看+方案汇总+认知/心理/关系测评) |
 
 ### 实施计划(plans/)
 
@@ -409,6 +411,7 @@
 | `2026-08-04-family-challenge-custom.md` | 🟢 已实施 | 家庭挑战自定义管理(创建/编辑/删除/模板) |
 | `2026-08-08-family-challenge-participation.md` | ✅ 已实施(9 commits:迁移182-185/3实体/ChallengeScoreService/respond端点/评分配置页/小程序同意拒绝+成员多选) | 家庭挑战参与机制重构(任意成员发起/可选参与/同意后开始/方向性评分) |
 | `2026-08-09-lifetime-membership.md` | ✅ 已实施(11 Tasks:实体/DTO/迁移/Mapper/后端API/Web前端/小程序前端/文档) | LIFETIME 终身会员全栈实施计划(方案A:等级扩展+实时聚合+管理员审核) |
+| `health-data-center-implementation-plan.md` | ✅ 已实施(6 Tasks:身维度首页Tab改造/题库扩展/方案汇总页/后端CRUD/API注册/验证) | 健康数据中心实施计划(设计稿:2026-08-08-health-data-center-design.md) |
 
 ### 计划与设计文档(specs/)