维护规范:
- 新增接口前必须先查阅本文档,确认是否已有可复用或可修改的接口
- 有相似功能但需调整 → 评估修改成本,必要时新增(标注依赖)
- 实在没有 → 才新增接口,并在此文档同步记录
- 废弃接口保留注释,不直接删除,待确认无调用后清理
| 项目 | 规范 |
|---|---|
| 请求方法 | 统一 @PostMapping,禁止 @GetMapping/@PutMapping/@DeleteMapping(仅支付回调等第三方 webhook 例外) |
| 响应格式 | Result<T> — { code, message, data } |
| 认证 | JWT Bearer Token,Header: Authorization: Bearer {token} |
| 角色校验 | Controller 内手动检查 @RequestAttribute("role") |
| DI | @Resource,字段名与 Bean Name 一致 |
| 公开路径(免鉴权) | /api/auth/*、/api/config/public/*、/api/media/upload、/api/articles/*(部分) |
# 1. 搜索现有相似接口
grep -rn "功能关键词" cfc-backend/src/main/java/com/etotem/cfc/controller/ --include="*.java"
# 2. 检查路由冲突
grep -rn '@PostMapping("' cfc-backend/src/main/java/com/etotem/cfc/controller/ | grep -oP '@\w+Mapping\("\K[^"]*' | sort -u
# 3. 检查 Bean 命名冲突(新增 Service/Controller 时)
find cfc-backend/src/main/java -name "*XxxService.java" -o -name "*XxxController.java" | xargs grep -l "class Xxx"
| Controller | 路由前缀 | 说明 | 废弃状态 |
|---|---|---|---|
AuthController |
/api/auth |
登录/注册/角色切换 | — |
UserController |
/api/user |
用户信息/头像/吉祥物 | — |
FamilyController |
/api/family |
家庭基础操作 | 部分废弃见下 |
FamilyMembersController |
/api/family/member |
家庭成员 CRUD/切换/可见性 | — |
FamilyInviteController |
/api/family/invite |
邀请码/二维码/申请加入 | — |
FamilyUserController |
/api/family/user |
家长端家庭成员管理 | 部分废弃见下 |
PointsController |
/api/points |
积分余额/流水 | — |
TaskController |
/api/tasks |
任务 CRUD/完成/审核 | — |
WishController |
/api/wishes |
心愿 CRUD/审批/兑换 | — |
RewardController |
/api/rewards |
奖励模板/兑换 | — |
AssessmentAppointmentController |
/api/assessment/appointment |
测评预约 | — |
DanAssessmentController |
/api/dan-assessment |
DAN 测评全链路 | — |
EnergyController |
/api/energy |
五维能量概览/流水/配置 | — |
GrowthController |
/api/growth |
成长记录 | — |
GrowthPlanController |
/api/growth/plan |
成长计划 | — |
HealthCheckinController |
/api/health/checkin |
健康打卡(行为记录) | — |
DailyCheckinController |
/api/daily/checkin |
每日健康打卡(饮食/运动/心情) | — |
EmotionCheckinController |
/api/mind/checkin |
情绪日记(心情打卡同步目标) | — |
HealthStatusController |
/api/health-status |
健康现状档案 | — |
ProductController |
/api/product |
商品 | — |
ProductOrderController |
/api/product/order |
商品订单 | — |
CartController |
/api/cart |
购物车 | — |
MembershipController |
/api/membership |
会员 | — |
SubscriptionController |
/api/subscription |
订阅 | — |
AIChatController |
/api/ai |
AI 对话 | — |
InnatePortraitController |
/api/mind/innate |
先天画像(画像/AI解读/数字能量/成长轨迹) | — |
ArticleController |
/api/articles |
文章 | — |
NotificationController |
/api/notification |
通知 | — |
StatsController |
/api/stats |
统计 | — |
CfCommissionController |
/api/commission/cf |
CF 分佣(团队规模/比例/钱包/流水) | — |
CfTransferController |
/api/cf/transfer |
CF 成员间转让 | — |
CfBalanceController |
/api/cf |
C 端 CF 查询(余额快照/流水/家庭券,只读) | F-7a |
AdminCfRateTierController |
/api/admin/cf-rate-tier |
CF 返佣阶梯配置(admin) | — |
ContactController |
/api/contact |
联系人 CRUD/互动/邀请入家庭 | — |
ContactMatchController |
/api/contact/match |
联系人对接(send/accept/reject/列表) | — |
OctopusController |
/api/octopus |
章鱼图(帮助记录/触手聚合) | — |
PearlController |
/api/pearl |
珍珠图(25 类社会连接聚合 + 互动/提醒/优先级) | — |
AbilityController |
/api/ability |
能力图(SKILL 帮助记录聚合为能力节点) | — |
ServiceRoleApplicationController |
/api/service-role |
统一服务角色申请(多角色合一 + 管理端审批) | — |
GuideTeamController |
/api/guide/team |
规划师团队/邀请码/上下级 | — |
GuideFamilyTaskController |
/api/guide/families |
规划师侧家庭任务管理 + 家庭解绑 | — |
PlannerCertificationController |
/api/planner |
规划师培训认证中心(我的认证/课程/线下课打卡/考核) | — |
XiaoeWebhookController |
/api/xiaoe |
小鹅通 webhook 回调(线上课时事件) | — |
AdminPlannerCertCategoryController |
/api/admin/planner-cert-categories |
管理端-学习种类 CRUD | — |
AdminPlannerCourseController |
/api/admin/planner-courses |
管理端-线上课程 CRUD | — |
AdminPlannerOfflineCourseController |
/api/admin/planner-offline-course-map |
管理端-线下课↔类别映射 CRUD | — |
AdminActivityCheckinController |
/api/admin/activity-checkins |
管理端-签到记录/手动补录 | — |
AdminPlannerExamController |
/api/admin/planner-exam |
管理端-试卷/题库 CRUD | — |
AdminPlannerCertificationController |
/api/admin/planner-certifications |
管理端-认证看板/同步课时/存量补登 | — |
标记
410 Gone响应,前端已迁移至新接口。可考虑在确认无调用后清理。
FamilyController — 邀请码系统(已废弃)| 路径 | 说明 | 替代接口 |
|---|---|---|
POST /api/family/invite-code |
获取邀请码(已废弃) | POST /api/family/invite/generate |
POST /api/family/invite-code/generate |
生成邀请码(已废弃) | POST /api/family/invite/generate |
FamilyUserController — 角色切换(已废弃)| 路径 | 说明 | 替代接口 |
|---|---|---|
POST /api/family/user/switch-mode |
切换家长/孩子模式(已废弃) | POST /api/family/member/switch |
POST /api/family/user/switch-to-child |
切换到孩子身份(已废弃) | POST /api/family/member/switch |
POST /api/family/user/switch-back-to-parent |
切回家长身份(已废弃) | POST /api/family/member/switch |
POST /api/family/user/switch-back-verify |
切换验证(已废弃) | — |
ButlerController — 服务记录/佣金(已废弃)| 路径 | 说明 | 替代接口 |
|---|---|---|
POST /api/butler/service-records |
服务记录(已废弃) | — |
POST /api/butler/commissions |
佣金记录(已废弃) | — |
TeacherController — 教学任务(已废弃)| 路径 | 说明 | 替代接口 |
|---|---|---|
POST /api/teacher/tasks |
创建教学任务(已废弃) | POST /api/guide/families/{familyId}/tasks/{taskId} |
其余 /api/teacher/* 多个接口均标注 @Deprecated |
— | — |
DanAssessmentController — 当前测评(已废弃)| 路径 | 说明 | 替代接口 |
|---|---|---|
POST /api/dan-assessment/current |
获取当前测评(已废弃) | — |
NoticeController — 公告列表(已废弃)| 路径 | 说明 | 替代接口 |
|---|---|---|
GET /api/notices/list |
使用 GET 方法,违反统一 POST 规范 | — |
/api/auth, /api/user)| 路径 | 说明 | 参数 | 废弃 |
|---|---|---|---|
POST /api/auth/send-code |
发送验证码 | phone | — |
POST /api/auth/phone-login |
手机号登录 | phone, code | — |
POST /api/auth/wechat-phone-login |
微信一键绑定手机号 | code | — |
POST /api/auth/silent-login |
静默登录(仅获取 token) | — | — |
POST /api/auth/auto-login |
自动登录(refresh token) | — | — |
POST /api/auth/register-with-idcard |
身份证注册 | — | — |
POST /api/auth/wechat-login |
微信授权登录 | code | — |
POST /api/auth/info |
获取当前用户信息 | — | — |
POST /api/auth/set-password |
设置密码 | password | — |
POST /api/auth/verify |
验证密码 | password | — |
POST /api/auth/check-phone |
检查手机号是否存在 | phone | — |
POST /api/auth/direct-register |
直接注册(无邀请码) | — | — |
POST /api/auth/register-with-invite |
邀请码注册 | inviteCode | — |
POST /api/auth/switch-role |
切换角色 | role | — |
POST /api/user/address/list |
收货地址列表 | — | — |
POST /api/user/address/get |
获取地址详情 | id | — |
POST /api/user/address/create |
创建地址 | — | — |
POST /api/user/address/update |
更新地址 | — | — |
POST /api/user/address/delete |
删除地址 | id | — |
POST /api/user/address/setDefault |
设为默认 | id | — |
POST /api/user/mascot/set |
设置吉祥物 | mascotId | — |
POST /api/user/mascot/get |
获取吉祥物 | — | — |
/api/family/*, /api/family/member/*)| 路径 | 说明 | 废弃 |
|---|---|---|
POST /api/family/invite-code |
✅ 废弃 | |
POST /api/family/invite-code/generate |
✅ 废弃 | |
POST /api/family/guide-bind |
绑定规划师 | — |
POST /api/family/member/add |
添加成员 | — |
POST /api/family/member/list |
成员列表(统一入口) | — |
POST /api/family/member/switch |
切换成员视角 | — |
POST /api/family/member/kick |
移除成员 | — |
POST /api/family/member/leave |
主动退出家庭(微信用户;创建者需先转让管理员) | — |
POST /api/family/member/recycle |
从回收箱回收成员(管理员操作) | — |
POST /api/family/member/update |
更新成员信息;body 可含 isChild(1=孩子/0=非孩子,仅家庭管理员可设置,落库到 users.is_child;非管理员返回 403) |
— |
POST /api/family/member/rename-family |
修改家庭名称(仅家庭管理员);body {name},返回新名称 |
— |
POST /api/family/member/editable |
检查是否可编辑 | — |
POST /api/family/member/logs |
成员变更日志 | — |
POST /api/family/invite/qrcode |
生成邀请二维码 | — |
POST /api/family/invite/request-join-by-code |
申请加入(token 路径绑定邀请人,等待邀请人确认;旧码路径管理员兜底) | inviteCode 或 token + familyRole |
POST /api/family/invite/approve-request |
同意加入申请(审批人=邀请人且仍为目标家庭成员;旧数据无邀请人时家庭管理员兜底) | — |
POST /api/family/invite/reject-request |
拒绝加入申请(权限规则同上) | — |
POST /api/family/invite/pending-requests |
待我处理的申请列表(按邀请人查询;旧数据由目标家庭管理员兜底可见) | — |
POST /api/family/invite/my-request |
我的申请 | — |
POST /api/family/invite/cancel-request |
取消申请 | — |
POST /api/family/invite/generate |
生成邀请令牌(复用同家庭未过期未用尽的有效令牌;仅未过期记录计入 10 条额度) | — |
POST /api/family/invite/validate |
验证邀请令牌 | — |
POST /api/family/invite/accept |
接受邀请 | — |
POST /api/family/invite/check-family |
检查家庭状态 | — |
POST /api/family/invite/revoke |
撤销邀请 | — |
POST /api/family/invite/transfer-admin |
转让管理员 | — |
POST /api/family/invite/validate-family-code |
验证家庭短邀请码(落地页展示用,不创建请求) | inviteCode |
POST /api/family/invite/bind-inviter |
绑定家庭邀请人(仅首次注册调用) | familyInviteCode |
POST /api/family/member/leave — 主动退出家庭说明:微信登录用户主动退出当前家庭,回到自己的初始家庭(自己创建的家庭 families.creator_id = userId);若无初始家庭则自动创建新家庭。退出时成员资产(测评/报告/能量值/档案属性)随成员迁移到目标家庭,CF 值(system_points)清零丢弃留在原家庭。
约束:
openid 非 phone: 前缀);非微信用户调用返回错误POST /api/family/invite/transfer-admin 转让管理员请求体:无(空 body 或 {})
响应:
{
"code": 200,
"message": "退出成功",
"data": null
}
错误码: | code | message | 处理建议 | |------|---------|----------| | 500 | 您是家庭创建者,请先转让管理员权限后再退出 | 先转让管理员 | | 500 | 非微信登录用户不能自主退出家庭 | 非微信用户不支持主动退出 | | 500 | 用户未加入家庭 / 家庭不存在 / 未找到该用户的家庭成员记录 | 提示用户状态异常 |
POST /api/family/member/kick — 移除成员(含回收箱分流)说明:家庭管理员将成员移出家庭。行为按成员类型分流:
system_points)随成员带走,同时收回该家庭发放给该成员的人口券(POPULATION,来源 member:{id},仅作废 AVAILABLE 状态的券)family_members.status = recycled),users.family_id 置空,资产保留在原家庭记录上,后续可通过 POST /api/family/member/recycle 回收约束:仅家庭创建者可踢出;不能踢出家庭创建者本人。
请求体:
{
"memberId": 12345
}
响应:
{
"code": 200,
"message": "踢出成功",
"data": null
}
POST /api/family/member/recycle — 从回收箱回收成员说明:目标家庭管理员将回收箱中的成员(非微信用户,status=recycled)重新加入指定家庭,资产(测评/报告/能量值/档案属性)迁移到目标家庭,关联用户 family_id 归位到目标家庭。
约束:仅目标家庭创建者可回收;成员必须在回收箱中。
请求体:
{
"memberId": 12345,
"targetFamilyId": 67890
}
响应:
{
"code": 200,
"message": "回收成功",
"data": null
}
错误码: | code | message | 处理建议 | |------|---------|----------| | 500 | 该成员不在回收箱中 | 仅回收箱成员可回收 | | 500 | 只有目标家庭管理员才能回收成员 | 权限不足 |
POST /api/family/invite/request-join-by-code — 申请加入家庭说明:用户通过邀请码/令牌提交加入家庭的申请,等待邀请人审批。
请求体:
{
"inviteCode": "fam_abc123", // 必填,邀请码或令牌
"familyRole": "爸爸" // 可选,用户在目标家庭中的身份
}
响应:
{
"code": 200,
"message": "申请已提交,等待邀请人确认",
"data": {
"requestId": 12345,
"familyName": "张三的家庭"
}
}
POST /api/family/invite/bind-inviter — 绑定家庭邀请人说明:新用户首次注册时调用,建立「被邀请人 → 邀请人」关系,用于追踪邀请来源。仅首次注册调用,已有家庭邀请人的用户调用会返回失败。
请求体:
{
"familyInviteCode": "fam_abc123"
}
响应:
{
"code": 200,
"message": "绑定成功",
"data": null
}
错误码: | code | message | 处理建议 | |------|---------|----------| | 400 | 用户已有家庭邀请人 | 跳过,已在目标家庭中 | | 404 | 邀请码无效 | 提示用户链接无效 |
POST /api/family/invite/validate — 验证邀请令牌说明:邀请落地页使用,验证 token 有效性并返回家庭信息(仅供展示)。
请求体:
{
"token": "abc123def456"
}
响应:
{
"code": 200,
"data": {
"familyId": 100,
"familyName": "张三的家庭",
"inviterName": "张三",
"inviterAvatar": "/static/avatar.jpg",
"memberCount": 3
}
}
POST /api/family/invite/check-family — 检查用户家庭状态请求体:无额外参数(从 JWT 取 userId)
响应:
{
"code": 200,
"data": {
"inFamily": true,
"familyId": 100,
"familyName": "张三的家庭",
"isAdmin": true
}
}
POST /api/family/invite/pending-requests — 查询待我处理的申请说明:邀请人视角,查询他人提交给自己的加入申请。
请求体:无额外参数
响应:
{
"code": 200,
"data": [
{
"id": 1001,
"requesterUserId": 200,
"requesterNickname": "李四",
"requesterAvatar": "/static/avatar.jpg",
"familyRole": "妈妈",
"status": "pending",
"createdAt": "2026-08-31T10:00:00"
}
]
}
POST /api/family/invite/approve-request — 批准加入申请请求体:
{
"requestId": 1001,
"comment": ""
}
响应:
{
"code": 200,
"message": "已同意"
}
POST /api/family/invite/reject-request — 拒绝加入申请请求体:
{
"requestId": 1001,
"comment": "不符合条件"
}
响应:
{
"code": 200,
"message": "已拒绝"
}
POST /api/family/invite/my-request — 查询我的申请请求体:无额外参数
响应:
{
"code": 200,
"data": {
"id": 1001,
"targetFamilyId": 100,
"targetFamilyName": "张三的家庭",
"familyRole": "爸爸",
"status": "pending",
"createdAt": "2026-08-31T10:00:00"
}
}
status 枚举:pending | approved | rejected
/api/tasks)| 路径 | 说明 |
|---|---|
POST /api/tasks/minigame-options |
小游戏选项 |
POST /api/tasks/create |
创建任务 |
POST /api/tasks/today |
今日任务(memberId 查单成员;familyWide=true 查全家庭今日任务) |
POST /api/tasks/{id}/start |
开始任务(两阶段入口,含购物任务自动加购/下单) |
POST /api/tasks/{id}/complete |
完成任务 |
POST /api/tasks/{id}/review |
审核任务 |
POST /api/tasks/history |
历史任务 |
POST /api/tasks/pending-review |
待审核 |
POST /api/tasks/today-parent |
家长今日任务 |
POST /api/tasks/{id} |
任务详情 |
POST /api/tasks/{id}/complete-minigame |
小游戏完成 |
POST /api/tasks/batch-complete |
批量完成 |
POST /api/tasks/batch-delete |
批量删除 |
POST /api/tasks/my-pending |
我的待办 |
POST /api/tasks/accept |
接受任务 |
POST /api/tasks/reject/{id} |
拒绝任务 |
actionType = cart/order)任务创建时通过 actionType + actionConfig 声明购物联动;调用 POST /api/tasks/{id}/start 时,后端自动执行加购/下单。
actionConfig JSON 格式:
| 字段 | 必填 | 说明 |
|---|---|---|
productId |
✅ | 商品ID |
quantity |
❌ | 数量,默认 1 |
skuId |
❌ | SKU ID(可选) |
consigneeId |
❌ | 收货地址ID(order 模式下可选;未提供时取用户默认地址) |
deliveryMethod |
❌ | 配送方式:1=快递/2=自提/4=线上可选人/5=线上单人 |
actionType 行为:
| actionType | 行为 | 返回字段 |
|---|---|---|
minigame |
跳转小游戏页 | — |
focus |
跳转专注计时器页 | — |
survey |
跳转问卷填写页 | — |
article |
跳转文章中心页 | — |
activity |
跳转活动列表页 | — |
cart |
自动加购,返回加购结果 | execution.extra 含 cartAdded=true、productId、quantity |
order |
先加购,再创建 pending 订单 | execution.extra 含 orderId、orderNo(成功时)或 orderFailed=true、orderError(失败时) |
diet |
跳转饮食打卡页(/pages/growth/diet-checkin?taskId={id}) |
— |
sleep |
跳转睡眠打卡页(/pages/growth/sleep-checkin?taskId={id}) |
— |
exercise |
跳转运动打卡页(/pages/growth/exercise-checkin?taskId={id}) |
— |
下单失败常见原因: 缺默认收货地址、商品已下架、库存不足、配送方式校验失败。失败时加购结果保留,任务状态正常置 in_progress,前端可引导用户去购物车/结算页手动完成。
/api/wishes)| 路径 | 说明 |
|---|---|
POST /api/wishes/create |
创建心愿 |
POST /api/wishes/{id}/set-price |
设置价格 |
POST /api/wishes/{id}/reject |
拒绝心愿 |
POST /api/wishes/{id}/exchange |
兑换心愿 |
POST /api/wishes/{id}/approve-exchange |
审批兑换 |
POST /api/wishes/{id}/fulfill |
完成心愿 |
POST /api/wishes/{id}/confirm |
确认心愿 |
POST /api/wishes/{id}/cancel |
取消心愿 |
POST /api/wishes/list |
心愿列表 |
POST /api/wishes/pending |
待审批心愿 |
POST /api/wishes/{id} |
心愿详情 |
/api/energy, /api/points)| 路径 | 说明 |
|---|---|
POST /api/energy/overview |
能量概览 |
POST /api/energy/logs |
能量流水 |
POST /api/energy/config |
能量配置 |
POST /api/energy/dimension |
五维详情 |
POST /api/points/balance |
积分余额 |
POST /api/points/logs |
积分流水 |
POST /api/points/adjust |
手动调整 |
POST /api/points/system-balance |
系统余额 |
POST /api/points/logs-by-category |
分类流水 |
/api/growth/*)| 路径 | 说明 |
|---|---|
POST /api/growth/record/create |
创建记录 |
POST /api/growth/record/create-with-order |
下单关联创建 |
POST /api/growth/record/list |
记录列表 |
POST /api/growth/record/child/{memberId} |
指定成员记录 |
POST /api/growth/record/{id} |
记录详情 |
POST /api/growth/record/{id}/delete |
删除记录 |
POST /api/growth/record/external/sync |
外部同步 |
POST /api/growth/record/upload-and-parse |
上传解析 |
POST /api/growth/record/create-from-upload |
从上传创建 |
POST /api/growth/record/supplement |
补充记录 |
POST /api/growth/plan/create |
创建计划 |
POST /api/growth/plan/child/{memberId} |
成员计划 |
POST /api/growth/plan/{id} |
计划详情 |
POST /api/growth/plan/{id}/review |
审核计划 |
/api/health/*, /api/daily/checkin, /api/mind/checkin)| 路径 | 说明 |
|---|---|
POST /api/health/checkin/list |
行为打卡列表 |
POST /api/health/checkin/create |
创建行为打卡 |
POST /api/daily/checkin/list |
每日打卡列表(饮食/运动/睡眠/心情) |
POST /api/daily/checkin/create |
创建每日打卡 |
POST /api/daily/checkin/update |
更新打卡 |
POST /api/daily/checkin/delete |
删除打卡 |
POST /api/mind/checkin/create |
情绪日记创建 |
POST /api/mind/checkin/list |
情绪日记列表 |
POST /api/mind/checkin/latest |
最新情绪日记 |
POST /api/mind/checkin/trend |
情绪趋势 |
POST /api/mind/checkin/stats |
情绪统计 |
POST /api/mind/checkin/weekly-report |
周报 |
POST /api/mind/checkin/emotion/recognize |
|
POST /api/mind/emotion/analyze |
照片情绪识别(文件上传,走 LangGraph DeepFace) |
POST /api/mind/emotion/analyze-url |
照片情绪识别(URL方式,走 LangGraph DeepFace) |
POST /api/health-status/get |
健康现状档案获取 |
POST /api/health-status/save |
健康现状档案保存 |
POST /api/health-status/signature |
提交手签名(仅更新 signature + signed_at 列,不影响其他字段;body: {memberId, signature},signature 为 base64 PNG data URL) |
POST /api/health/exercise/sync-wechat-steps |
同步微信运动步数(传 encryptedData+iv,返回当日步数与近30天数据) |
POST /api/health/meal/list |
饮食打卡列表 |
POST /api/health/meal/create |
创建饮食打卡(支持 taskId 任务联动 + isBackfill 补打) |
POST /api/health/meal/daily |
获取某天的饮食记录 |
POST /api/health/meal/weekly |
获取某周食材频次与营养汇总 |
POST /api/health/meal/alerts |
获取食材摄入预警 |
POST /api/health/sleep/list |
睡眠打卡列表 |
POST /api/health/sleep/create |
创建睡眠打卡(支持 taskId 任务联动) |
POST /api/health/exercise/list |
运动打卡列表 |
POST /api/health/exercise/create |
创建运动打卡(支持 taskId 任务联动 + stepCount 微信步数) |
taskId 参数)饮食/睡眠/运动打卡接口均支持可选 taskId 参数(Long),用于将打卡记录与任务系统联动。
请求体新增参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
taskId |
Long | ❌ | 关联任务ID;为 null 时仅存打卡记录,不触发任务逻辑 |
联动逻辑:
| 场景 | 行为 |
|---|---|
taskId 指向 tasks.is_daily_progress=1 的任务 |
调用 TaskService.updateProgress(userId, taskKey, 1) 累加进度,达标后自动 completed + 发放积分/能量 |
taskId 指向普通任务(is_daily_progress=0) |
调用 TaskService.completeTask(taskId, memberId, ...) 直接完成 |
taskId 为 null |
仅存打卡记录 + 发放 5CF 打卡积分,不触发任务逻辑 |
补打(isBackfill=1) |
忽略 taskId,不触发任何任务逻辑 |
taskKey 约定(每日进度型任务):
| actionType | taskKey | 匹配方式 |
|---|---|---|
diet |
"DIET" |
title 精确匹配 OR title 以 "[DIET]" 前缀匹配 |
sleep |
"SLEEP" |
同上 |
exercise |
"EXERCISE" |
同上 |
前端跳转路径:/pages/growth/{type}-checkin?taskId={id}(由 tasks.vue 的 navigateByAction() 自动构造)
/api/product/*)| 路径 | 说明 |
|---|---|
POST /api/product/list |
商品列表 |
POST /api/product/detail |
商品详情 |
POST /api/product/create |
创建商品 |
POST /api/product/update |
更新商品 |
POST /api/product/my |
我的商品 |
POST /api/product/shelve |
上下架 |
POST /api/product/order/create |
创建订单 |
POST /api/product/order/pay |
支付 |
POST /api/product/order/cancel |
取消订单 |
POST /api/product/order/my |
我的订单 |
POST /api/product/order/detail |
订单详情 |
POST /api/product/order/confirm |
确认收货 |
POST /api/product/order/refund/apply |
申请退款 |
POST /api/product/order/vendor |
服务商查询收到的订单 |
POST /api/product/order/vendor-confirm |
服务商确认发出/服务完成 |
POST /api/product/order/ship |
服务商/管理端发货(填物流单号+快递公司)。发货成功后自动调用微信「小程序交易管理服务」upload_shipping_info 同步物流到微信订单管理(用户在微信侧收发货通知/查物流/确认收货);自提订单或无单号跳过;失败只记日志不阻塞(fail-open);wechat.test-mode=true 或 wechat.fulfillment-enabled=false(环境变量 WECHAT_FULFILLMENT_ENABLED)时跳过 |
POST /api/product/order/review/update |
供应商审核修改待支付订单(修改价格/配送方式/添加优惠券/赠品) |
POST /api/cart/add |
加入购物车 |
POST /api/cart/list |
购物车列表 |
POST /api/cart/update |
更新数量 |
POST /api/cart/remove |
移除商品 |
POST /api/cart/count |
购物车数量 |
POST /api/consignee/list |
收货地址列表 |
POST /api/consignee/save |
保存地址 |
POST /api/consignee/delete |
删除地址 |
/api/ai/*)| 路径 | 说明 |
|---|---|
POST /api/ai/chat/send |
发送消息 |
POST /api/ai/chat/conversations |
对话列表 |
POST /api/ai/chat/messages |
消息列表 |
POST /api/ai/chat/conversations/{id}/delete |
删除对话 |
POST /api/ai/nutrition/send |
营养对话 |
POST /api/ai/health-coach/send |
健康教练(请求体可选字段 coach_id 由服务端自动注入,客户端无需传;LangGraph 按 xibao/fubao 三级回退路由话术) |
POST /api/ai/butler/send |
管家对话 |
POST /api/ai/context |
上下文管理 |
POST /api/butler/sessions/create |
创建会话 |
POST /api/butler/sessions/update-conversation |
更新会话 |
POST /api/butler/sessions/archive |
归档会话 |
POST /api/butler/sessions/list |
会话列表 |
POST /api/butler/sessions/detail |
会话详情 |
POST /api/butler/sessions/delete |
删除会话 |
/api/assessment/*, /api/dan-assessment/*)| 路径 | 说明 |
|---|---|
POST /api/assessment/appointment/create |
预约测评 |
POST /api/assessment/appointment/confirm/{id} |
确认预约 |
POST /api/assessment/appointment/cancel/{id} |
取消预约 |
POST /api/assessment/appointment/my-list |
我的预约 |
POST /api/assessment/latest-result |
最新测评结果 |
POST /api/assessment/history |
测评历史 |
POST /api/dan-assessment/result/upload |
上传报告 |
POST /api/dan-assessment/result/{resultId}/guidance/save |
保存指导建议 |
POST /api/dan-execution/complete |
完成测评执行 |
POST /api/dan-execution/confirm |
确认执行 |
POST /api/dan-execution/rate |
评分 |
POST /api/dan-execution/my-list |
我的执行记录 |
/api/diet/*)| 路径 | 说明 |
|---|---|
POST /api/diet/preferences/current-member |
当前成员饮食偏好 |
POST /api/diet/preferences/save |
保存饮食偏好 |
POST /api/diet/recommendation/today |
今日推荐(返回 data.id / data.menu / data.nutritionSummary / data.status) |
POST /api/diet/recommendation/generate |
生成推荐(body: date, meal_type, selected_foods JSON string;返回 data.id / data.menu / data.nutritionSummary) |
POST /api/diet/recommendation/complete |
完成推荐 |
POST /api/diet/record/save |
保存饮食记录 |
POST /api/diet/record/daily |
每日记录 |
POST /api/diet/ingredients/suggest |
食材推荐(返回 data.ingredients 列表) |
POST /api/diet/ingredients/recommend |
换一批(返回 data.ingredients,每次不同) |
POST /api/diet/ingredients/search |
搜索食材(body {keyword},返回 data.foods:[{id, name, category}]) |
POST /api/diet/meals/config |
餐食配置(body: date_type + meal_type,返回 data.participantMemberIds 等) |
POST /api/diet/meals/config/save |
保存餐食配置,批量格式(推荐,单次调用):body {date_type:"weekday", configs:{breakfast:"[1,2]", lunch:"[]", dinner:"[3]"}}(各餐次值为成员ID数组的 JSON 字符串);亦兼容单条格式:body {date_type, meal_type, participant_member_ids, notes?}。前端 saveMealConfig 位于 cfc-frontend/utils/api.js(2772行) |
/api/articles, /api/content/*)| 路径 | 说明 |
|---|---|
POST /api/articles/list |
文章列表 |
POST /api/articles/detail |
文章详情 |
POST /api/articles/featured |
精选文章 |
POST /api/articles/record-read |
记录阅读 |
POST /api/articles/report-reading-time |
上报阅读时长(按 articleId+childId+日期累加,首次上报递增 view_count) |
POST /api/articles/reading-stats |
阅读统计 |
POST /api/articles/daily-tip |
每日提示 |
POST /api/articles/ai-questions |
AI 生成问题 |
POST /api/articles/submit-answers |
提交答案 |
POST /api/articles/my-posts |
我的文章 |
POST /api/articles/comments/list |
评论列表 |
POST /api/articles/comments/create |
创建评论 |
POST /api/articles/comments/audit |
审核评论 |
POST /api/articles/quiz/generate |
生成测验 |
POST /api/articles/quiz/submit |
提交测验 |
POST /api/content-sections/visible |
可见区块 |
POST /api/content-sections/list |
区块列表 |
POST /api/content/related-items |
内容关联推荐:以活动/文章/商品任一为源(sourceType+sourceId),按共享标签一次返回 data.articles / data.activities / data.products 三组(支持 size/page 分页,游客可访问) |
/api/admin/*)管理员接口需
role=admin,详见AdminInterceptor。
| 路径前缀 | 说明 |
|---|---|
/api/admin/articles/* |
文章管理 |
POST /api/admin/articles/move |
调整精选文章的推荐顺序(`{ id, direction: 'up' |
/api/admin/articles/reading-records |
按文章查询阅读记录明细(分页,含孩子昵称/时长) |
/api/admin/assessment/* |
测评材料管理 |
/api/admin/bazi-config/* |
八字配置 |
/api/admin/blood-type-config/* |
血型配置 |
/api/admin/butler/* |
管家分配管理(分配列表/强制解绑/停接开关) |
/api/admin/commission/* |
佣金管理 |
/api/admin/dimension/* |
维度配置 |
/api/admin/dimension-config/* |
维度权重 |
/api/admin/energy/* |
能量配置 |
/api/admin/energy-config/* |
五行能量来源/每日限制配置 |
/api/admin/ecom-supplier/* |
电商供应商管理 |
/api/admin/file-record/* |
后台素材库(上传入库/检索/标签字典/统计,见 §4.56) |
/api/admin/guide/* |
成长规划师管理(申请/套餐) |
/api/admin/growth-archive-product/* |
成长档案关联商品 |
/api/admin/health-plan/* |
健康方案管理(跨家庭列表/详情) |
/api/admin/knowledge-base/* |
知识库管理 |
/api/admin/notices/* |
公告管理 |
/api/admin/innate-portrait-config/* |
先天画像来源权重配置(list/update/invalidate) |
/api/admin/numsoul-detail-config/* |
数字能量详细配置(list/create/update/delete) |
/api/admin/package-templates/* |
套餐模板 |
/api/admin/ppoint-config/* |
P点配置(品类级比例+商品级固定值) |
/api/admin/product/* |
商品管理 |
/api/admin/report-parser/* |
报告解析配置 |
/api/admin/report-template/* |
报告展示模板管理 |
/api/admin/supply-* |
供应链相关 |
/api/admin/system/* |
系统配置 |
/api/admin/unlock-gates/* |
通关配置 |
/api/migration/run |
数据迁移 |
/api/mind/innate/*)五维能量体系"心维度"先天画像聚合接口,基于星座/八字/血型/数字能量生成,AI 解读失败时自动降级模板文案。
| 路径 | 说明 |
|---|---|
POST /api/mind/innate/portrait |
先天画像(聚合 mind_base_score + 数字能量详情 + 来源贡献明细) |
POST /api/mind/innate/reading |
AI 解读(缓存到 innate_portrait_report,失败降级模板) |
POST /api/mind/innate/numsoul |
数字能量计算(生命灵数/天赋数/生日数/命运数) |
POST /api/mind/innate/trajectory |
先天+后天成长轨迹(EnergyBalance 后天能量对比) |
请求参数(portrait/reading/trajectory):
{ "memberId": 123, "memberType": "child", "familyId": 1 }
numsoul 请求参数:
{ "year": 1990, "month": 5, "day": 15 }
/api/stats, /api/notification)| 路径 | 说明 |
|---|---|
POST /api/stats/dashboard |
统计仪表盘 |
POST /api/stats/overview |
总览 |
POST /api/stats/revenue |
收入统计 |
POST /api/stats/membership |
会员统计 |
POST /api/stats/trend |
趋势 |
POST /api/notification/list |
通知列表 |
POST /api/notification/read |
标记已读 |
/api/admin/report-template)| 路径 | 说明 |
|---|---|
POST /api/admin/report-template/list |
模板列表,支持 reportType/isActive 过滤 |
POST /api/admin/report-template/get |
按 reportType 获取模板,参数 reportType |
POST /api/admin/report-template/save |
保存模板(创建或更新),body 含 id/name/reportType/config |
POST /api/admin/report-template/delete |
删除模板,参数 id |
POST /api/admin/report-template/toggle |
启停模板,body { id, isActive } |
POST /api/admin/report-template/indicators |
获取可选指标列表,支持 domain 过滤 |
config JSON 结构:
{
"fixedBlocks": [
{ "type": "score", "title": "健康评分", "items": ["overallScore","gutHealthScore"] },
{ "type": "indicator", "title": "血脂指标", "groupLabel": "血脂", "indicatorNames": ["总胆固醇","甘油三酯"] },
{ "type": "list", "title": "菌种详情", "listKey": "flora" },
{ "type": "text", "title": "评语", "content": "..." }
],
"freeDisplay": { "enabled": true, "groupName": "其他指标" }
}
| 路径 | 说明 |
|---|---|
POST /api/config/public/value |
公开配置值 |
POST /api/media/upload |
媒体上传(免鉴权) |
POST /api/recommend/search |
推荐搜索 |
POST /api/recommend/repurchase-reminders |
复购提醒 |
POST /api/task-reminders/upcoming/{memberId} |
即将到期提醒 |
POST /api/tianpan/dashboard |
天盘概览 |
POST /api/tianpan/member/{memberId} |
成员详情 |
POST /api/tianpan/compatibility |
兼容性分析 |
POST /api/tianpan/annual-energy |
年度能量 |
POST /api/tianpan/daily-fortune |
每日运势 |
POST /api/tianpan/related-items |
相关事项 |
POST /api/tianpan/recalibrate |
重算五维基础分(管理员) |
POST /api/wisdom/gut-cognition |
肠道认知 |
POST /api/wealth/checkin/* |
财富打卡 |
POST /api/insurance/* |
保险规划 |
/api/daily-task/*)| 路径 | 说明 |
|---|---|
POST /api/daily-task/overview |
今日任务总览(打卡/任务/阅读活动/测评报告四类聚合) |
/api/dimension/*)| 路径 | 说明 |
|---|---|
POST /api/dimension/overview |
获取健康维度概览(七维评分+百分位) |
POST /api/dimension/upload |
手动录入维度评分 |
POST /api/dimension/questionnaire |
问卷提交维度评分 |
POST /api/dimension/history |
获取维度历史记录 |
/api/family/relationship/*)| 路径 | 说明 |
|---|---|
POST /api/family/relationship/scores |
获取家庭成员关系质量评分 |
POST /api/family/relationship/calculate |
计算并保存关系质量评分 |
POST /api/family/relationship/health-alerts |
获取健康预警列表 |
POST /api/family/relationship/milestones |
获取即将到来的里程碑 |
POST /api/family/relationship/pairwise |
获取以指定成员为中心的所有成员关系 |
/api/commission/*)| 路径 | 说明 |
|---|---|
POST /api/commission/summary |
获取佣金汇总 |
POST /api/commission/list |
佣金流水列表 |
POST /api/commission/team |
团队统计(L1/L2) |
POST /api/commission/stats |
佣金统计面板 |
POST /api/commission/balance |
可提现余额详情 |
POST /api/commission/team/list |
团队成员列表 |
POST /api/commission/funnel |
佣金转化漏斗 |
POST /api/commission/team/list |
扩展:返回中每个成员新增 memberConsumption(该成员已完成履约订单总额,分)、myCfEarnedFromMember(我从该成员消费获得的 CF 总额,分) |
POST /api/commission/team/consumption |
团队总消费额分级汇总,请求 {maxLevel}(默认 3),返回 {totalConsumption: 分, levelBreakdown[{level, memberCount, consumption}], totalMembers, maxLevel} |
POST /api/commission/my-referrer |
获取我的直推人信息,返回 {hasReferrer, referrerId, nickname, avatar, referralCode, bindTime},无推荐人时 hasReferrer=false |
POST /api/commission/team/tree |
团队树形扁平数据(不含根节点),请求 {maxLevel}(默认 3),返回 {nodes[{userId, nickname, avatar, level, parentId, referrerId, memberConsumption, myCfEarnedFromMember}], totalMembers, maxLevel} |
/api/admin/energy-config/*)| 路径 | 说明 |
|---|---|
POST /api/admin/energy-config/source-list |
能量来源配置列表 |
POST /api/admin/energy-config/source-save |
保存能量来源配置(新增/更新) |
POST /api/admin/energy-config/source-delete |
删除能量来源配置 |
POST /api/admin/energy-config/daily-limits |
获取每日能量限制 |
POST /api/admin/energy-config/daily-limit-save |
保存每日能量限制 |
POST /api/admin/energy-config/overview |
能量配置总览(来源+限制) |
/api/admin/notices/*)| 路径 | 说明 |
|---|---|
POST /api/admin/notices/list |
公告列表(分页) |
POST /api/admin/notices/all |
全量公告列表 |
POST /api/admin/notices/create |
创建公告 |
POST /api/admin/notices/update |
更新公告 |
POST /api/admin/notices/delete |
删除公告(软删) |
POST /api/admin/notices/pin |
置顶公告 |
/api/admin/guide/*)| 路径 | 说明 |
|---|---|
POST /api/admin/guide/applications/pending |
待审批规划师申请 |
POST /api/admin/guide/applications/{id}/approve |
审批通过 |
POST /api/admin/guide/applications/{id}/reject |
驳回申请 |
POST /api/admin/guide/guides |
获取所有成长规划师列表 |
POST /api/admin/guide/guides/level/{level} |
按级别获取规划师 |
POST /api/admin/guide/guides/approved |
获取已入驻(approved)的服务商列表 |
POST /api/admin/guide/packages |
获取所有套餐模板 |
POST /api/admin/guide/packages/create |
创建套餐 |
POST /api/admin/guide/packages/{id}/update |
更新套餐 |
POST /api/admin/guide/packages/{id}/status |
更新套餐状态 |
/api/admin/product/*)| 路径 | 说明 |
|---|---|
POST /api/admin/product/list |
商品列表(分页/筛选/搜索) |
POST /api/admin/product/review |
审核商品(approve/reject) |
POST /api/admin/product/shelve |
商品上下架 |
POST /api/admin/product/detail |
商品详情 |
POST /api/admin/product/create |
创建商品 |
POST /api/admin/product/update |
更新商品 |
POST /api/admin/product/copy |
复制商品 |
POST /api/admin/product/delete |
删除商品 |
POST /api/admin/product/batch-shelve |
批量上下架(body: {productIds, shelve}) |
/api/admin/growth-archive-product/*)| 路径 | 说明 |
|---|---|
POST /api/admin/growth-archive-product/save |
保存关联商品规则 |
POST /api/admin/growth-archive-product/detail |
关联商品规则详情 |
POST /api/admin/growth-archive-product/delete |
删除关联商品规则 |
/api/admin/ecom-supplier/*)| 路径 | 说明 |
|---|---|
POST /api/admin/ecom-supplier/list |
供应商列表(分页/搜索) |
POST /api/admin/ecom-supplier/all |
所有供应商(下拉选择) |
POST /api/admin/ecom-supplier/save |
创建供应商 |
POST /api/admin/ecom-supplier/update |
更新供应商 |
POST /api/admin/ecom-supplier/delete |
删除供应商 |
/api/admin/assessment/*)| 路径 | 说明 |
|---|---|
POST /api/admin/assessment/materials |
测评资料列表 |
POST /api/admin/assessment/materials/{id} |
测评资料详情 |
POST /api/admin/assessment/materials/create |
创建测评资料 |
POST /api/admin/assessment/materials/{id}/update |
更新测评资料 |
POST /api/admin/assessment/materials/{id}/delete |
删除测评资料(软删) |
POST /api/admin/assessment/config |
获取积分配置 |
POST /api/admin/assessment/config/update |
更新积分配置 |
/api/admin/ppoint-config/*)| 路径 | 说明 |
|---|---|
POST /api/admin/ppoint-config/category/list |
品类级P点比例列表 |
POST /api/admin/ppoint-config/category/save |
保存品类级P点比例 |
POST /api/admin/ppoint-config/category/delete |
删除品类级P点比例 |
POST /api/admin/ppoint-config/category/by-category |
按品类ID获取P点比例 |
POST /api/admin/ppoint-config/product/list |
商品级P点列表 |
POST /api/admin/ppoint-config/product/save |
保存商品级P点 |
POST /api/admin/ppoint-config/product/delete |
删除商品级P点 |
POST /api/admin/ppoint-config/product/by-product |
按商品ID获取P点 |
POST /api/admin/ppoint-config/effective |
获取商品综合有效P点值 |
/api/admin/report-parser/*)| 路径 | 说明 |
|---|---|
POST /api/admin/report-parser/types |
报告类型列表 |
POST /api/admin/report-parser/types/save |
保存/更新报告类型 |
POST /api/admin/report-parser/types/toggle |
启用/停用报告类型 |
POST /api/admin/report-parser/types/delete |
删除报告类型 |
POST /api/admin/report-parser/fingerprints/list |
指纹规则列表 |
POST /api/admin/report-parser/fingerprints/save |
保存指纹规则 |
POST /api/admin/report-parser/fingerprints/delete |
删除指纹规则 |
POST /api/admin/report-parser/imports |
导入记录列表 |
POST /api/admin/report-parser/imports/import |
上传导入包 |
POST /api/admin/report-parser/imports/approve |
审批导入 |
POST /api/admin/report-parser/imports/reject |
驳回导入 |
POST /api/admin/report-parser/unknown-clusters |
未知报告聚类列表 |
POST /api/admin/report-parser/unknown-uploads |
聚类上传记录 |
POST /api/admin/report-parser/generate-type |
自学习生成报告类型 |
1. 搜索现有接口:grep -rn "关键词" cfc-backend/src/main/java/com/etotem/cfc/controller/
2. 检查路由冲突:grep -rn '@PostMapping("' cfc-backend/src/main/java/com/etotem/cfc/controller/ | grep -oP '@\w+Mapping\("\K[^"]*' | sort -u
3. 检查 Bean 冲突:find ... -name "*XxxService.java" | xargs grep "class Xxx"
4. 如有相似接口:评估修改成本,必要时扩展
5. 如确需新增:
a. 创建 Entity(如需要新表)
b. 创建 Mapper
c. 创建 Service
d. 创建 Controller(放在合适子目录)
e. 数据库迁移(DatabaseInitializer + schema.sql)
f. 更新本文档
6. mvn clean compile 验证
/api/butler/*)| 路径 | 说明 |
|---|---|
POST /api/butler/available-list |
可选管家列表(浏览开放,脱敏;仅 L2 有效订阅家庭可绑定) |
POST /api/butler/my-butler |
我家当前管家绑定信息(含管家昵称/等级/分配时间) |
POST /api/butler/select |
绑定/更换管家(校验 L2 订阅、管家容量与接单状态;换绑自动解绑旧关系) |
/api/coupon/* + /api/admin/coupon/*)2026-08-31 起,优惠券由「用户维度」全链路改为「家庭维度」。
user_coupon保留历史数据,新发放与消费统一走family_coupon。
| 路径 | 说明 | |||
|---|---|---|---|---|
POST /api/admin/coupon/list |
优惠券模板分页列表(admin),{ page, size, keyword?, sort? },返回 Page<Coupon>(records/total/current/size),keyword 对名称/ID 模糊匹配 |
|||
POST /api/admin/coupon/create |
新建优惠券模板(admin) | |||
POST /api/admin/coupon/update |
更新优惠券模板(admin) | |||
POST /api/admin/coupon/issue |
批量发放到家庭,{ couponId, familyIds: [Long] }(admin) |
|||
POST /api/admin/coupon/issue-family |
单家庭发放,{ familyId, couponId, quantity }(admin,家庭管理页使用) |
|||
POST /api/admin/coupon/grant-log |
家庭发券流水查询,{ familyId?, couponId?, grantType?, source? }(admin,返回 family_coupon_grant_log,每行含批量填充的 familyName,消除前端逐条查家庭名 N+1) |
|||
POST /api/admin/coupon/grant-user |
管理员定向发放「会员升级券」给指定用户,{ userId, amountYuan \| amount, validUntil?, remark? }(admin,自动创建 applicableTo=MEMBERSHIP 无门槛券模板并发放到该用户家庭,落 grantType=MANUAL 流水) |
|||
POST /api/admin/coupon/toggle-status |
启用/停用优惠券模板(admin) | |||
POST /api/coupon/list |
当前家庭可用优惠券(小程序) | |||
POST /api/coupon/my |
我的(家庭)优惠券(小程序) | |||
POST /api/coupon/apply |
下单抵扣(家庭券) | |||
POST /api/coupon/claim |
领取优惠券(发到家庭) | |||
POST /api/coupon/checkout-list |
结算页可兑换未拥有券 | |||
POST /api/coupon/available-templates |
领券中心可取券模板:上架(status 空/ACTIVE)、有效期内、未领完(total_count 空/≤0 视为不限量,否则 used_count(字段为id等模板字段),与/claim` 去重口径对齐(COUPON-C3)
|
| 路径 | 说明 |
|---|---|
POST /api/commission/cf/rate |
我的团队规模 + 两级销售奖档位。返回 { totalTeamSize, ratePercent, tierName, teamDepth, teamAnnualPpoints, selfAnnualPpoints, directRatePercent, directTierName, indirectRatePercent, indirectTierName };legacy 字段 ratePercent/tierName 取 F03a 值供旧端兼容(未入档时 ratePercent=0、tierName="未入档") |
POST /api/commission/cf/summary |
我的 CF 钱包汇总,返回 PlatformBalanceService.getBalance(userId) 结果 |
POST /api/commission/cf/list |
我的 CF 流水(分页),请求 { page, size },返回 Page<PlatformBalanceLog> |
两级销售奖档位(迁移418 种子,管理端可配置):
共同基数 = 本单消费产生的 P 点(商品:实付元 × 有效 P 点 / 100;非商品:实付元 × cf.commission.service_rate(bps) / 10000)。第 1 个非同家庭引荐人拿 F03a,第 2 个拿 F03b,最多两级。
F03a 直接销售奖(cf_direct_sales_tier,按团队 8 层内滚动一年累计 P 点):
| 团队年度 P 点下限 | 档位 | 比例 |
|---|---|---|
| 100 | 青铜 | 10% |
| 500 | 白银 | 25% |
| 2000 | 黄金 | 40% |
| 5000 | 铂金 | 55% |
| 10000 | 钻石 | 70% |
F03b 间接销售奖(cf_indirect_sales_tier,按自身滚动一年累计消费 P 点):
| 自身年度 P 点下限 | 档位 | 比例 |
|---|---|---|
| 100 | 青铜 | 2% |
| 500 | 白银 | 5% |
| 2000 | 黄金 | 10% |
| 5000 | 铂金 | 15% |
| 10000 | 钻石 | 20% |
匹配语义:
enabled=1 AND min_xxx <= 值 ORDER BY min_xxx DESC LIMIT 1,无匹配档位不发放;比例按cf_earn_rule.params_json.max_rate_percent(F03a=70、F03b=20)封顶。 金额由cf_earn_rule.formula = floor(base_ppoints * rate_percent / 100)计算,发放统一走CfBalanceService.earnByRule(幂等键复用 F-2uk_ref_type),只写cf_balance+cf_balance_log。 滚动一年口径:消费支付成功时落ppoint_consumption_log一行(唯一键order_type + order_id幂等),按created_at >= now() - 365d聚合(迁移420)。
/api/cf/transfer/*)| 路径 | 说明 |
|---|---|
POST /api/cf/transfer/send |
成员间转让 CF,请求 { toUserId, amount }。仅限同一家庭(校验 familyId 一致);amount 必须为正数。转出扣减 + 转入增加在同一事务 |
POST /api/cf/transfer/list |
转让记录(分页,按当前用户家庭过滤),请求 { page, size },返回 Page<CfTransferRecord> |
/api/admin/cf-rate-tier/*)| 路径 | 说明 |
|---|---|
POST /api/admin/cf-rate-tier/list |
阶梯列表(按 sort_order 升序),返回 List<CfRateTier> |
POST /api/admin/cf-rate-tier/save |
新增/更新阶梯,请求体为 CfRateTier(含 id 则更新,否则新增,默认 enabled=1),返回 "已保存" |
POST /api/admin/cf-rate-tier/delete |
删除阶梯,请求 { id },返回 "已删除" |
CfRateTier 字段: id / tierName(档位名)/ minTeamSize(团队规模下限含)/ ratePercent(返佣比例%)/ sortOrder(排序,越大越高)/ enabled(1启用/0停用)/ createdAt / updatedAt。
注意:家庭券接口为
POST /api/coupon/my与POST /api/coupon/list(见 4.32),不存在/api/coupon/family/list路由。
/api/health/report/*, /api/report-parser/*)健康报告上传后进入异步采集流程:后端解析 PDF(先 pdftotext 提取文本内联,避免依赖代理工具执行),指纹判定报告类型 → 已知类型走专用采集脚本,未知类型交本地 opencode 服务(模型 agnes-ai/agnes-2.5-flash,在 session body 中显式指定)。前端提示「数据采集中」,完成后自动入库,列表页轮询刷新,无需用户等待。
| 路径 | 说明 |
|---|---|
POST /api/health/report/upload-only |
生产小程序上传入口:上传 PDF → 落草稿 health_report_drafts(parse_status=collecting)→ 异步触发采集 → 返回草稿 ID(前端留意 data.draftId 后轮询) |
POST /api/report-parser/upload |
专用采集接口:同 async 流程,统一进异步采集 |
POST /api/health/report/collect/status |
查询单草稿采集状态,请求 { draftId },返回 { status, parseError }(collecting/completed/failed) |
POST /api/health/report/collecting-list |
当前用户「采集中」草稿列表,返回 List<Draft>(前端轮询用) |
采集流程状态机:
collecting:指纹判定 + 异步解析中completed:解析成功 + 已自动入库(指标/菌群/疾病风险/食材)failed:解析失败,parse_error 记录原因专属采集脚本路径(在 HealthReportDraftService): getDraftById / markCollecting / updateParseMethod / markCollectCompleted / markCollectFailed / listCollectingByUser。
/api/health/report/*)报告归属由 health_reports.subject_id 字段表示(关联家庭成员 ID,可为 null)。无归属的报告不参与方案生成,但可在管理端或小程序手动绑定/重新分配。
| 路径 | 说明 |
|---|---|
POST /api/health/report/reassign |
重新分配报告归属(含维度重算),请求 { reportId, subjectId? },subjectId 为 null 表示解绑 |
POST /api/health/report/unlinked |
获取家庭内所有未绑定归属的报告,请求 { familyId },返回 List<HealthReport> |
POST /api/health/report/bind |
绑定报告到成员(仅绑定,不可解绑),请求 { reportId, subjectId } |
/api/health/report/reassign 请求体:
{
"reportId": 123,
"subjectId": 456 // 可为 null 表示解除绑定
}
响应: Result<String>,"归属已更新"
归属变更触发联动:
subject_id IS NULL 的报告自动跳过(triggerAutoPlanAfterConfirm 已有此逻辑)权限检查: 通过 familyId(JWT 注入)验证报告属于当前家庭,跨家庭操作抛出 RuntimeException("报告不属于该家庭")。
/api/health/report/*)舌诊功能已集成 aikanshe.com(愛看舌)开放 API,作为首选方案;当 aikanshe.com 不可用时回退至 LangGraph Python 服务。调用流程如下:
请求路径:POST /api/health/report/parse-preview(type=tongue)
请求体示例:
{
"type": "tongue", // 必填:指定舌诊流程
"memberId": 12345, // 可选:家庭成员 ID
"filePath": "/data/...",// 可选:图片路径(auto模式会先检测}
}
响应结构:
{
"code": 200,
"message": "success",
"data": {
"recordId": 67890, // 舌诊记录 ID
"imageUrl": "http://...", // 图片访问 URL
"overallAssessment": "舌象基本正常...", // 整体评估
"indicators": [ // 7类舌诊指标
{"code": "tongue_color", "value": "淡红"},
{"code": "coating_color", "value": "薄白"},
{"code": "coating_texture", "value": "润"},
{"code": "fissure", "value": "无"},
{"code": "teeth_mark", "value": "无齿痕"},
{"code": "sublingual_vein", "value": "无点刺"},
{"code": "constitution", "value": "平和质"}
],
"createTime": "2026-10-08T..."
}
}
优先级方案(aikanshe.com 优先,LangGraph 兜底):
aikanshe.com API(POST /agency/quanxi,基于 AI 视觉模型)/api/v1/tongue/diagnose)置信度阈值:默认 0.2,可通过 application.yml 的 aikanshe.confidence 配置。
相关配置:
aikanshe:
appkey: ${AIKANSHE_APPKEY:}
base-url: ${AIKANSHE_BASE_URL:https://api.aikanshe.com}
token: ${AIKANSHE_TOKEN:}
confidence: ${AIKANSHE_CONFIDENCE:0.2}
lang: ${AIKANSHE_LANG:zh-CN}
已废弃接口(保留,待清理):
POST /api/health/report/upload-only(PDF流程入口,已被 /api/health/report/parse-preview?type=tongue 部分取代)/api/health/feedback/*)用户对健康报告提交疑问/建议,后端持久化到 report_feedback 表并调用 AI 解答(经 AiGateway,免费版每日 1 次,付费版不限)。反馈记录含 aiAnswer/aiStatus,前端可据此展示 AI 解答结果。
| 路径 | 说明 |
|---|---|
POST /api/health/feedback/submit |
提交报告反馈(持久化 + AI 解答),请求 { reportId?, draftId?, memberId?, type, content },返回 Result<ReportFeedback> |
POST /api/health/feedback/list |
我的报告反馈列表(含 AI 解答),请求 { reportId? },返回 Result<List<ReportFeedback>>(按创建时间倒序,最多 50 条) |
/api/health/feedback/submit 请求体:
{
"reportId": 123, // 可选,关联健康报告ID
"draftId": null, // 可选,关联解析草稿ID(reportId 与 draftId 二选一,均可为空)
"memberId": 456, // 可选,关联家庭成员ID(默认当前成员)
"type": "question", // question=疑问 / suggestion=建议,其他值默认 question
"content": "这份报告里菌群多样性偏低是什么意思?"
}
响应示例(Result<ReportFeedback>,data 字段):
{
"code": 200,
"message": "ok",
"data": {
"id": 1,
"userId": 1001,
"memberId": 456,
"reportId": 123,
"draftId": null,
"feedbackType": "question",
"content": "这份报告里菌群多样性偏低是什么意思?",
"aiAnswer": "菌群多样性反映肠道微生物的丰富程度……",
"aiStatus": "answered",
"conversationId": "conv_abc123",
"createdAt": "2026-09-22 14:30:00"
}
}
aiStatus 取值:pending(待解答)/ answered(AI 已解答)/ failed(AI 调用失败,仍会落库,aiAnswer 为空)。report:feedback:free:{userId}:{date},memberLevel=FREE 或为空时生效),超限返回 Result.error("免费版每日仅限 1 次反馈解答,升级会员解锁更多");Redis 异常时 fail-open 放行。content 必填且不超过 500 字。/api/cognitive/*)六维认知体系:感知(perception) / 专注(focus) / 记忆(memory) / 逻辑(logic) / 空间(spatial) / 加工速度(processingSpeed)。
| 路径 | 说明 |
|---|---|
POST /api/cognitive/child |
获取孩子最新六维认知得分 |
POST /api/cognitive/family |
获取家庭所有孩子最新六维认知得分 |
POST /api/cognitive/update |
更新认知维度得分(由规划师录入,需已有 completed 行) |
POST /api/cognitive/self-test |
提交认知自测结果(自动创建档案,写入六维认知档案,综合分自动计算) |
POST /api/cognitive/norms |
获取认知维度百分位常模 |
POST /api/cognitive/trend |
获取认知维度历史趋势 |
POST /api/cognitive/recommendations |
获取认知训练建议(按薄弱维度生成) |
POST /api/cognitive/recommendations/create-task |
从建议创建每日任务 |
/api/cognitive/self-test 请求体:
{
"memberId": 12345,
"dimension": "memoryScore",
"score": 85
}
dimension 取值:memoryScore / logicScore / perceptionScore / spatialScore / processingSpeedScore
score 范围:0-100(整数)
响应: Result<String>,成功返回 "提交成功",失败返回错误原因。
行为: 若该孩子尚无任何 status=completed 的 DanAssessmentResult 行,自动创建(source='self_test'),写入对应维度分,重新计算综合分(7 维度非空均值)。
已记录认知自测 API 端点 — 禁止重复注册。
/api/pearl/*, /api/ability/*)关系三图体系:章鱼图(谁帮过我)→ 珍珠图(我有什么)→ 能力图(谁会什么)。珍珠图聚合 25 类社会连接(12 必备内圈 + 13 理想外圈),附带互动日志、价值分级、定期提醒。
| 路径 | 说明 |
|---|---|
POST /api/pearl/resources |
珍珠图聚合:25 组(ESSENTIAL 内圈 + IDEAL 外圈)+ legacyGroups(历史资源) |
POST /api/pearl/connection-types |
获取 25 类连接类型列表(code/label/category/suggestIntervalMonth) |
POST /api/pearl/item/add |
登记珍珠图资源(connectionType 必填,type 可选,name 必填,contactId 可选) |
POST /api/pearl/item/delete |
删除登记的珍珠图资源(itemId) |
POST /api/pearl/item/update-priority |
手动覆盖优先级(itemId/priority 1-3),同步 valueScore |
POST /api/pearl/interaction/add |
记录互动(itemId/interactionType/content),更新价值分并关闭 PENDING 提醒 |
POST /api/pearl/interaction/list |
互动历史分页(itemId/page/size) |
POST /api/pearl/reminder/list |
待办提醒列表(PENDING) |
POST /api/ability/map |
能力图:SKILL 帮助记录按联系人聚合为能力节点 |
/api/pearl/resources 响应结构:
{
"code": 200,
"data": {
"groups": [
{
"type": "MEDICAL", "typeName": "医疗", "category": "ESSENTIAL", "ring": "inner",
"items": [
{
"id": 1, "name": "社区王医生", "description": "儿科主治", "avatar": null,
"valueScore": 72, "priority": 1, "contactId": 5,
"lastInteractionAt": "2026-08-15T10:30:00",
"interactionCount": 8, "daysSinceLast": 26
}
]
}
// ... 共 25 组,为空时 items=[]
],
"legacyGroups": [
{ "type": "PERSON", "typeName": "人脉", "items": [...] },
{ "type": "SKILL", "typeName": "技能", "items": [...] },
{ "type": "INFO", "typeName": "信息", "items": [...] },
{ "type": "PLACE", "typeName": "场所", "items": [...] }
]
}
}
价值分算法(/api/pearl/interaction/add 后自动重算):
priority=1(高/大珍珠)→ valueScore≥70,priority=2(中)→ 40-69,priority=3(低/小珍珠)→ <40/api/ability/map 响应结构: data 为数组,元素结构同 SKILL 组 items(contactId/name/avatar/relationshipType/skillCount/skills/lastHelpedAt)。
珍珠图前端组件: PearlDiagram.vue(Canvas 2D,两层同心圆,内圈 radiusPct=0.28 / 外圈 0.55,珍珠半径按 priority/valueScore 映射 8-26px)。
珍珠图定时提醒: PearlReminderScheduledTask 每日 08:00 执行,遍历 connection_type 非空资源,daysSinceLast ≥ suggestIntervalMonth×30 时生成 PENDING 提醒。
珍珠图交互流程: 打开页 → 加载 resources → 渲染两层同心圆 → 点击珍珠弹窗(联系/优先级/删除)→ 记录互动 → 重算价值分 → 逾期角标红点。
/api/pearl/interaction/add 请求体: { "itemId": 1, "interactionType": "WECHAT", "content": "咨询过敏问题" }
interactionType 取值:PHONE / WECHAT / MEETING / OTHER。
/api/pearl/item/update-priority 请求体: { "itemId": 1, "priority": 1 }(1=高/大珍珠,2=中,3=低/小珍珠)。
珍珠图前端页面:
pages/action-detail/index.vue(内嵌 PearlDiagram.vue 组件)pages/action-detail/pearl-add-resource.vue(25 类类型分组选择器)pages/pearl-reminders/index.vue(PENDING 提醒列表)前端 API(utils/api.js):
getPearlResources()getConnectionTypes()addPearlResource(data) (data.connectionType 必填)deletePearlResource(data)addPearlInteraction(data)getPearlInteractionList(data)getPearlReminders()updatePearlPriority(data)已记录珍珠图/能力图 API 端点 — 禁止重复注册。
/api/octopus/*)替代旧章鱼图(help_logs)。核心:成效记录 → 关键人画像 → 高频词分析 → 拓展方向。
| 路径 | 说明 |
|---|---|
POST /api/octopus/tentacles |
⚠️ 已废弃(410) 旧章鱼图:触手榜 |
POST /api/octopus/add |
⚠️ 已废弃(410) 旧章鱼图:新增帮助记录 |
POST /api/octopus/delete |
⚠️ 已废弃(410) 旧章鱼图:删除帮助记录 |
POST /api/octopus/records |
⚠️ 已废弃(410) 旧章鱼图:帮助记录明细 |
POST /api/octopus/effect/list |
成效记录分页列表(支持 effect_type 筛选) |
POST /api/octopus/effect/add |
新增成效(member_order_id + effect_type bitmask + amount + desc) |
POST /api/octopus/effect/delete |
删除成效(级联关系) |
POST /api/octopus/key-person/add |
新增关键人(姓名/单位/部门/职务/初识场合/如何认识) |
POST /api/octopus/key-person/update |
修改关键人画像 |
POST /api/octopus/key-person/delete |
删除关键人(级联关系) |
POST /api/octopus/effect/key-persons |
某成效的关键人列表 |
POST /api/octopus/analysis/keywords |
高频词统计(单位/部门/职务/场合/路径) |
POST /api/octopus/analysis/summary |
高频词提炼 ≤8 个拓展方向 |
POST /api/octopus/expansion/suggest |
基于分析推荐关键人画像模板(预填) |
已记录关键人拓展 API 端点 — 禁止重复注册。
| 路径 | 说明 |
|---|---|
POST /api/doa/stage/create |
创建阶段(memberId?+title+durationWeeks+goals[1-3]) |
POST /api/doa/overview |
家庭总览:各成员当前 active 阶段 |
POST /api/doa/stage/detail |
阶段详情:stage + goals + weeks |
POST /api/doa/stage/cancel |
取消阶段(仅 active 可取消) |
POST /api/doa/week/plan |
提交周计划(A表周行动宣告) |
POST /api/doa/week/review |
提交周复盘(B表五问) |
POST /api/doa/week/list |
周记录列表(按阶段查周记录) |
已记录 DOA 个人目标 API 端点 — 禁止重复注册。
| 路径 | 说明 |
|---|---|
POST /api/guide/popup/list |
查询当前用户应展示的激活弹窗列表 |
POST /api/guide/popup/trigger |
上报触发行为,返回匹配弹窗 |
POST /api/guide/popup/consume |
消费弹窗(点击/关闭上报,防止重复弹出) |
POST /api/admin/guide/popup/list |
管理端:列表(分页筛选 status/slug) |
POST /api/admin/guide/popup/create |
管理端:创建弹窗(含触发条件+步骤) |
POST /api/admin/guide/popup/update |
管理端:更新弹窗(全量覆盖步骤和条件) |
POST /api/admin/guide/popup/status |
管理端:启用/禁用(toggle) |
POST /api/admin/guide/popup/delete |
管理端:软删除 |
POST /api/admin/guide/popup/stats |
管理端:数据看板(曝光/点击/完成率/分时段趋势) |
设计文档:
docs/superpowers/specs/2026-09-22-guide-popup-config-design.md实施计划:
docs/superpowers/plans/2026-09-22-guide-popup-config.md说明:本功能将小程序弹窗引导页从硬编码改为配置化管理,支持管理员在后台配置弹出条件与内容。旧方案(sys_config onboarding_guide_config)保留,新方案通过 4 张新表 + 9 接口实现。
| Controller | 废弃接口 | 替代方案 | 当前状态 | 清理条件 |
|---|---|---|---|---|
| ------------ | ---------- | ---------- | ---------- | ---------- |
FamilyController |
/invite-code, /invite-code/generate |
/api/family/invite/generate |
@Deprecated + 410 ✓ | 确认前端无调用 |
FamilyUserController |
/switch-mode, /switch-to-child |
/api/family/member/switch |
@Deprecated + 410 ✓ | 确认前端无调用 |
FamilyUserController |
/switch-back-to-parent, /switch-back-verify |
/api/family/member/switch |
已修复:@Deprecated + 410 | 确认前端无调用 |
ButlerController |
/service-records, /commissions |
— | @Deprecated + 410 ✓ | 可删除 |
TeacherController |
全部 /api/teacher/* 方法 |
/api/guide/families/* |
@Deprecated + UnsupportedOperationException | 确认规划师端无调用 |
DanAssessmentController |
/current |
— | 需验证 | 无前端调用方 |
NoticeController |
GET /list(违反 POST 规范) |
/api/admin/notices/list |
已修复:@Deprecated + 410 | 可删除 |
OctopusController |
/tentacles, /add, /delete, /records |
/api/octopus/effect/*, /api/octopus/key-person/* |
@Deprecated + 410 ✓(2026-09-10 替换为关键人拓展) | 确认前端无调用(旧页面已删除) |
/api/mind/emotion/*)基于 DeepFace 的人脸情绪识别,通过 LangGraph /api/v1/emotion/recognize 调用。
| 路径 | 说明 |
|---|---|
POST /api/mind/emotion/analyze |
上传照片进行情绪识别(multipart 文件) |
POST /api/mind/emotion/analyze-url |
通过 URL 进行情绪识别(兼容旧调用方) |
POST /api/mind/emotion/analyze
请求:multipart/form-data,字段 file(JPEG/PNG,最大 10MB)
返回:
{
"code": 200,
"data": {
"dominant_emotion": "happy",
"dominant_label_zh": "开心",
"emotions": [
{ "emotion": "happy", "confidence": 0.85 },
{ "emotion": "neutral", "confidence": 0.10 },
{ "emotion": "sad", "confidence": 0.03 },
{ "emotion": "surprise", "confidence": 0.01 },
{ "emotion": "angry", "confidence": 0.005 },
{ "emotion": "fear", "confidence": 0.003 },
{ "emotion": "disgust", "confidence": 0.002 }
],
"all_emotions": {
"happy": 0.85,
"neutral": 0.10,
"sad": 0.03,
"surprise": 0.01,
"angry": 0.005,
"fear": 0.003,
"disgust": 0.002
}
}
}
POST /api/mind/emotion/analyze-url
请求体:
{ "image_url": "https://cdn.example.com/photo.jpg" }
返回:同上。
/api/membership/gift-membership-progress)家庭维度累计「赠会员商品」原价实付金额,达到阈值后自动赠送会员。
| 路径 | 说明 |
|---|---|
POST /api/membership/gift-membership-progress |
获取当前家庭的赠会员累计进度 |
POST /api/membership/gift-membership-progress
请求:无(familyId 由 JWT userId 反查)
返回:
{
"code": 200,
"data": {
"familyId": 12,
"accumulatedAmount": 158000,
"granted": 0,
"grantedLevel": null,
"grantedOrderNo": null,
"grantedAt": null,
"threshold": 198000,
"remaining": 40000
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
accumulatedAmount |
Integer | 累计赠会员商品原价金额(分),仅统计无积分/无券/无折扣的实付订单 |
granted |
Integer | 1=已赠送 0=未赠送 |
grantedLevel |
String | 已赠送的会员等级(当前全局配置默认 FAMILY) |
threshold |
Integer | 阈值(分),由 sys_config.gift_membership_threshold 动态填入 |
remaining |
Integer | 还差多少达标(分)= max(0, threshold - accumulatedAmount),已达标为 0 |
注意:
threshold、remaining为@TableField(exist = false)非数据库列,仅接口返回用。 无家庭时:接口返回空对象,threshold/remaining/accumulatedAmount均为null(此时不存在赠会员累计口径),前端据此隐藏进度条。 阈值单位为分(1980 元 = 198000 分),实际生效值以sys_config表中gift_membership_threshold为准(insertSysConfigSeed仅在缺失时插入,不覆盖已有配置)。
/api/service-role/*)多角色(规划师/营养师/管家/供应商/内容管理员/活动策划)统一申请入口,一次提交可含多个角色,管理端审批通过后回写 users.roles 并按角色初始化附属记录。
| 路径 | 说明 |
|---|---|
POST /api/service-role/apply |
提交服务角色申请(roles 必填) |
POST /api/service-role/my-apply |
查询我的最新申请记录 |
POST /api/service-role/upload-image |
上传身份证/资质证书图片(multipart,字段名 file) |
POST /api/service-role/admin/list |
管理端:申请列表(status 查询参数,默认 0) |
POST /api/service-role/admin/approve |
管理端:批准({ id }) |
POST /api/service-role/admin/reject |
管理端:驳回({ id, reason }) |
权限:
admin/list、admin/approve、admin/reject三个端点校验@RequestAttribute("role"),仅role=admin或role=operator可访问(与AdminHealthPlanController审核类端点口径一致),其他角色返回「无权限」。前端菜单由perm: 'audit:service-role'控制。
状态语义(service_role_applications.status)
| 值 | 含义 |
|---|---|
0 |
待审核(同一 userId 仅允许一条待审,重复提交返回「您已提交过申请,请等待审核」) |
1 |
已通过 |
2 |
已驳回(原因存 reject_reason) |
POST /api/service-role/apply 请求体(ServiceRoleApplyDTO)
| 字段 | 类型 | 说明 |
|---|---|---|
roles |
List<String> | 申请角色,@NotEmpty 至少一个 |
idCard |
String | 身份证号 |
idCardImages |
List<String> | 身份证图片 URL 数组(落库转 JSON 字符串) |
certificateImages |
List<String> | 资质证书图片 URL 数组 |
province / city / district / street |
String | 四级地址 |
addressDetail |
String | 详细地址 |
审批通过后的角色落地规则(ServiceRoleApplicationServiceImpl.approve)
| 申请角色 | 副作用 |
|---|---|
planner |
guides 新增一行(status=active)+ users.roles 追加 teacher |
nutritionist |
users.nutritionist_status=approved + roles 追加 nutritionist |
butler |
users.butler_status=approved + butler_profiles 新增一行 + roles 追加 butler |
vendor |
users.vendor_status=approved + roles 追加 supplier |
article_admin |
users.article_admin_status=approved + roles 追加 knowledge_admin |
activity_provider |
users.activity_provider_status=approved + roles 追加 activity_manager |
注意:approve/reject 仅对
status=0的记录生效,已处理返回「该申请已处理」。upload-image对图片类型文件先走wechatService.checkImage()内容安全检测,未通过直接拒绝。
POST /api/guide/families/unbind)| 路径 | 说明 |
|---|---|
POST /api/guide/families/unbind |
规划师解除自己名下的家庭绑定(请求体 { id },即 guide_families.id) |
role=teacher 可调用,否则返回 Access denied。GuideFamilyService.unbindByGuide() 按 id + guide_id + status='binding' 定位,只能解除属于自己的绑定。guide_families.status 置为 cancelled。POST /api/bind/unbind(按 familyId 定位,并通知规划师)。注意:前端
unbindFamily(id)需传guide_families.id(绑定记录 ID),不是familyId。
/api/health/plan/pending-review/*)| 路径 | 说明 |
|---|---|
POST /api/health/plan/pending-review/list |
待审核方案列表(teacher 取当前登录人;admin 可传 teacherId 过滤,不传则返回该家庭全部) |
POST /api/health/plan/pending-review/update |
编辑方案内容(仅 status 为 draft/pending_review 允许) |
POST /api/health/plan/pending-review/approve |
审核通过并发布 |
POST /api/health/plan/pending-review/reject |
驳回 |
role=teacher 或 role=admin,且必须携带 familyId,否则返回 familyId不能为空。listPendingReviewPlans() 在 teacherId 非空时按 (teacher_id = ? OR teacher_id IS NULL) 过滤 —— 规划师既能看到分配给自己的方案,也能看到本家庭内尚未指定规划师的方案(health_plans.teacher_id 为 NULL),避免用户未选规划师时保存的 pending_review 方案成为无人可见的孤儿记录。status IN ('draft','pending_review'),按 created_at 倒序。注意:
health_plans.teacher_id列由迁移 251 建立(DatabaseInitializer),schema.sql已同步。 前端getPendingReviewPlans()(utils/api.js)目前尚无页面消费,规划师审核页未接通;新审核工作台改用4.47的plans/pending端点,本节 4 个端点保留但不再被前端调用。⚠️ 2026-10-04:
/pending-review/approve响应由Result<HealthPlan>改为Result<PlanApproveResultDTO>(新增taskGenerated/taskCount/message字段)。该端点无前端调用点(health-plan-summary.vue仅有未调用的死导入),变更安全。✅ 2026-10-04:
/{familyId}/overview、/{familyId}/children/{memberId}/tasks、/{familyId}/children/{memberId}/pending-review、/{familyId}/tasks/{taskId}/review、/{familyId}/tasks/batch-review、/{familyId}/tasks/{taskId}、/{familyId}/tasks/{taskId}/delete共 7 个端点已接入guide_families绑定校验,修复跨家庭越权。
/api/guide/families/*)规划师侧审核工作台的统一入口,授权源为 guide_families.status='binding'(与 GuideFamilyService.isBound(guideId, familyId) 同源),不使用 users.teacher_family_ids。
| 端点 | 权限 |
|---|---|
POST /api/guide/families/my-families |
teacher / admin |
POST /api/guide/families/{familyId}/members |
teacher 需 isBound;admin 放行 |
POST /api/guide/families/{familyId}/plans/pending |
teacher 需 isBound;admin 可传 teacherId 过滤 |
POST /api/guide/families/{familyId}/plans/{planId}/update |
同上 + planId IDOR 反查 |
POST /api/guide/families/{familyId}/plans/{planId}/approve |
同上 + planId IDOR 反查;返回 PlanApproveResultDTO |
POST /api/guide/families/{familyId}/plans/{planId}/reject |
同上 + planId IDOR 反查 |
my-families 不走 checkFamilyAccess(role, userId, null) —— 该路径下 familyId == null 会把 teacher 直接拒掉,故改为显式角色判断 + 按 guide_id 查本人绑定家庭,返回体含 familyName(取自 Family.name,注意字段名不是 familyName)。members 返回该家庭可审核成员,供工作台「成员」选择器使用。plans/pending 复用 listPendingReviewPlans(),teacherId 非空时按 (teacher_id = ? OR teacher_id IS NULL) 过滤;teacher 无需传该参数,admin 可显式传以过滤。{planId} 类端点先 checkFamilyAccess(role, userId, familyId),再用 getPlanForFamily(planId, familyId) 按 familyId 反查,返回 null 即 403。控制器内 resolvePlan 的第二次 recheck 仅为纵深防御,getPlanForFamily 已按 familyId 过滤,该 recheck 永不单独拦截请求,不可依赖它替代首道校验。approve 返回 PlanApproveResultDTO:planId / status / taskGenerated / taskCount / message。任务生成器 generateDailyTasksFromPlan 返回 void,故实现改为生成后按 source_type='health_plan' AND source_id=planId 统计实际条数;生成异常或计数为 0 时方案仍发布并返回 taskGenerated=false,属部分成功,前端须与失败区分提示。注意:配套前端为
pages/teacher/review-workbench.vue、review-family.vue、plan-detail.vue,入口在pages/teacher/families.vue。
/api/guide/messages/*)家长(家庭主账号)与成长规划师之间的咨询消息接口。
| 端点 | 权限 | 说明 |
|---|---|---|
POST /api/guide/messages/send |
家长(需 familyId) |
发送咨询,请求体 { teacherId, content } |
POST /api/guide/messages/{messageId}/reply |
仅 role=teacher + 认证闸门 |
规划师回复,请求体 { replyContent } |
POST /api/guide/messages/list |
仅 role=teacher |
规划师获取咨询列表(分页 { page, size }),响应条目在 content 尾部追加 [家庭主账号:<昵称>] |
POST /api/guide/messages/unread-count |
仅 role=teacher |
规划师未读消息数 |
POST /api/guide/messages/my |
家长(按自身 parentId 查询,无 role 限制) |
家庭主账号获取自己的咨询记录,响应 TeacherMessage 列表 |
POST /api/guide/messages/my:家庭主账号获取自己的咨询记录。响应 TeacherMessage 列表,每条含 teacherName(规划师昵称,按 teacherId 从 users 表回填,查不到时留空由前端兜底「规划师」)。不新增路由、不改鉴权(/my 无 role 限制,按 parentId 查自己的记录)。文档更新:2026-11-01(
/my新增teacherName回显,见specs/2026-11-01-home-greet-shortcut-and-my-messages-design.md)。
/api/indicator/* + /api/admin/indicator/*)指标变化曲线 / 指标速查 / 指标关联的统一读接口与管理端接口。读接口 subjectId 必填且做家庭归属校验(family_members.id = subjectId AND family_id = 当前用户家庭,由 JwtInterceptor 注入 @RequestAttribute("familyId"));管理端接口校验 @RequestAttribute("role"),仅 role=admin 可访问,否则「无权操作」。
视图接口(IndicatorController,/api/indicator)
| 端点 | 请求要点 | 用途 |
|---|---|---|
POST /api/indicator/trend |
{subjectId, definitionIds:[...]} |
指标曲线(按 definitionId 分组、report_date 升序点序列) |
POST /api/indicator/change-ranking |
{subjectId, reportType?, category?, scope:adjacent\|first-vs-latest, orderBy:up\|down\|magnitude, limit} |
变化幅度排名(含 overall.improvedCount/worsenedCount/flatCount 汇总) |
POST /api/indicator/quick-lookup |
{subjectId, category?, page, pageSize} |
指标速查(分类分页 + 类别汇总 + dimensionScores 五/七维评分小节) |
POST /api/indicator/correlation/list |
{subjectId, definitionId} |
指标关联查询(含 subjectEvidence 成员级配对证据) |
管理端接口(/api/admin/indicator/correlation/*、/api/admin/indicator/mapping/*)
| 端点 | 请求要点 | 用途 |
|---|---|---|
POST /api/admin/indicator/correlation/save |
{definitionIdA, definitionIdB, direction, manualStrength, description, manualLocked, sourceNote} |
关联对定义/编辑(写入前按 indicator_definitions.code 字典序强制对序,保证唯一键对称) |
POST /api/admin/indicator/correlation/list |
{page, size} |
关联对分页(按 updated_at 倒序,含校准状态) |
POST /api/admin/indicator/correlation/calibrate |
{pairId?} |
手动触发校准(返回「校准完成,共更新 N 对」) |
POST /api/admin/indicator/mapping/import |
{sourceType, seeds:[{rawName, definitionId?}]} |
映射种子批量导入(返回「导入完成,共 N 条」) |
POST /api/admin/indicator/mapping/list |
{page, size, status?, sourceType?} |
映射规则分页/review(status=0 为 ai_fallback 待确认) |
关联校准:
save时effective_strength = manual_strength;每日 03:00IndicatorCalibrationJob(@Scheduled(cron = "0 0 3 * * ?"))对status=active且manual_locked=0的关联对按 subject 分组做 Spearman + Fisher z 聚合,有效样本>=30才用computed_strength覆盖manual_strength。correlation/calibrate手动触发同一逻辑(pairId传入时仍走全量逐对幂等)。 统一指标层写入(单一写者):报告入库 / 报告编辑 / 食材推荐刷新三处流程由NormalizeIndicatorPipeline幂等写入indicator_values(唯一键source_type + source_id + definition_id,upsertMappingON DUPLICATE KEY)。本层读接口只读indicator_values,不写时序;五维/七维评分在速查接口按原表 join,不进时序。 关联表:indicator_correlations(迁移 360)、indicator_mapping_rules(迁移 359)。
文档更新:2026-10-09(指标统一层新增,见 specs/2026-10-09-indicator-change-curve-design.md)
⚠️
/api/health/indicator/list已被取代:老接口返回裸List<HealthIndicator>(无上一期对照、无 summary)。新接口/api/health/report/indicators返回同一批指标 +previous/change/summary五档形态数据。/api/health/indicator/list保留不动(cfc-webviews/nutritionist/HealthIndicators.vue仍在调),新接入一律走/api/health/report/indicators。
/api/health/report/indicators、/api/indicator/periods、/api/admin/indicator/backfill)本节为 §4.48 指标统一层的多期展示增量。所有
change计算统一由IndicatorChangeService.computeChange单点产出(trendCode 五档:improved/worsened/flat/first_record/pending_backfill),读路径一律过滤indicator_definitions.status=1,拿不到 active definition 的观测直接剔除,不降级为「指标」+id 假名称(QP17)。
① POST /api/health/report/indicators — 报告指标明细(含上一期对照,D12 报告详情页接入点)
| 端点 | 权限 | 请求 | 返回 |
|---|---|---|---|
POST /api/health/report/indicators |
登录(JWT;管理员/本人/被授权成员,校验逻辑同 /api/health/report/detail) |
{reportId, withPrevious?} |
{reportId, reportType, subjectId, reportDate, dateSource, olderReportCount, summary, items} |
reportId(必填);withPrevious(选填,默认 true,false 时跳过 previous/change 计算,供编辑模式快速返回单期)。subjectId 的报告(历史未绑定成员)仅本人上传者或家庭管理员可见;有 subjectId 时走 ReportMemberPermissionService.canViewMemberReports。indicatorId/definitionId/category/indicatorName/indicatorValue/numericValue/unit/refRange/status)+ 字典字段(goodDirection/valueType)+ previous(上一期观测,无则 null)+ change({delta, deltaPct, movement, trendLabel, trendCode, skipGaps, unitMismatch, comparable},首期时为 first_record,报告日期未知时为 pending_backfill)。totalCount / abnormalCount(status 非「正常」)/ abnormalDelta(预留字段,当前固定 0,单报告视角无法直接算)/ changedCount(trendCode 为 improved/worsened 的条数)/ comparableCount / firstRecordCount / pendingCount / dataIncomplete(存在 pending_backfill 时为 true,驱动残缺横幅组件)。withPrevious=false:返回单期 items(每项含 indicatorId/category/indicatorName/indicatorValue/unit/refRange/status,不含 definitionId/previous/change/goodDirection/valueType)。olderReportCount:该成员在本报告之前(同 sourceType)的历史报告数,用于 first_record 档区分「真的首期」与「更早报告未回填」。IndicatorMappingService.resolveBatch 用 indicator_mapping_rules JOIN indicator_definitions 单查询批量解析,严禁逐指标查库。② POST /api/indicator/periods — 期次列表(双期对比页 picker 数据源)
| 端点 | 权限 | 请求 | 返回 |
|---|---|---|---|
POST /api/indicator/periods |
登录(JWT;subjectId 须属于当前家庭) |
{subjectId, sourceType?} |
{subjectId, sourceType, items} |
{reportDate, reportId, dateSource, indicatorCount},按 reportDate 倒序;reportDate=null(日期未知期)恒定排最后,picker 显示「日期未知」。unknown < confirm < upload < real),诚实口径——只要有一项来源是上传推断,整期就标 upload。value 非空)的指标数,picker 显示「2026-10-08(42 项)」。③ POST /api/admin/indicator/backfill — 存量时序回填(admin)
| 端点 | 权限 | 请求 | 返回 |
|---|---|---|---|
POST /api/admin/indicator/backfill |
admin(@RequestAttribute("role") 校验,非 admin 返回「权限不足」) |
{subjectId?, reportId?, limit?, dryRun?, fixReportDates?} |
{scanned, eligible, written, skippedNoSubject, skippedNoPayload, failed, dryRun, fixReportDates, dateFixable, dateFixed, details[]} |
indicator_values(P0-3 数据面补全),并可顺带用 ReportDateExtractor 修复被 new Date() 污染的历史报告日期。subjectId(选填,指定成员;不传扫全部 status=active 报告);reportId(选填,只回填指定报告,灰度验证用);limit(选填,默认 200,上限 500);dryRun(默认 true);fixReportDates(默认 false)。dryRun=true:预演只统计不写入,返回 eligible/dateFixable 计数,且不触发 mappingService.resolve(避免惰性建定义这类副作用);首次执行必须 dryRun,核对无误后传 false。indicator_values 再修就晚了)。日期修复判定条件:能提取到真实日期 且 report_date != extracted 且 report_date >= created_at 当天(new Date() 污染特征签名);修后需连带 refreshMemberIndicatorCurrent。NormalizeIndicatorPipeline 按唯一键 source_type + source_id + definition_id upsert,已覆盖报告返回 already_covered,重复执行不产生重复时序。④ 升级改造的既有端点(IndicatorController)
| 端点 | 变更 |
|---|---|
POST /api/indicator/trend |
新增可选入参 {sourceType, fromDate, toDate, granularity: raw\|month, sourceKind: all\|report\|device};出参新增 refLow/refHigh/goodDirection/valueType/pointsCount/totalReportCount/olderReportCount/chartMode/unitMismatch/latest/change/points/missingPeriods。破坏性:无 |
POST /api/indicator/change-ranking |
新增可选入参 {scope: pair, fromReportDate, toReportDate, filter: improved\|worsened\|flat\|incomparable\|all, page, pageSize};scope=pair 缺 fromReportDate/toReportDate 返回明确错误;magnitude 排序口径从 \|Δ\| 改为 \|Δ%\| 降序(视觉有变化,属预期修正,见 §4.48 变更汇总);deltaPct=null 的项恒定排最后且不参与 improved/worsened 筛选(Q14)。破坏性:无 |
POST /api/indicator/quick-lookup |
新增可选入参 {withSparkline, sparkLimit};出参每项新增 previous/change/latestDateSource/latestReportId/goodDirection/valueType/sparkline;修复 reportDate=null 观测被当作最新值的 bug。破坏性:无 |
POST /api/indicator/source-types |
出参新增 periodCount / latestReportDate(曲线页类型筛选用,原只返回类型名)。破坏性:无 |
chartMode判定表(后端单点定义,IndicatorChangeService.chartModeOf):pointsCount=0 → empty;=1 → single;=2 → pair;<20 → line;≥20 → line_aggregated(granularity=month时强制line_aggregated)。 SQL 预算(严禁 N+1,均有单测锁死):/report/indicators42 项指标 → 服务层恒 3 次协作调用(控制器另加 2 次,合计 ≤ 5);/quick-lookup与/source-types均恒 1 次indicator_values查询(上一期与periodCount全部内存计算)。IndicatorService.listDefinitions:status传 null 时默认按status=1过滤(防止 P1-6 自动创建的status=0definition 冒进管理端字典列表,QP17)。missingPeriods:该成员有报告、但本指标无有效值的期次,IndicatorTimelineService固定 2 次查询算完(原 1+缺失期数,会 N+1)。 老接口兼容矩阵见specs/2026-10-25-indicator-timeline-display-design.md§4.7。
文档更新:2026-10-27(指标多期展示 T02 后端接口,见 specs/2026-10-25-indicator-timeline-display-design.md)
/api/indicator/favorite/*)本节为 T04「关注指标收藏」后端化(方案A)增量。收藏从 localStorage(方案B)升级为后端持久化,可跨设备同步、跨端一致。全部
@PostMapping;JWT Bearer鉴权;@Resource注入;userId/familyId由JwtInterceptor注入@RequestAttribute,服务端不信任前端传值。
① POST /api/indicator/favorite/toggle — 收藏/取消(存在则删、不存在则插,幂等于单次调用)
| 端点 | 权限 | 请求 | 返回 |
|---|---|---|---|
POST /api/indicator/favorite/toggle |
登录(JWT;已加入 LOGIN_REQUIRED_PATHS,无 token 直接 401;memberId 须属于当前家庭) |
{memberId, sourceType, definitionId} |
{definitionId, added} |
memberId/definitionId(必填 Long)、sourceType(必填 String,非空)。added=true 本次加入收藏(新插入);added=false 本次取消收藏(已删除)。400(缺参/成员不属家庭/definitionId 非法)、401(未登录)。② POST /api/indicator/favorite/list — 查已收藏集合
| 端点 | 权限 | 请求 | 返回 |
|---|---|---|---|
POST /api/indicator/favorite/list |
登录(JWT;memberId 须属于当前家庭) |
{memberId, sourceType} |
{memberId, sourceType, definitionIds} |
definitionIds:该成员×该报告类型下已收藏的指标定义 ID 列表(升序,按 id);空集合返回 []。user_id = userId AND family_id = familyId AND member_id AND source_type(家庭/用户隔离)。③ POST /api/indicator/favorite/remove — 移除收藏(显式删除)
| 端点 | 权限 | 请求 | 返回 |
|---|---|---|---|
POST /api/indicator/favorite/remove |
登录(JWT;memberId 须属于当前家庭) |
{memberId, sourceType, definitionId} |
{definitionId, removed} |
removed=true:该条收藏已删除(不存在则视作已删除,幂等)。供前端「清空对比/切换成员」等需显式删除而非 toggle 语义的场景使用。文档更新:2026-10-30(T04 指标收藏后端化,见 specs/2026-10-30-indicator-favorite-backend-design.md)
/api/health/plan/delete、/api/admin/health-plan/delete)已生成的健康方案可删除,级联删除其产生的全部任务(含每日实例)。
| 端点 | 权限 | 请求 | 返回 |
|---|---|---|---|
POST /api/health/plan/delete |
登录用户(JWT) | {planId} |
{planId, taskCount} |
POST /api/admin/health-plan/delete |
admin/teacher/butler/nutritionist/operator | {planId} |
{planId, taskCount} |
health_plans 方案行 + tasks 中 source_type='health_plan' AND source_id=planId 的直接任务(周期模板/一次性任务/购买锚点)+ tasks 中 template_id IN 直接任务ID 的每日实例(RepeatTaskGenerator 生成,只透传 template_id 不带 source_id,必须二次删除,否则任务删后次日仍被再生产)。points_log(积分流水,已完成任务的积分保留不撤回)、task_executions / growth_task_log(执行历史)。HealthPlanServiceImpl.deletePlanCascade 标注 @Transactional(rollbackFor = Exception.class),任一步失败整体回滚,不留无方案的孤儿任务。@RequestAttribute("familyId") 取家庭做归属校验,方案不属于该家庭返回「无权删除该方案」;管理端传 familyId=null 跳过归属校验。文档更新:2026-10-17(健康方案级联删除,见 specs/2026-10-17-health-plan-deletion-design.md)
/api/admin/poster-template/* + /api/poster-template/*)Web 管理端定义活动海报模板(迁移381 activity_poster_templates 表),小程序端活动详情页「生成海报」拉取可用模板渲染画布。管理端接口校验 @RequestAttribute("role"),仅 admin/operator 可访问;templateKey 限定 gradient(渐变)/minimal(深色)/card(白底卡片),name 全局唯一。
| 端点 | 权限 | 用途 |
|---|---|---|
POST /api/admin/poster-template/list |
admin/operator | 模板列表(含停用,按 sort_order + id 升序) |
POST /api/admin/poster-template/save |
admin/operator | 新增/更新(body 为实体字段:id/name/templateKey/mainColor/darkColor/lightColor/bgColors/qrSize/sortOrder/status;id 为空为新增;色板须为合法 JSON 数组,空则按主色生成,qrSize 默认 100) |
POST /api/admin/poster-template/delete |
admin/operator | 删除(body: {id}) |
POST /api/poster-template/list |
登录 | 小程序端可用模板(status=1;生成海报场景本身要求登录) |
文档更新:2026-10-17(活动海报模板管理,见 specs/2026-10-17-activity-poster-template-design.md)
/api/membership/compare)购买页(pages/membership/upgrade.vue)与会员中心(pages/membership/index.vue)的权益对比表数据源。全部权益值由后端聚合实际逻辑后返回展示文本,前端不再硬编码权益文案,避免出现「文案说不限量 / 实际 20 个」这类偏差。
| 路径 | 说明 |
|---|---|
POST /api/membership/compare |
返回 {columns, rows},无需请求参数 |
返回值结构
{
"code": 200,
"data": {
"columns": ["FREE", "BASIC", "FAMILY", "PREMIUM"],
"rows": [
{ "name": "商品价格", "free": "普通价格", "basic": "会员价", "family": "会员价", "premium": "会员价" },
{ "name": "家庭成员上限", "free": "1人", "basic": "3人", "family": "6人", "premium": "10人" },
{ "name": "每日任务上限", "free": "5个/日", "basic": "3个/日", "family": "20个/日", "premium": "50个/日" }
]
}
}
行值口径(事实源)
| 权益行 | 数据来源 |
|---|---|
| 商品价格 | FREE=普通价格,BASIC/FAMILY/PREMIUM 统一=会员价。实际结算由 MemberPriceResolver 取 products.member_price,仅按 products.min_discount_level 判定是否达门槛,不存在按等级递增的额外折扣 |
| 家庭成员上限 | membership_levels.max_children(0/空视为无该权益 → —) |
| 每日任务上限 | membership_levels.max_tasks_per_day |
| AI健康顾问 / 报告解读 / 测评预约 / 食材图片解析 | BasicQuotaService.QUOTA_LIMITS 月度配额常量(BASIC 限次)+ canUseFeature 判定(FAMILY/PREMIUM 不限) |
| 优惠券权益 | 普通券面向所有登录用户(discount_purchase feature,BASIC 起可用);会员专享券仅 FAMILY/PREMIUM(CouponService.canUseMemberCoupon) |
| 会员专属活动 | member_activities feature,BASIC 及以下为部分活动 |
| 邀请佣金 / 消费返佣 | referral_commission / purchase_commission feature |
| 专属管家、规划师咨询 | membership_levels.priority_support / teacher_consultation 对应的产品权益设定 |
列口径:仅
FREE/BASIC/FAMILY/PREMIUM四列。LIFETIME为赠送/特殊发放、不可购买,不作为列展示;PROVIDER是服务商角色,不属于会员权益体系(level_order=1与 FREE 同级,features为 NULL),不参与本表。/api/membership/plans同步变更:除LIFETIME外再过滤PROVIDER,并附加maxChildren/maxTasksPerDay两个字段,前端档位卡片可直接引用。
文档更新:2026-10-18(会员权益对比表动态化 + PROVIDER 退出会员权益体系);2026-11-06(「商品折扣」行改为「商品价格」:FREE=普通价格,其余付费档统一=会员价,去除按等级 9折/8折 的表述)
文档最后更新:2026-10-04
/api/fatloss/*)减脂专题(
xiaofat-miniprogram)新增接口,与主系统用户体系共享(JWT 认证,需登录)。 所有接口统一@PostMapping,响应格式Result<T>。
| 端点 | 权限 | 说明 |
|---|---|---|
POST /api/fatloss/weight/list |
登录 | 体重记录列表(params: memberId/startDate/endDate,memberId 优先取 params,fallback currentMemberId) |
POST /api/fatloss/weight/create |
登录 | 创建体重记录(body: memberId/weight/bodyFatPercent/waistCircumference/measureDate/remark) |
POST /api/fatloss/weight/update |
登录 | 更新体重记录(body: id/weight/bodyFatPercent/waistCircumference) |
POST /api/fatloss/weight/delete |
登录 | 删除体重记录(body: id) |
POST /api/fatloss/diet/list |
登录 | 饮食记录列表(params: memberId/startDate/endDate) |
POST /api/fatloss/diet/create |
登录 | 创建饮食记录(body: memberId/mealType/foodName/foodWeight/calories/protein/fat/carbs/eatDate/remark) |
POST /api/fatloss/diet/delete |
登录 | 删除饮食记录(body: id) |
POST /api/fatloss/diet/calories-summary |
登录 | 当日总热量(params: memberId/date,date 默认今日) |
POST /api/fatloss/exercise/list |
登录 | 运动记录列表(params: memberId/startDate/endDate) |
POST /api/fatloss/exercise/create |
登录 | 创建运动记录(body: memberId/exerciseType/durationMin/distanceKm/caloriesBurned/exerciseDate/remark) |
POST /api/fatloss/exercise/delete |
登录 | 删除运动记录(body: id) |
POST /api/fatloss/goal/active |
登录 | 获取当前活跃目标(params: memberId,返回最新 status=active 的目标) |
POST /api/fatloss/goal/create |
登录 | 创建目标(body: memberId/startWeight/targetWeight/targetBodyFat/targetDate/startDate,targetWeight/startWeight/startDate 必填) |
POST /api/fatloss/goal/update |
登录 | 更新目标(body: id/targetWeight/targetBodyFat/targetDate) |
POST /api/fatloss/goal/complete |
登录 | 完成目标(body: id,status → completed) |
POST /api/fatloss/goal/abandon |
登录 | 放弃目标(body: id,status → abandoned) |
新增表: fat_weight_record、fat_diet_record、fat_exercise_record、fat_goal(迁移 355–358,DatabaseInitializer)
文档更新:2026-10-09(减脂专题新增)
设计规格:
specs/2026-10-20-limited-time-special-price-design.md; 新建special_price_deals表(迁移 389)+product_orders.special_deal_id列(迁移 390)。
用户端(公开接口,无需登录)
| 路径 | 说明 |
|---|---|
POST /api/special-price/info |
查询活动详情(白名单,JwtInterceptor 公开路径;userPurchased/userRemaining 恒 0,每人限购由下单接口兜底) |
请求体:{ "dealId": 1 }
响应 data 字段:
{
"id": 1, "productId": 10, "productName": "示例商品",
"name": "开售闪购", "specialPrice": 500, "productPrice": 990,
"startTime": "2026-10-20 12:00:00", "endTime": "2026-10-21 12:00:00",
"totalQuantity": 100, "soldQuantity": 23, "remainingQuantity": 77,
"perUserLimit": 2, "allowCoupon": 0, "runStatus": "ACTIVE",
"userPurchased": 0, "userRemaining": 0
}
runStatus 枚举:ACTIVE(进行中)/NOT_STARTED(未开始)/SOLD_OUT(已售罄)/ENDED(已结束)/DISABLED(已停用)/DRAFT(草稿)/INVALID(活动不存在)。白名单路径不写 request attribute,每人限购由下单接口最终校验。
下单(特价路径)
POST /api/product/order/create 请求体新增 specialDealId(Long,可选)。若 specialDealId != null 走特价下单分支:
status=active、NOW() ∈ [start_time, end_time]、商品一致countByDeal 累计 < perUserLimit)allowCoupon=0 且 couponId 非空 → 拒绝consumeQuota(id, qty)(失败按 runStatus 返回明确原因)insert 订单行 special_deal_id = dealId,unit_price = specialPricecancel(用户取消)、approveRefund(退款完成)、OrderTimeoutCancelTask(超时取消),三处调用 releaseQuota(GREATEST(sold_quantity - qty, 0) 防负)供应商改价拒绝:reviewUpdate 开头若 order.specialDealId != null 直接 Result.error("特价订单不允许修改价格")。
管理端(admin 角色)
| 路径 | 权限 | 说明 |
|---|---|---|
POST /api/admin/special-price/list |
admin | 分页列表(body: {page,size,keyword,runStatus};runStatus 可传 ACTIVE/NOT_STARTED/SOLD_OUT/ENDED 或 draft/disabled,空=全部;响应 data.records[] + data.total) |
POST /api/admin/special-price/create |
admin | 新建(body: {productId,name,specialPrice,startTime,endTime,totalQuantity,perUserLimit,allowCoupon};specialPrice/productPrice/totalQuantity 单位均为分;同商品互斥 active) |
POST /api/admin/special-price/update |
admin | 修改(body 同 create + id;仅 draft/disabled 可修改) |
POST /api/admin/special-price/status |
admin | 启停(body: {id, action};action ∈ {enable, disable};启用时再次校验互斥) |
POST /api/admin/special-price/delete |
admin | 删除(body: {id};已有特价订单时拒绝) |
POST /api/admin/special-price/qrcode |
admin | 生成小程序码(body: {id};scene=id={productId}&sp={dealId},落地页 product-detail;返回 data:{qrCodeBase64, scene, note?};测试模式 note 提示无法生成真实码) |
文档更新:2026-10-20(限时特价/扫码闪购新增)
POST /api/activity/registration-roster)活动详情页「报名情况」区块数据源。面向所有访客(含游客,
/api/**下无需登录),返回脱敏的报名统计与最近已通过报名人,用于社交证明与名额紧迫感展示。姓名经DataMaskUtil.maskName脱敏(如"张小明"→"张某"),不返回手机号。
请求体: { "activityId": 1 }(兼容 id)
响应 data 字段:
{
"activityId": 1,
"maxParticipants": 50,
"approvedCount": 12,
"pendingCount": 3,
"remaining": 38,
"registrants": [
{ "name": "张某", "registeredAt": "2026-10-22T10:00:00" }
]
}
| 字段 | 说明 |
|---|---|
maxParticipants |
人数上限(0 = 不限制) |
approvedCount |
已通过报名人数 |
pendingCount |
待审核报名人数 |
remaining |
剩余名额 = max - approved(不限制时为 null,下限 0) |
registrants |
最多 20 条已通过报名人(按报名时间倒序,姓名脱敏) |
前端使用:activity-detail.vue 加载详情后并行拉取;报名成功/取消报名后重新拉取。区块仅当 activity.requireRegistration === 1 时展示,含统计列、进度条(限人数时)与最近报名人列表。
文档更新:2026-10-22(活动详情页新增报名情况)
以下接口在 2026-10-23 的 T15/T16/T17 任务链路中新增或变更,此前未在本文档登记,此处统一补录。
ActivityController,前缀 /api/activity)| 路径 | 说明 |
|---|---|
POST /api/activity/register |
活动报名(body: activityId;批量报名历史字段 registrants)。活动 requireReview=1(默认免审)→ 报名记录为 pending 不占名额;免审即 approved 并原子占用名额 |
ActivityController)| 路径 | 说明 |
|---|---|
POST /api/activity/checkin |
活动签到(body: activityId)。活动级 requireCheckinReview=1 时签到进入 pending_review,审核通过才发奖励;免审直接发放 |
POST /api/activity/checkin-review |
签到审核(仅活动管理员/平台管理员)。通过发放积分/能量/CF,驳回不发放 |
AdminActivityCheckinController,前缀 /api/admin/activity-checkins)| 路径 | 说明 |
|---|---|
POST /api/admin/activity-checkins/list |
按活动分页查询签到记录 |
POST /api/admin/activity-checkins/add |
手动补录签到(幂等,桥接触发课时入账) |
POST /api/admin/activity-checkins/review |
修改签到审核状态(通过发放课时/奖励) |
与规划师课时桥接:签到审核通过会触发课时发放,与 AdminPlannerOfflineCourseController 的活动↔类别映射联动(见第五章)。
RelationshipQuestionnaireController,前缀 /api/family/questionnaire)| 路径 | 说明 |
|---|---|
POST /api/family/questionnaire/generate |
AI 生成关系问卷快照(body: memberId;respondentId 由后端按登录用户覆盖,校验调用人与目标成员同家庭),返回题目集与 snapshotId |
POST /api/family/questionnaire/submit |
提交答卷(body: snapshotId + 答案),写入响应记录 |
POST /api/family/questionnaire/snapshot/{memberId} |
查询某成员当前快照 |
POST /api/family/questionnaire/history/{memberId} |
某成员问卷历史提交记录 |
POST /api/activity/registration-roster 的 approvedCount 现直接读 activities.approved_count(迁移回填),不再实时统计;剩余名额 = max - approved,下单/退款链路(register/cancel/OrderTimeoutCancelTask)通过原子 SQL 维护该计数,防超卖。
ReviewCenterController 的 guidePending / nutritionistPending 统计新增 real_name IS NOT NULL 过滤,与列表接口口径一致(commit f61547a21);前端 ArticleAudit.vue 驳回原因字段由 row.reason 修正为 row.rejectReason。
文档更新:2026-10-23(T15/T16/T17 回归补登记:活动报名、签到与签到审核、管理端签到、家庭关系问卷、名册口径、审核中心统计口径)
ActivityTeamController,前缀 /api/activity/team)—— T35T35 规格 §2.2/§5:新增「活动管理团队」类型,
activities.team_id关联activity_team;团队成员可协作运营团队名下活动,复用服务指派机制(service_type=ACTIVITY_SUPPORT,见 T34)。团队数据独立于 supply_system(供应体系),避免活动运营人员误入商品分销同体系判定。
权限规则:
| 路径 | 说明 |
|---|---|
POST /api/activity/team/create |
创建活动团队(body: {name, description?},管理员可指定 ownerId;普通用户以自己 userId 建团,自动成为团长 owner) |
POST /api/activity/team/list |
我的团队列表(管理员返回全部;普通用户返回在团团队),含 id/name/description/ownerId/status |
POST /api/activity/team/detail |
团队详情(body: {teamId}),返回 team + members |
POST /api/activity/team/member/list |
团队成员列表(body: {teamId}) |
POST /api/activity/team/member/add |
添加成员(body: {teamId, userId, role?},role 可选:owner/manager/operator,默认 operator;幂等:已在团则更新角色) |
POST /api/activity/team/member/remove |
移出成员(body: {teamId, userId},团长不可被移出;移出时级联撤销该成员在团内的 ACTIVITY_SUPPORT 指派) |
POST /api/activity/team/assign |
服务指派(ACTIVITY_SUPPORT,body: {teamId, targetType, targetId, assigneeId, role, remark?},targetType: ACTIVITY/ACTIVITY_TEAM,role: lead/support/checkin/content;被指派人须为团队在团成员) |
POST /api/activity/team/assign/list |
服务指派列表(body: {teamId, targetType?, targetId?}) |
POST /api/activity/team/assign/revoke |
撤销服务指派(body: {id, teamId?}) |
POST /api/activity/team/activities |
团队名下活动列表(body: {teamId}) |
ActivityController 权限扩展(T35 协作判定):
/api/activity/create:团队活动(teamId 非空)须由团队在团成员创建;/api/activity/update:团队活动的编辑权限扩展到团队在团成员 + 该活动(或其团队)的 ACTIVITY_SUPPORT 被指派人。文档更新:2026-11-01(T35 活动管理团队:活动团队创建/成员管理/服务指派、ActivityController 协作权限扩展)
平台角色(admin/operator/finance)可管理所有组织并查看全量统计;组织管理员(users.roles 含 org_admin)登录管理端后默认跳转自身组织统计大屏,仅能访问本组织数据。实现方案见规格 docs/superpowers/specs/2026-10-22-org-admin-management-design.md。
数据模型:
organizations:组织主表(name/type/code/admin_userid/contact*/description/status)org_members:组织成员关联表(org_id/user_id/member_type/role_in_org/status),唯一键 (org_id, user_id)权限规则:
org_admin → 仅能访问自身组织(organizations.admin_user_id = userId 且 status='active'),返回 403「无权访问该组织」/「组织已停用」/api/admin/auth/login 流(AdminRoles.RESIDENT_ROLES 新增 org_admin)@PostMapping)| 路径 | 说明 |
|---|---|
/api/admin/org/list |
组织列表(分页/筛选;org_admin 只返回自己组织) |
/api/admin/org/create |
创建组织(同步创建管理员账号;仅平台角色) |
/api/admin/org/update |
更新组织信息 |
/api/admin/org/disable |
停用/启用组织(仅平台角色) |
/api/admin/org/detail |
组织详情 |
/api/admin/org/my-org |
组织管理员获取自身组织(登录跳转目标) |
/api/admin/org/user/search |
按手机号/昵称搜索平台用户(添加成员下拉选人) |
/api/admin/org/member/list |
成员列表(含家庭数/订单数/消费额摘要) |
/api/admin/org/member/add |
添加成员(软删成员复活为 active 并更新类型) |
/api/admin/org/member/remove |
移除成员(软删 status=inactive) |
/api/admin/org/member/change-type |
变更成员类型(planner ↔ user,复活 inactive) |
/api/admin/org/stats/overview |
总览卡片(成员/规划师/家庭/订单/消费) |
/api/admin/org/stats/families |
家庭维度(活跃家庭/任务完成率/打卡率) |
/api/admin/org/stats/active |
活跃度趋势(任务完成/打卡/报告上传,按天) |
/api/admin/org/stats/revenue |
营收(订单金额/会员订阅/佣金,按天) |
/api/admin/org/stats/trend |
趋势图(活跃成员数/订单数/收入,按天) |
请求参数: 成员/统计接口统一从 body 取 orgId;stats 可选 startDate/endDate(yyyy-MM-dd,默认近 30 天)。
统计口径:
org_members 中 status='active' 的 user_id 集合families.creator_id IN (成员userId) 去重计数product_orders.buyer_id IN (成员userId) AND status IN ('PAID','COMPLETED')total_amount 求和(单位分)health_checkins.user_id + daily_checkin(经 family_members.user_id 关联)+ emotion_checkindan_report_uploads.uploader_user_idcommission_records.referrer_id(受益人)commission_amount 求和member_subscription_order.status='paid'前端入口: cfc-web 新增 /org 路由四页面(List/Form/Detail/Dashboard);菜单「组织管理」挂在系统配置分组下。组织管理员登录后自动跳 /org/:id/dashboard,不展示组织列表页。
文档更新:2026-10-22(组织管理功能上线)
/api/planner/*, /api/admin/planner-*, /api/xiaoe/*)设计文档:
docs/superpowers/specs/2026-10-22-planner-learning-assessment-gate-design.md核心链路:身份审核通过 → Guide.status=pending_cert + 按类别初始化planner_certifications→ 线上课时(小鹅通 webhook/手动同步)+ 线下课时(activities 打卡桥接)→ 考核通过 → 类别certified(基础类别 planner 通过时同步翻Guide.status=active)→ 接单闸门放行。
/api/planner/*)| 路径 | 说明 |
|---|---|
POST /api/planner/certification/my |
我的全部类别认证状态(线上/线下课时拆分、考核分、证书号、是否可考) |
POST /api/planner/courses |
某类别线上课程列表(含小鹅通跳转/H5 链接;body: categoryCode) |
POST /api/planner/training-activities |
可报名/签到的培训活动列表(复用 activities,过滤映射表+规划师可见) |
POST /api/planner/training-activities/check-in |
扫码/手动签到(body: qr_token 或 activityId+admin)→ 桥接发放课时 |
POST /api/planner/exam/start |
开始某类别考核(前置校验课时达标;body: categoryCode) |
POST /api/planner/exam/submit |
提交判分(body: attemptId+答案,写入 exam_score/exam_passed) |
POST /api/planner/exam/result |
考核结果 |
/api/admin/*)| 路径 | 说明 |
|---|---|
POST /api/admin/planner-cert-categories/list |
学习种类列表 |
POST /api/admin/planner-cert-categories/create |
创建学习种类(含 required_hours、is_base,首批种子:planner/nutritionist/assessor) |
POST /api/admin/planner-cert-categories/update |
更新学习种类 |
POST /api/admin/planner-cert-categories/delete |
删除学习种类 |
POST /api/admin/planner-courses/list |
线上课程列表 |
POST /api/admin/planner-courses/create |
创建线上课程(挂类别) |
POST /api/admin/planner-courses/update |
更新线上课程 |
POST /api/admin/planner-courses/delete |
删除线上课程 |
POST /api/admin/planner-offline-course-map/list |
培训活动↔类别映射列表 |
POST /api/admin/planner-offline-course-map/create |
创建映射(activities 建课后关联类别与计课时) |
POST /api/admin/planner-offline-course-map/update |
更新映射 |
POST /api/admin/planner-offline-course-map/delete |
删除映射 |
POST /api/admin/activity-checkins/list |
签到记录查询 |
POST /api/admin/activity-checkins/add |
手动补录签到(桥接触发课时入账) |
POST /api/admin/activity-checkins/review |
签到审核 |
POST /api/admin/planner-exam/papers |
试卷列表(按类别) |
POST /api/admin/planner-exam/paper/create |
创建试卷 |
POST /api/admin/planner-exam/paper/update |
更新试卷 |
POST /api/admin/planner-exam/paper/delete |
删除试卷 |
POST /api/admin/planner-exam/questions |
题库列表 |
POST /api/admin/planner-exam/questions/save |
保存题目(新建/更新) |
POST /api/admin/planner-certifications/list |
认证看板(按类别:课时进度、考核分、证书号、有效期) |
POST /api/admin/planner-certifications/sync-hours |
手动同步线上课时(小鹅通 webhook 兜底,body: userId+categoryCode+课时) |
POST /api/admin/planner-certifications/sync-hours/batch |
批量同步线上课时 |
POST /api/admin/planner-certifications/init-by-user |
按用户初始化各类别认证记录 |
POST /api/admin/planner-certifications/backfill |
存量补登(迁移401 幂等重跑) |
/api/xiaoe/*)| 路径 | 说明 |
|---|---|
POST /api/xiaoe/webhook |
线上学习进度/课程完成事件(签名校验、幂等;课时入账 + 认证记录更新) |
POST /api/xiaoe/webhook/test |
webhook 联调用测试入口 |
PlannerCertificationGuard)assertCertified(userId, categoryCode[, baseRequired]):查询该类别 planner_certifications.status == certified(且 Guide.status == active)方可放行,否则返回 Result.error("规划师未完成【类别名】培训认证,暂不可提供该类服务")(null=放行,非 null=拒绝)。| 服务动作 | 入口 | 所需类别 |
|---|---|---|
| 上架/修改服务套餐 | GuideManagementController package/add、package/{packageId}/update |
planner |
| 家庭绑定(开始服务) | BindController.accept |
planner |
| 激活成长方案(下发任务) | PlanReviewController.activate |
planner |
| 咨询响应/接单 | TeacherMessageController.reply |
planner |
| 订单中心(列表/统计/详情) | GuideOrderController /list、/stats、/detail |
planner |
| 测评录入/解读 | GuideAssessmentController family/enable |
assessor |
nutritionist)。口径:
docs/superpowers/plans/2026-10-24-cf-value-unification-plan.md§3.6.6 / §3.7 W0.1 本批只提供 数据层 + 配置层 接口,发放/扣减接口在 F-2/F-3 批新增。
/api/admin/service-config)唯一配置中心(service_config 表):CF 通用运营参数(key 前缀 cf.,product_key 为空)+ product 侧配置(product_key 非空,key 形如 product.{productKey}.{key},W0.2 由 product_config 并入)。保存后自动 CfConfigCache.invalidate()(本地缓存 TTL 60s)+ cf.version 自增。
| 路径 | 说明 |
|---|---|
POST /api/admin/service-config/list |
配置列表,body 可选 {"groupKey":"cf.rate","productKey":"gut_health"},不传返回全部(productKey 为产品维度筛选,W0.2 新增) |
POST /api/admin/service-config/save |
保存配置(upsert),body {"configKey":"cf.rate.points_multiplier","configValue":"1.0","updatedBy":1};传 productKey 则写入 product 侧配置(自动加 product.{productKey}. 前缀并回填 product_key,W0.2 新增),可另传 description |
POST /api/admin/service-config/invalidate |
手动失效 CF 配置缓存(排障用) |
已登记配置项:cf.rate.points_multiplier、cf.rate.repeat_rate_default、cf.commission.settle_days、cf.invite.valid_days、cf.price.default_factor、cf.stock.deduction_mode、cf.rate.share_read_reward_points、cf.commission.service_rate、cf.product.gut_health_price、cf.product.platform_points_share、cf.version。
/api/admin/cf-earn-rule)24 条规则(F02–F24,F03 拆 F03a/F03b)配置入口;每次保存/开关写 cf_earn_rule_history 并失效配置缓存。
| 路径 | 说明 |
|---|---|
POST /api/admin/cf-earn-rule/list |
规则列表,body 可选 {"category":"behavior","enabled":1} |
POST /api/admin/cf-earn-rule/save |
新建/编辑(按 code 判重),body 含 code/name/category/ruleType/amount/formula/paramsJson/dailyLimitPerMember/totalLimitPerMember/cooldownSeconds/dedupRefType/remark/changedBy/changeReason |
POST /api/admin/cf-earn-rule/toggle |
启停,body {"code":"F07","enabled":0,"changedBy":1,"changeReason":"..."} |
POST /api/admin/cf-earn-rule/history |
变更历史,body 可选 {"code":"F07","limit":100} |
读取封装:
ConfigService.getConfig(key)(缓存 60s → DB → 兜底常量);product 侧配置读取:ConfigService.getProductConfig(productKey, key)(W0.2);规则读取:CfEarnRuleService.getByCode(code)。
/api/admin/product-config,已废弃 410 Gone)W0.2 双配置中心合并:product_config 已并入 service_config(唯一配置中心),product 侧配置通过 product_key 关联产品;本控制器写接口统一返回 410 Gone(HTTP 410 + body code=410),保留 30 天只读窗口后由运维删表。
| 路径 | 说明 |
|---|---|
POST /api/admin/product-config/list |
【410 Gone】已废弃,改用 POST /api/admin/service-config/list(body 传 productKey 筛选) |
POST /api/admin/product-config/save |
【410 Gone】已废弃,改用 POST /api/admin/service-config/save(body 传 productKey) |
时间线:2026-10-24 起写接口下线(product_config 只读保留 30 天回滚用);2026-11-23 起确认无回滚需求后删表并移除本控制器。
启动时由 DatabaseInitializer → CfLegacyLedgerMigrationService 一次性执行,无 REST API。迁移只读旧表、不回写旧表:
| 来源 | 目标成员 | cf_balance_log.ref_type |
ref_id |
口径 |
|---|---|---|---|---|
family_platform_balance |
家庭 families.creator_id 对应的 family_members |
migration_family_pool |
0 |
available + frozen 合入新 available,withdrawn/exchanged 原样带入 |
family_members.system_points > 0 |
当前成员 | migration_system_points |
family_members.id |
system_points 合入新 available |
user_platform_balance |
该用户本人对应的 family_members |
migration_user_wallet |
user_platform_balance.id |
available + frozen 合入新 available,withdrawn/exchanged 原样带入 |
幂等键为 (member_id, type='adjust', ref_type, ref_id)(对齐 F-2 迁移416 升级后的唯一键 uk_ref_type);重复启动按三类 ref_type 逐笔跳过,余额与流水同事务提交。三套旧账本保留为只读历史,写接口 410 Gone 由 F-8 收口。
口径:计划 §四 / §3.1 / §4.2 / §4.4。发放链路由
CfCommissionService统一承载,无新增 REST 接口;/api/commission/cf/rate返回值扩展两级档位字段(见 4.33)。
迁移内容:
| 迁移 | 内容 | 幂等键 |
|---|---|---|
| 418 | cf_direct_sales_tier / cf_indirect_sales_tier 各补 5 档种子(青铜/白银/黄金/铂金/钻石,缺行才补、不覆盖)+ cf_earn_rule.dedup_ref_type 对齐为规则编码(F03a→'F03a'、F03b→'F03b') |
按 min_annual_ppoints / min_self_ppoints 判重;UPDATE 带 WHERE dedup_ref_type <> code |
| 420 | 新建 ppoint_consumption_log(滚动一年档位聚合数据源:消费支付成功落一行,created_at >= now()-365d 聚合)。注:迁移419 已被 membership_levels.max_daily_analyze 占用,本表顺延为 420 |
UNIQUE uk_order (order_type, order_id) 同一订单重复触发只记一行 |
发放链路(CfCommissionService.settle / settleReferrerOnly):
本单 P 点基数(商品: 元×有效P点/100;非商品: 元×service_rate bps/10000)
→ 落 ppoint_consumption_log(幂等)
→ referral_tree 按 level 升序上溯,跳过同家庭(D5)
→ 第1个非同家庭引荐人 → getTeamAnnualPpoints(referrerId, 8) → matchDirectSalesTier → F03a
→ 第2个非同家庭引荐人 → getSelfAnnualPpoints(referrerId) → matchIndirectSalesTier → F03b
→ cfBalanceService.earnByRule(memberId, "F03a"/"F03b", orderId, {base_ppoints, rate_percent})
(公式 floor(base_ppoints*rate_percent/100),幂等键复用 F-2 uk_ref_type,只写 cf_balance + cf_balance_log)
→ F03a 且非幂等命中时 autoCreateGratitudeEffect(感恩记录)
cf_earn_rule.params_json.max_rate_percent,金额由公式计算。CfCommissionService 同时承载两条链路 —— 当前消费人 F02(CfEarnDispatchService.earnConsumeCf,按实付金额,商品订单实付与分润基数分离)与推荐人 F03a/F03b(本节);两条链路都只写 cf_balance + cf_balance_log,cf_transfer_record 不再由本服务写入。CommissionDistService.distribute 已废弃:抛 IllegalStateException(消息含 "410 Gone",经 GlobalExceptionHandler 转 Result.error(400, ...)),无调用方;commission_dist_log 转只读历史表,管理端读取接口(/api/admin/commission-dist/*)保留不变。cf_rate_tier 表保留只读,仅供等级展示(PromotionTierService / 管理端档位配置)使用。文档更新:2026-10-24(CF 值体系统一 F-1 数据层 + W0.1 配置归口:8 张新表/迁移407-412 + service_config 与 cf_earn_rule 管理端接口);同日补登 W0.2 双配置中心合并(service_config 收编 product_config:迁移413 + product_key 维度 + product-config 接口 410 Gone + 配置中心统一入口);同日补登 F-6 存量迁移(迁移417 + 三套旧账本幂等迁入 cf_balance);2026-10-25 补登 F-4 分佣收口(迁移418/420 + 两级销售奖档位 + /rate 扩展字段 + CommissionDistService.distribute 410 Gone)
口径:计划 §七 F-7a。个人 CF 值账本为成员维度(
family_members.id),登录userId → memberId解析与CfEarnDispatchService.resolveMemberId(F-3a)口径一致:user_id匹配 + 按id升序LIMIT 1;未找到对应家庭成员时返回Result.error(404, "未找到当前用户对应的家庭成员,..."),不返回空数据。控制器:
CfBalanceController,前缀/api/cf(GET,需登录;注:本项目接口惯例为 POST,本组 只读接口按 F-7a 任务要求采用 GET,若团队统一要求 POST 可一行改回)。
| 路径 | 说明 |
|---|---|
GET /api/cf/balance |
我的 CF 值快照。按登录用户解析 memberId 后读 cf_balance,返回 CfBalanceView:memberId / available(可用) / frozen(冻结) / totalEarned(累计获得) / totalWithdrawn(已提现) / exchanged(已兑换消费)。无 cf_balance 记录时返回全 0 |
GET /api/cf/logs?page=1&size=20 |
我的 CF 流水分页(时间倒序),复用 CfBalanceService.getLogs(memberId, page, size),输出转 CfBalanceLogVO:id / type(earn/spend/freeze/unfreeze/withdraw/adjust/skip) / refType(规则编码或迁移标识) / amount(带符号变动) / balanceAfter(变动后可用余额) / remark / createdAt(ISO 8601)。返回 MyBatis-Plus Page 结构(current/size/total/pages/records) |
GET /api/cf/family-coupons |
家庭共享优惠券列表(N3 口径)。复用 CouponService.listMyCoupons(userId):按登录用户所属家庭查 family_coupon + coupon 联合数据(券家庭化全链路已切换至 family_coupon,user_coupon 为只读历史表),返回 userCouponId / couponId / name(券名) / type / value(面额,分) / discountRate / minSpend / applicableTo / status(AVAILABLE/USED/EXPIRED/DISABLED) / validFrom / validUntil(有效期) / receivedAt / usedAt / orderId / productId,家庭内成员共享可见 |
CfBalanceService / CouponService,本控制器不直接写库、不提供任何写接口。cfc-backend/src/test/java/com/etotem/cfc/unit/CfBalanceControllerTest.java(memberId 解析命中/未命中 + balance/logs 字段映射)。/api/admin/file-record/*)控制器:
FileRecordController(controller/admin/FileRecordController.java),前缀/api/admin/file-record。 服务层:FileRecordService;文件存储复用StorageService.storeFileRecord(MultipartFile, category)(JdCloudStorageService/LocalDiskStorageService实现),统一写入file_record并推导file_type。 权限:全部@PostMapping,控制器内@RequestAttribute("role") == "admin"守卫(无 token 时为anonymous,直接拒绝)。 数据表:file_record(唯一键uk_hash去重)、file_tag(uk_name)、file_tag_rel(uk_file_tag),均为既有表,无新增迁移。
file_type 口径(与 util/FileTypeResolver.java 一致):
| file_type | 判定 |
|---|---|
image |
content_type LIKE 'image/%' |
video |
content_type LIKE 'video/%' |
audio |
content_type LIKE 'audio/%' |
document |
content_type LIKE 'text/%' 或 PDF/Office/RTF/ODF 白名单 |
other |
其它(含 application/octet-stream、content_type 缺失) |
写入侧(新数据):content_type 缺失或为
application/octet-stream时按扩展名兜底;历史回填见docs/migrations/20261025_asset_library_file_type_backfill.sql(严格按 content_type 分类,不用扩展名兜底)。
接口清单:
| 路径 | 说明 |
|---|---|
POST /api/admin/file-record/list |
分页检索。Body:{ page, pageSize, category, fileType, search, dateFrom, dateTo, tagIds };tagIds 为数组或逗号分隔字符串,前置过滤(先按标签 JOIN 过滤再分页,保证 total 正确)。返回 { records, total, page, pageSize },records 元素含 id/hash/url/fileSize/contentType/originalFilename/category/fileType/description/createdAt/updatedAt/tags |
POST /api/admin/file-record/upload |
统一上传入库。multipart 字段:file(必填)、category(选填,默认 general)、tagIds(选填,数组或逗号分隔)。存储 → 写 file_record(SHA-256 去重,命中返回既有记录并补打本次标签)→ 关联标签。图片(contentType 以 image 开头)先过微信内容安全检测(WechatServiceInterface.checkImage,fail-open,与旧 AdminArticleController#uploadImage 保持一致)。返回素材记录 map |
POST /api/admin/file-record/update |
更新描述/标签。Body:{ id, description?, tagIds? };tagIds 传空数组表示清空标签,不传表示不改动 |
POST /api/admin/file-record/delete |
删除素材。Body:{ id };先删 OSS 文件(失败仅告警)再删记录及其标签关联 |
POST /api/admin/file-record/tags |
标签字典列表(按 sortOrder 排序) |
POST /api/admin/file-record/tag/create |
新建标签。Body:{ name, color?, sortOrder? },name 唯一 |
POST /api/admin/file-record/tag/update |
更新标签。Body:{ id, name?, color?, sortOrder? } |
POST /api/admin/file-record/tag/delete |
删除标签。Body:{ id }(级联清理 file_tag_rel) |
POST /api/admin/file-record/stats |
统计。返回 { total, totalBytes, byFileType: [{file_type, cnt}], byCategory: [{category, cnt}] } |
上传响应示例(data 为素材记录):
{
"id": 1024,
"hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"url": "https://bucket.endpoint/uploads/general/xxx.png",
"fileSize": 102400,
"contentType": "image/png",
"originalFilename": "cover.png",
"category": "articles",
"fileType": "image",
"description": null,
"createdAt": "2026-10-25T12:00:00",
"updatedAt": "2026-10-25T12:00:00",
"tags": []
}
前端配套: cfc-web/src/utils/asset.js(API 封装 + resolveAssetUrl)、cfc-web/src/components/AssetPicker.vue(素材选择弹窗,image/video/document 三类)、cfc-web/src/views/admin/AssetLibrary.vue(素材库管理页,路由 /admin/asset-library)、cfc-web/src/utils/editorAssetUpload.js(wangEditor 上传配置公共封装,端点统一指向本组 upload)。
上传点接入范围与跳过说明(cfc-web/src 全量 el-upload 排查结果):
| 页面 | 处理 |
|---|---|
ArticleEdit / ActivityEdit / ProductEdit |
接入:富文本 MENU_CONF.uploadImage/uploadVideo.server 改指本组 upload(fieldName=file + Bearer),customInsert 统一 resolveAssetUrl;新增「从素材库选择图片/视频」按钮 |
HomeBannerManage / ProductSkuEditor / GuidePackages |
接入:封面上传改指本组 upload,并加「从素材库选择」 |
KnowledgeDialog |
接入:文档可从素材库选取(assetType=document),原有的本地知识文件上传通道保留不变 |
Activities / ArticleManage / SupplierProductManage |
跳过:仅列表展示页,无上传控件 |
RecommendationRules / IndicatorMappings |
跳过:无文件上传控件(后者为文本批量导入) |
ProxyReportUpload / teacher/ProxyReport / ReportParserImport / ReportCollectorTrainer / ReportUnknownCluster / teacher/GrowthRecords |
跳过:业务报告/JSON 解析包上传,走报告解析专用端点(/api/admin/report-parser/* 等),非 jdcloud 媒体资产,纳入素材库会污染 file_record 分类语义 |
ReportTemplateManage |
跳过:仅表单 tab,无图片字段 |
旧端点
POST /api/admin/articles/upload/image|video保留可用(兼容既有调用方),但后台页面已统一改走素材库 upload,以便自动入库与打标签。
存量回填: docs/migrations/20261025_asset_library_file_type_backfill.sql(备份 → 按 content_type 回填 file_type → 修正列注释 → 校验),不占用 DatabaseInitializer 迁移编号(407-421 为 CF 体系保留)。
文档更新:2026-10-25(后台素材库:/api/admin/file-record/ 上传入库 + 标签字典 + 统计;file_type 口径统一为 image/video/audio/document/other)*
/api/attribution/* + /api/survey/attribution/*)阶段二(ATT-S2,B1–B4):「归因分析 → 条件问卷 → 自然语言调整 → 七章干预方案」。 E12 合规后置:全流程由
app.attribution.enabled(默认false)开关控制,仅测试/mock 数据环境开启; 真实用户放行 = 阶段四 D1 完成日。未开启时返回Result.error(4001, …)。 合规即服务:红线 RL01–RL10 由规则层硬注入,AI 只产叙述/调整,不负责合规判定(§1.3)。
POST /api/attribution/analyze — ③ 归因分析(十节结构报告){ familyId?, memberIds[], gutReportIds[], danResultIds[], confirmSurveyRecordId?, planId?, mock?, mockFlags? }
(mockFlags 仅 E12 测试环境,可显式注入中间态键)data:AttributionReportVO { id, familyId, status, reportJson, intermediateState, redlineHits, conclusionLocked, createdAt }
reportJson:十节结构(一结论先行/二四人数据速览/三逐人归因/四家庭系统归因/五应对方案/六12周可检验目标/七教练提问序列/八问诊清单/九红线与转介/十一句话收尾)intermediateState:含 l.reuteriAbnormal/ironLow/hasDan/isFemaleTeen/hasDiabetes 等键(B1 中间态)redlineHits:RL01–RL08(阶段③④注入);RL09/RL10 属方案阶段⑤ANALYZING(插入)→ READY(回填报告后更新)warnings 携带说明)POST /api/survey/attribution/confirm-questions — ② 条件问卷路由{ familyId, memberId, attributionId, answeredSummary? }data:ConfirmQuestionVO { templateId, questions[], hasHighRisk, highRiskQuestionIds }
questions[]:按 对象×年龄×结论 条件下发 family_attribution 模板子集(16 条中)riskLevel=high;命中 → hasHighRisk=true(E4 弱提示,不阻断)POST /api/survey/submit — ② 提交(B2 扩展:riskHits){ userId, memberId, templateId, answersJson, periodStart?, periodEnd?, riskHits? }
riskHits(Q11/Q12/Q13 命中标记)并入 answersJson._attributionRiskHits 落库,供 B1 红线检测POST /api/attribution/adjust — ④ 自然语言调整{ attributionId, message, conversationId? }data:AdjustResult { attributionId, status, answer, fieldDeltas, intermediateState, redlineHits, redlineTerminate, blocking, referral, planInvalidated }
[ATTR_DELTA]{"键":新值} 结构化增量 → 回填 intermediate_state(七层 Socratic,PRD §C ④)redlineTerminate=true、blocking=false(E4 弱提示不阻断)、referral 露出转介信息 + 家长确认status=GENERATED → 作废为 INVALIDATED(⑤ 失效重生成)POST /api/attribution/confirm-adjust — ④ 确认调整{ attributionId }data:AdjustResult { status=CONFIRMED, conclusionLocked=true }(结论锁定,B4 前置条件)POST /api/attribution/plan — ⑤ 七章干预方案{ attributionId }CONFIRMED(否则 Result.error(4000, …))data:FamilyPlanVO { planId, planJson, totalDays, status }
planJson:header + 7 章(数据速览/主线产品/分人方案/家庭共享/12周节奏/红线与转介/附录)level(P0/P1/daily/P2) + reviewHook(复盘钩子)health_plans,plan_type=family_attribution_plan,status=GENERATED(⑤)文档更新:2026-10-28(家庭归因核心闭环 B1–B4:/api/attribution/analyze、/api/attribution/adjust、/api/attribution/confirm-adjust、/api/attribution/plan、/api/survey/attribution/confirm-questions;/api/survey/submit 扩展 riskHits)
五维能量页(身/智/富/行/心)三视角:① 个人看自己各维度;② 家庭管理员看家庭成员各维度;③ 看整个家庭各维度汇总。 家庭各维度汇总方式可配置:SUM=合计 / AVG=平均 / COLLECT=汇集(如行页面珍珠图、章鱼图)。 配置作用域 = 平台级全局一份(
family_metric_agg_config表,按数据项一行一条,迁移433)。 默认五维 AVG 保持既有页面数值表现不变(向后兼容);SUM/COLLECT 由后台配置页调整即生效。
数据表 family_metric_agg_config:
| 字段 | 说明 |
|---|---|
metric_key (UNIQUE) |
数据项唯一标识:energy.body/energy.mind/energy.wisdom/energy.action/energy.wealth/energy.overall/pearl.resources/octopus.effects |
metric_name |
中文名 |
dimension_code |
所属维度:body/mind/wisdom/action/wealth/common |
agg_type |
SUM=合计 / AVG=平均 / COLLECT=汇集 |
value_type |
NUMBER(数值)/ COLLECTION(集合) |
display_mode |
number/bar/radar/merge_graph |
sort_order / status / remark |
排序 / active |
配置 CRUD(/api/admin/family-metric-agg/*,供 cfc-web 管理端,admin 角色守卫):
| 路径 | 说明 |
|---|---|
POST /api/admin/family-metric-agg/list |
全量配置列表(配置项 < 50,无需分页)。返回 [ { id, metricKey, metricName, dimensionCode, aggType, valueType, displayMode, sortOrder, status, remark } ] |
POST /api/admin/family-metric-agg/save |
新增/更新(body 带 id 则更新,否则新增)。Body:{ id?, metricKey, metricName, dimensionCode, aggType, valueType, displayMode?, sortOrder?, status?, remark? } → true |
POST /api/admin/family-metric-agg/delete |
Body { id } → true |
POST /api/admin/family-metric-agg/update-status |
Body { id, status } → true |
家庭汇集数据(供小程序行页面,全 POST):
| 路径 | 说明 |
|---|---|
POST /api/pearl/family/resources |
珍珠图家庭汇集。data:{ members: [ { memberId, memberName, memberType, colorKey, items: [原珍珠资源项结构 + groupType/groupTypeName/ring] } ] } |
POST /api/octopus/effect/family/list |
章鱼图家庭汇集。data:{ members: [ { memberId, memberName, memberType, colorKey, effects: [原章鱼成效项结构] } ] } |
memberType:user(家庭主账号,memberId=users.id)/ member(家庭成员,memberId=family_members.id)colorKey:稳定色值键(0..n-1 索引,同一成员前后一致),供前端按成员着色EnergyService.doCalculateFamilyEnergy 一致(家庭主账号 role=parent + getActualChildren 去重);个人数据查询复用既有逻辑(ResourceService.getPearlResources / KeyPersonService.listEffects),不重写业务规则五维聚合改造(EnergyService.doCalculateFamilyEnergy 第 4 步):按 metric_key(energy.body…)查配置取 agg_type:
文档更新:2026-10-31(家庭数据汇总方式配置(后端):family_metric_agg_config 表 + 配置 CRUD 4 接口 + 珍珠图/章鱼图家庭汇集 2 接口 + 五维聚合读配置)
/api/admin/supply-team/*)—— T38需求来源:廖总 2026-11-02「在我的团队加一个邀请功能,邀请其他用户加入团队」。规格:
docs/superpowers/specs/2026-11-01-team-system-design.md§3.5 / §4.2 / §4.3(任务 T38)。语义:团队成员 = 邀请加入(与
referral_tree推广返佣是两套独立模型,不在此范围)。凭邀请码加入者成为团队成员(非客户),且以邀请人为上级(supply_hierarchy.parent_id=邀请人,level=父级level+1)→ 成员子树 = 该成员自己的团队,与 §0.5「唯一负责人整体结算、平台不拆分」口径一致。数据模型:
supply_system_member扩列invite_code VARCHAR(50)(个人专属邀请码,迁移444 幂等ensureColumn+ 唯一索引uk_supply_member_invite_code;schema.sql 已同步)。
@PostMapping)| 路径 | 说明 |
|---|---|
POST /api/admin/supply-team/invite-code |
生成/获取我的邀请码(幂等)。body:{ systemId, refresh? };refresh=true 重置旧码(旧码立即失效)。返回 { inviteCode, systemId, teamName, shareText }。越权防护:须为该体系的 admin/active 成员 |
POST /api/admin/supply-team/invite/info |
邀请码信息(确认页展示)。body:{ inviteCode } → { systemId, teamName, inviterId, inviterNickname, inviterAvatar, memberCount, active }。仅展示团队名/邀请人昵称头像/成员数,不泄露其他隐私 |
POST /api/admin/supply-team/invite/join |
凭邀请码加入团队(挂邀请人为上级)。body:{ inviteCode } → 加入后的团队/邀请人信息(同 invite/info 结构) |
(systemId, userId) 仅加入一次:已 active 加入 → 报错「您已在该团队中,无需重复加入」;被移除(status=inactive)→ 可再次申请(自动恢复 active)。role=member 不可自助变更(沿用 member/change-role 管理员权限)。refresh 可重置为新码。status != active 时不可生成邀请码、不可加入。cfc-frontend/pages/vendor/team-system/team-system.vue:团队成员区新增「邀请成员」按钮 → 弹窗(邀请码 + 复制 + 刷新重置;小程序码可后置)。cfc-frontend/pages/vendor/team-invite/team-invite.vue(新增,已注册 pages.json):受邀确认页——展示邀请人/团队 → 点「加入团队」→ 成功态 → 跳转「我的团队」;支持 ?code=XXX 带参进入,也可手动输入邀请码。cfc-frontend/utils/api.js:getVendorInviteCode / getVendorInviteInfo / joinVendorTeamByInvite(各 URL 唯一规范入口)。文档更新:2026-11-02(T38 团队邀请功能:supply_system_member 扩 invite_code + 邀请码生成/信息/凭码加入 3 接口 + 前端邀请入口与受邀确认页)