Files
persionalBrand/docs/03-data-and-api-design.md

4.3 KiB
Raw Blame History

数据库与 API 设计

1. 关系概览

订单模型和接口的最新增量见 首轮需求访谈决策。实现时必须包含客户微信身份、套餐价格快照、标签、未读状态和客户订单查询;与本文早期枚举冲突时,以该文档为准。

BrandProfile 1
  ├── Services 1..n
  └── PortfolioItems 1..n

Service 1 ── n Booking
Booking 1 ── 0..n Feedback
AdminUser 1 ── n AuditLog

第一版数据库只有一个品牌记录,但所有内容表仍通过 brand_id 关联,便于后续扩展。

2. 表与约束

brand_profiles

  • id UUID 主键
  • name 必填
  • is_published 默认 true
  • created_atupdated_at 必填

services

  • id UUID 主键
  • brand_id 外键
  • name 必填
  • price_text 可空
  • price_amount 可空,单位为分,第一版不用于支付
  • booking_enabled 默认 true
  • is_enabled 默认 true
  • sort_order 默认 0
  • (brand_id, sort_order) 建索引

portfolio_items

  • id UUID 主键
  • brand_id 外键
  • image_urls 可使用 JSON 数组,或拆分为 media_assets 表
  • is_visible 默认 true
  • sort_order 默认 0

bookings

  • id UUID 主键
  • booking_no 唯一
  • brand_id 外键
  • service_id 可空,防止服务删除后历史预约无法读取
  • status 枚举:pending/contacted/completed/cancelled
  • extra_data JSON可存储受控的行业扩展字段
  • (brand_id, status, created_at) 建索引
  • 不存支付状态

extra_data 不是任意键值存储。字段定义必须由品牌行业配置决定API 需要校验键名、类型和必填规则;通用字段仍保持结构化。

feedbacks

  • id UUID 主键
  • brand_id 外键
  • booking_id 可空
  • status 枚举:pending/approved/hidden
  • (brand_id, status, created_at) 建索引

admin_users

  • id UUID 主键
  • username 唯一
  • password_hash 必填
  • role 枚举:admin/operator
  • is_enabled 默认 true

audit_logs

  • id UUID 主键
  • admin_user_id 外键
  • actionresource_typeresource_id 必填
  • metadata JSON可记录变更摘要不记录密码和完整联系方式

3. API 约定

响应格式

{
  "data": {},
  "error": null,
  "requestId": "..."
}

失败时:

{
  "data": null,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "请填写有效的联系方式",
    "fields": { "phone": "格式不正确" }
  },
  "requestId": "..."
}

公开接口

GET  /api/public/brand
GET  /api/public/services
GET  /api/public/services/:id
GET  /api/public/portfolio
GET  /api/public/portfolio/:id
GET  /api/public/feedbacks
POST /api/public/bookings
POST /api/public/feedbacks

公开接口只能返回启用、可见和已审核数据。

管理接口

POST   /api/auth/login
POST   /api/auth/logout
GET    /api/auth/me

GET    /api/admin/brand
PUT    /api/admin/brand
GET    /api/admin/services
POST   /api/admin/services
PUT    /api/admin/services/:id
DELETE /api/admin/services/:id
GET    /api/admin/portfolio
POST   /api/admin/portfolio
PUT    /api/admin/portfolio/:id
DELETE /api/admin/portfolio/:id
GET    /api/admin/bookings
GET    /api/admin/bookings/:id
PATCH  /api/admin/bookings/:id/status
GET    /api/admin/feedbacks
PATCH  /api/admin/feedbacks/:id/status
POST   /api/admin/uploads/presign

4. 预约接口规则

  • 服务不存在或已停用时拒绝提交。
  • 期望日期早于当天时拒绝提交。
  • 联系方式至少一项非空。
  • 服务端再次执行所有校验,不能只依赖小程序校验。
  • 使用请求幂等键或短时间重复检测避免重复预约。
  • 创建成功后返回 booking_no,不返回管理员数据。

5. 文件上传流程

  1. 后台请求上传凭证。
  2. API 校验管理员权限和文件元数据。
  3. 前端直接上传对象存储。
  4. 上传完成后提交文件 URL 和元数据。
  5. 内容实体引用该资源。

不得让浏览器上传任意路径或任意 MIME 文件。图片最大尺寸和大小由环境变量配置。

6. 远期支付边界

未来新增:

orders
payments
refunds

Booking 表示客户意向或服务预约;Order 表示应收业务;Payment 表示微信支付交易;三者必须独立建模。支付成功不能直接等价于预约完成,预约仍由业务流程决定。