# 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` 通过