2026-06-09-article-activity-publishing-design.md 11 KB

文章与活动发布系统设计文档

日期: 2026-06-09 状态: 设计稿 v1


1. 概述

在 浠艾福(CFC) 平台中新增文章和活动发布功能:

  • 文章: 任何登录用户可发布,需运营审核后展示
  • 活动: 仅活动管理员可发布,无需审核
  • 分类: 独立分类体系 + 五维能量维度(body/mind/wisdom/action/wealth)关联
  • 展示: 微信小程序嵌入各页面的内容模块

2. 架构选择

方案 B: 统一内容表 + 扩展表

  • contents 表存储文章和活动的公共字段
  • activities_ext 表存储活动的独有字段
  • 文章独有字段少,直接放在 contents 表中

3. 数据模型

3.1 contents 表 — 统一内容基表

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 表 — 活动扩展

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 表 — 内容分类

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. 验收标准

  • articles 表可正常创建和迁移
  • activities_ext 表可正常创建和迁移
  • content_categories 表可正常创建和迁移,含 5 条能量维度默认分类
  • 文章 CRUD API 正常工作
  • 文章提交-审核-通过/驳回 状态流转正常
  • 活动 CRUD API 正常工作
  • 分类 CRUD API 正常工作
  • 所有 Controller 测试通过
  • 所有 Service 测试通过
  • 小程序页面展示正常