feat(health): 内容管理模块 — 审核/分类/标签/富文本编辑器
后端: - 文章审核状态机:draft → pending_review → published(含 reject/unpublish) - 文章分类 CRUD(article_category entity + service + handler) - 文章标签 CRUD(article_tag + article_article_tag 关联) - 文章修订版快照(article_revision) - 阅读计数、排序、slug、审核备注 - 新增 health.articles.review 权限 前端: - ArticleManageList:状态标签页 + 分类筛选 + 关键字搜索 + 审核操作 - ArticleEditor:Wangeditor 富文本编辑器 + 元数据侧栏 - ArticleCategoryManage:分类 CRUD + 父子层级 - ArticleTagManage:标签 CRUD 修复: - diagnosis_service/health_data_service/dialysis_service: 补充 key_version 字段 - ArticleCategoryManage: 补充 Select 组件导入
This commit is contained in:
39
docs/discussions/2026-04-26-content-management-brainstorm.md
Normal file
39
docs/discussions/2026-04-26-content-management-brainstorm.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 内容管理模块设计讨论
|
||||
|
||||
> 日期: 2026-04-26 | 参与者: 用户 + AI
|
||||
|
||||
## 背景
|
||||
|
||||
HMS 项目已有文章(article)基础 CRUD 实现(后端 API + 小程序列表/详情页),但缺少 Web 管理后台、富文本编辑、审核流程、分类管理等核心内容管理能力。用户希望围绕内容管理功能展开发散式讨论,确定设计方向。
|
||||
|
||||
## 讨论要点
|
||||
|
||||
### 需求确认
|
||||
|
||||
- **定位**:综合内容平台 — 健康科普 + 医院公告 + 活动通知 + 科室介绍等
|
||||
- **编辑体验**:富文本可视化编辑(非 Markdown)
|
||||
- **发布流程**:需要审核流程(作者提交 → 审核员审批 → 发布)
|
||||
- **角色**:内容作者、审核员、患者读者(不需要独立的内容管理员角色)
|
||||
- **媒体**:先做图片上传,视频/附件后续再加
|
||||
|
||||
### 方案选择
|
||||
|
||||
讨论了两个方案:
|
||||
|
||||
1. **方案 A:在 erp-health 内扩展** — 改动最小,复用现有 CRUD + 权限体系
|
||||
2. **方案 B:拆分为独立 erp-content crate** — 关注点分离但工作量大
|
||||
|
||||
最终选择:**方案 A + 预留拆分接口**。内容管理代码放在 `content/` 子目录,通过事件总线与 health 核心通信,未来可拆分。
|
||||
|
||||
### 设计决策
|
||||
|
||||
- 数据模型:articles 表 ALTER 增加 status/slug/reviewed_by 等字段 + 新增 4 张表(category/tag/relation/revision)
|
||||
- 审核状态机:draft → pending_review → published,支持 reject 和 unpublish
|
||||
- 富文本编辑器:Wangeditor v5(MIT、轻量、中文优先)
|
||||
- 图片存储:本地文件系统,后续可迁移至 OSS
|
||||
- 新增权限码:`health.articles.review`
|
||||
- 新增事件:article.submitted/approved/rejected/published
|
||||
|
||||
## 结论
|
||||
|
||||
设计规格已写入 `docs/superpowers/specs/2026-04-26-content-management-design.md`,估算工作量 7-10 天(后端 3-4 天 + 前端 3-4 天 + 小程序 1-2 天)。
|
||||
328
docs/superpowers/specs/2026-04-26-content-management-design.md
Normal file
328
docs/superpowers/specs/2026-04-26-content-management-design.md
Normal file
@@ -0,0 +1,328 @@
|
||||
# HMS 内容管理模块设计规格
|
||||
|
||||
> 日期: 2026-04-26 | 状态: Draft | 依赖: erp-health (现有 article 基础)
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
|
||||
### 1.1 目标
|
||||
|
||||
将现有 article 基础 CRUD 扩展为综合内容管理平台,支持:
|
||||
|
||||
- 健康科普、医院公告、活动通知、科室介绍等多种内容类型
|
||||
- 富文本可视化编辑(Wangeditor)
|
||||
- 作者 → 审核员 → 发布的审核工作流
|
||||
- 受控分类 + 多对多标签
|
||||
- 图片上传
|
||||
- 阅读统计
|
||||
|
||||
### 1.2 方案选择
|
||||
|
||||
**在 erp-health 内扩展 + 预留拆分接口。**
|
||||
|
||||
理由:内容管理与健康管理强关联(科普、体检解读),现有后端 CRUD 完整只需增强。所有 article 相关代码放在 `crates/erp-health/src/content/` 子目录,通过事件总线与 health 核心通信,未来可拆分为独立 crate。
|
||||
|
||||
### 1.3 角色定义
|
||||
|
||||
| 角色 | 职责 | 权限 |
|
||||
|------|------|------|
|
||||
| 内容作者 | 创建/编辑/提交文章 | `health.articles.manage` |
|
||||
| 审核员 | 审核/批准/拒绝文章 | `health.articles.review` |
|
||||
| 患者读者 | 小程序阅读已发布内容 | 无需权限(公开端点) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 数据模型
|
||||
|
||||
### 2.1 articles 表改造
|
||||
|
||||
新增字段(在现有表基础上 ALTER):
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `status` | String(20) | `draft` / `pending_review` / `approved` / `rejected` / `published`,默认 `draft` |
|
||||
| `slug` | String(可选) | URL 友好标识 |
|
||||
| `content_type` | String(20) | `rich_text`(默认) / `markdown`,预留扩展 |
|
||||
| `reviewed_by` | UUID(可选) | 审核人 ID |
|
||||
| `reviewed_at` | DateTime(可选) | 审核时间 |
|
||||
| `review_note` | Text(可选) | 审核备注/拒绝原因 |
|
||||
| `view_count` | i32 | 阅读次数,默认 0 |
|
||||
| `sort_order` | i32 | 置顶/排序权重,默认 0 |
|
||||
|
||||
**发布语义变更:** 原来通过 `published_at IS NOT NULL` 判断发布状态,改为通过 `status = 'published'` 控制。`published_at` 保留作为实际发布时间。
|
||||
|
||||
**现有字段保留:** id, tenant_id, title, summary, content, cover_image, category(过渡期保留,迁移完成后废弃), author, published_at, 标准字段。
|
||||
|
||||
### 2.2 新增 article_category 表
|
||||
|
||||
```sql
|
||||
CREATE TABLE article_category (
|
||||
id UUID PRIMARY KEY,
|
||||
tenant_id UUID NOT NULL,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
slug VARCHAR(100),
|
||||
parent_id UUID REFERENCES article_category(id),
|
||||
description TEXT,
|
||||
sort_order INT DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
version INT NOT NULL DEFAULT 1
|
||||
);
|
||||
```
|
||||
|
||||
### 2.3 新增 article_tag 表
|
||||
|
||||
```sql
|
||||
CREATE TABLE article_tag (
|
||||
id UUID PRIMARY KEY,
|
||||
tenant_id UUID NOT NULL,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
version INT NOT NULL DEFAULT 1
|
||||
);
|
||||
```
|
||||
|
||||
### 2.4 新增 article_article_tag 关联表
|
||||
|
||||
```sql
|
||||
CREATE TABLE article_article_tag (
|
||||
article_id UUID NOT NULL REFERENCES articles(id),
|
||||
tag_id UUID NOT NULL REFERENCES article_tag(id),
|
||||
PRIMARY KEY (article_id, tag_id)
|
||||
);
|
||||
```
|
||||
|
||||
### 2.5 新增 article_revision 表(预留版本历史)
|
||||
|
||||
```sql
|
||||
CREATE TABLE article_revision (
|
||||
id UUID PRIMARY KEY,
|
||||
tenant_id UUID NOT NULL,
|
||||
article_id UUID NOT NULL REFERENCES articles(id),
|
||||
revision_number INT NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
summary TEXT,
|
||||
created_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 审核工作流
|
||||
|
||||
### 3.1 状态机
|
||||
|
||||
```
|
||||
draft ──submit()──→ pending_review ──approve()──→ published
|
||||
↑ │
|
||||
│ reject()
|
||||
│ ↓
|
||||
└─────rejected ←──────┘
|
||||
(修改后重新 submit → pending_review)
|
||||
|
||||
published ──unpublish()──→ draft
|
||||
```
|
||||
|
||||
| 状态 | 可见性 | 允许操作 |
|
||||
|------|--------|---------|
|
||||
| `draft` | 仅作者 | 编辑、提交审核、删除 |
|
||||
| `pending_review` | 作者 + 审核员 | 审核员:通过/拒绝;作者:撤回 |
|
||||
| `approved` | 过渡态,自动发布 | — |
|
||||
| `rejected` | 作者 | 编辑后重新提交 |
|
||||
| `published` | 所有人(含小程序) | 撤回、删除 |
|
||||
|
||||
### 3.2 事件
|
||||
|
||||
| 事件 | 触发时机 | 消费者 |
|
||||
|------|---------|--------|
|
||||
| `article.submitted` | draft → pending_review | 通知审核员 |
|
||||
| `article.approved` | 审核通过 | 记录日志 |
|
||||
| `article.rejected` | 审核拒绝 | 通知作者 |
|
||||
| `article.published` | 正式发布 | 记录日志 |
|
||||
|
||||
---
|
||||
|
||||
## 4. API 设计
|
||||
|
||||
### 4.1 文章 CRUD(增强已有)
|
||||
|
||||
| Method | Path | 说明 | 权限 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/api/v1/health/articles` | 文章列表(管理端,支持 status/category/tag 筛选) | `health.articles.list` |
|
||||
| GET | `/api/v1/health/articles/{id}` | 文章详情 | `health.articles.list` |
|
||||
| POST | `/api/v1/health/articles` | 创建文章(默认 draft) | `health.articles.manage` |
|
||||
| PUT | `/api/v1/health/articles/{id}` | 更新文章 | `health.articles.manage` |
|
||||
| DELETE | `/api/v1/health/articles/{id}` | 软删除 | `health.articles.manage` |
|
||||
|
||||
**列表查询参数**:`page`, `page_size`, `status`, `category_id`, `tag_id`, `keyword`(标题搜索)
|
||||
|
||||
### 4.2 审核流程
|
||||
|
||||
| Method | Path | 说明 | 权限 |
|
||||
|--------|------|------|------|
|
||||
| POST | `/api/v1/health/articles/{id}/submit` | 提交审核 | `health.articles.manage` |
|
||||
| POST | `/api/v1/health/articles/{id}/approve` | 审核通过并发布 | `health.articles.review` |
|
||||
| POST | `/api/v1/health/articles/{id}/reject` | 审核拒绝(body: `{ "note": "..." }`) | `health.articles.review` |
|
||||
| POST | `/api/v1/health/articles/{id}/unpublish` | 撤回发布 | `health.articles.manage` |
|
||||
|
||||
### 4.3 分类管理
|
||||
|
||||
| Method | Path | 说明 | 权限 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/api/v1/health/article-categories` | 分类列表(树形) | `health.articles.list` |
|
||||
| POST | `/api/v1/health/article-categories` | 创建分类 | `health.articles.manage` |
|
||||
| PUT | `/api/v1/health/article-categories/{id}` | 更新分类 | `health.articles.manage` |
|
||||
| DELETE | `/api/v1/health/article-categories/{id}` | 删除分类 | `health.articles.manage` |
|
||||
|
||||
### 4.4 标签管理
|
||||
|
||||
| Method | Path | 说明 | 权限 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/api/v1/health/article-tags` | 标签列表 | `health.articles.list` |
|
||||
| POST | `/api/v1/health/article-tags` | 创建标签 | `health.articles.manage` |
|
||||
| DELETE | `/api/v1/health/article-tags/{id}` | 删除标签 | `health.articles.manage` |
|
||||
|
||||
### 4.5 图片上传
|
||||
|
||||
| Method | Path | 说明 | 权限 |
|
||||
|--------|------|------|------|
|
||||
| POST | `/api/v1/health/articles/upload-image` | 上传图片,返回 `{ url }` | `health.articles.manage` |
|
||||
|
||||
图片存储:本地文件系统 `uploads/articles/{tenant_id}/{yyyy-MM}/{uuid}.{ext}`,后续可迁移至 OSS。
|
||||
|
||||
### 4.6 权限变更
|
||||
|
||||
新增权限码:
|
||||
|
||||
| 权限码 | 名称 | 说明 |
|
||||
|--------|------|------|
|
||||
| `health.articles.review` | 审核资讯 | 新增 |
|
||||
|
||||
保留已有:
|
||||
|
||||
| 权限码 | 名称 |
|
||||
|--------|------|
|
||||
| `health.articles.list` | 查看资讯 |
|
||||
| `health.articles.manage` | 管理资讯 |
|
||||
|
||||
---
|
||||
|
||||
## 5. Web 前端
|
||||
|
||||
### 5.1 新增页面
|
||||
|
||||
| 页面 | 路由 | 组件 |
|
||||
|------|------|------|
|
||||
| 文章列表 | `/health/articles` | `ArticleManageList` |
|
||||
| 创建文章 | `/health/articles/new` | `ArticleEditor` |
|
||||
| 编辑文章 | `/health/articles/:id/edit` | `ArticleEditor` |
|
||||
| 文章详情/预览 | `/health/articles/:id` | `ArticlePreview` |
|
||||
| 分类管理 | `/health/article-categories` | `ArticleCategoryManage` |
|
||||
| 标签管理 | `/health/article-tags` | `ArticleTagManage` |
|
||||
|
||||
### 5.2 文章列表页
|
||||
|
||||
- 状态 Tab 筛选:全部 | 草稿 | 待审核 | 已发布 | 已拒绝
|
||||
- 分类下拉筛选
|
||||
- 标题关键词搜索
|
||||
- 表格列:标题、分类、标签、状态(色块)、作者、阅读数、发布时间、操作
|
||||
- 操作按钮根据状态和权限动态显示:
|
||||
- 草稿:编辑、删除、提交审核
|
||||
- 待审核:查看(审核员可看到审核/拒绝)
|
||||
- 已发布:查看、撤回
|
||||
- 已拒绝:编辑、重新提交
|
||||
|
||||
### 5.3 富文本编辑器
|
||||
|
||||
**选型:Wangeditor v5**
|
||||
|
||||
- MIT 协议,轻量(~200KB)
|
||||
- 中文优先,React 集成简单(`@wangeditor/editor-for-react`)
|
||||
- 支持图片上传 hook(对接后端 upload-image API)
|
||||
- 支持标题/列表/链接/表格等常用格式
|
||||
|
||||
编辑器页面布局:
|
||||
- 左侧:富文本编辑区域
|
||||
- 右侧:标题、分类选择、标签选择、摘要、封面图上传、slug
|
||||
- 底部:保存草稿 / 提交审核 按钮
|
||||
|
||||
### 5.4 侧边栏菜单
|
||||
|
||||
在健康管理分组下新增「内容管理」菜单项,图标使用 `FileTextOutlined`。
|
||||
|
||||
---
|
||||
|
||||
## 6. 小程序端增强
|
||||
|
||||
### 6.1 文章列表页改造
|
||||
|
||||
- 增加顶部分类 Tab(从 article-category API 获取)
|
||||
- 下拉刷新 + 无限滚动
|
||||
- 搜索框(标题关键词)
|
||||
|
||||
### 6.2 文章详情页改造
|
||||
|
||||
- 增加 `view_count` 展示
|
||||
- 进入详情页时调用阅读计数 API(POST 或 PUT 递增)
|
||||
|
||||
### 6.3 新增 API 调用
|
||||
|
||||
- `GET /api/v1/health/articles` — 增加 `category_id`、`keyword` 参数
|
||||
- `POST /api/v1/health/articles/{id}/view` — 阅读计数
|
||||
|
||||
---
|
||||
|
||||
## 7. 实施步骤
|
||||
|
||||
### Phase 1:后端增强(3-4 天)
|
||||
|
||||
1. 数据库迁移:articles 表 ALTER + article_category/article_tag/article_article_tag/article_revision 四张新表
|
||||
2. Entity 定义:修改 Article entity + 新增 ArticleCategory、ArticleTag、ArticleArticleTag、ArticleRevision
|
||||
3. Service 层:ArticleService 增强(状态机、审核、搜索)+ CategoryService + TagService + RevisionService
|
||||
4. Handler 层:新增审核/分类/标签/上传端点
|
||||
5. 权限注册:新增 `health.articles.review`
|
||||
6. 事件发布:article.submitted/approved/rejected/published
|
||||
7. 图片上传:文件存储端点
|
||||
|
||||
### Phase 2:Web 前端(3-4 天)
|
||||
|
||||
1. 安装 Wangeditor 依赖
|
||||
2. 文章列表页(筛选、状态 Tab、表格)
|
||||
3. 文章编辑页(富文本编辑器 + 元数据表单)
|
||||
4. 文章预览/审核页
|
||||
5. 分类管理页
|
||||
6. 标签管理页
|
||||
7. 路由注册 + 侧边栏菜单
|
||||
|
||||
### Phase 3:小程序增强(1-2 天)
|
||||
|
||||
1. 文章列表分类 Tab
|
||||
2. 搜索功能
|
||||
3. 阅读计数
|
||||
4. API 调用适配
|
||||
|
||||
### 总估算:7-10 天
|
||||
|
||||
---
|
||||
|
||||
## 8. 验收标准
|
||||
|
||||
- [ ] 作者可创建/编辑文章(富文本),保存为草稿
|
||||
- [ ] 作者可提交审核
|
||||
- [ ] 审核员可看到待审列表,通过或拒绝
|
||||
- [ ] 已发布文章在小程序端可见
|
||||
- [ ] 分类和标签可管理
|
||||
- [ ] 图片可上传并在编辑器中插入
|
||||
- [ ] 阅读计数正确递增
|
||||
- [ ] `cargo check` + `cargo test` 通过
|
||||
- [ ] 前端 `pnpm build` 通过
|
||||
Reference in New Issue
Block a user