# 小程序云接口迁移清单 2026-10-19:除微信数据预拉取外,本地开发中的小程序运行代码已切换到 doodle-store HTTP 接口;当前已发布的线上版仍使用旧云开发接口。以下路径均以 `/api/v1` 为前缀。新接口共用成功信封 `{code:0,message:"ok",data:...}`,由 Swagger 展示已注册的参数。 ## 接口对照 | 旧调用或功能 | 新接口 | 权限 | | ---------------------------------------- | ----------------------------------------------------------------------- | -------------- | | `userLogin` | `POST /auth/wechat/login` | 微信 code 验证 | | 本人资料 | `GET /me`、`PUT /me/profile` | 本人 | | `userLogin.updateProfile` | `PUT /me/profile`,头像传 `avatarAssetId` | 本人 | | 头像云存储上传 | `POST /me/avatar-upload`,multipart:`file`、UUID `uploadId` | 本人 | | `userSettings.clearProfile` | `DELETE /me/profile` | 本人 | | `userSettings.deleteAccount` | `DELETE /me` | 本人 | | `userFavorites.add/remove` | `PUT /me/favorites/{worksheetId}`、`DELETE /me/favorites/{worksheetId}` | 本人 | | `userFavorites.list` | `GET /me/favorites?page=1&pageSize=20` | 本人 | | `userFavorites.check/batchCheck` | `POST /me/favorites/check`,`{worksheetIds:[]}` | 本人 | | 收藏/下载计数 | `GET /me/stats` | 本人 | | `userDownloadLogs.add` | `POST /me/downloads`,`{worksheetId,exportId}` | 本人 | | `userDownloadLogs.list` | `GET /me/downloads?page=1&pageSize=30` | 本人 | | `ageRecommendedQuery` | `GET /recommendations/age?ageBand=5-6` | 公开 | | `pageConfigFetch` 动态兜底 | `GET /page-config` | 公开 | | `categoriesQuery/Create/Update` 管理调用 | `GET/POST /admin/categories`、`PUT /admin/categories/{id}` | 管理员 | | 分类删除 | `DELETE /admin/categories/{id}` | 管理员 | | `worksheetsQuery` 管理调用 | `GET /admin/catalog/worksheets`,完整分页、真实计数与 seed 分开 | 管理员 | | `worksheetsUpdateStatus` | `PUT /admin/worksheets/{id}/status` | 管理员 | | `worksheetsBatchPatch` | `POST /admin/worksheets/batch`,`{patches,dryRun}`,最多 500 项 | 管理员 | | 预览图云存储上传 | `POST /admin/assets/preview-upload`,multipart:`file`、UUID `uploadId` | 管理员 | | `worksheetsPublish` | `POST /admin/worksheets/publish`,元数据与 `previewAssetId` | 管理员 | | 首页内容管理读取 | `GET /admin/site/config` | 管理员 | | `pageContentBuild` | `POST /admin/site/rebuild`,`page=home/category/all` | 管理员 | | 云数据库 `settings.homeAutoRefresh` 读取 | `GET /admin/site/timer` | 管理员 | | `homeTimerControl` | `PUT /admin/site/timer`,`{enabled}` | 管理员 | 公开分类、题型查询仍为既有 `/categories`、`/worksheets`、`/worksheets/{id}`。Web 原有 PATCH 分类/发布状态接口保留,同时提供 PUT 入口适配小程序请求方法。 ## 预拉取保留范围 - 保留 `wx.getBackgroundFetchData` 及微信后台现有预拉取地址。 - 预拉取/缓存先渲染首屏;随后后台读取新 `/page-config`,更新内存、缓存与首页。旧响应迟到不能覆盖更新的请求。 - 动态接口每次按当前题型、分类祖先和资产状态重新过滤,不会借旧快照恢复下架内容。管理变更后主动刷新首页配置。 - 新的首页刷新开关控制新后端快照任务。任务默认 UTC 22:00(北京时间次日 06:00)运行,可通过 `SITE_REFRESH_HOUR_UTC` 调整。任务使用 `job_runs` 唯一键和租约去重、有限重试,服务进程需要在线。 - 旧云端预拉取文件的生成、发布链路和定时任务继续保留,不由新开关控制;新后端不改该文件、不修改预拉取地址。 - 当前线上版仍依赖旧云开发。全部旧云函数源码、部署配置及线上服务均须保留,不将“本地开发版已无调用”作为删除、停用或修改旧接口契约的依据。未经另行明确安排,不迁移预拉取模式,不清理旧云函数、云数据库或云存储。 ## 数据与权限 - 所有用户接口只使用本站 JWT 确认的用户 ID;运行代码已删除旧登录兼容层、通用云调用封装与无调用方的旧统计接口。 - 收藏以用户+题型幂等;下载以用户+`exportId` 幂等。记录与真实计数同事务提交,下载只在保存图片成功后上报。原页面用户变化时停止补报。 - 本人列表只查本人数据;已下架或删除的题型仅保留记录,附属 `worksheet` 返回 null。用户删除不破坏其他用户数据。 - 管理接口使用当前数据库角色校验,写事务重新锁定核对身份;不会根据 develop 环境或“第一个用户”自动授予管理员。 - 资料只允许昵称和本人 ready 头像资源 ID,不接受 OpenID、role、userId 或任意头像 URL。头像按用户确认放在同一七牛公开空间,仍要求本人拥有且用途正确。 - 头像/预览只接收完整 PNG/JPEG,单文件不超过 2 MiB,并校验像素尺寸。服务端持有 AK/SK,以固定空间、明确对象 key 和仅新增策略上传,上传后核对远端 ETag/大小。相同 `uploadId` 和内容可恢复,冲突不覆盖。 - 当前单实例限制每人每小时新增 30 个上传标识,同一标识重试不重复计数;多实例硬配额后续使用共享限流存储。 - 替换或清除头像将旧资源标记 deleting;每分钟后台清理七牛对象,失败保留队列重试。注销与慢上传交错时再次安排清理。 - 管理批次整批验证、原子提交,支持不写库预演。真实统计和展示种子分开,允许管理员显式重置统计;不会把合并展示值悄悄写回真实计数。 ## 配置与迁移 服务端 `QINIU_PUBLIC_DOMAIN`、`QINIU_KEY_PREFIX`、`QINIU_BUCKET` 与 asset-sync 一致;新增上传需 `QINIU_AK`、`QINIU_SK` 成对配置,`QINIU_REGION` 可选。实际凭据只在被忽略的 `.env` 中,本地已沿用 asset-sync 的配置,不下发小程序。 迁移 `20261019000000_member_assets` 允许公开头像,并为本人变更加入 user 审计类型,已应用到本地 doodle_dev。它不搬运旧云端用户、收藏或下载历史;这些历史数据需要单独导出并导入、核对用户关联后再切换正式环境。旧云函数仍服务当前线上版,并承担旧预拉取链路维护;源码和线上服务均继续保留。 ## 验证 - `pnpm typecheck`:后端类型检查。 - `pnpm test`:后端 HTTP、校验、SDK 适配与资源工具回归。 - `pnpm test:db`:自动创建并删除临时库;覆盖权限、并发幂等、归属、发布与回滚、清理和注销,不向真实七牛上传测试文件。 - 小程序:`node --import tsx --test tests/auth-api.test.mjs tests/category-api.test.mjs tests/preview-assets.test.mjs`。 真实微信 code 兑换、微信后台白名单及真机上传仍需使用实际微信环境联调。生产域名当前尚未确定,体验/正式版不会回退到本机接口。