414 lines
10 KiB
Markdown
414 lines
10 KiB
Markdown
# OpenSpec 开发归档
|
||
|
||
## 归档日期
|
||
|
||
- 2026-03-28
|
||
|
||
## 归档范围
|
||
|
||
本次归档覆盖 PocketBase hooks 项目在附件统一存储、文档管理页增强、字典项图片、用户图片字段附件化、SDK 直连权限页、文档文件字段 `document_file`、大文件上传 body limit 修复、以及对应 OpenAPI / 表结构文档同步方面的工作,涉及:
|
||
|
||
- 所有业务文件统一收敛到 `tbl_attachments`
|
||
- 业务表只保存 `attachments_id`,并由 hooks 联表返回文件流链接
|
||
- `tbl_document` 新增 `document_file`,与 `document_image`、`document_video` 一样支持多附件和 `|` 分隔存储
|
||
- `manage/document-manage` 页面新增文件附件区、初始隐藏编辑区、保存后保持当前编辑态、局部状态提示、拖拽上传与全屏图片预览
|
||
- `manage/dictionary-manage` 页面支持字典枚举项图片上传和全屏查看原图
|
||
- `manage/sdk-permission-manage` 页面支持按角色配置 collection CRUD 直连权限,并优化为即时保存
|
||
- 上传路由显式放宽 PocketBase custom route `bodyLimit`
|
||
- 使用 `POCKETBASE_AUTH_TOKEN` 在线补齐 `tbl_document.document_file`
|
||
- 新增 OpenSpec 归档目录 `openspec/changes/archive/2026-03-28-pocketbase-manage-media-and-sdk-permissions/`
|
||
|
||
---
|
||
|
||
## 一、附件集中存储
|
||
|
||
### 1. 附件表作为唯一文件存储点
|
||
|
||
- 仅 `tbl_attachments.attachments_link` 保留真实 `file` 字段
|
||
- 其他业务表不再保存实际文件
|
||
- 文档、字典、用户图片字段统一改为保存 `attachments_id`
|
||
|
||
### 2. 附件回读策略
|
||
|
||
hooks 查询时统一联查 `tbl_attachments`,并补充:
|
||
|
||
- 文件流链接
|
||
- 下载链接
|
||
- 附件元数据对象
|
||
|
||
适用对象包括:
|
||
|
||
- 文档图片 / 视频 / 文件
|
||
- 字典枚举项图片
|
||
- 用户头像 / 身份图 / 资质图
|
||
|
||
### 3. 附件访问控制
|
||
|
||
- PocketBase 原生 `tbl_attachments` 已放开公开读取与下载
|
||
- hooks 层原有 `ManagePlatform` 限制保持不变
|
||
- 业务访问控制继续由保存附件 ID 的业务表承担
|
||
|
||
---
|
||
|
||
## 二、文档管理增强
|
||
|
||
### 1. `tbl_document` 新增 `document_file`
|
||
|
||
- 新字段:`document_file`
|
||
- 类型:`text`
|
||
- 用途:保存多个文件类 `attachments_id`
|
||
- 存储格式:`id1|id2|id3`
|
||
|
||
### 2. 文档管理页行为
|
||
|
||
- 首次进入页面时只显示列表,不显示编辑区
|
||
- 点击“新建模式”或“编辑”后才进入编辑区
|
||
- 保存成功后保持当前文档编辑态,不再强制清空回到新建
|
||
- 保存 / 报错信息同时显示在顶部与保存按钮下方
|
||
- 图片、视频、文件三块附件区都支持拖拽上传
|
||
|
||
### 3. 上传链路修复
|
||
|
||
- 上传接口继续使用 `/pb/api/attachment/upload`
|
||
- 为自定义路由显式增加更大的 `bodyLimit`
|
||
- 解决了文件未超过数据库与网关限制但仍在 hooks 层被 413 拒绝的问题
|
||
|
||
---
|
||
|
||
## 三、SDK 直连权限管理
|
||
|
||
### 1. 管理页能力
|
||
|
||
- 新增 `/pb/manage/sdk-permission-manage`
|
||
- 支持创建角色后按角色给 `tbl_auth_users` 用户授权
|
||
- 支持逐 collection 配置 `list / view / create / update / delete`
|
||
|
||
### 2. 页面交互约束
|
||
|
||
- 页面不显示角色 ID,只显示角色名称
|
||
- 勾选权限后立即保存
|
||
- `public` 和 `custom` 规则不允许在页面里继续勾选改写
|
||
- 支持集合级 `全选`
|
||
- 当某集合下所有操作都不可编辑时,`全选` 自动禁用
|
||
|
||
---
|
||
|
||
## 四、OpenSpec 记录
|
||
|
||
本次新增的 OpenSpec 记录包括:
|
||
|
||
- `openspec/specs/attachment-backed-media/spec.md`
|
||
- `openspec/specs/document-manage-console/spec.md`
|
||
- `openspec/specs/sdk-collection-permissions/spec.md`
|
||
- `openspec/changes/archive/2026-03-28-pocketbase-manage-media-and-sdk-permissions/`
|
||
|
||
---
|
||
|
||
## 归档日期
|
||
|
||
- 2026-03-23
|
||
|
||
## 归档范围
|
||
|
||
本次归档覆盖 PocketBase hooks 项目在微信登录注册、PocketBase 原生 token、openid 身份收敛、错误观测、索引修复与 auth 兼容字段方面的修复与规范同步,涉及:
|
||
|
||
- `pocket-base/` 作为正式 hooks 项目继续收敛规范
|
||
- 微信登录链路错误显式返回
|
||
- `recordAuthResponse` 使用空 `authMethod`
|
||
- 登录/资料更新阶段 auth 保存失败信息透传
|
||
- 移除 hooks 查询中的 `-created` 排序,修复 `invalid sort field "created"`
|
||
- `users_phone` 唯一索引改普通索引,允许空手机号用户注册
|
||
- `tbl_auth_users` 继续以 `openid` 作为业务身份锚点
|
||
- 为 PocketBase `auth` 集合兼容写入占位 `email`、随机密码与 `passwordConfirm`
|
||
- OpenSpec 变更文档补录到 `pocket-base/spec/`
|
||
|
||
---
|
||
|
||
## 一、接口与认证结果
|
||
|
||
### 当前 active hooks 接口
|
||
|
||
- `POST /api/system/test-helloworld`
|
||
- `POST /api/system/health`
|
||
- `POST /api/wechat/login`
|
||
- `POST /api/wechat/profile`
|
||
- `POST /api/wechat/refresh-token`
|
||
|
||
### 当前认证规则
|
||
|
||
- 正式鉴权仅使用 `Authorization: Bearer <token>`
|
||
- `Open-Authorization` 不属于接口契约
|
||
- `users_wx_openid` Header 已移除
|
||
- 业务身份由当前 auth record 的 `openid` 唯一确定
|
||
|
||
---
|
||
|
||
## 二、数据模型与落库策略
|
||
|
||
### 1. `tbl_auth_users`
|
||
|
||
- 维持 PocketBase `auth` 集合
|
||
- 业务身份锚点为 `openid`
|
||
- 目标规则:除 `openid` 外,自定义业务字段均允许为空
|
||
|
||
### 2. auth 集合兼容字段
|
||
|
||
由于 `tbl_auth_users` 是 auth 集合,为满足 PocketBase 原生 auth 保存要求,登录创建阶段补充:
|
||
|
||
- `email = <openid>@wechat.local`
|
||
- 随机密码
|
||
- `passwordConfirm`
|
||
|
||
说明:
|
||
|
||
- 上述 `email` 为占位认证标识,不代表真实邮箱。
|
||
|
||
---
|
||
|
||
## 三、问题修复归档
|
||
|
||
### 1. 通用 400 `Something went wrong while processing your request.`
|
||
|
||
处理方式:
|
||
|
||
- 登录路由本地 try/catch 显式返回 `{ statusCode, errMsg, data }`
|
||
- 全局错误包装提前注册
|
||
- 保存 auth 用户时透传原始错误信息
|
||
|
||
### 2. `invalid sort field "created"`
|
||
|
||
原因:
|
||
|
||
- hooks 内多个精确查询误用了 `-created` 排序
|
||
|
||
处理方式:
|
||
|
||
- 统一移除 active hooks 中所有 `-created` 排序
|
||
|
||
### 3. 注册成功前数据库无新记录
|
||
|
||
已识别的高风险点:
|
||
|
||
- `users_phone` 唯一索引会让空手机号重复冲突
|
||
|
||
处理方式:
|
||
|
||
- 改为普通索引
|
||
- 手机号唯一性改由资料完善阶段业务校验负责
|
||
|
||
---
|
||
|
||
## 四、规范同步位置
|
||
|
||
本次 OpenSpec 记录新增:
|
||
|
||
- `pocket-base/spec/changes.2026-03-23-pocketbase-hooks-auth-hardening.md`
|
||
|
||
当前 active 契约文件:
|
||
|
||
- `pocket-base/spec/openapi.yaml`
|
||
|
||
---
|
||
|
||
## 五、当前边界
|
||
|
||
1. `tbl_auth_users` 作为 PocketBase `auth` 集合,仍受 PocketBase 内置 auth 规则影响。
|
||
2. schema 脚本放宽自定义字段必填约束时,PocketBase 服务端更新 auth 集合可能返回通用 500,需要结合服务端日志进一步确认。
|
||
3. 若线上仍报旧错误,通常表示最新 hooks 或 schema 尚未部署生效。
|
||
|
||
---
|
||
|
||
## 归档日期
|
||
|
||
- 2026-03-20
|
||
|
||
## 归档范围
|
||
|
||
本次归档覆盖微信小程序后端交互相关接口的设计、实现、规范同步与部署调整,涉及:
|
||
|
||
- 接口路径统一收敛到 `/api`
|
||
- 微信登录/注册合一
|
||
- 微信资料完善接口重构
|
||
- 微信手机号服务端换取
|
||
- `users_type` 自动维护
|
||
- JWT 认证与刷新 token
|
||
- PocketBase Token 模式访问
|
||
- OpenAPI 与项目文档同步
|
||
- dist 构建与部署产物
|
||
|
||
---
|
||
|
||
## 一、接口演进结果
|
||
|
||
### 系统接口
|
||
|
||
- `POST /api/test-helloworld`
|
||
- `POST /api/health`
|
||
|
||
### 微信小程序接口
|
||
|
||
- `POST /api/wechat/login`
|
||
- 登录/注册合一
|
||
- 接收 `users_wx_code`
|
||
- 自动换取 `users_wx_openid`
|
||
- 若无账号则自动创建游客账号
|
||
- 返回 `status`、`is_info_complete`、`token`、完整用户信息
|
||
|
||
- `POST /api/wechat/profile`
|
||
- 从 headers 读取 `users_wx_openid`
|
||
- 需要 `Authorization`
|
||
- body 接收:
|
||
- `users_name`
|
||
- `users_phone_code`
|
||
- `users_picture`
|
||
- 服务端调用微信接口换取真实手机号后写入 `users_phone`
|
||
|
||
- `POST /api/wechat/refresh-token`
|
||
- 仅依赖 `users_wx_openid`
|
||
- 不要求旧 `Authorization`
|
||
- 返回新的 JWT token
|
||
|
||
---
|
||
|
||
## 二、关键业务规则
|
||
|
||
### 1. 用户类型 `users_type`
|
||
|
||
- 新账号初始化:`游客`
|
||
- 当且仅当用户首次从:
|
||
- `users_name` 为空
|
||
- `users_phone` 为空
|
||
- `users_picture` 为空
|
||
|
||
变为:
|
||
- 三项全部完整
|
||
|
||
时,自动升级为:`注册用户`
|
||
|
||
- 后续资料修改不再覆盖已确定类型
|
||
|
||
### 2. 用户资料完整度 `is_info_complete`
|
||
|
||
以下三项同时存在时为 `true`:
|
||
|
||
- `users_name`
|
||
- `users_phone`
|
||
- `users_picture`
|
||
|
||
否则为 `false`
|
||
|
||
### 3. 微信手机号获取
|
||
|
||
服务端使用微信官方接口:
|
||
|
||
- `getuserphonenumber`
|
||
|
||
通过 `users_phone_code` 换取真实手机号,再写入数据库字段 `users_phone`。
|
||
|
||
---
|
||
|
||
## 三、鉴权规则
|
||
|
||
### 标准请求头
|
||
|
||
- `Authorization: Bearer <token>`
|
||
- `users_wx_openid: <openid>`
|
||
|
||
### 当前规则
|
||
|
||
- `/api/wechat/login`:不需要 token
|
||
- `/api/wechat/profile`:需要 `users_wx_openid + Authorization`
|
||
- `/api/wechat/refresh-token`:**只需要** `users_wx_openid`
|
||
|
||
---
|
||
|
||
## 四、请求格式规则
|
||
|
||
所有微信写接口统一要求:
|
||
|
||
- `Content-Type: application/json`
|
||
|
||
不符合时返回:
|
||
|
||
- `415 请求体必须为 application/json`
|
||
|
||
---
|
||
|
||
## 五、PocketBase 访问策略
|
||
|
||
当前统一使用:
|
||
|
||
- `POCKETBASE_API_URL`
|
||
- `POCKETBASE_AUTH_TOKEN`
|
||
|
||
已移除:
|
||
|
||
- `POCKETBASE_USER_NAME`
|
||
- `POCKETBASE_PASSWORD`
|
||
|
||
---
|
||
|
||
## 六、部署与产物
|
||
|
||
后端已支持 dist 构建:
|
||
|
||
- `npm run build`
|
||
- 产物目录:`back-end/dist/`
|
||
|
||
当前发布目录包含:
|
||
|
||
- `dist/src/`
|
||
- `dist/spec/`
|
||
- `dist/package.json`
|
||
- `dist/package-lock.json`
|
||
- `dist/.env`
|
||
|
||
生产启动方式:
|
||
|
||
- `npm start`
|
||
- 实际运行:`node dist/src/index.js`
|
||
|
||
---
|
||
|
||
## 七、文档同步结果
|
||
|
||
已同步更新:
|
||
|
||
- `back-end/spec/openapi.yaml`
|
||
- `docs/api.md`
|
||
- `docs/deployment.md`
|
||
- `README.md`
|
||
|
||
其中 `openapi.yaml` 已与当前真实接口行为对齐。
|
||
|
||
---
|
||
|
||
## 八、质量验证结果
|
||
|
||
本次归档前已验证通过:
|
||
|
||
- `npm run lint`
|
||
- `npm run test`
|
||
- `npm run build`
|
||
|
||
测试覆盖包括:
|
||
|
||
- 系统接口
|
||
- 统一 404
|
||
- 登录/注册合一
|
||
- 非 JSON 拒绝
|
||
- 资料更新
|
||
- token 刷新
|
||
- `users_type` 升级逻辑
|
||
- `is_info_complete` 返回逻辑
|
||
|
||
---
|
||
|
||
## 九、当前已知边界
|
||
|
||
1. `refresh-token` 当前仅依赖 `users_wx_openid`,未校验旧 token
|
||
2. 微信手机号能力依赖微信官方 `access_token` 与 `users_phone_code`
|
||
3. 当前后端为 JavaScript + Express 架构,未引入 TypeScript 编译链
|
||
|
||
|