文档目录
收藏夹管理

简介

本开发文档面向 DouPHP 小程序“收藏夹”模块,覆盖收藏的添加、删除、分类管理与列表展示等核心能力。该模块支持商品、文章、案例等多类型对象的收藏,采用统一的 module + item_id 标识策略,后端以 favorites 表集中存储;前端通过 API 完成状态切换与分页加载,并提供空态、操作反馈与跳转等交互体验。

项目结构

收藏夹功能由“API 控制器层 + 前台服务层 + 数据模型层 + 后台管理”共同组成:

  • API 层:提供小程序端收藏增删查接口(favorites/user/*)
  • 前台服务层:封装收藏写入、删除、列表渲染逻辑
  • 数据模型层:favorites 表 ORM 映射
  • 后台管理:收藏记录查询、批量操作、按关键字筛选
  • 跨模块只读能力:core 层提供 mapFavoritedIds/getFavoritesState,供商品详情等场景读取当前用户收藏标记
graph TB
subgraph "小程序前端"
MP["小程序页面<br/>user.ts"]
end
subgraph "API 层"
FC["FavoritesController"]
UC["UserController"]
end
subgraph "前台服务层"
FS["FavoritesService(只读)"]
US["UserService(写/列表)"]
end
subgraph "数据模型"
M["Favorites Model"]
end
subgraph "后台管理"
AC["Admin FavoritesController"]
AS["Admin FavoritesService"]
end
MP --> UC
UC --> FS
UC --> US
US --> M
AC --> AS
AS --> M

核心组件

  • 小程序入口控制器:提供模块入口与路由兜底
  • 会员中心控制器:收藏添加、删除、列表分页
  • 前台服务:
    • FavoritesService:获取收藏状态文案与样式(跨端共享)
    • UserService:添加收藏(去重)、删除收藏、构建会员收藏列表
  • 数据模型:favorites 表 ORM 映射,包含 user_id、module、item_id、price、created_at
  • 后台管理:收藏记录分页、按 item_id/user_id 筛选、批量删除
  • 跨模块只读:core 层 FavoritesService 提供批量命中查询,用于商品列表/详情标注收藏状态

架构总览

小程序端通过 API 调用实现收藏的增删与列表展示;后台提供收藏记录的审计与管理。跨模块通过 core 层只读服务在商品/内容列表上标注收藏状态。

sequenceDiagram
participant U as "小程序页面"
participant A as "API UserController"
participant S as "前台 UserService"
participant R as "Favorites Service(只读)"
participant D as "数据库(favorites)"
U->>A : POST /favorites/user/store(module,item_id)
A->>R : getFavoritesState(module,item_id,userId)
R-->>A : {class,text}
A->>S : addIfNotExists(userId,module,item_id)
S->>D : INSERT IF NOT EXISTS
D-->>S : OK
A->>R : getFavoritesState(...)
R-->>A : {class,text}
A-->>U : {favorites : {class,text}, message}
U->>A : GET /favorites/user?page=1
A->>S : buildUserListPage(userId,page)
S->>D : SELECT ... ORDER BY id DESC LIMIT/PAGINATE
D-->>S : list,pager
S-->>A : {favorites_list,pager}
A-->>U : {title,favorites_list,pager,total}

详细组件分析

小程序端收藏交互流程

  • 点击收藏按钮触发 AJAX 请求,携带 module、item_id
  • 服务端返回新的收藏状态与文案,前端更新 UI(如添加 ed 类、替换文案)
  • 若返回 jump_url,则直接跳转
flowchart TD
Start(["点击收藏"]) --> Check["检查是否已收藏"]
Check --> |未收藏| Ajax["POST /favorites/user/store"]
Check --> |已收藏| End(["结束"])
Ajax --> Resp{"响应包含跳转?"}
Resp --> |是| Jump["window.location.href = data.jump_url"]
Resp --> |否| Update["更新UI: 添加ed类/替换文案"]
Jump --> End
Update --> End

收藏添加与删除(API)

  • 添加:store 方法先读取 before 状态,再执行 addIfNotExists,最后读取 after 状态并返回差异文案
  • 删除:destroy 方法根据 id 与 userId 删除记录,不存在返回 404
  • 列表:index 方法分页加载,并将 URL 转换为小程序路由
sequenceDiagram
participant C as "客户端"
participant UC as "UserController"
participant FS as "FavoritesService(只读)"
participant US as "UserService"
participant DB as "favorites表"
C->>UC : store(module,item_id)
UC->>FS : getFavoritesState(module,item_id,userId)
FS-->>UC : before
UC->>US : addIfNotExists(userId,module,item_id)
US->>DB : INSERT IF NOT EXISTS
DB-->>US : OK
UC->>FS : getFavoritesState(module,item_id,userId)
FS-->>UC : after
UC-->>C : {favorites : after,message}
C->>UC : destroy(id)
UC->>US : deleteByIdAndUser(id,userId)
US->>DB : DELETE WHERE id=user_id
DB-->>US : affected?
US-->>UC : bool
UC-->>C : success or 404

收藏列表与分页

  • 列表接口分页默认每页 16 条,按 id 倒序
  • 列表项动态关联对应 module 表,取标题/图片/价格等信息
  • 小程序侧维护 page、nomore 状态,支持下拉加载更多
flowchart TD
Load["onShow 鉴权后加载"] --> Page["page=1, nomore=false"]
Page --> Call["loadData(false,1)"]
Call --> API["GET /favorites/user?page=1"]
API --> Render["渲染 favorites_list"]
Render --> More{"是否还有更多"}
More --> |是| Next["page++, loadData(true,page)"]
More --> |否| nomore["nomore=true"]

跨模块收藏状态标注

  • 商品/内容列表可通过 HasForUserScope 自动注入 favorites 字段
  • core 层 FavoritesService::mapFavoritedIds 批量查询命中,O(1) 判定
  • 列表项可显示收藏按钮与文案
classDiagram
class HasForUserScope {
+forUserScope(query, module, userId)
}
class CoreFavoritesService {
+mapFavoritedIds(module, ids, userId) array
+getFavoritesState(module, itemId, userId) array|null
}
class FrontFavoritesService {
+getFavoritesState(module, itemId, userId) array|null
}
HasForUserScope --> CoreFavoritesService : "批量命中查询"
FrontFavoritesService <|-- CoreFavoritesService : "复用只读能力"

后台管理

  • 列表支持按 item_id 或 user_id 筛选,支持分页
  • 支持批量删除与单项删除
  • 列表项会回显模块名、创建时间、关联对象信息
flowchart TD
Admin["后台访问 favorites"] --> Build["buildFavoritesListData(keyField,keyword,page)"]
Build --> Query["过滤+分页"]
Query --> View["渲染 favorites.htm"]
View --> Action{"批量操作?"}
Action --> |删除| Del["action(del_all)"]
Action --> |删除单条| Destroy["destroy(id)"]

依赖关系分析

  • API 控制器依赖前台服务进行业务处理
  • 前台服务依赖 favorites 模型与数据库
  • 后台管理独立于小程序端,但共用同一张 favorites 表
  • 跨模块只读能力通过 core 层服务暴露,避免重复查询
graph LR
UC["API UserController"] --> FS["Front FavoritesService"]
UC --> US["Front UserService"]
US --> M["Favorites Model"]
AC["Admin FavoritesController"] --> AS["Admin FavoritesService"]
AS --> M
FS -.->|只读| M

性能与扩展性

  • 列表分页:默认每页 16 条,减少单次传输与渲染压力
  • 批量命中:core 层 mapFavoritedIds 使用 IN 查询与内存映射,O(1) 判断收藏状态
  • 去重插入:addIfNotExists 先 exists 再 insert,避免重复记录
  • 可扩展点:
    • 新增收藏类型:只需传入不同 module 值,无需改动数据结构
    • 搜索过滤:可在列表接口增加 keyword/sort 参数,结合现有分页机制
    • 缓存策略:对热点商品/内容的收藏状态可引入缓存层(如 Redis),降低频繁查询

故障排查指南

  • 收藏无效:确认 features.favorites 配置开启且用户已登录;检查 module、item_id 是否正确
  • 重复收藏:确认 addIfNotExists 的去重逻辑生效;查看 favorites 表是否存在唯一约束
  • 列表为空:检查 userId 是否正确、分页参数是否合理;确认对应 module 表存在相应 item_id
  • 删除失败:确认 id 与 userId 匹配;接口返回 404 表示记录不存在
  • 后台筛选异常:确认 keyField 与 keyword 组合条件解析正确

结论

DouPHP 小程序收藏夹模块以统一的数据模型与清晰的职责分层实现了多类型对象的收藏能力。通过 API 提供稳定的增删查接口,配合后台管理满足运营需求;跨模块只读能力使商品/内容列表能便捷标注收藏状态。建议在后续迭代中补充搜索、排序与缓存优化,进一步提升用户体验与系统性能。

附录:接口与数据模型

数据模型(favorites)

  • 字段说明:
    • id:主键
    • user_id:会员ID
    • module:模块名(如 product、article、cases)
    • item_id:对象ID
    • price:收藏时的价格快照
    • created_at:收藏时间

接口定义(小程序端)

  • 添加收藏
    • 路径:/favorites/user/store
    • 方法:POST
    • 参数:module、item_id
    • 返回:{favorites:{class,text}, message}
  • 删除收藏
    • 路径:/favorites/user/destroy
    • 方法:DELETE/POST
    • 参数:id
    • 返回:success 或 404
  • 我的收藏列表
    • 路径:/favorites/user
    • 方法:GET
    • 参数:page
    • 返回:{title, favorites_list[], pager, total}

语言与提示

  • 常用文案键:
    • favorites_btn:收藏
    • favorites_ed:已收藏
    • favorites_create_success:添加到收藏夹
    • favorites_delete_success:已删除
    • favorites_price_deducted:收藏后降价提示
添加日期:2026-10-05