Initial commit: Happy Up monorepo through Sprint 5.

Document-driven MVP with FastAPI backend, Vue H5, WeChat mini shell, product demo, and Docker dev stack.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-07-23 11:42:40 +08:00
commit 1aaef71f52
116 changed files with 10550 additions and 0 deletions
@@ -0,0 +1,922 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>儿童 AI 体态管理平台 · 系统架构与建设规划 V1.0</title>
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<style>
:root {
--bg: #f4f7fb;
--surface: #ffffff;
--primary: #1a6fb5;
--primary-dark: #0f4f86;
--accent: #2bb673;
--accent-soft: #e8f7ef;
--warn: #e6a23c;
--danger: #d9534f;
--text: #1f2937;
--text-muted: #6b7280;
--border: #e5e7eb;
--shadow: 0 4px 24px rgba(15, 79, 134, 0.08);
--radius: 14px;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.65;
font-size: 15px;
}
/* Hero */
.hero {
background: linear-gradient(135deg, #0f4f86 0%, #1a6fb5 45%, #2bb673 100%);
color: #fff;
padding: 56px 24px 48px;
text-align: center;
}
.hero-badge {
display: inline-block;
background: rgba(255,255,255,0.18);
border: 1px solid rgba(255,255,255,0.3);
border-radius: 999px;
padding: 6px 16px;
font-size: 13px;
margin-bottom: 20px;
letter-spacing: 0.5px;
}
.hero h1 {
font-size: clamp(26px, 4vw, 40px);
font-weight: 700;
margin-bottom: 12px;
letter-spacing: -0.5px;
}
.hero p {
font-size: 17px;
opacity: 0.92;
max-width: 680px;
margin: 0 auto 28px;
}
.hero-meta {
display: flex;
flex-wrap: wrap;
gap: 12px;
justify-content: center;
font-size: 13px;
opacity: 0.85;
}
.hero-meta span {
background: rgba(255,255,255,0.12);
padding: 4px 12px;
border-radius: 6px;
}
.hero-actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
justify-content: center;
margin-top: 8px;
}
.hero-btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 12px 28px;
border-radius: 999px;
font-size: 15px;
font-weight: 600;
text-decoration: none;
transition: transform 0.15s, box-shadow 0.15s;
}
.hero-btn-primary {
background: #fff;
color: var(--primary-dark);
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
}
.hero-btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 28px rgba(0,0,0,0.2);
}
.hero-btn-outline {
background: rgba(255,255,255,0.12);
color: #fff;
border: 1.5px solid rgba(255,255,255,0.45);
}
.hero-btn-outline:hover { background: rgba(255,255,255,0.22); }
/* Floating demo entry */
.fab-demo {
position: fixed;
right: 24px;
bottom: 24px;
z-index: 200;
display: flex;
align-items: center;
gap: 8px;
padding: 14px 22px;
background: linear-gradient(135deg, var(--accent), #1e9e5a);
color: #fff;
border-radius: 999px;
text-decoration: none;
font-size: 14px;
font-weight: 600;
box-shadow: 0 8px 32px rgba(43,182,115,0.45);
transition: transform 0.15s;
}
.fab-demo:hover { transform: scale(1.04); }
.fab-demo .icon { font-size: 18px; }
/* Layout */
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 20px 80px;
}
/* Nav */
.toc-bar {
position: sticky;
top: 0;
z-index: 100;
background: rgba(255,255,255,0.95);
backdrop-filter: blur(8px);
border-bottom: 1px solid var(--border);
padding: 10px 20px;
overflow-x: auto;
white-space: nowrap;
}
.toc-bar a {
display: inline-block;
color: var(--text-muted);
text-decoration: none;
font-size: 13px;
padding: 6px 14px;
border-radius: 999px;
margin-right: 4px;
transition: all 0.2s;
}
.toc-bar a:hover, .toc-bar a.active {
background: var(--primary);
color: #fff;
}
/* Sections */
section {
margin-top: 48px;
}
.section-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 24px;
}
.section-num {
width: 36px;
height: 36px;
background: var(--primary);
color: #fff;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 14px;
flex-shrink: 0;
}
.section-header h2 {
font-size: 22px;
font-weight: 700;
color: var(--primary-dark);
}
/* Cards */
.card {
background: var(--surface);
border-radius: var(--radius);
box-shadow: var(--shadow);
border: 1px solid var(--border);
padding: 28px;
margin-bottom: 20px;
}
.card h3 {
font-size: 16px;
font-weight: 600;
color: var(--primary-dark);
margin-bottom: 16px;
padding-bottom: 10px;
border-bottom: 2px solid var(--accent-soft);
}
/* KPI Grid */
.kpi-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 16px;
margin-bottom: 8px;
}
.kpi {
background: linear-gradient(145deg, #fff, #f0f7ff);
border: 1px solid var(--border);
border-radius: 12px;
padding: 20px;
text-align: center;
}
.kpi .value {
font-size: 28px;
font-weight: 800;
color: var(--primary);
line-height: 1.2;
}
.kpi .label {
font-size: 13px;
color: var(--text-muted);
margin-top: 6px;
}
/* Tables */
table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
th {
background: #f0f6fc;
color: var(--primary-dark);
font-weight: 600;
text-align: left;
padding: 11px 14px;
border-bottom: 2px solid var(--border);
}
td {
padding: 10px 14px;
border-bottom: 1px solid var(--border);
vertical-align: top;
}
tr:last-child td { border-bottom: none; }
tr:hover td { background: #fafbfc; }
/* Tags */
.tag {
display: inline-block;
padding: 2px 10px;
border-radius: 999px;
font-size: 12px;
font-weight: 500;
}
.tag-must { background: #fde8e8; color: #c0392b; }
.tag-should { background: #fef3cd; color: #856404; }
.tag-could { background: #e8f4fd; color: #1a6fb5; }
.tag-p0 { background: #fde8e8; color: #c0392b; }
.tag-p1 { background: #e8f4fd; color: #1a6fb5; }
.tag-p2 { background: #e8f7ef; color: #1e7e4a; }
.tag-p3 { background: #f3e8ff; color: #6b21a8; }
/* Timeline */
.timeline {
position: relative;
padding-left: 32px;
}
.timeline::before {
content: '';
position: absolute;
left: 10px;
top: 8px;
bottom: 8px;
width: 3px;
background: linear-gradient(to bottom, var(--primary), var(--accent));
border-radius: 3px;
}
.timeline-item {
position: relative;
margin-bottom: 28px;
}
.timeline-item::before {
content: '';
position: absolute;
left: -26px;
top: 6px;
width: 14px;
height: 14px;
background: var(--surface);
border: 3px solid var(--primary);
border-radius: 50%;
}
.timeline-item h4 {
font-size: 16px;
font-weight: 600;
color: var(--primary-dark);
margin-bottom: 4px;
}
.timeline-item .period {
font-size: 13px;
color: var(--accent);
font-weight: 600;
margin-bottom: 8px;
}
.timeline-item p {
color: var(--text-muted);
font-size: 14px;
}
/* Mermaid */
.mermaid-wrap {
background: #fafbfc;
border-radius: 10px;
padding: 20px;
overflow-x: auto;
border: 1px solid var(--border);
}
/* Alert boxes */
.alert {
border-radius: 10px;
padding: 14px 18px;
font-size: 14px;
margin: 16px 0;
display: flex;
gap: 10px;
align-items: flex-start;
}
.alert-info { background: #e8f4fd; border-left: 4px solid var(--primary); }
.alert-warn { background: #fef3cd; border-left: 4px solid var(--warn); }
.alert-danger { background: #fde8e8; border-left: 4px solid var(--danger); }
/* Action checklist */
.checklist { list-style: none; }
.checklist li {
padding: 10px 0;
border-bottom: 1px dashed var(--border);
display: flex;
gap: 10px;
align-items: flex-start;
font-size: 14px;
}
.checklist li::before {
content: '☐';
color: var(--primary);
font-size: 16px;
flex-shrink: 0;
}
.checklist li.done { color: var(--accent); font-weight: 600; }
.checklist li.done::before { content: '✓'; color: var(--accent); }
/* Two column */
.grid-2 {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
/* Footer */
footer {
text-align: center;
padding: 32px 20px;
color: var(--text-muted);
font-size: 13px;
border-top: 1px solid var(--border);
margin-top: 60px;
}
/* Print */
@media print {
.toc-bar { display: none; }
.hero { padding: 24px; }
section { page-break-inside: avoid; }
.card { box-shadow: none; }
}
@media (max-width: 640px) {
.card { padding: 18px; }
.kpi .value { font-size: 22px; }
}
</style>
</head>
<body>
<!-- Hero -->
<div class="hero">
<div class="hero-badge">商业交付包 V1.0 · 合伙人讨论稿</div>
<h1>儿童 AI 体态管理平台</h1>
<p>系统架构与建设规划 — 从 MVP 到商业试点的完整技术路线与落地节奏</p>
<div class="hero-meta">
<span>版本 V1.0</span>
<span>2026-07-23</span>
<span>目标用户 316 岁</span>
<span>非医疗诊断 · 健康管理</span>
</div>
<div class="hero-actions">
<a href="产品交互Demo.html" class="hero-btn hero-btn-primary">📱 进入产品交互 Demo</a>
<a href="产品交互Demo.html#page-live-prep" class="hero-btn hero-btn-outline">🎥 AI 跟练 Demo</a>
</div>
</div>
<!-- TOC -->
<nav class="toc-bar">
<a href="#overview">项目定位</a>
<a href="#architecture">系统架构</a>
<a href="#modules">模块划分</a>
<a href="#flow">核心流程</a>
<a href="#tech">技术选型</a>
<a href="#roadmap">建设规划</a>
<a href="#team">团队分工</a>
<a href="#security">安全合规</a>
<a href="#risk">风险应对</a>
<a href="#action">行动清单</a>
<a href="产品交互Demo.html" style="background:var(--accent);color:#fff;margin-left:8px">📱 产品 Demo</a>
</nav>
<div class="container">
<!-- 1. Overview -->
<section id="overview">
<div class="section-header">
<div class="section-num">1</div>
<h2>项目定位与建设目标</h2>
</div>
<div class="card">
<h3>我们在做什么</h3>
<p>面向 <strong>316 岁儿童青少年</strong> 的 AI 体态管理与运动康复平台,围绕含胸驼背、头前伸、高低肩、骨盆姿态、膝内扣、足弓与运动协调等常见问题,提供 AI 筛查、结构化报告、训练计划、打卡复测与机构 SaaS 运营闭环。</p>
<div class="alert alert-danger" style="margin-top:16px">
<span>⚠️</span>
<span><strong>合规边界</strong>:平台输出用于健康管理与运动训练,<strong>不替代医院诊断</strong>。涉及疼痛、明显畸形、外伤或医生已明确限制运动的情况,必须提示线下专业评估。</span>
</div>
</div>
<div class="card">
<h3>试点阶段核心指标</h3>
<div class="kpi-grid">
<div class="kpi"><div class="value">≥90%</div><div class="label">分析任务达成率</div></div>
<div class="kpi"><div class="value">≥80%</div><div class="label">报告 30 分钟内查看率</div></div>
<div class="kpi"><div class="value">≥60%</div><div class="label">14 天训练完成率</div></div>
<div class="kpi"><div class="value">≥50%</div><div class="label">60 天复测率</div></div>
<div class="kpi"><div class="value">≥20%</div><div class="label">报告→课程转化率</div></div>
</div>
</div>
</section>
<!-- 2. Architecture -->
<section id="architecture">
<div class="section-header">
<div class="section-num">2</div>
<h2>总体系统架构</h2>
</div>
<div class="card">
<h3>分层架构</h3>
<div class="mermaid-wrap">
<pre class="mermaid">
flowchart TB
subgraph CLIENT["客户端层"]
MP["微信小程序 / H5 家长端"]
TR["儿童训练端"]
AD["Web 管理后台"]
end
subgraph GATEWAY["网关层"]
GW["鉴权 JWT · 限流 · 审计 · requestId"]
end
subgraph BIZ["业务服务层"]
AUTH["Auth / User"]
CHILD["Child Profile"]
VIDEO["Video / Analysis"]
TRAIN["Training"]
COMM["Commerce"]
OPS["Admin / Ops"]
end
subgraph AI["AI 服务层(异步)"]
VW["Video Worker"]
POSE["Pose 服务"]
SCORE["评分服务"]
AGENT["Agent 解释"]
end
subgraph DATA["数据设施层"]
MYSQL[("MySQL 8.x")]
REDIS[("Redis")]
OSS[("对象存储 OSS")]
LOG["日志 / 监控"]
end
CLIENT --> GATEWAY --> BIZ
BIZ --> AI
BIZ --> DATA
AI --> DATA
</pre>
</div>
</div>
<div class="card">
<h3>五大设计原则</h3>
<div class="grid-2">
<div>
<p><strong>① 业务与 AI 解耦</strong><br>长任务异步化,HTTP 不阻塞,前端轮询/WebSocket 查状态。</p>
</div>
<div>
<p><strong>② 全链路可追溯</strong><br>保留关键点、指标、模型版本、Agent 提示词版本。</p>
</div>
<div>
<p><strong>③ 多租户隔离</strong><br>机构数据按 tenant_id 隔离,教练仅访问授权儿童。</p>
</div>
<div>
<p><strong>④ 接口契约优先</strong><br>以 openapi.yaml 为单一事实来源,向后兼容扩展。</p>
</div>
<div>
<p><strong>⑤ 幂等与审计</strong><br>写接口 Idempotency-Key;复核/退款/权限变更全量审计。</p>
</div>
</div>
</div>
</section>
<!-- 3. Modules -->
<section id="modules">
<div class="section-header">
<div class="section-num">3</div>
<h2>模块划分与职责</h2>
</div>
<div class="card">
<h3>业务服务模块</h3>
<table>
<thead>
<tr><th>模块</th><th>职责</th><th>核心数据</th></tr>
</thead>
<tbody>
<tr><td><strong>Auth/User</strong></td><td>手机/微信登录、角色、租户</td><td>users, tenants</td></tr>
<tr><td><strong>Child Profile</strong></td><td>儿童档案、成长指标、授权</td><td>children, child_measurements</td></tr>
<tr><td><strong>Video/Analysis</strong></td><td>直传签名、任务、报告</td><td>videos, analysis_tasks, reports</td></tr>
<tr><td><strong>Training</strong></td><td>动作库、计划、打卡、复测</td><td>exercises, training_plans</td></tr>
<tr><td><strong>Commerce</strong></td><td>套餐、订单、会员权益</td><td>products, orders</td></tr>
<tr><td><strong>Admin/Ops</strong></td><td>线索、看板、审计</td><td>operation_leads, audit_logs</td></tr>
</tbody>
</table>
</div>
<div class="grid-2">
<div class="card">
<h3>AI 服务组件</h3>
<table>
<thead><tr><th>组件</th><th>技术</th></tr></thead>
<tbody>
<tr><td>Video Worker</td><td>FFmpeg + 队列</td></tr>
<tr><td>Pose 服务</td><td>MediaPipe Pose33 关键点)</td></tr>
<tr><td>评分服务</td><td>规则引擎 + 加权算法</td></tr>
<tr><td>Agent 服务</td><td>LLM + 模板约束</td></tr>
</tbody>
</table>
</div>
<div class="card">
<h3>Agent 角色分工</h3>
<table>
<thead><tr><th>Agent</th><th>输出</th></tr></thead>
<tbody>
<tr><td>Assessment</td><td>风险摘要、复核建议</td></tr>
<tr><td>Coach</td><td>周期计划、每日动作</td></tr>
<tr><td>Parent</td><td>家长可读报告文案</td></tr>
<tr><td>Operation</td><td>线索分层、触达话术</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- 4. Flow -->
<section id="flow">
<div class="section-header">
<div class="section-num">4</div>
<h2>核心业务流程</h2>
</div>
<div class="card">
<h3>家长端主流程</h3>
<div class="mermaid-wrap">
<pre class="mermaid">
flowchart LR
A["授权登录"] --> B["创建档案"]
B --> C["拍摄上传"]
C --> D["创建分析任务"]
D --> E["AI 异步处理"]
E --> F["生成报告"]
F --> G["查看建议"]
G --> H["训练打卡"]
H --> I["复测对比"]
</pre>
</div>
</div>
<div class="card">
<h3>AI 分析异步链路</h3>
<div class="mermaid-wrap">
<pre class="mermaid">
sequenceDiagram
participant P as 家长端
participant API as 后端 API
participant Q as 消息队列
participant W as AI Worker
participant A as Agent
P->>API: POST /api/analysis/tasks
API->>Q: 入队 QUEUED
API-->>P: 返回 taskId
W->>Q: 拉取任务
W->>W: 抽帧 + Pose + 指标计算
alt 置信度不足
W->>API: FAILED + 建议重拍
else 置信度合格
W->>A: 生成报告文案
A->>API: 写入 report
API-->>P: 推送/轮询 SUCCEEDED
end
</pre>
</div>
</div>
<div class="alert alert-info">
<span>💡</span>
<span><strong>MVP 最小闭环</strong>:家长 2 分钟内完成建档 + 视频上传 → 5 分钟内收到 AI 报告 → 报告含风险等级、指标解释、建议动作、免责声明。</span>
</div>
</section>
<!-- 5. Tech -->
<section id="tech">
<div class="section-header">
<div class="section-num">5</div>
<h2>技术选型建议</h2>
</div>
<div class="card">
<h3>MVP 推荐技术栈</h3>
<table>
<thead><tr><th>层级</th><th>推荐方案</th><th>说明</th></tr></thead>
<tbody>
<tr><td>后端 API</td><td>Python FastAPI / Node.js NestJS</td><td>与 OpenAPI 契约对齐</td></tr>
<tr><td>任务队列</td><td>Redis + Celery / BullMQ</td><td>分析任务削峰、重试</td></tr>
<tr><td>数据库</td><td>MySQL 8.x</td><td>已有完整 schema</td></tr>
<tr><td>对象存储</td><td>阿里云 OSS / MinIO</td><td>视频直传、生命周期归档</td></tr>
<tr><td>AI 推理</td><td>MediaPipe Pose + Python Worker</td><td>一期快速落地</td></tr>
<tr><td>Agent</td><td>大模型 API + Prompt 模板</td><td>输出受控、版本化</td></tr>
<tr><td>家长端</td><td>微信小程序(Taro/uni-app</td><td>覆盖微信生态</td></tr>
<tr><td>管理后台</td><td>Vue 3 + Element Plus</td><td>高密度信息布局</td></tr>
</tbody>
</table>
</div>
<div class="card">
<h3>环境规划</h3>
<table>
<thead><tr><th>环境</th><th>用途</th><th>要求</th></tr></thead>
<tbody>
<tr><td>dev</td><td>日常开发联调</td><td>模拟支付、测试 OSS</td></tr>
<tr><td>test</td><td>测试验收回归</td><td>数据可重置</td></tr>
<tr><td>staging</td><td>预发布/客户演示</td><td>与生产同拓扑</td></tr>
<tr><td>prod</td><td>正式服务</td><td>备份、监控、告警</td></tr>
</tbody>
</table>
</div>
</section>
<!-- 6. Roadmap -->
<section id="roadmap">
<div class="section-header">
<div class="section-num">6</div>
<h2>分阶段建设规划</h2>
</div>
<div class="card">
<div class="timeline">
<div class="timeline-item">
<h4><span class="tag tag-p0">P0</span> 方案确认</h4>
<div class="period">1 周</div>
<p>范围、架构、数据、合规边界对齐。交付:PRD 签字、架构文档、接口/DB 契约、Git 工程初始化。</p>
</div>
<div class="timeline-item">
<h4><span class="tag tag-p1">P1</span> MVP 研发</h4>
<div class="period">46 周</div>
<p>家长端 + 视频分析 + 报告 + 基础后台。交付:可演示版本、测试报告、staging 部署。</p>
</div>
<div class="timeline-item">
<h4><span class="tag tag-p2">P2</span> 试点交付</h4>
<div class="period">4 周</div>
<p>接入 1–3 家机构,跑通筛查→课程闭环。交付:试点数据、运营 SOP、教练培训。</p>
</div>
<div class="timeline-item">
<h4><span class="tag tag-p3">P3</span> 商业化增强</h4>
<div class="period">68 周</div>
<p>支付、权限、模型评估、生产运维。交付:商业版 V1.0、监控告警、备份演练。</p>
</div>
</div>
</div>
<div class="card">
<h3>P1 MVP 六周排期</h3>
<table>
<thead><tr><th>周次</th><th>模块</th><th>交付标准</th><th>优先级</th></tr></thead>
<tbody>
<tr><td>W1</td><td>工程初始化 + Auth + 儿童档案</td><td>登录、建档 CRUD、DB 迁移</td><td><span class="tag tag-must">Must</span></td></tr>
<tr><td>W2</td><td>视频上传链路</td><td>OSS 直传、视频登记、拍摄引导 UI</td><td><span class="tag tag-must">Must</span></td></tr>
<tr><td>W3</td><td>AI Worker 骨架</td><td>抽帧 + MediaPipe + 基础指标</td><td><span class="tag tag-must">Must</span></td></tr>
<tr><td>W4</td><td>报告生成 + Agent</td><td>结构化 report + 家长文案</td><td><span class="tag tag-must">Must</span></td></tr>
<tr><td>W5</td><td>家长端小程序</td><td>建档→上传→看报告完整流程</td><td><span class="tag tag-must">Must</span></td></tr>
<tr><td>W6</td><td>基础管理后台 + 联调</td><td>报告列表、任务监控、冒烟测试</td><td><span class="tag tag-should">Should</span></td></tr>
</tbody>
</table>
<div class="alert alert-warn" style="margin-top:16px">
<span>📌</span>
<span><strong>MVP 可后置</strong>:支付与会员、完整训练打卡、运营线索漏斗、多机构租户管理 → 放入 P2/P3。</span>
</div>
</div>
</section>
<!-- 7. Team -->
<section id="team">
<div class="section-header">
<div class="section-num">7</div>
<h2>团队分工建议</h2>
</div>
<div class="card">
<table>
<thead><tr><th>角色</th><th>人数</th><th>核心职责</th></tr></thead>
<tbody>
<tr><td>产品负责人</td><td>1</td><td>需求拆解、验收标准、试点反馈闭环</td></tr>
<tr><td>前端工程师</td><td>1</td><td>小程序/H5、儿童训练页、Web 后台</td></tr>
<tr><td>后端工程师</td><td>1</td><td>API、任务队列、权限、数据模型</td></tr>
<tr><td>算法工程师</td><td>1</td><td>关键点、评分规则、质量检测、Agent 约束</td></tr>
<tr><td>测试/交付</td><td>0.51</td><td>场景测试、部署验证、SOP 落地</td></tr>
</tbody>
</table>
</div>
</section>
<!-- 8. Security -->
<section id="security">
<div class="section-header">
<div class="section-num">8</div>
<h2>安全与合规架构</h2>
</div>
<div class="grid-2">
<div class="card">
<h3>数据分级</h3>
<table>
<thead><tr><th>等级</th><th>类型</th><th>策略</th></tr></thead>
<tbody>
<tr><td>L1 敏感</td><td>手机号、姓名、视频</td><td>加密/哈希、脱敏</td></tr>
<tr><td>L2 业务</td><td>报告、训练、订单</td><td>MySQL + 租户隔离</td></tr>
<tr><td>L3 衍生</td><td>关键点、指标 JSON</td><td>绑定任务、保留版本</td></tr>
<tr><td>L4 运营</td><td>线索、看板聚合</td><td>脱敏聚合</td></tr>
</tbody>
</table>
</div>
<div class="card">
<h3>合规硬性约束</h3>
<ul class="checklist">
<li>报告不得出现确诊、治疗、治愈等医疗表述</li>
<li>Agent 输出引用输入字段,保留提示词版本</li>
<li>低置信度 → 仅「建议重拍/教练复核」</li>
<li>审计日志保留 ≥ 180 天</li>
<li>写接口幂等保护(Idempotency-Key</li>
</ul>
</div>
</div>
</section>
<!-- 9. Risk -->
<section id="risk">
<div class="section-header">
<div class="section-num">9</div>
<h2>风险与应对</h2>
</div>
<div class="card">
<table>
<thead><tr><th>风险</th><th>影响</th><th>应对策略</th></tr></thead>
<tbody>
<tr><td>AI 置信度不足</td><td>报告不可用、信任低</td><td>拍摄质量前置检测 + 降级文案</td></tr>
<tr><td>医疗合规边界模糊</td><td>法律风险</td><td>PRD 约束 + Agent 过滤 + 人工复核</td></tr>
<tr><td>MVP 范围膨胀</td><td>延期交付</td><td>严格 MoSCoW,支付/运营后置</td></tr>
<tr><td>机构数据隔离</td><td>合作受阻</td><td>一期引入 tenant_id</td></tr>
<tr><td>儿童个体差异大</td><td>误报/漏报</td><td>保留教练复核,不做全自动闭环</td></tr>
</tbody>
</table>
</div>
</section>
<!-- 10. Engineering -->
<section id="engineering">
<div class="section-header">
<div class="section-num">10</div>
<h2>工程化进展(P3</h2>
</div>
<div class="grid-2">
<div class="card">
<h3>Monorepo 结构</h3>
<pre style="background:#f8fafc;padding:14px;border-radius:10px;font-size:12px;line-height:1.6;overflow:auto">happy-up/
├── contracts/ openapi + database.sql
├── apps/api/ FastAPI Starter
├── doc/ 商业交付文档包
├── docker-compose.yml
└── Makefile</pre>
<p style="margin-top:12px;font-size:13px;color:var(--muted)">
<code>make up</code> 启动 MySQL/Redis · <code>make api-dev</code> 启动 API · Swagger <code>/docs</code>
</p>
</div>
<div class="card">
<h3>产品 DemoP2 能力)</h3>
<ul class="checklist">
<li class="done">AI 实时跟练 · Ghost · 五维评分</li>
<li class="done">WebRTC 摄像头预览(校准/跟练/拍摄)</li>
<li class="done">真实 PDF 导出(4 类报告)</li>
<li class="done">28 天趋势 · 三报告对比 · 儿童端</li>
</ul>
<a href="产品交互Demo.html" class="hero-btn hero-btn-primary" style="margin-top:14px;display:inline-block">进入 Demo</a>
</div>
</div>
<div class="card" style="margin-top:16px">
<h3>Sprint 1 下一步</h3>
<table>
<thead><tr><th>序号</th><th>任务</th><th>交付标准</th></tr></thead>
<tbody>
<tr><td>1</td><td>Alembic 迁移</td><td>对接 database.sql 核心表</td></tr>
<tr><td>2</td><td>Auth JWT</td><td>登录签发 + 鉴权中间件</td></tr>
<tr><td>3</td><td>儿童档案 CRUD</td><td>落库 + 单元测试</td></tr>
<tr><td>4</td><td>分析任务队列</td><td>Redis 入队 + Worker 骨架</td></tr>
</tbody>
</table>
</div>
</section>
<!-- 11. Action -->
<section id="action">
<div class="section-header">
<div class="section-num">11</div>
<h2>近期行动清单(合伙人讨论)</h2>
</div>
<div class="grid-2">
<div class="card">
<h3>本周 P0 — 需要合伙人拍板</h3>
<ul class="checklist">
<li>确认 MVP 范围与 6 周交付目标</li>
<li>确认技术选型(FastAPI vs NestJS、云厂商)</li>
<li>确认团队配置与外包边界</li>
<li class="done">Git 初始化 + monorepo 目录结构</li>
<li class="done">从 openapi.yaml / database.sql 生成工程骨架</li>
</ul>
</div>
<div class="card">
<h3>下周起 P1 — 研发启动</h3>
<ul class="checklist">
<li>Sprint 1Auth + 儿童档案 + DB 迁移</li>
<li>确定 1 家种子机构作为试点需求来源</li>
<li>算法完成 MediaPipe 本地验证(正/侧面站姿)</li>
<li>staging 环境搭建与 CI 流水线</li>
<li>每周需求评审 + 风险评审机制启动</li>
</ul>
</div>
</div>
</section>
</div>
<a href="产品交互Demo.html" class="fab-demo" title="体验产品交互 Demo">
<span class="icon">📱</span> 产品 Demo
</a>
<footer>
儿童 AI 体态管理与运动康复平台 · 商业交付包 V1.0 · 系统架构与建设规划<br>
配套 Markdown 文档:<code>03_技术架构/系统架构与建设规划.md</code> · 生成日期 2026-07-23
</footer>
<script>
mermaid.initialize({
startOnLoad: true,
theme: 'neutral',
flowchart: { curve: 'basis', padding: 16 },
sequence: { actorMargin: 50 }
});
// Highlight active TOC on scroll
const sections = document.querySelectorAll('section[id]');
const tocLinks = document.querySelectorAll('.toc-bar a');
window.addEventListener('scroll', () => {
let current = '';
sections.forEach(s => {
if (window.scrollY >= s.offsetTop - 120) current = s.id;
});
tocLinks.forEach(a => {
a.classList.toggle('active', a.getAttribute('href') === '#' + current);
});
});
</script>
</body>
</html>
@@ -0,0 +1,424 @@
# 儿童 AI 体态管理平台 · 系统架构与建设规划
> **版本**V1.0 · **日期**2026-07-23
> **适用阶段**:MVP → 商业试点 → 商业交付 V1.0
> **主要读者**:创始团队、合伙人、产品、研发、运营、机构合作方
---
## 1. 项目定位与建设目标
### 1.1 产品定位
面向 **316 岁儿童青少年** 的 AI 体态管理与运动康复平台,围绕含胸驼背、头前伸、高低肩、骨盆姿态、膝内扣、足弓与运动协调等常见问题,提供:
- **AI 筛查**(非医疗诊断)
- **结构化报告**与可解释建议
- **训练计划**与打卡复测
- **机构 SaaS** 运营与转化闭环
> **合规边界**:平台输出用于健康管理与运动训练,不替代医院诊断;涉及疼痛、明显畸形、外伤或医生已明确限制运动的情况,必须提示线下专业评估。
### 1.2 本期建设目标
| 维度 | 目标 |
|------|------|
| 业务闭环 | 建档 → 视频采集 → AI 分析 → 报告 → 训练 → 复测 → 机构转化 |
| 技术目标 | 业务与 AI 解耦、多租户隔离、全链路可追溯、异步分析 ≤ 5 分钟 |
| 商业目标 | 4–6 周可演示 MVP,8–10 周接入 1–3 家机构试点 |
### 1.3 核心成功指标(试点阶段)
| 指标 | 定义 | 目标 |
|------|------|------|
| 分析任务达成率 | 任务进入 PROCESSING 并生成报告或可解释失败 | ≥ 90% |
| 报告查看率 | 报告产生后 30 分钟内家长首次查看 | ≥ 80% |
| 训练任务完成率 | 14 天内计划任务完成比例 | ≥ 60% |
| 训练后复测率 | 60 天内完成复测的儿童比例 | ≥ 50% |
| 课程转化率 | 看完报告后进入课程/会员 | ≥ 20% |
---
## 2. 总体系统架构
### 2.1 分层架构概览
系统采用 **云原生分层架构**:客户端层 → 网关层 → 业务服务层 → AI 服务层 → 数据设施层。
```
┌─────────────────────────────────────────────────────────────────┐
│ 客户端层 (Client) │
│ 微信小程序/H5 家长端 │ 儿童训练端 │ Web 管理后台 │
└───────────────────────────────┬─────────────────────────────────┘
│ HTTPS
┌───────────────────────────────▼─────────────────────────────────┐
│ 网关层 (API Gateway) │
│ 鉴权 JWT · 限流 · 审计 · 请求追踪 (requestId) │
└───────────────────────────────┬─────────────────────────────────┘
┌───────────────────────────────▼─────────────────────────────────┐
│ 业务服务层 (Business Services) │
│ Auth/User │ Child Profile │ Video/Analysis │ Training │ Commerce │
│ Admin/Ops │
└───────────────┬─────────────────────────────┬───────────────────┘
│ REST + 任务创建 │ 异步回调
┌───────────────▼───────────────┐ ┌───────────▼───────────────────┐
│ AI 服务层 (AI Layer) │ │ 消息队列 (Queue) │
│ Video Worker │ Pose │ Score │◄──│ Redis/RabbitMQ │
│ Agent 解释服务 │ └───────────────────────────────┘
└───────────────┬───────────────┘
┌───────────────▼─────────────────────────────────────────────────┐
│ 数据设施层 (Data Layer) │
│ MySQL 8.x │ Redis │ 对象存储 OSS │ 向量记忆 │ 日志/监控平台 │
└─────────────────────────────────────────────────────────────────┘
```
### 2.2 关键设计原则
1. **业务与 AI 解耦**:长任务异步化,前端只创建任务并轮询/WebSocket 查状态,不阻塞 HTTP 链路。
2. **全链路可追溯**:保留原始关键点、计算指标、模型版本、Agent 提示词版本与审核状态。
3. **多租户隔离**:机构数据按 `tenant_id` 隔离,教练仅访问授权儿童。
4. **接口契约优先**:以 `openapi.yaml` 为单一事实来源,向后兼容扩展。
5. **幂等与审计**:写接口支持 `Idempotency-Key`;报告复核、退款、权限变更全量审计。
---
## 3. 模块划分与职责
### 3.1 业务服务模块
| 模块 | 职责 | 核心数据表 |
|------|------|-----------|
| **Auth/User** | 手机/微信登录、角色、租户、隐私协议 | `users`, `tenants`, `users_passwords` |
| **Child Profile** | 儿童档案、成长指标、授权关系 | `children`, `child_measurements` |
| **Video/Analysis** | 直传签名、视频登记、分析任务、报告 | `videos`, `analysis_tasks`, `reports` |
| **Training** | 动作库、训练计划、打卡、复测 | `exercises`, `training_plans`, `training_records` |
| **Commerce** | 套餐、订单、会员权益 | `products`, `orders` |
| **Admin/Ops** | 运营线索、看板、审计、配置 | `operation_leads`, `audit_logs`, `data_retention_rules` |
### 3.2 AI 服务模块
| 组件 | 输入 | 输出 | 技术选型 |
|------|------|------|----------|
| **Video Worker** | 对象存储视频 | 帧序列、质量检测结果 | FFmpeg + 队列消费 |
| **Pose 服务** | 图片/视频帧 | 33 关键点坐标 + 置信度 | MediaPipe Pose(一期) |
| **评分服务** | 关键点序列 | 体态指标、动作评分、风险等级 | 规则引擎 + 加权算法 |
| **Agent 服务** | 结构化指标 | 报告文案、训练建议、家长话术 | LLM + 模板约束 |
#### Agent 角色分工
| Agent | 职责 | 输出 |
|-------|------|------|
| Assessment Agent | 解读视觉指标与置信度 | 风险摘要、重点指标、复核建议 |
| Coach Agent | 结合年龄与目标生成计划 | 周期计划、每日动作、进阶规则 |
| Parent Agent | 专业内容家长化翻译 | 报告文案、提醒、复测建议 |
| Operation Agent | 机构线索分层与触达 | 人群标签、话术、任务建议 |
### 3.3 客户端模块
| 端 | 用户 | 核心页面/流程 |
|----|------|--------------|
| **小程序/H5 家长端** | 家长 | 登录 → 建档 → 拍摄引导上传 → 报告 → 训练计划 → 订单 |
| **儿童训练端** | 儿童/家长陪同 | 今日训练 → 动作演示 → 跟练计时 → 打卡反馈 |
| **Web 管理后台** | 教练/运营/管理员 | 线索 → 档案 → 报告复核 → 课程 → 数据看板 |
---
## 4. 核心业务流程
### 4.1 家长端主流程
```
授权登录 → 隐私协议确认 → 创建儿童档案
→ 按引导拍摄/upload-token 直传 OSS
→ 登记视频 → 创建 analysis_task
→ 异步 AI 处理(Pose + 评分 + Agent
→ 生成 report → 家长查看
→ 购买/领取 training_plan → 每日打卡 → 复测
```
### 4.2 AI 分析异步链路
```
POST /api/analysis/tasks (返回 taskId)
队列 QUEUED → Worker 拉取
PROCESSING: 抽帧 → Pose → 指标计算 → 质量校验
├── 置信度不足 → FAILED + 建议重拍
Agent 生成报告文案 → 写入 reports
Webhook 回调后端 → status=SUCCEEDED + reportId
家长端轮询/推送 → 展示报告
```
### 4.3 教练复核流程(试点阶段)
```
AI 报告 (draft) → 教练后台复核 → 调整建议/关联课程
→ 报告 published → 下发家长端 → 跟踪训练与复测
```
---
## 5. 技术选型建议
### 5.1 推荐技术栈(MVP 阶段)
| 层级 | 推荐方案 | 说明 |
|------|----------|------|
| **后端 API** | Python FastAPI 或 Node.js NestJS | 与 OpenAPI 契约对齐,异步友好 |
| **任务队列** | Redis + Celery / BullMQ | 分析任务削峰、重试 |
| **数据库** | MySQL 8.x | 已有完整 schema`database.sql` |
| **缓存** | Redis | Session、限流、队列、热点数据 |
| **对象存储** | 阿里云 OSS / MinIO(dev) | 视频直传、生命周期归档 |
| **AI 推理** | MediaPipe Pose + Python Worker | 一期快速落地,后续可替换模型 |
| **Agent** | OpenAI API / 国产大模型 + Prompt 模板 | 输出受控,版本化管理 |
| **家长端** | 微信小程序(Taro/uni-app | 覆盖微信生态 |
| **管理后台** | Vue 3 + Element Plus | 高密度信息布局 |
| **网关** | Nginx / Kong | 鉴权、限流、TLS 终结 |
| **监控** | Prometheus + Grafana / 云监控 | 业务 + AI 任务双维度 |
### 5.2 环境规划
| 环境 | 用途 | 要求 |
|------|------|------|
| dev | 日常开发联调 | 模拟支付、测试 OSS |
| test | 测试验收回归 | 数据可重置,配置接近生产 |
| staging | 预发布/客户演示 | 与生产同版本、同拓扑 |
| prod | 正式服务 | 备份、监控、告警、权限收敛 |
---
## 6. 分阶段建设规划
### 6.1 阶段总览
| 阶段 | 周期 | 目标 | 关键交付物 |
|------|------|------|-----------|
| **P0 方案确认** | 1 周 | 范围、架构、数据、合规边界对齐 | PRD 签字、架构文档、接口/DB 契约、Git 工程初始化 |
| **P1 MVP 研发** | 4–6 周 | 家长端 + 视频分析 + 报告 + 基础后台 | 可演示版本、测试报告、staging 部署 |
| **P2 试点交付** | 4 周 | 接入 1–3 家机构,跑通筛查→课程闭环 | 试点数据、运营 SOP、教练培训材料 |
| **P3 商业化增强** | 6–8 周 | 支付、权限、模型评估、生产运维 | 商业版 V1.0、监控告警、备份演练 |
### 6.2 P1 MVP 详细排期(建议)
| 周次 | 模块 | 交付标准 |
|------|------|----------|
| W1 | 工程初始化 + Auth + 儿童档案 | 登录、建档 CRUD、DB 迁移跑通 |
| W2 | 视频上传链路 | OSS 直传、视频登记、质量预检 UI |
| W3 | AI Worker 骨架 | 抽帧 + MediaPipe + 基础指标输出 |
| W4 | 报告生成 + Agent | 结构化 report + 家长可读文案 |
| W5 | 家长端小程序 | 建档→上传→看报告完整流程 |
| W6 | 基础管理后台 + 联调 | 报告列表、任务监控、冒烟测试 |
**MVP 最小闭环(Must Have):**
> 家长 2 分钟内完成建档 + 视频上传 → 5 分钟内收到 AI 报告 → 报告含风险等级、指标解释、建议动作、免责声明
**MVP 可后置(Should/Could):**
- 支付与会员
- 完整训练打卡
- 运营线索漏斗
- 多机构租户管理
### 6.3 团队分工建议
| 角色 | 人数 | 职责 |
|------|------|------|
| 产品负责人 | 1 | 需求拆解、验收标准、试点反馈闭环 |
| 前端工程师 | 1 | 小程序/H5、儿童训练页、Web 后台 |
| 后端工程师 | 1 | API、任务队列、权限、数据模型 |
| 算法工程师 | 1 | 关键点、评分规则、质量检测、Agent 约束 |
| 测试/交付 | 0.5–1 | 场景测试、部署验证、SOP 落地 |
---
## 7. 数据与安全架构
### 7.1 数据分层
| 等级 | 数据类型 | 存储策略 |
|------|----------|----------|
| L1 敏感 | 手机号、儿童姓名、视频原片 | 加密/哈希、脱敏展示、访问审计 |
| L2 业务 | 报告、训练记录、订单 | MySQL + 租户隔离 |
| L3 衍生 | 关键点、指标 JSON、Agent 输出 | 与任务绑定,保留模型版本 |
| L4 运营 | 线索、看板聚合 | 脱敏聚合,按租户隔离 |
### 7.2 安全与合规要点
- 报告 **不得** 出现确诊、治疗、治愈等医疗表述
- Agent 输出引用输入字段,保留提示词版本
- 低置信度 → 仅输出「建议重拍/教练复核」,不给强结论
- 审计日志保留 ≥ 180 天;视频/报告按 `retention_days` 归档
- 写接口幂等保护(`api_idempotency_keys` 表)
---
## 8. 部署拓扑
### 8.1 MVP 单区域部署
```
┌─────────────┐
用户 ──────────► │ Nginx │
│ API Gateway│
└──────┬──────┘
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ API 服务 │ │AI Worker │ │ 后台服务 │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
┌────┴────────────┴────────────┴────┐
│ MySQL │ Redis │ OSS │ 日志 │
└───────────────────────────────────┘
```
### 8.2 商业化阶段演进
- AI Worker、视频转码、报告生成 **拆分为独立队列消费者**
- 引入灰度发布、多环境配置、自动扩缩容
- 模型/评分规则/报告模板 **版本化独立发布**
---
## 9. 风险与应对
| 风险 | 影响 | 应对策略 |
|------|------|----------|
| AI 置信度不足导致报告不可用 | 用户体验差、机构信任低 | 拍摄质量前置检测 + 低置信度降级文案 |
| 医疗合规边界模糊 | 法律风险 | PRD 硬性约束 + Agent 过滤 + 人工复核 |
| MVP 范围膨胀 | 延期交付 | 严格 MoSCoW,支付/运营后置 |
| 机构试点数据隔离 | 合作受阻 | 一期即引入 tenant_id,权限最小化 |
| 算法儿童个体差异 | 误报/漏报 | 保留教练复核环节,不做全自动闭环 |
---
## 10. 工程化 MonorepoP3
### 10.1 仓库结构
```
happy-up/
├── contracts/ # openapi.yaml + database.sql(从 doc/ 同步)
├── apps/api/ # FastAPI 后端 Starter
├── doc/ # 商业交付文档包 V1.0
├── docker-compose.yml # MySQL 8 + Redis 7
└── Makefile
```
### 10.2 产品 Demo 能力(P1/P2
| 能力 | 状态 | 说明 |
|------|------|------|
| AI 实时跟练打卡 | ✅ | Ghost 叠加 · Coach Agent cue · 五维评分 |
| WebRTC 摄像头预览 | ✅ | 机位校准/跟练/拍摄引导页 |
| 真实 PDF 导出 | ✅ | 筛查/跟练/趋势/三报告对比 |
| 28 天趋势 + 三报告对比 | ✅ | 商业闭环可视化 |
| 儿童训练端 | ✅ | 大按钮 + 儿童版 cue |
入口:`doc/.../03_技术架构/产品交互Demo.html`
### 10.3 API Starter
- **框架**FastAPI + Pydantic v2 + SQLAlchemy 2
- **契约对齐**:路由覆盖 `openapi.yaml` 全部 path(当前 Mock 数据,与 Demo 一致)
- **统一响应**`StandardResponse` + `requestId` 中间件
- **本地依赖**`make up` 启动 MySQL/Redis`make api-dev` 启动 API
详见仓库根目录 `README.md``apps/api/README.md`
### 10.4 Sprint 1 已完成
- JWT 登录(验证码 682139+ Bearer 鉴权
- 儿童档案 CRUD 落库(MySQL
- Alembic baseline + `make api-seed`
- 产品 Demo **API 联调模式**(登录 + 首页档案)
### 10.5 Sprint 2 已完成
- 视频直传凭证 + 登记落库(`videos` 表)
- 分析任务 Redis 队列 + Worker 骨架 + 内联处理(开发模式)
- 报告生成落库(`reports` 表 · 对齐 Demo 指标)
- Demo **筛查全流程 API 联调**(上传 → 分析 → 报告)
### 10.6 Sprint 3 已完成
- 训练计划 CRUD + 打卡记录落库(`training_plans` / `training_records`
- Admin 运营看板真实 DB 聚合
- Demo 全链路 API 联调(含训练计划页 + 打卡写入 + 后台 KPI)
- `apps/web/` 前端工程占位
### 10.7 Sprint 4 已完成
- 本地直传 + MinIO 预签名 URL`OSS_ENABLED=true` + `docker compose` MinIO
- `PUT /api/videos/direct-upload` 本地上传回退
- MediaPipe 分析骨架(`pip install -e ".[ai]"` 可选)
- `apps/web` Vue 3 H5(登录 / 档案 / 筛查联调)
- Admin 看板按 `tenant_id` 隔离聚合
### 10.8 Sprint 5 已完成
- MediaPipe 帧级评分(`pose_metrics.py` 纯函数 + OpenCV 抽帧)
- 服务端 PDF 导出 `GET /api/reports/{id}/pdf`
- OSS 生产配置:`OSS_PROVIDER=aliyun` + `OSS_CDN_BASE_URL`
- H5 四 Tab UI(首页/筛查/报告/训练)对齐 Demo 配色
- 微信小程序壳 `apps/mini`
### 10.9 Sprint 6 下一步
1. 真实视频数据集标定与模型精度调优
2. 小程序完整 Tab + 跟练页
3. 报告复核工作流 + 消息通知
4. 生产部署(K8s / CI-CD
---
## 11. 近期行动清单(合伙人讨论用)
### 本周(P0
- [ ] 合伙人确认 MVP 范围与 6 周交付目标
- [ ] 确认技术选型(FastAPI vs NestJS、云厂商)
- [ ] 确认团队配置与外包边界
- [x] Git 初始化 + monorepo 目录结构
- [x]`openapi.yaml` / `database.sql` 生成工程骨架
### 下周起(P1 启动)
- [ ] Sprint 1Auth + 儿童档案 + DB 迁移
- [ ] 确定 1 家种子机构作为试点需求来源
- [ ] 算法同学完成 MediaPipe 本地验证(正面/侧面站姿)
---
## 附录:文档索引
| 文档 | 路径 |
|------|------|
| 产品 PRD | `02_企业级PRD/PRD完整版.docx` |
| 企业级架构 | `03_技术架构/企业级系统架构.docx` |
| **本架构与建设规划** | `03_技术架构/系统架构与建设规划.md` |
| **合伙人讨论 HTML** | `03_技术架构/系统架构与建设规划.html` |
| 数据库设计 | `06_数据库设计/database.sql` |
| API 契约 | `07_API接口/openapi.yaml` |
| AI 算法设计 | `04_AI视觉算法/AI视觉算法详细设计.docx` |
| Agent 规范 | `08_Agent智能系统/Agent设计规范.docx` |
| 研发计划 | `12_研发计划/研发计划与项目管理.docx` |
| 部署运维 | `14_部署运维/生产部署运维.docx` |
---
*本文档基于商业交付包 V1.0 现有材料整理,用于创始团队与合伙人架构讨论及研发启动对齐。*
@@ -0,0 +1,316 @@
-- Kids AI Posture Platform V1.0 database schema
-- MySQL 8.x
-- 目标:满足审计、幂等、治理、隐私与可追溯性要求
CREATE TABLE tenants (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(128) NOT NULL,
type VARCHAR(32) NOT NULL DEFAULT 'organization',
status VARCHAR(32) NOT NULL DEFAULT 'active',
retention_days INT NOT NULL DEFAULT 1095,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CHECK (type IN ('organization','school','clinic','mall','other')),
CHECK (status IN ('active','inactive','frozen','closed')),
CHECK (retention_days BETWEEN 30 AND 3650)
);
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
tenant_id BIGINT NULL,
phone VARCHAR(32),
phone_hash VARCHAR(128),
wechat_openid VARCHAR(128),
role VARCHAR(32) NOT NULL DEFAULT 'parent',
status VARCHAR(32) NOT NULL DEFAULT 'active',
consent_signed BOOLEAN NOT NULL DEFAULT FALSE,
privacy_version VARCHAR(16) DEFAULT 'v1',
last_login_at TIMESTAMP NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_users_tenant_role (tenant_id, role),
UNIQUE KEY uk_users_phone_hash (phone_hash),
UNIQUE KEY uk_users_wechat_openid (wechat_openid),
CHECK (role IN ('parent','coach','org_admin','platform_admin')),
CHECK (status IN ('active','inactive','blocked'))
);
CREATE TABLE users_passwords (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
password_hash VARCHAR(256) NOT NULL,
salt VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_user_password (user_id)
);
CREATE TABLE children (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
tenant_id BIGINT NULL,
parent_user_id BIGINT NOT NULL,
coach_user_id BIGINT NULL,
name VARCHAR(64) NOT NULL,
gender VARCHAR(16) NOT NULL DEFAULT 'unknown',
birthday DATE NOT NULL,
height DECIMAL(5,2),
weight DECIMAL(5,2),
contraindications TEXT,
status VARCHAR(32) NOT NULL DEFAULT 'active',
deleted_at TIMESTAMP NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_children_parent (parent_user_id),
KEY idx_children_tenant_coach (tenant_id, coach_user_id),
KEY idx_children_status (status),
CHECK (gender IN ('male','female','unknown')),
CHECK (status IN ('active','inactive','archived')),
CHECK (height IS NULL OR (height > 20 AND height < 240)),
CHECK (weight IS NULL OR (weight > 5 AND weight < 250))
);
CREATE TABLE child_measurements (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
child_id BIGINT NOT NULL,
height DECIMAL(5,2),
weight DECIMAL(5,2),
source VARCHAR(32) NOT NULL DEFAULT 'manual',
measured_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_measurements_child_time (child_id, measured_at),
CHECK (source IN ('manual','device','coach','report')),
CHECK (height IS NULL OR (height > 20 AND height < 240)),
CHECK (weight IS NULL OR (weight > 5 AND weight < 250))
);
CREATE TABLE videos (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
child_id BIGINT NOT NULL,
uploaded_by BIGINT NOT NULL,
scene VARCHAR(64) NOT NULL,
object_key VARCHAR(512) NOT NULL,
duration_seconds INT,
width INT,
height INT,
size_bytes BIGINT,
codec VARCHAR(32),
quality_result JSON,
status VARCHAR(32) NOT NULL DEFAULT 'uploaded',
archive_until_date DATE NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_videos_child_scene (child_id, scene),
KEY idx_videos_status (status),
UNIQUE KEY uk_videos_object_key (object_key),
CHECK (scene IN ('front_posture','side_posture','squat','balance','gait','custom')),
CHECK (status IN ('uploaded','transcoding','failed','ready','archived')),
CHECK (duration_seconds IS NULL OR duration_seconds BETWEEN 1 AND 1800),
CHECK (size_bytes IS NULL OR size_bytes BETWEEN 1 AND 10737418240)
);
CREATE TABLE analysis_tasks (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
child_id BIGINT NOT NULL,
video_id BIGINT NOT NULL,
task_type VARCHAR(64) NOT NULL,
status VARCHAR(32) NOT NULL DEFAULT 'CREATED',
progress INT NOT NULL DEFAULT 0,
model_version VARCHAR(64),
error_code VARCHAR(64),
error_message VARCHAR(512),
result JSON,
idempotency_key VARCHAR(128),
retry_count INT NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
started_at TIMESTAMP NULL,
finished_at TIMESTAMP NULL,
UNIQUE KEY uk_analysis_idempotency (child_id, video_id, task_type, idempotency_key),
KEY idx_analysis_child_status (child_id, status),
KEY idx_analysis_video (video_id),
KEY idx_analysis_created (created_at),
CHECK (status IN ('CREATED','QUEUED','PROCESSING','SUCCEEDED','FAILED','CANCELLED')),
CHECK (task_type IN ('posture_screening','movement_scoring','reassessment')),
CHECK (progress BETWEEN 0 AND 100),
CHECK (retry_count BETWEEN 0 AND 20)
);
CREATE TABLE reports (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
child_id BIGINT NOT NULL,
task_id BIGINT NOT NULL,
report_type VARCHAR(64) NOT NULL DEFAULT 'posture_screening',
risk_level VARCHAR(32) NOT NULL,
summary TEXT NOT NULL,
metrics JSON NOT NULL,
recommendations JSON NOT NULL,
disclaimer TEXT NOT NULL,
status VARCHAR(32) NOT NULL DEFAULT 'draft',
reviewed_by BIGINT NULL,
reviewed_at TIMESTAMP NULL,
published_at TIMESTAMP NULL,
expires_at DATE NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_reports_task (task_id),
KEY idx_reports_child_status (child_id, status),
CHECK (risk_level IN ('low','medium','high','review_required')),
CHECK (status IN ('draft','published','retracted','archived'))
);
CREATE TABLE exercises (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(128) NOT NULL,
category VARCHAR(64) NOT NULL,
target_issue VARCHAR(128),
difficulty VARCHAR(32) NOT NULL DEFAULT 'basic',
duration_seconds INT NOT NULL DEFAULT 60,
media_url VARCHAR(512),
thumbnail_url VARCHAR(512),
rules JSON,
status VARCHAR(32) NOT NULL DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_exercises_category (category, status),
CHECK (difficulty IN ('basic','intermediate','advanced')),
CHECK (status IN ('active','offline','deprecated')),
CHECK (duration_seconds BETWEEN 20 AND 1800)
);
CREATE TABLE training_plans (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
child_id BIGINT NOT NULL,
report_id BIGINT NULL,
coach_user_id BIGINT NULL,
goal VARCHAR(256) NOT NULL,
cycle_days INT NOT NULL DEFAULT 28,
status VARCHAR(32) NOT NULL DEFAULT 'draft',
plan_detail JSON NOT NULL,
started_at TIMESTAMP NULL,
ended_at TIMESTAMP NULL,
deleted_at TIMESTAMP NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_training_plans_child_status (child_id, status),
CHECK (cycle_days BETWEEN 7 AND 180),
CHECK (status IN ('draft','active','completed','paused','cancelled'))
);
CREATE TABLE training_records (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
plan_id BIGINT NOT NULL,
child_id BIGINT NOT NULL,
exercise_id BIGINT NOT NULL,
completed BOOLEAN NOT NULL DEFAULT FALSE,
score INT,
duration_seconds INT,
feedback JSON,
note VARCHAR(512),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_training_records_plan (plan_id),
KEY idx_training_records_child_time (child_id, created_at),
CHECK (score IS NULL OR score BETWEEN 0 AND 100),
CHECK (duration_seconds IS NULL OR duration_seconds BETWEEN 1 AND 7200)
);
CREATE TABLE products (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
tenant_id BIGINT NULL,
name VARCHAR(128) NOT NULL,
product_type VARCHAR(32) NOT NULL,
price_cents INT NOT NULL,
duration_days INT NULL,
benefits JSON NOT NULL,
limit_child INTEGER NOT NULL DEFAULT 1,
status VARCHAR(32) NOT NULL DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CHECK (product_type IN ('video_pack','training_plan','membership','assessment_bundle','course_package')),
CHECK (status IN ('active','inactive','discontinued')),
CHECK (price_cents >= 0),
CHECK (duration_days IS NULL OR duration_days BETWEEN 1 AND 3650)
);
CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
child_id BIGINT NULL,
product_id BIGINT NOT NULL,
amount_cents INT NOT NULL,
pay_status VARCHAR(32) NOT NULL DEFAULT 'pending',
payment_channel VARCHAR(32),
paid_at TIMESTAMP NULL,
canceled_at TIMESTAMP NULL,
refund_status VARCHAR(32) DEFAULT 'none',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_orders_user_status (user_id, pay_status),
KEY idx_orders_child (child_id),
CHECK (pay_status IN ('pending','paid','failed','closed','refunding','refunded')),
CHECK (refund_status IN ('none','requested','processing','completed','rejected')),
CHECK (amount_cents >= 0)
);
CREATE TABLE operation_leads (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
tenant_id BIGINT NOT NULL,
child_id BIGINT NULL,
source VARCHAR(64) NOT NULL,
stage VARCHAR(32) NOT NULL DEFAULT 'new',
owner_user_id BIGINT NULL,
score INT DEFAULT 0,
priority TINYINT DEFAULT 3,
next_follow_at TIMESTAMP NULL,
note TEXT,
touched_at TIMESTAMP NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_leads_tenant_stage (tenant_id, stage),
KEY idx_leads_owner_next (owner_user_id, next_follow_at),
CHECK (source IN ('wechat','h5','miniapp','partner','referral','offline_campaign')),
CHECK (stage IN ('new','contacted','qualified','closed','lost','churned')),
CHECK (priority BETWEEN 1 AND 5),
CHECK (score BETWEEN 0 AND 100)
);
CREATE TABLE audit_logs (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
tenant_id BIGINT NULL,
actor_user_id BIGINT NOT NULL,
action VARCHAR(128) NOT NULL,
resource_type VARCHAR(64) NOT NULL,
resource_id BIGINT NULL,
request_id VARCHAR(64),
ip VARCHAR(64),
user_agent VARCHAR(256),
payload JSON,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_audit_actor_time (actor_user_id, created_at),
KEY idx_audit_resource (resource_type, resource_id)
);
CREATE TABLE data_retention_rules (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
tenant_id BIGINT NULL,
resource_type VARCHAR(64) NOT NULL,
archive_after_days INT NOT NULL,
delete_after_days INT NOT NULL,
legal_basis VARCHAR(128),
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_retention (tenant_id, resource_type),
CHECK (delete_after_days >= archive_after_days),
CHECK (archive_after_days >= 30)
);
CREATE TABLE api_idempotency_keys (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
scope VARCHAR(32) NOT NULL,
idempotency_key VARCHAR(128) NOT NULL,
request_path VARCHAR(255) NOT NULL,
request_hash CHAR(64) NOT NULL,
response_status INT,
response_body JSON,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_idempotency_scope_key (scope, idempotency_key),
KEY idx_idempotency_created (created_at)
);
-- 运行时可选索引补充说明(按需执行)
-- CREATE INDEX idx_analysis_status_updated ON analysis_tasks(status, updated_at);
-- CREATE INDEX idx_reports_risk_level ON reports(risk_level, created_at);
-- CREATE INDEX idx_orders_pay_status_updated ON orders(pay_status, updated_at);
@@ -0,0 +1,670 @@
openapi: 3.0.3
info:
title: Kids AI Posture Platform API
version: 1.0.0
description: |
儿童AI体态管理与运动康复平台 V1.0 API 契约。
所有报告用于健康管理建议,不构成医疗诊断。接口返回统一包含 requestId 以便追踪。
servers:
- url: https://api.example.com
description: production
- url: https://staging-api.example.com
description: staging
security:
- bearerAuth: []
x-error-model: &error-model
code: integer
message: string
details:
type: object
additionalProperties: true
requestId: string
tags:
- name: Auth
- name: Children
- name: Videos
- name: Analysis
- name: Reports
- name: Training
- name: Admin
paths:
/api/auth/login:
post:
tags: [Auth]
summary: 手机号或微信授权登录
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
examples:
phone:
summary: 手机验证码
value:
loginType: phone_code
credential: "186xxxx0000"
code: "682139"
wechat:
summary: 微信授权码
value:
loginType: wechat
credential: "wx_auth_code"
responses:
'200':
description: 登录成功
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
'401':
description: 登录失败
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/children:
get:
tags: [Children]
summary: 获取当前用户可访问的儿童档案
parameters:
- name: page
in: query
schema: { type: integer, minimum: 1, default: 1 }
- name: pageSize
in: query
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
responses:
'200':
description: 儿童档案分页列表
content:
application/json:
schema:
$ref: '#/components/schemas/ChildrenPagedResponse'
post:
tags: [Children]
summary: 创建儿童档案
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChildCreateRequest'
responses:
'201':
description: 创建成功
headers:
Idempotency-Key:
description: 冪等键回显,用于重试去重核对
schema: { type: string }
content:
application/json:
schema:
$ref: '#/components/schemas/ChildResponse'
'400':
description: 请求参数错误
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/children/{childId}:
parameters:
- $ref: '#/components/parameters/ChildId'
get:
tags: [Children]
summary: 获取儿童档案详情
responses:
'200':
description: 档案详情
content:
application/json:
schema:
$ref: '#/components/schemas/ChildResponse'
'404':
description: 资源不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
patch:
tags: [Children]
summary: 更新儿童档案
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChildUpdateRequest'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
$ref: '#/components/schemas/ChildResponse'
'409':
description: 更新冲突(数据并发)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags: [Children]
summary: 注销/归档儿童档案
responses:
'204':
description: 归档成功
/api/videos/upload-token:
post:
tags: [Videos]
summary: 获取视频直传凭证
description: 建议请求头携带 Idempotency-Key,避免重试产生重复录像对象。
parameters:
- name: Idempotency-Key
in: header
required: false
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UploadTokenRequest'
responses:
'200':
description: 上传凭证
content:
application/json:
schema:
$ref: '#/components/schemas/UploadTokenResponse'
'429':
description: 请求过于频繁
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/videos:
post:
tags: [Videos]
summary: 登记已上传视频
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/VideoCreateRequest'
responses:
'201':
description: 视频登记成功
content:
application/json:
schema:
$ref: '#/components/schemas/VideoResponse'
'409':
description: 去重/重复提交
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/analysis/tasks:
post:
tags: [Analysis]
summary: 创建AI分析任务
description: 同一 childId+videoId+taskType 可复用幂等键创建。
parameters:
- name: Idempotency-Key
in: header
required: false
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AnalysisTaskCreateRequest'
responses:
'201':
description: 任务创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/AnalysisTaskResponse'
'409':
description: 重复任务,返回已有任务
content:
application/json:
schema:
$ref: '#/components/schemas/AnalysisTaskResponse'
/api/analysis/tasks/{taskId}:
get:
tags: [Analysis]
summary: 查询分析任务状态
parameters:
- $ref: '#/components/parameters/TaskId'
responses:
'200':
description: 任务状态
content:
application/json:
schema:
$ref: '#/components/schemas/AnalysisTaskResponse'
'404':
description: 任务不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/analysis/tasks/{taskId}/cancel:
post:
tags: [Analysis]
summary: 取消分析任务
parameters:
- $ref: '#/components/parameters/TaskId'
responses:
'200':
description: 取消成功
content:
application/json:
schema:
$ref: '#/components/schemas/StandardResponse'
/api/analysis/webhook:
post:
tags: [Analysis]
summary: 分析结果回调(异步)
description: 系统内部回调给后端事件网关,需使用 HMAC 签名。
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AnalysisTaskWebhook'
responses:
'204':
description: 接收成功
/api/reports/{reportId}:
get:
tags: [Reports]
summary: 获取体态分析报告
parameters:
- $ref: '#/components/parameters/ReportId'
responses:
'200':
description: 报告详情
content:
application/json:
schema:
$ref: '#/components/schemas/ReportResponse'
/api/training/plans:
post:
tags: [Training]
summary: 创建训练计划
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TrainingPlanCreateRequest'
responses:
'201':
description: 训练计划创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/TrainingPlanResponse'
/api/training/plans/{planId}:
parameters:
- name: planId
in: path
required: true
schema:
type: integer
get:
tags: [Training]
summary: 获取训练计划
responses:
'200':
description: 训练计划详情
content:
application/json:
schema:
$ref: '#/components/schemas/TrainingPlanResponse'
/api/training/plans/{planId}/records:
post:
tags: [Training]
summary: 提交训练打卡记录
parameters:
- name: planId
in: path
required: true
schema: { type: integer }
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TrainingRecordCreateRequest'
responses:
'201':
description: 打卡成功
content:
application/json:
schema:
$ref: '#/components/schemas/TrainingRecordResponse'
/api/admin/dashboard:
get:
tags: [Admin]
summary: 获取机构运营看板
responses:
'200':
description: 看板指标
content:
application/json:
schema:
$ref: '#/components/schemas/AdminDashboardResponse'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
parameters:
ChildId:
name: childId
in: path
required: true
schema: { type: integer }
TaskId:
name: taskId
in: path
required: true
schema: { type: integer }
ReportId:
name: reportId
in: path
required: true
schema: { type: integer }
schemas:
ApiMeta:
type: object
properties:
requestId: { type: string }
timestamp: { type: string, format: date-time }
traceId: { type: string }
StandardResponse:
type: object
properties:
code: { type: integer }
message: { type: string }
data: { type: object, nullable: true }
meta: { $ref: '#/components/schemas/ApiMeta' }
ErrorResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
code: { type: integer, example: 10003 }
message: { type: string, example: parameter_validation_failed }
data:
type: object
properties:
errorCode: { type: string }
path: { type: string }
PagedMeta:
type: object
properties:
page: { type: integer }
pageSize: { type: integer }
total: { type: integer }
hasMore: { type: boolean }
LoginRequest:
type: object
required: [loginType, credential]
properties:
loginType: { type: string, enum: [phone_code, wechat] }
credential: { type: string }
code: { type: string }
LoginResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data:
type: object
properties:
token: { type: string }
user: { $ref: '#/components/schemas/User' }
User:
type: object
properties:
id: { type: integer }
phoneMasked: { type: string }
role: { type: string, enum: [parent, coach, org_admin, platform_admin] }
ChildCreateRequest:
type: object
required: [name, birthday]
properties:
name: { type: string }
birthday: { type: string, format: date }
gender: { type: string, enum: [male, female, unknown] }
height: { type: number }
weight: { type: number }
contraindications: { type: string }
ChildUpdateRequest:
allOf:
- $ref: '#/components/schemas/ChildCreateRequest'
Child:
type: object
properties:
id: { type: integer }
name: { type: string }
birthday: { type: string, format: date }
age: { type: integer }
height: { type: number }
weight: { type: number }
status: { type: string }
ChildResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data: { $ref: '#/components/schemas/Child' }
ChildrenPagedResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data:
type: object
properties:
list:
type: array
items: { $ref: '#/components/schemas/Child' }
page: { $ref: '#/components/schemas/PagedMeta' }
UploadTokenRequest:
type: object
required: [childId, fileName, contentType, size]
properties:
childId: { type: integer }
fileName: { type: string }
contentType: { type: string, example: video/mp4 }
size: { type: integer }
UploadTokenResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data:
type: object
properties:
uploadUrl: { type: string }
objectKey: { type: string }
expireAt: { type: string, format: date-time }
VideoCreateRequest:
type: object
required: [childId, objectKey, scene]
properties:
childId: { type: integer }
objectKey: { type: string }
scene:
type: string
enum: [front_posture, side_posture, squat, balance, gait]
captureHint: { type: string }
VideoResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data:
type: object
properties:
id: { type: integer }
status: { type: string, enum: [uploaded, rejected, archived] }
AnalysisTaskCreateRequest:
type: object
required: [childId, videoId, taskType]
properties:
childId: { type: integer }
videoId: { type: integer }
taskType: { type: string, enum: [posture_screening, movement_scoring, reassessment] }
AnalysisTaskResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data:
type: object
properties:
id: { type: integer }
status:
type: string
enum: [CREATED, QUEUED, PROCESSING, SUCCEEDED, FAILED, CANCELLED]
progress: { type: integer, minimum: 0, maximum: 100 }
errorCode: { type: string }
reportId: { type: integer }
retryCount: { type: integer }
AnalysisTaskWebhook:
type: object
required: [taskId, status]
properties:
taskId: { type: integer }
status:
type: string
enum: [SUCCEEDED, FAILED, CANCELLED]
progress: { type: integer }
errorCode: { type: string }
result: { type: object }
signature: { type: string }
ReportResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data:
type: object
properties:
id: { type: integer }
childId: { type: integer }
taskId: { type: integer }
riskLevel: { type: string, enum: [low, medium, high, review_required] }
summary: { type: string }
metrics:
type: array
items:
type: object
properties:
name: { type: string }
value: { type: number }
level: { type: string }
confidence: { type: number }
recommendations:
type: array
items: { type: string }
disclaimer: { type: string }
reviewedBy: { type: integer, nullable: true }
TrainingPlanCreateRequest:
type: object
required: [childId, goal, cycleDays]
properties:
childId: { type: integer }
reportId: { type: integer }
goal: { type: string }
cycleDays: { type: integer, minimum: 7 }
exerciseIds:
type: array
items: { type: integer }
constraints:
type: object
properties:
maxDailyMinutes: { type: integer }
coachNotes: { type: string }
TrainingPlanResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data:
type: object
properties:
id: { type: integer }
status: { type: string, enum: [draft, active, completed, paused] }
detail: { type: object }
startedAt: { type: string, format: date-time }
endedAt: { type: string, format: date-time, nullable: true }
TrainingRecordCreateRequest:
type: object
required: [exerciseId, completed]
properties:
exerciseId: { type: integer }
completed: { type: boolean }
score: { type: integer, minimum: 0, maximum: 100 }
durationSeconds: { type: integer }
note: { type: string }
media:
type: array
items:
type: string
TrainingRecordResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data:
type: object
properties:
id: { type: integer }
planId: { type: integer }
createdAt: { type: string, format: date-time }
AdminDashboardResponse:
allOf:
- $ref: '#/components/schemas/StandardResponse'
- type: object
properties:
data:
type: object
properties:
newChildren: { type: integer }
uploadedVideos: { type: integer }
completedReports: { type: integer }
activePlans: { type: integer }
conversionRate: { type: number }
reassessmentCompletionRate: { type: number }
@@ -0,0 +1,61 @@
# 儿童 AI 体态管理与运动康复平台 · 商业交付版本 V1.0
> 面向 3–16 岁儿童青少年的 AI 体态管理与运动康复平台(非医疗诊断)
---
## 文档目录
| 序号 | 模块 | 文档 | 说明 |
|:----:|------|------|------|
| 01 | 商业计划书 | [儿童AI体态管理商业计划书.docx](../01_商业计划书/儿童AI体态管理商业计划书.docx) | 商业模式与市场分析 |
| 02 | 企业级 PRD | [PRD完整版.docx](../02_企业级PRD/PRD完整版.docx) | 产品需求、指标、用户故事 |
| 03 | 技术架构 | [企业级系统架构.docx](./03_技术架构/企业级系统架构.docx) | 云原生分层架构设计 |
| 03 | **架构与建设规划** | **[系统架构与建设规划.md](./03_技术架构/系统架构与建设规划.md)** | **合伙人讨论用 · 架构 + 排期 + 行动清单** |
| 03 | **架构 HTML 演示** | **[系统架构与建设规划.html](./03_技术架构/系统架构与建设规划.html)** | **浏览器打开 · 可视化架构图与路线图** |
| 03 | **产品交互 Demo** | **[产品交互Demo.html](./03_技术架构/产品交互Demo.html)** | **P2:摄像头 + PDF · 跟练/趋势/儿童端** |
| — | **工程 Starter** | **[apps/api/README.md](../../apps/api/README.md)** | **P3FastAPI 骨架 · 对齐 OpenAPI** |
| 04 | AI 视觉算法 | [AI视觉算法详细设计.docx](../04_AI视觉算法/AI视觉算法详细设计.docx) | Pose、指标、评分、质量控制 |
| 05 | 视频处理 | [视频处理工程设计.docx](../05_视频处理系统/视频处理工程设计.docx) | 上传、转码、质量检测 |
| 06 | 数据库设计 | [database.sql](../06_数据库设计/database.sql) | MySQL 8.x 完整表结构 |
| 07 | API 接口 | [openapi.yaml](../07_API接口/openapi.yaml) | REST API 契约(OpenAPI 3.0 |
| 08 | Agent 智能系统 | [Agent设计规范.docx](../08_Agent智能系统/Agent设计规范.docx) | 评估/教练/家长/运营 Agent |
| 09 | 前端产品设计 | [前端产品详细设计.docx](../09_前端产品设计/前端产品详细设计.docx) | 小程序、训练端、后台 |
| 10 | 后端工程设计 | [后端工程详细设计.docx](../10_后端工程设计/后端工程详细设计.docx) | 服务模块、权限、安全 |
| 11 | 管理后台 | [管理后台详细设计.docx](../11_管理后台/管理后台详细设计.docx) | 运营、复核、看板 |
| 12 | 研发计划 | [研发计划与项目管理.docx](../12_研发计划/研发计划与项目管理.docx) | P0–P3 里程碑与团队分工 |
| 13 | 测试验收 | [测试验收标准.docx](../13_测试验收/测试验收标准.docx) | 场景测试与验收清单 |
| 14 | 部署运维 | [生产部署运维.docx](../14_部署运维/生产部署运维.docx) | 环境、发布、监控、备份 |
| 15 | 运营 SOP | [商业运营与课程SOP.docx](../15_运营SOP/商业运营与课程SOP.docx) | 机构运营与课程流程 |
---
## 快速开始
### 合伙人 / 投资人讨论
1. 用浏览器打开 **[系统架构与建设规划.html](./03_技术架构/系统架构与建设规划.html)**
2. 点击 **「进入产品交互 Demo」** 体验完整产品流程(无需开发,纯演示)
3. 配合阅读 **[系统架构与建设规划.md](./03_技术架构/系统架构与建设规划.md)** 获取完整文字版
### 研发启动
1. 阅读 [PRD完整版.docx](../02_企业级PRD/PRD完整版.docx) 确认 MVP 范围
2. 以 [openapi.yaml](../07_API接口/openapi.yaml) 为 API 契约单一来源(工程副本:`../../contracts/`
3. 以 [database.sql](../06_数据库设计/database.sql) 初始化数据库(`make up`
4. 启动 API Starter:见仓库根 [README.md](../../README.md)
5. 按 [系统架构与建设规划.md](./03_技术架构/系统架构与建设规划.md) Sprint 1 排期
---
## 版本信息
| 字段 | 值 |
|------|-----|
| 版本 | V1.0 |
| 更新日期 | 2026-07-23 |
| 适用阶段 | MVP → 商业试点 → 商业交付 |
---
*本交付包所有 AI 报告输出用于健康管理建议,不构成医疗诊断。*