# 后端重构进度 ## 已完成 - Docker Desktop + Supabase local 已可用。 - API Docker 镜像 `tiku-saas-dev-api:latest` 已可构建,并可从容器连接宿主 Supabase PostgreSQL。 - API 已按 `core/features` 分层: - `auth`:短信验证码登录、迁移期 session、OAuth provider 预留。 - `catalog`:公开题库、地区、内容入口、分类树、题目集合、练习蓝图、手册、商品、SVIP 套餐、资料资源只读/下载接口。 - `learning`:顺序/随机/全真模拟组卷 session、答题记录、错题、收藏、背单词进度/收藏/统计。 - `profile`:学生个人中心、目标院校/专业、会员状态、统计聚合、最近练习。 - `scoreline`:分数线字段、院校、专业、记录、趋势、年份。 - `video`:题目视频讲解、批量预加载、通用视频搜索。 - `commerce`:订单、支付确认、激活码兑换、权益查询。 - `referral`:销售/代理邀请码、首绑客资保护、销售统计、团队关系、CRM 队列。 - `platform-admin`:平台方租户管理、SaaS 套餐、订阅、账单、服务费收款、使用量。 - `tenant-admin`:租户资料、品牌、公开设置、域名、支付账户、登录 provider、私密密钥掩码、活动内容、激活码批次、优惠券、成员管理、权限矩阵、审计查询。 - `tenant-content`:租户后台内容入口、任意深度分类树、考试意向标记、题目集合、练习蓝图、题目、视频、分数线、单词、知识手册、资料资源、题目/单词/知识手册 JSON 导入维护。 - `tenant`:域名/租户解析。 - `src/services/supabaseApi.ts` 已加入新 API 客户端方法,供旧 Web 逐步替换和后续 Taro 复用。 - 已新增 `npm run db:smoke-seed`,用于 `supabase:reset` 后恢复最小烟测数据。 - 已新增 `npm run smoke:core-api`,用于验证个人中心、分数线、题目视频、背单词进度/收藏等学生端核心 API。 - 已新增 `npm run test:api`,自动 seed、构建、启动临时 API,并断言核心学生端接口、内容导航/组卷、租户隔离、资源权限和题目导入。 ## 已验证接口 ```text GET /health POST /api/auth/sms/send POST /api/auth/sms/verify GET /api/auth/me POST /api/auth/logout POST /api/auth/oauth/wechat POST /api/auth/oauth/wechat-miniapp POST /api/auth/oauth/qq GET /api/tenant/resolve GET /api/platform-admin/overview GET /api/platform-admin/plans GET /api/platform-admin/tenants POST /api/platform-admin/tenants GET /api/platform-admin/tenants/detail PATCH /api/platform-admin/tenants/status PUT /api/platform-admin/tenants/billing-profile POST /api/platform-admin/subscriptions GET /api/platform-admin/invoices POST /api/platform-admin/invoices POST /api/platform-admin/invoices/from-subscription POST /api/platform-admin/invoices/payments/manual-confirm GET /api/platform-admin/usage POST /api/platform-admin/usage GET /api/catalog/* GET /api/catalog/content-entries GET /api/catalog/content-nodes GET /api/catalog/question-collections GET /api/catalog/question-collections/questions GET /api/catalog/practice-blueprints GET /api/catalog/assets GET /api/catalog/assets/download POST /api/learning/answers GET /api/learning/favorites/questions POST /api/learning/favorites/questions GET /api/learning/wrong-questions GET /api/learning/vocabulary/progress POST /api/learning/vocabulary/progress GET /api/learning/vocabulary/favorites POST /api/learning/vocabulary/favorites GET /api/learning/vocabulary/stats GET /api/profile/me PATCH /api/profile/me GET /api/scoreline/fields GET /api/scoreline/schools GET /api/scoreline/majors GET /api/scoreline/records GET /api/scoreline/trend GET /api/scoreline/years GET /api/questions/{questionId}/videos POST /api/questions/videos/batch GET /api/videos/search POST /api/videos/play GET /api/tenant-content/content-entries PUT /api/tenant-content/content-entries GET /api/tenant-content/content-nodes PUT /api/tenant-content/content-nodes GET /api/tenant-content/question-collections PUT /api/tenant-content/question-collections PUT /api/tenant-content/question-collections/items GET /api/tenant-content/practice-blueprints PUT /api/tenant-content/practice-blueprints POST /api/tenant-content/questions PATCH /api/tenant-content/questions GET /api/tenant-content/assets PUT /api/tenant-content/assets POST /api/tenant-content/assets/sign-upload POST /api/tenant-content/assets/sign-download POST /api/tenant-content/imports/preview/questions POST /api/tenant-content/imports/questions POST /api/tenant-content/imports/preview/vocabulary POST /api/tenant-content/imports/vocabulary POST /api/tenant-content/imports/preview/handbook POST /api/tenant-content/imports/handbook GET /api/tenant-content/imports GET /api/tenant-content/imports/issues PUT /api/tenant-content/videos POST /api/tenant-content/question-videos PUT /api/tenant-content/scoreline/schools PUT /api/tenant-content/scoreline/majors PUT /api/tenant-content/scoreline/fields PUT /api/tenant-content/scoreline/records PUT /api/tenant-content/vocabulary-units PUT /api/tenant-content/vocabulary-words PUT /api/tenant-content/handbook-subjects PUT /api/tenant-content/handbook-chapters PUT /api/tenant-content/handbook-entries POST /api/commerce/orders GET /api/commerce/orders POST /api/commerce/payments/manual-confirm POST /api/commerce/activation-codes/redeem GET /api/commerce/entitlements GET /api/commerce/entitlements/check POST /api/referral/invite-code POST /api/referral/resolve POST /api/referral/track-event POST /api/referral/bind GET /api/referral/stats GET /api/referral/sales-stats GET /api/referral/sales-clients POST /api/referral/manual-bind GET /api/referral/team PUT /api/referral/team POST /api/referral/qrcode GET /api/crm/config PUT /api/crm/config GET /api/crm/queue GET /api/tenant-admin/permissions GET /api/tenant-admin/overview PUT /api/tenant-admin/branding PUT /api/tenant-admin/settings GET /api/tenant-admin/domains POST /api/tenant-admin/domains GET /api/tenant-admin/payment-accounts PUT /api/tenant-admin/payment-accounts GET /api/tenant-admin/auth-providers PUT /api/tenant-admin/auth-providers GET /api/tenant-admin/secrets PUT /api/tenant-admin/secrets GET /api/tenant-admin/banners PUT /api/tenant-admin/banners GET /api/tenant-admin/faqs PUT /api/tenant-admin/faqs GET /api/tenant-admin/announcements PUT /api/tenant-admin/announcements GET /api/tenant-admin/code-batches PUT /api/tenant-admin/code-batches GET /api/tenant-admin/activation-codes PUT /api/tenant-admin/activation-codes POST /api/tenant-admin/activation-codes/generate GET /api/tenant-admin/coupons PUT /api/tenant-admin/coupons GET /api/tenant-admin/members PUT /api/tenant-admin/members POST /api/tenant-admin/members/disable GET /api/tenant-admin/audit-logs ``` ## 迁移期约定 - 当前写接口用 `x-tenant-id` 和 `x-user-id` 做迁移期上下文。 - `auth` 当前签发迁移期 `tk_` session,token hash 存在 `app_private.auth_sessions`;后续接 Supabase Auth 后,`x-user-id` 要替换为 JWT 用户身份解析。 - 短信验证码只保存 HMAC hash,不保存明文;本地 `mock` provider 才会返回 `debugCode`。 - `platform-admin` 当前用 `x-platform-admin-key` 做迁移期保护,生产后必须替换为平台管理员 JWT/服务端会话。 - B 端合作商年费/服务费使用 `tenant_invoices`、`tenant_invoice_items`、`tenant_invoice_payments`,不与 C 端学生订单混表。 - 订单金额以后端套餐价格为准,不信任前端传价。 - 激活码兑换和支付成功都走同一套 `grantSvipEntitlement` 权益开通逻辑。 - 租户支付账户、短信、OAuth 登录配置接口只保存公开配置;密钥进入 `app_private.tenant_secrets` 或生产 KMS/Vault,API 只返回 `secretRef` 和掩码状态。 - `tenant-admin` 采用角色默认权限 + `tenant_memberships.permissions` 覆盖的权限矩阵。成员可进入后台,但每个接口会校验具体权限点;学生和跨租户成员会被拒绝。 - 当前默认角色:`tenant_owner`/`tenant_admin` 全权限,`tenant_operator` 可维护内容和活动,`teacher` 可维护内容,`sales` 可维护激活码和优惠券,`agent` 只读部分兑换码/优惠券。 - 销售/代理客资采用首绑保护:普通扫码/分享事件不会覆盖已有归属,只有具备 `referral:write` 的租户成员可手动强制补绑。 - CRM 当前完成配置、密钥入私密表、客资入队和队列查询;真实 webhook 发送、重试、签名在后续 `apps/worker` 中实现。 - 内容资源当前完成台账、租户后台维护、学生端 SVIP 下载权限,以及 `local_dev`、阿里云 OSS、腾讯 COS、Supabase Storage 的上传/下载签名 provider。真实对象存在性校验、PDF 预览渲染、防盗链、水印和大文件上传后 worker 校验仍需继续补。 - 题库内容导航当前以 `content_entries/content_nodes` 为主模型,可表达“入口 -> 多级分类 -> 院校/专业/学科/销售意向标记”;题目集合和练习方式由 `question_collections/practice_blueprints` 管理,练习 session 会保存当次题目 ID 快照。 - 批量导入当前支持题目、单词、知识手册 JSON 预览、逐行 issue、job/item 台账、执行导入、幂等跳过,并可落到新内容入口和分类节点。旧单词模板的 `vocabulary_units_示例数据` / `vocabulary_示例数据`、知识手册的书籍/章节/小节/知识点嵌套结构都由后端规范化。Excel/CSV、分数线/视频导入会继续复用同一套 `content_import_jobs` 管线。 ## 下一步 1. 完善内容导入和文件上传:Excel/CSV、分数线、视频导入,对象存储上传后校验、PDF 预览、防盗链和视频水印。 2. 接入真实短信 provider:阿里云/腾讯云,密钥放 `app_private.tenant_secrets` 或生产 Vault。 3. 接入真实 OAuth provider:微信网页、微信小程序、QQ,并处理旧 PocketBase 身份映射。 4. 增加真实支付 provider:XPay、微信支付、支付宝,并完善 webhook 幂等。 5. 增加 `apps/worker`:支付补偿、CRM webhook、日报统计、导入后检查。 6. 开始 Taro scaffold,把 `supabaseApi` 抽到跨端包或适配层。 ## 测试命令 ```text npm run test:api npm run check:refactor ```