Преглед на файлове

docs: 添加文章与活动发布系统设计文档

Sisyphus преди 4 месеца
родител
ревизия
722a81d414
променени са 1 файла, в които са добавени 317 реда и са изтрити 0 реда
  1. 317 0
      docs/superpowers/specs/2026-06-09-article-activity-publishing-design.md

+ 317 - 0
docs/superpowers/specs/2026-06-09-article-activity-publishing-design.md

@@ -0,0 +1,317 @@
+# 文章与活动发布系统设计文档
+
+**日期:** 2026-06-09
+**状态:** 设计稿 v1
+
+---
+
+## 1. 概述
+
+在 浠艾福(CFC) 平台中新增文章和活动发布功能:
+- **文章**: 任何登录用户可发布,需运营审核后展示
+- **活动**: 仅活动管理员可发布,无需审核
+- **分类**: 独立分类体系 + 五维能量维度(body/mind/wisdom/action/wealth)关联
+- **展示**: 微信小程序嵌入各页面的内容模块
+
+---
+
+## 2. 架构选择
+
+**方案 B**: 统一内容表 + 扩展表
+- `contents` 表存储文章和活动的公共字段
+- `activities_ext` 表存储活动的独有字段
+- 文章独有字段少,直接放在 contents 表中
+
+---
+
+## 3. 数据模型
+
+### 3.1 contents 表 — 统一内容基表
+
+```sql
+CREATE TABLE IF NOT EXISTS contents (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    title VARCHAR(200) NOT NULL COMMENT '标题',
+    summary VARCHAR(500) COMMENT '摘要',
+    content TEXT COMMENT '富文本内容(HTML)',
+    cover_image VARCHAR(500) COMMENT '封面图URL',
+    type VARCHAR(20) NOT NULL COMMENT 'article/activity',
+    category_id BIGINT COMMENT '分类ID',
+    energy_dimension VARCHAR(20) COMMENT 'body/mind/wisdom/action/wealth',
+    author_id BIGINT NOT NULL COMMENT '发布者用户ID',
+    status VARCHAR(20) NOT NULL DEFAULT 'draft' COMMENT 'draft/pending/approved/rejected',
+    reject_reason VARCHAR(500) COMMENT '驳回原因',
+    view_count INT DEFAULT 0 COMMENT '浏览量',
+    publish_time DATETIME COMMENT '发布时间',
+    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    INDEX idx_type_status (type, status),
+    INDEX idx_energy_dimension (energy_dimension),
+    INDEX idx_author_id (author_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='统一内容表';
+```
+
+### 3.2 activities_ext 表 — 活动扩展
+
+```sql
+CREATE TABLE IF NOT EXISTS activities_ext (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    content_id BIGINT NOT NULL UNIQUE COMMENT '关联contents.id',
+    location VARCHAR(300) COMMENT '活动地点',
+    start_time DATETIME COMMENT '开始时间',
+    end_time DATETIME COMMENT '结束时间',
+    max_participants INT COMMENT '最大参与人数',
+    sign_up_deadline DATETIME COMMENT '报名截止时间',
+    contact_phone VARCHAR(20) COMMENT '联系电话',
+    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+    INDEX idx_start_time (start_time),
+    FOREIGN KEY (content_id) REFERENCES contents(id) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='活动扩展信息';
+```
+
+### 3.3 content_categories 表 — 内容分类
+
+```sql
+CREATE TABLE IF NOT EXISTS content_categories (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    name VARCHAR(50) NOT NULL COMMENT '分类名称',
+    energy_dimension VARCHAR(20) COMMENT '关联能量维度',
+    sort_order INT DEFAULT 0 COMMENT '排序',
+    type VARCHAR(20) NOT NULL COMMENT 'article/activity/both',
+    status VARCHAR(20) DEFAULT 'active' COMMENT 'active/inactive',
+    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+    INDEX idx_type (type),
+    INDEX idx_energy_dimension (energy_dimension)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='内容分类';
+```
+
+---
+
+## 4. 后端 API
+
+### 4.1 文章 API (`controller/article/ArticleController.java`)
+
+| 端点 | 方法 | 说明 | 权限 |
+|------|------|------|------|
+| `/api/articles/create` | POST | 创建文章(draft) | 登录用户 |
+| `/api/articles/submit` | POST | 提交审核(draft→pending) | 作者 |
+| `/api/articles/update` | POST | 更新文章 | 作者 |
+| `/api/articles/list` | POST | 已发布文章列表(分页) | 公开 |
+| `/api/articles/detail` | POST | 文章详情 | 公开 |
+| `/api/articles/my` | POST | 我的文章列表 | 登录用户 |
+
+### 4.2 文章审核 API (`controller/admin/ArticleAdminController.java`)
+
+| 端点 | 方法 | 说明 | 权限 |
+|------|------|------|------|
+| `/api/admin/articles/pending` | POST | 待审核列表 | admin |
+| `/api/admin/articles/approve` | POST | 审核通过 | admin |
+| `/api/admin/articles/reject` | POST | 审核驳回 | admin |
+
+### 4.3 活动 API (`controller/activity/ActivityController.java`)
+
+| 端点 | 方法 | 说明 | 权限 |
+|------|------|------|------|
+| `/api/activities/create` | POST | 创建活动 | admin |
+| `/api/activities/update` | POST | 更新活动 | admin |
+| `/api/activities/list` | POST | 活动列表(分页) | 公开 |
+| `/api/activities/detail` | POST | 活动详情 | 公开 |
+
+### 4.4 分类 API (`controller/content/ContentCategoryController.java`)
+
+| 端点 | 方法 | 说明 | 权限 |
+|------|------|------|------|
+| `/api/content-categories/list` | POST | 分类列表 | 公开 |
+| `/api/content-categories/create` | POST | 创建分类 | admin |
+| `/api/content-categories/update` | POST | 更新分类 | admin |
+| `/api/content-categories/delete` | POST | 删除分类 | admin |
+
+---
+
+## 5. 文件结构
+
+### 后端 (cfc-backend)
+```
+src/main/java/com/etotem/cfc/
+├── config/DatabaseInitializer.java     # DDL迁移(追加)
+├── entity/
+│   ├── Content.java                     # 统一内容实体
+│   ├── ActivityExt.java                 # 活动扩展实体
+│   └── ContentCategory.java             # 分类实体
+├── mapper/
+│   ├── ContentMapper.java
+│   ├── ActivityExtMapper.java
+│   └── ContentCategoryMapper.java
+├── service/
+│   ├── ArticleService.java              # 文章业务+审核
+│   ├── ActivityService.java             # 活动业务
+│   └── ContentCategoryService.java      # 分类业务
+├── controller/
+│   ├── article/ArticleController.java
+│   ├── admin/ArticleAdminController.java
+│   ├── activity/ActivityController.java
+│   └── content/ContentCategoryController.java
+├── dto/
+│   ├── ArticleCreateDTO.java
+│   ├── ArticleUpdateDTO.java
+│   ├── ActivityCreateDTO.java
+│   ├── ActivityUpdateDTO.java
+│   └── ContentCategoryDTO.java
+```
+
+### 前端 (cfc-frontend)
+```
+pages/
+├── article/
+│   ├── index.vue      # 文章列表
+│   └── detail.vue     # 文章详情
+└── activity/
+    ├── index.vue      # 活动列表
+    └── detail.vue     # 活动详情
+
+components/
+├── article-card.vue   # 文章卡片组件
+└── activity-card.vue  # 活动卡片组件
+```
+
+### 测试
+```
+src/test/java/com/etotem/cfc/
+├── controller/
+│   ├── ArticleControllerTest.java
+│   ├── ArticleAdminControllerTest.java
+│   ├── ActivityControllerTest.java
+│   └── ContentCategoryControllerTest.java
+└── service/
+    ├── ArticleServiceTest.java
+    ├── ActivityServiceTest.java
+    └── ContentCategoryServiceTest.java
+```
+
+---
+
+## 6. 状态机
+
+### 文章状态流转
+```
+draft ──submit──→ pending ──approve──→ approved
+                    │                      │
+                    ├──reject──→ rejected   │
+                    │                      │
+                    └──withdraw→ withdrawn  │
+                                           │
+              rejected ──resubmit──→ pending
+              withdrawn ──resubmit──→ pending
+```
+
+### 活动状态
+活动由 admin 直接发布,无需审核:
+```
+draft ──publish──→ published ──close──→ closed
+```
+
+---
+
+## 7. 测试用例
+
+### ArticleControllerTest (~15 用例)
+- createArticle_Success — 创建文章(draft)
+- createArticle_NoTitle — 标题为空
+- createArticle_NoContent — 内容为空
+- submitArticle_Success — 提交审核
+- submitArticle_AlreadyApproved — 已审核文章不能提交
+- updateArticle_Success — 更新文章
+- updateArticle_NotAuthor — 非作者不能更新
+- getArticleList_Success — 已发布文章列表
+- getArticleList_ByCategory — 按分类筛选
+- getArticleList_ByEnergyDimension — 按能量维度筛选
+- getArticleDetail_Success — 文章详情
+- getArticleDetail_NotFound — 文章不存在
+- getMyArticles_Success — 我的文章列表
+- getMyArticles_Empty — 没有文章
+
+### ArticleAdminControllerTest (~10 用例)
+- getPendingList_Success — 待审核列表
+- approveArticle_Success — 审核通过
+- approveArticle_NotPending — 非待审状态不能通过
+- approveArticle_NotFound — 文章不存在
+- rejectArticle_Success — 审核驳回
+- rejectArticle_WithReason — 驳回带原因
+
+### ActivityControllerTest (~10 用例)
+- createActivity_Success — 创建活动
+- createActivity_MissingRequired — 缺少必填字段
+- updateActivity_Success — 更新活动
+- getActivityList_Success — 活动列表
+- getActivityList_ByEnergyDimension — 按能量维度筛选
+- getActivityDetail_Success — 活动详情
+
+### ContentCategoryControllerTest (~8 用例)
+- createCategory_Success — 创建分类
+- createCategory_Duplicate — 分类名重复
+- updateCategory_Success — 更新分类
+- deleteCategory_Success — 删除分类
+- getCategoryList_Success — 分类列表
+- getCategoryList_ByEnergyDimension — 按能量维度查分类
+
+### ArticleServiceTest (~10 用例)
+- submitReview_Success — 提交审核状态变化
+- approve_Success — 审核通过状态变化
+- reject_Success — 审核驳回状态变化
+- reject_WithReason — 驳回带原因
+- submit_FromWrongStatus — 错误状态不能提交
+- approve_FromWrongStatus — 非待审不能通过
+- getUserArticles_Success — 用户文章列表
+- searchByEnergyDimension — 按能量维度搜索
+
+---
+
+## 8. 前端页面设计
+
+### 文章列表页 (pages/article/index.vue)
+- 顶部筛选:分类滚动条 + 能量维度标签
+- 文章卡片列表:封面图、标题、摘要、作者、发布时间
+- 点击进入详情
+
+### 文章详情页 (pages/article/detail.vue)
+- 富文本渲染(rich-text 组件)
+- 作者信息、发布时间、浏览量
+- 能量维度标签展示
+
+### 活动列表页 (pages/activity/index.vue)
+- 时间筛选(进行中/即将开始/已结束)
+- 活动卡片:封面、标题、时间、地点
+
+### 活动详情页 (pages/activity/detail.vue)
+- 基本信息 + 富文本内容
+- 报名信息、地点、时间
+
+### 嵌入组件 (components/article-card.vue / activity-card.vue)
+- 横滑推荐卡片
+- 用于首页、发现页等嵌入
+
+---
+
+## 9. 与现有系统的集成
+
+- **认证复用**: 使用现有 JWT 认证,`@RequestAttribute("userId")` 获取用户
+- **角色权限**: admin 角色可访问审核/活动管理 API
+- **数据库**: 通过 DatabaseInitializer 执行 DDL 迁移
+- **MediaController**: 图片上传复用现有文件上传接口
+- **统一响应**: 使用 `Result<T>` 包装
+- **统一 @PostMapping**: 遵循项目规范
+
+---
+
+## 10. 验收标准
+
+- [x] articles 表可正常创建和迁移
+- [x] activities_ext 表可正常创建和迁移
+- [x] content_categories 表可正常创建和迁移,含 5 条能量维度默认分类
+- [x] 文章 CRUD API 正常工作
+- [x] 文章提交-审核-通过/驳回 状态流转正常
+- [x] 活动 CRUD API 正常工作
+- [x] 分类 CRUD API 正常工作
+- [x] 所有 Controller 测试通过
+- [x] 所有 Service 测试通过
+- [x] 小程序页面展示正常