Files
gongxue-base/README.md
2026-06-29 23:31:38 +08:00

353 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# tiku-supabase
这是题库项目从 PocketBase/SQLite 重构到 Supabase/PostgreSQL 的新后端仓库。
当前仓库重点承载“商用 SaaS 版本”的新架构代码,包括多租户数据库、业务 API、PocketBase 数据导入器、本地验证脚本和重构进度文档。旧 PocketBase/React 项目仍保留在原工作区作为功能参照和迁移来源,但这个 Git 仓库不打算作为旧项目全量镜像。
## 当前状态
更新时间2026-06-29
目前已经完成并在本地验证通过的内容:
- Supabase/PostgreSQL 多租户数据库 schema、RLS、索引、触发器。
- `apps/api` 独立业务 API后续供 H5、Taro 小程序、管理后台统一调用;已支持 Supabase Auth JWT 和迁移期 `tk_` session 双入口。
- 租户后台能力:品牌、主题模板/草稿/发布、域名、公开设置、支付账户、登录配置、私密密钥掩码、活动内容、考试日期、题目反馈处理、激活码、优惠券规则/核销报表、勋章管理/发放、成员权限、自定义角色模板、班级/教师/学生范围权限、学生批量导入、批量分班、学生备注、跟进任务、审计日志。
- 租户内容能力:可配置题库入口、任意深度分类树、考试意向标记、题目集合、顺序/随机/全真模拟蓝图、题目录入/更新、视频绑定、分数线、单词、知识手册、资料资源台账、题目/单词/知识手册/分数线/视频 JSON/CSV/Excel 批量导入。
- 学生端能力:题库入口、分类树、题目集合、顺序/随机/模考 session 组卷快照、答题、错题本、收藏夹、背单词进度、个人中心、勋章、考试倒计时、签到积分、题目反馈、排行榜、分数线、AI 择校推荐、题目视频、订单详情/状态轮询、优惠券领取/抵扣、权益、激活码预检查/兑换、资料下载。
- 平台后台能力租户管理、SaaS 套餐、订阅、账单、服务费收款、用量记录、公共题库授权。
- 公共题库商业化能力:租户可采纳平台授权题库为本租户副本,并可手动或由 worker 自动同步平台新增/更新题目;同步会保护租户自改题目,返回冲突而不覆盖,后台可查询冲突明细。
- 题库导出能力:租户内容编辑可按题目集合、内容入口或分类节点导出 JSON、`paper_json`、打印 payload、PDF、Word 和每日一练图片 ZIP 素材包,后端强制租户隔离、答案/解析开关、复合题子题脱敏、导出 job 和审计PDF/Word/ZIP 由 exports worker 生成水印文件或运营素材并发布到 `content_assets``daily_practice` 支持每日一练九宫格 metadata、PDF/Word 版式、9 张 PNG/SVG 卡片和拼图包。
- 销售/代理/CRM 增长链路:邀请码、扫码/分享事件、首绑客资保护、销售统计、团队关系、CRM 配置、跟进分配策略和队列。
- `apps/worker` 后台任务进程CRM webhook 队列消费、generic/钉钉/飞书/企微机器人发送、签名、失败重试和日志commerce worker 可补偿查询微信/支付宝支付和退款状态provider-bills worker 可下载微信/支付宝官方账单并导入资金对账assets worker 可复检托管资源元数据、执行内置安全扫描并自动下架异常资源imports worker 可执行大批量导入public-banks worker 可自动同步公共题库采纳副本exports worker 可渲染 PDF/Word 导出文件和每日一练 ZIP 图片素材包。
- 销售/代理分佣结算基础闭环:租户默认比例、成员比例、激活码批次比例、订单/激活码归因、结算单生成、审核、线下打款状态、CSV/JSON 导出、打款凭证登记/复核和权限隔离。
- 订单售后基础闭环:退款请求、审核、处理状态流、微信/支付宝发起退款、微信/支付宝退款查询确认、微信/支付宝退款通知 webhook、退款金额累计、部分/全额退款订单状态、全额退款权益撤销、退款事件和审计日志。
- 资金对账、异常订单和财务凭证闭环:租户财务/运营可通过 `/api/commerce/reconciliation/*` 导入或预览支付/退款账单行,也可创建微信/支付宝官方账单下载任务;后端按租户隔离比对本地订单、支付、退款记录,识别已匹配、金额不一致、状态不一致、供应商有本地无、本地有供应商无、重复行和无效行,并写入对账批次、明细和审计日志;异常明细可创建差错工单,支持分配、开始处理、升级、解决、忽略、重开和事件留痕;`/api/commerce/operations/anomalies` 聚合异常订单风险,`/api/commerce/adjustment-vouchers*` 支持人工调整凭证、复核、事件轨迹和报表。工单和凭证只做财务审核闭环,不直接修改订单、支付、退款或权益。
- PocketBase schema/数据导入器雏形和导入后校验脚本。
- 本地 Supabase reset、烟测 seed、API 集成测试、完整重构检查命令。
还没有达到生产交付的部分:
- Supabase Auth/JWT、租户角色模板、班级/教师/学生范围权限已可联调;生产前还要做真实云端 Auth/JWKS 回归和 RLS 深测。
- 阿里云/腾讯云短信、微信小程序登录、微信网页登录、QQ 登录、手机号绑定/换绑、微信支付、支付宝主链路、微信/支付宝发起退款/查询确认/退款通知、支付/退款补偿 worker 已完成本地适配;资金对账已支持手工/API 账单导入、微信/支付宝官方账单下载任务、provider-bills worker 自动导入比对、差错工单处理、异常订单运营台和人工调整凭证复核报表;真实生产账号、真实回调域名和真实生产账单抽样验收还没接完。
- OSS/COS/Supabase Storage 上传下载签名 provider 已接入上传后校验、PDF/图片预览、资源访问事件、动态水印上下文、锁定资源 CDN 边界、资源复检 worker、内置 `metadata_rules` 安全扫描和外部 HTTP 杀毒/内容安全 scanner 接入层已完成。生产还要配置真实扫描服务 endpoint/token并继续补转码/CDN 级水印、CDN 刷新和对象生命周期策略。
- Excel/CSV 导入解析已完成并复用 `content_import_jobs/items/issues` 管线;大批量异步导入 worker 基础已接入,支持 queued job 消费、重试和审计;导入后复检、模板下载和字段映射 API 已完成,前端 UI 待接。
- 题库导出已完成服务端结构化 payload、PDF/Word 二进制 worker、每日一练基础导出和每日一练 ZIP 图片素材包;后续还要补更精细试卷模板、多模板排版和导出操作台体验。
- 优惠券复杂规则和核销报表已可联调,包含状态启停、活动分组、最低订单金额、优惠封顶、单用户限次、首单限制、适用套餐/地区、核销明细和活动报表Taro 租户营销中心已接优惠券规则表单、筛选、核销明细和报表第一版。
- 勋章管理/手动发放已可联调;自动发放规则、积分活动联动、分佣真实打款 provider、发票、批量凭证上传、CRM 富卡片模板、失败告警、死信运营台、销售转化看板、公共题库版本通知和冲突处理操作台还没完成。
- `apps/taro` 已建立 Taro 4 React 跨端前端地基,包含 H5 学生端、租户后台、平台后台三套构建入口、租户解析、统一 API client 和 Supabase Auth client 初始化学生端第一批页面已接入登录、首页、题库、练习、背单词、知识手册、分数线、AI 择校推荐、资料和个人中心;租户后台第一批页面已接入工作台、数据看板、学生/班级、题库内容、营销中心、财务运营和租户设置,营销中心已接 CRM、分佣结算、优惠券规则/核销报表,财务运营已接退款状态机、官方账单任务、对账异常、差错工单和调整凭证第一版,设置页已接主题模板、草稿预览/发布、角色模板和成员绑定第一版;平台后台已接入工作台、租户管理、账务中心、公共题库授权,以及创建租户、状态变更、订阅、账单、收款、用量和题库授权第一版写操作。
- 根目录已清理为新 Supabase SaaS monorepo 编排层;旧 PocketBase/React 项目和旧构建产物仅保留在 `参考/` 目录作为迁移参考,不进入 Git 提交。
更完整的进度看这些文档:
- `docs/refactor/implementation-status.md`
- `docs/refactor/backend-progress.md`
- `docs/refactor/backend-handoff-roadmap.md`
- `docs/refactor/ai-development-guardrails.md`
- `docs/refactor/content-import-contract.md`
- `docs/refactor/object-storage.md`
- `docs/refactor/project-structure.md`
- `docs/refactor/frontend-handoff-index.md`
- `docs/refactor/backend-capability-status.md`
- `docs/refactor/legacy-feature-gap-matrix.md`
- `docs/refactor/supabase-frontend-access-strategy.md`
- `docs/refactor/taro-frontend-integration.md`
- `docs/refactor/multitenant-auth-security-contract.md`
- `docs/refactor/next-development-todo.md`
- `docs/refactor/blueprint-coverage.md`
- `docs/refactor/api-structure.md`
## 目录结构
```text
apps/api/ Node.js 业务 API
apps/taro/ Taro 4 React 跨端前端H5 三入口,后续扩展小程序
apps/worker/ 后台异步任务CRM webhook、支付/退款补偿、官方账单下载、资源复检、导入执行、公共题库同步、题库导出渲染等
packages/config/ 共享配置
packages/db/ PostgreSQL 连接池和查询封装
packages/domain/ 领域常量和共享类型
supabase/migrations/ 数据库迁移schema、RLS、索引、触发器
supabase/seed.sql 最小租户 seed
scripts/import-pocketbase/ PocketBase schema/数据导入器和校验器
scripts/smoke-seed.js 本地集成测试 seed 数据
scripts/api-integration-test.js
docs/refactor/ 重构架构、进度、治理文档
docker-compose.api.yml API 容器化运行配置
```
旧项目参考文件在本机 `F:\project\参考\旧题库项目`,旧前端构建产物在 `F:\project\参考\旧构建产物`。这两个目录都只用于对照和迁移,不作为当前新项目源码。
## 本地开发
前置要求:
- Node.js 20+
- Docker Desktop
- Supabase CLI
启动本地 Supabase 和 API
```bash
npm install
npm run supabase:start
npm run supabase:reset
npm run db:smoke-seed
npm run dev:api
```
Taro H5 本地开发:
```bash
npm run dev:taro:h5
```
三套 H5 构建:
```bash
npm run build:taro:h5:student
npm run build:taro:h5:tenant
npm run build:taro:h5:platform
```
对应产物:
```text
apps/taro/dist/h5-student
apps/taro/dist/h5-tenant-admin
apps/taro/dist/h5-platform-admin
```
推荐分别部署到学生端域名、租户后台域名、平台后台域名;三者共用 `apps/taro/src/services/api.ts` 请求层,业务数据默认调用 `apps/api`,不要在页面里直写 Supabase 表。
学生端当前页面:
```text
apps/taro/src/pages/student/login
apps/taro/src/pages/student/home
apps/taro/src/pages/student/catalog
apps/taro/src/pages/student/practice
apps/taro/src/pages/student/vocabulary
apps/taro/src/pages/student/handbook
apps/taro/src/pages/student/scoreline
apps/taro/src/pages/student/ai-school
apps/taro/src/pages/student/assets
apps/taro/src/pages/student/profile
```
租户后台当前页面:
```text
apps/taro/src/pages/tenant-admin/workbench
apps/taro/src/pages/tenant-admin/dashboard
apps/taro/src/pages/tenant-admin/students
apps/taro/src/pages/tenant-admin/content
apps/taro/src/pages/tenant-admin/marketing
apps/taro/src/pages/tenant-admin/finance
apps/taro/src/pages/tenant-admin/settings
```
平台后台当前页面:
```text
apps/taro/src/pages/platform-admin/workbench
apps/taro/src/pages/platform-admin/tenants
apps/taro/src/pages/platform-admin/billing
apps/taro/src/pages/platform-admin/question-banks
```
单次运行 CRM worker
```bash
npm --workspace @tiku-saas/worker run crm:once
```
单次运行支付/退款补偿 worker
```bash
npm --workspace @tiku-saas/worker run commerce:once
```
单次运行微信/支付宝官方账单下载 worker
```bash
npm --workspace @tiku-saas/worker run provider-bills:once
```
单次运行内容资源复检 worker
```bash
npm --workspace @tiku-saas/worker run assets:once
```
单次运行内容导入 worker
```bash
npm --workspace @tiku-saas/worker run imports:once
```
单次运行公共题库自动同步 worker
```bash
npm --workspace @tiku-saas/worker run public-banks:once
```
单次运行题库 PDF/Word/每日一练 ZIP 导出 worker
```bash
npm --workspace @tiku-saas/worker run exports:once
```
默认本地数据库:
```text
postgresql://postgres:postgres@127.0.0.1:54322/postgres
```
默认 API 地址:
```text
http://127.0.0.1:8787
```
## 验证命令
完整后端重构检查:
```bash
npm run check:refactor
```
这个命令会依次执行:
- API TypeScript 检查
- PocketBase importer TypeScript 检查
- PocketBase 导入后校验
- 本地 smoke seed
- API 构建
- 本地 API 集成测试
常用单项命令:
```bash
npm run check:api
npm run check:worker
npm run check:importer
npm run check:taro
npm run audit:runtime
npm run pb:import:dry-run
npm run pb:import:validate
npm run test:readiness
npm run test:pb:dry-run
npm run test:api
npm run test:worker:crm
npm run test:worker:commerce
npm run test:worker:assets
npm run test:worker:exports
npm run test:worker:imports
npm run test:worker:public-banks
```
## 生产就绪检查
填好生产 `.env` 后,先跑环境变量级检查:
```bash
npm run readiness:production
```
确认 `DATABASE_URL` 指向生产 Supabase/PostgreSQL 后,再跑数据库配置检查:
```bash
npm run readiness:production:db
```
这个检查会阻断默认弱密钥、`CORS=*`、mock 短信、legacy 身份头、local_dev 存储、对象存储未配置、CRM insecure localhost 等生产风险;带 `:db` 的版本还会检查租户 provider 公开配置是否混入密钥、活跃短信/OAuth/支付 provider 是否缺少 `app_private.tenant_secrets`、域名是否未验证。
## PocketBase 迁移 Dry-Run
把旧 PocketBase 导出的集合 JSON 放到仓库根目录 `pb_export/` 后,先执行不写数据库的静态 dry-run
```bash
npm run pb:import:dry-run
```
需要给 CI 或脚本读取时:
```bash
npm run pb:import:dry-run -- --json
```
dry-run 会检查导出目录、JSON 形态、核心集合缺失、重复/缺失旧 ID、敏感字段、旧 schema 关系断裂和未映射集合。存在 blocker 时命令返回非 0所有 blocker 处理完后,再执行 `npm run pb:import:json``npm run pb:import:validate`
## API 模块
当前 API 目录:
```text
apps/api/src/features/
auth/ 短信登录、迁移期 session、微信小程序登录、微信网页登录、QQ 登录
catalog/ 学生端目录、内容入口、分类树、题目集合、资料、商城只读接口
commerce/ 订单、支付确认、退款、激活码、优惠券规则/核销、权益、资金对账和差错工单
health/ 健康检查
learning/ 练习 session 组卷、答题、错题、收藏、学习进度、排行榜
platform-admin/ 平台方租户、SaaS 套餐、订阅、账单、用量
profile/ 学生个人中心、勋章
referral/ 销售/代理客资追踪、CRM 队列
referral/commission.ts
分佣设置、汇总、来源明细、结算单、审核/打款、导出和凭证复核
scoreline/ 分数线
tenant/ 租户解析
tenant-admin/ 租户后台配置、主题、成员权限、班级学生、活动、勋章和审计
tenant-content/ 租户内容导航、题库维护、资源管理、批量导入和题库导出
video/ 题目视频讲解
```
API 身份上下文:
- 推荐:`Authorization: Bearer <supabase_access_token>`,可配合 `x-tenant-id` 提供当前租户上下文。
- 本地/迁移期:`Authorization: Bearer <tk_session>`
- 兼容旧测试:`x-user-id``x-platform-admin-key` 仅允许在 `ALLOW_LEGACY_AUTH_HEADERS=true``ALLOW_PLATFORM_ADMIN_KEY=true` 的非生产环境使用。
生产环境必须设置 `ALLOW_LEGACY_AUTH_HEADERS=false``ALLOW_PLATFORM_ADMIN_KEY=false`,前端不能再传 `x-user-id` 代表当前用户。
## 重要安全约定
- 租户公开配置和主题配置不能存放密钥;主题 token 只能是后端允许的颜色、半径、安全 CSS 变量、图标 token 和公开素材引用。
- 商户密钥、短信密钥、OAuth app secret 等必须进入 `app_private.tenant_secrets`,或后续生产 KMS/Vault。
- 资料、PDF、视频等资源必须先进入 `content_assets` 台账,再由 API 校验权限并下发签名 URL学生端预览、锁定资料和视频会使用短 TTL并返回带 `traceId``watermark` 上下文供前端渲染可见水印。`members/svip/private` 外部 CDN URL 默认拒绝,除非显式登记 provider-managed 访问;所有上传签名、上传确认、下载/预览 granted/denied 都写入 `content_asset_access_events`。托管对象必须 `uploadStatus=verified``securityScanStatus=passed` 后才能发布、下载、预览或播放;生产环境应定时运行 assets worker 复检对象元数据,执行 `metadata_rules` 和外部 HTTP scanner异常资源会被标记 failed/skipped 并退回 draft。
- 题库入口和分类使用 `content_entries/content_nodes`;题目列表和练习规则使用 `question_collections/practice_blueprints`,前端不要再把旧树字段当成唯一业务结构。
- 批量导入必须先写 `content_import_jobs/items/issues`,保留原始 payload、规范化 payload、逐行问题和审计记录。题目、单词、知识手册、分数线和视频 JSON/CSV/Excel 导入已走这套后台校验管线;大批量任务可提交 `executionMode=async`,由 imports worker 消费,前端只轮询 job 状态和展示 issues。
- 题库导出必须由后端按权限生成,不允许前端直接读取数据库拼导出文件;不开启答案/解析时顶层题目和复合题子题都必须脱敏PDF/Word/每日一练 ZIP 只通过 exports worker 写入 `content_assets` 后再签名下载/预览。
- 支付 webhook 必须先设计幂等键和验签流程,再进入生产使用;生产环境还应定时运行 commerce worker 兜底供应商漏通知和处理中退款,并定时运行 provider-bills worker 下载官方账单核对本地订单。官方账单下载任务只保存下载域名、hash 和对账批次 ID不向前端暴露下载 URL 或商户密钥。优惠券状态、最低金额、封顶、单用户限次、首单、适用套餐/地区和订单抵扣都由后端重新校验,前端只能展示后端返回金额。对账差错工单和人工调整凭证只允许记录财务处理结论、附件引用和审计事件,不允许前端、工单接口或凭证审批接口直接篡改订单、支付、退款或权益状态。
## 最近一次验证
最近本地验证命令:
```text
npx supabase db reset
npm run check:api
npm run check:worker
npm run test:worker:commerce
npm run test:worker:assets
npm run test:worker:exports
npm run test:api
npm run check:refactor
npm run audit:runtime
git diff --check
```
结果:通过。`npm run test:api` 覆盖资源访问事件、锁定 CDN 资源拒绝、provider-managed CDN 显式放行、学生短 TTL 下载/预览、访问记录查询、安全扫描门禁、官方账单下载任务权限和脱敏响应、异常订单运营台、人工调整凭证提交/复核/事件/报表、租户隔离,以及凭证审批不修改订单/支付/权益。`npm run test:worker:commerce` 覆盖支付/退款补偿、微信/支付宝官方账单下载、账单 hash 校验、导入 `provider_download` 对账批次和密钥不泄露。`npm run test:worker:assets` 覆盖托管资源复检、内置安全扫描、外部 HTTP scanner 通过/失败/不可用 fail-closed、扫描失败/跳过事件和异常资源自动下架。`npm run test:worker:exports` 覆盖导出 worker 生成可信资源并标记 `securityScanStatus=passed``npm run audit:runtime` 无 high/critical 漏洞;当前运行时依赖树仍有 `exceljs -> uuid` 的 moderate 级提示,修复需要破坏性降级 `exceljs`,后续应在导入 Excel 回归充分后单独处理。
注意:`apps/taro` 是静态构建工程,线上发布 `apps/taro/dist/**`,不发布 `node_modules`。Taro 4.2.0 当前构建工具链仍会触发 `npm run audit:taro:toolchain` 的上游 high/critical 提示,不能用 `npm audit fix --force` 降级到 Taro 3 破坏构建;上线验收时以 `audit:runtime`、构建产物、前端密钥检查和静态服务器配置为准,并持续跟进 Taro 官方修复。
## 下一步建议
优先继续补:
1. 真实云端 Auth/JWKS 回归、RLS 深测和生产环境配置验收。
2. 继续补 Taro 前端:学生端长题干/公式图片混排/小程序支付与分享,租户后台更细导入体验/数据范围 UI/主题素材库/财务复核细节,平台后台租户详情/审计/自动计费增强,小程序兼容验证。
3. 对象存储真实 AV/内容安全扫描服务联调、CDN 防盗链、转码/CDN 级水印和生命周期策略。
4. 题库导出模板精排、导出操作台、真实数据 dry-run、导入字段映射 UI 和复检结果操作台。
5. 真实 OAuth/短信/支付生产账号联调、真实生产账单抽样验收、真实打款 provider、发票、公共题库版本通知/冲突处理操作台、积分活动深化,以及排行榜防刷/预聚合。