Files
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

18 KiB
Raw Permalink Blame History

新闻资讯模块设计方案

1. 概述

1.1 模块定位

新闻资讯模块是飞点健康 CMS 系统的核心内容管理模块,用于发布和管理企业新闻、行业资讯、产品动态等内容。该模块与顶级菜单"新闻动态"关联,提供完整的栏目管理和资讯发布功能。

1.2 设计目标

  • 支持双格式发布:Markdown + HTML 富文本
  • 复用现有成熟代码(personal-blog)
  • 支持图片资源管理(可作为独立顶级模块)
  • 提供良好的编辑体验和预览功能

1.3 功能范围

┌─────────────────────────────────────────────────────────────┐
│                      新闻资讯模块                             │
├─────────────────┬─────────────────┬─────────────────────────┤
│    栏目管理      │    资讯管理      │       图片管理          │
├─────────────────┼─────────────────┼─────────────────────────┤
│ • 创建栏目      │ • 创建资讯      │ • 上传图片              │
│ • 编辑栏目      │ • 编辑资讯      │ • 图片列表              │
│ • 删除栏目      │ • 删除资讯      │ • 插入到文章            │
│ • 栏目排序      │ • 发布/草稿     │ • 删除图片              │
│                 │ • Markdown编辑  │                         │
│                 │ • HTML富文本    │                         │
│                 │ • 预览功能      │                         │
└─────────────────┴─────────────────┴─────────────────────────┘

2. 数据库设计

2.1 数据表关系图

┌─────────────────┐         ┌─────────────────┐         ┌─────────────────┐
│  news_categories│         │   news_posts    │         │    images       │
│    (栏目表)      │◄────────│   (资讯表)       │────────►│   (图片表)      │
├─────────────────┤   1:N   ├─────────────────┤   N:M   ├─────────────────┤
│ id (PK)         │         │ id (PK)         │         │ id (PK)         │
│ name            │         │ title           │         │ filename        │
│ slug (UQ)       │         │ slug (UQ)       │         │ file_path       │
│ description     │         │ content         │         │ thumb_path      │
│ sort_order      │         │ content_type    │◄───────│ description     │
│ is_enabled      │         │ summary         │         │ file_size       │
│ created_at      │         │ cover_image     │◄───────│ width           │
│ updated_at      │         │ category_id(FK) │         │ height          │
└─────────────────┘         │ is_published    │         │ created_at      │
                            │ is_draft        │         └─────────────────┘
                            │ view_count      │
                            │ created_at      │
                            │ updated_at      │
                            └─────────────────┘
                                      │
                                      │ 1:N
                                      ▼
                            ┌─────────────────┐
                            │ news_post_images│
                            │ (文章图片关联)   │
                            ├─────────────────┤
                            │ post_id (FK)    │
                            │ image_id (FK)   │
                            └─────────────────┘

2.2 表结构定义

2.2.1 news_categories - 栏目表

字段 类型 约束 说明
id INTEGER PK, AI 主键
name VARCHAR(50) NOT NULL 栏目名称
slug VARCHAR(50) UNIQUE, NOT NULL URL标识(如:company-news)
description VARCHAR(200) NULL 栏目描述
sort_order INTEGER DEFAULT 0 排序权重
is_enabled BOOLEAN DEFAULT 1 是否启用
created_at DATETIME DEFAULT NOW 创建时间
updated_at DATETIME DEFAULT NOW 更新时间
CREATE TABLE news_categories (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(50) NOT NULL,
    slug VARCHAR(50) UNIQUE NOT NULL,
    description VARCHAR(200),
    sort_order INTEGER DEFAULT 0,
    is_enabled BOOLEAN DEFAULT 1,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

2.2.2 news_posts - 资讯表

字段 类型 约束 说明
id INTEGER PK, AI 主键
title VARCHAR(200) NOT NULL 资讯标题
slug VARCHAR(200) UNIQUE, NOT NULL URL友好的标识
content TEXT NOT NULL 内容
content_type VARCHAR(10) DEFAULT 'markdown' 内容类型:markdown/html
summary VARCHAR(500) NULL 摘要(自动生成或手动填写)
cover_image VARCHAR(500) NULL 封面图路径
category_id INTEGER FK -> news_categories 栏目ID(必填)
is_published BOOLEAN DEFAULT 0 是否发布
is_draft BOOLEAN DEFAULT 1 是否草稿
view_count INTEGER DEFAULT 0 浏览次数
created_at DATETIME DEFAULT NOW 创建时间
updated_at DATETIME DEFAULT NOW 更新时间
CREATE TABLE news_posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title VARCHAR(200) NOT NULL,
    slug VARCHAR(200) UNIQUE NOT NULL,
    content TEXT NOT NULL,
    content_type VARCHAR(10) DEFAULT 'markdown',
    summary VARCHAR(500),
    cover_image VARCHAR(500),
    category_id INTEGER NOT NULL,
    is_published BOOLEAN DEFAULT 0,
    is_draft BOOLEAN DEFAULT 1,
    view_count INTEGER DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (category_id) REFERENCES news_categories(id) ON DELETE RESTRICT
);

2.2.3 images - 图片表(复用/扩展)

复用 personal-blog 的图片表结构,但提升为系统级资源表:

字段 类型 约束 说明
id INTEGER PK, AI 主键
filename VARCHAR(255) NOT NULL 存储文件名
original_name VARCHAR(255) NULL 原始文件名
file_path VARCHAR(500) NOT NULL 文件路径
thumb_path VARCHAR(500) NULL 缩略图路径
description VARCHAR(500) NULL 图片描述
file_size INTEGER NULL 文件大小(字节)
width INTEGER NULL 图片宽度
height INTEGER NULL 图片高度
module VARCHAR(20) DEFAULT 'news' 所属模块:news/product/page等
created_at DATETIME DEFAULT NOW 创建时间
CREATE TABLE images (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    filename VARCHAR(255) NOT NULL,
    original_name VARCHAR(255),
    file_path VARCHAR(500) NOT NULL,
    thumb_path VARCHAR(500),
    description VARCHAR(500),
    file_size INTEGER,
    width INTEGER,
    height INTEGER,
    module VARCHAR(20) DEFAULT 'news',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

3. 后端 API 设计

3.1 路由结构

/api/v1/
├── /news/
│   ├── GET    /categories              # 获取栏目列表
│   ├── POST   /categories              # 创建栏目
│   ├── GET    /categories/{id}         # 获取栏目详情
│   ├── PUT    /categories/{id}         # 更新栏目
│   ├── DELETE /categories/{id}         # 删除栏目
│   ├── GET    /posts                   # 获取资讯列表(分页、筛选)
│   ├── POST   /posts                   # 创建资讯
│   ├── GET    /posts/{id}              # 获取资讯详情
│   ├── PUT    /posts/{id}              # 更新资讯
│   ├── DELETE /posts/{id}              # 删除资讯
│   ├── POST   /posts/{id}/publish      # 发布资讯
│   ├── POST   /posts/{id}/unpublish    # 取消发布
│   └── GET    /posts/slug/{slug}       # 通过slug获取(访客端)
└── /images/
    ├── GET    /                        # 获取图片列表(分页)
    ├── POST   /upload                  # 上传图片
    ├── DELETE /{id}                    # 删除图片
    └── POST   /{id}/insert             # 获取图片插入URL

3.2 核心 API 定义

3.2.1 栏目管理 API

GET /api/v1/news/categories

// Response
{
  "items": [
    {
      "id": 1,
      "name": "公司新闻",
      "slug": "company-news",
      "description": "飞点健康最新动态",
      "sort_order": 1,
      "is_enabled": true,
      "post_count": 15,
      "created_at": "2024-01-15T08:00:00"
    }
  ],
  "total": 5
}

POST /api/v1/news/categories

// Request
{
  "name": "公司新闻",
  "slug": "company-news",
  "description": "飞点健康最新动态",
  "sort_order": 1
}

3.2.2 资讯管理 API

GET /api/v1/news/posts?page=1&size=10&category_id=1&keyword=xxx

// Response
{
  "items": [
    {
      "id": 1,
      "title": "飞点健康完成A轮融资",
      "slug": "feidian-series-a",
      "summary": "今日,飞点健康宣布完成数千万元A轮融资...",
      "cover_image": "/uploads/covers/xxx.jpg",
      "category": {
        "id": 1,
        "name": "公司新闻"
      },
      "content_type": "markdown",
      "is_published": true,
      "is_draft": false,
      "view_count": 1250,
      "created_at": "2024-01-20T10:30:00",
      "updated_at": "2024-01-20T10:30:00"
    }
  ],
  "total": 50,
  "page": 1,
  "size": 10
}

POST /api/v1/news/posts

// Request
{
  "title": "飞点健康完成A轮融资",
  "slug": "feidian-series-a",
  "content": "# 飞点健康完成A轮融资\n\n今日...",
  "content_type": "markdown",
  "summary": "今日,飞点健康宣布完成数千万元A轮融资...",
  "cover_image": "/uploads/covers/xxx.jpg",
  "category_id": 1,
  "is_draft": false
}

4. 前端设计

4.1 页面结构

/admin/news                    # 资讯管理首页(列表)
/admin/news/posts              # 资讯列表
/admin/news/posts/new          # 新建资讯
/admin/news/posts/:id/edit     # 编辑资讯
/admin/news/categories         # 栏目管理
/admin/images                  # 图片管理(可作为顶级菜单)

/news                          # 访客端新闻列表页
/news/:slug                    # 访客端新闻详情页

4.2 组件设计

4.2.1 管理端组件

src/pages/admin/news/
├── NewsLayout.jsx             # 新闻模块布局(侧边栏导航)
├── PostList.jsx               # 资讯列表页
├── PostEdit.jsx               # 资讯编辑页(双编辑器支持)
├── CategoryList.jsx           # 栏目列表页
└── components/
    ├── MarkdownEditor.jsx     # Markdown编辑器(复用blog)
    ├── HtmlEditor.jsx         # HTML富文本编辑器
    ├── PostForm.jsx           # 资讯表单(标题、栏目、封面等)
    ├── CategoryForm.jsx       # 栏目表单
    ├── ImagePicker.jsx        # 图片选择器
    └── PostPreview.jsx        # 文章预览组件

src/pages/admin/images/
├── ImageManager.jsx           # 图片管理页(可作为独立模块)
└── components/
    ├── ImageUploader.jsx      # 图片上传组件
    ├── ImageGrid.jsx          # 图片网格展示
    └── ImageDetail.jsx        # 图片详情/编辑

4.2.2 编辑器选型

格式 编辑器 特点 图片支持
Markdown react-markdown-editor-lite 轻量、性能好 支持粘贴/拖拽上传
HTML TinyMCE 6 功能丰富、稳定 内置图片上传插件

TinyMCE 配置要点:

{
  plugins: 'image link media table code fullscreen',
  toolbar: 'undo redo | formatselect | bold italic | alignleft aligncenter alignright | bullist numlist | image media link | table | code fullscreen',
  images_upload_url: '/api/v1/images/upload',
  images_upload_handler: customUploadHandler
}

4.3 路由配置

// 添加到 AdminLayout 侧边栏
{
  path: '/admin/news',
  label: '新闻资讯',
  icon: Newspaper,
  children: [
    { path: '/admin/news/posts', label: '资讯管理' },
    { path: '/admin/news/categories', label: '栏目管理' }
  ]
}

// 独立图片管理(可作为顶级菜单)
{
  path: '/admin/images',
  label: '图片管理',
  icon: Image
}

5. 复用代码清单

5.1 从 personal-blog 复用

组件/模块 源文件路径 目标路径 修改点
图片模型 backend/models.py Image backend/app/models/image.py 添加 module 字段
图片上传API backend/routers/images.py backend/app/routers/images.py 适配新路由前缀
图片管理页 frontend/src/pages/admin/Images.jsx frontend/src/pages/admin/images/ImageManager.jsx 样式统一
Markdown编辑器 无(需新增) frontend/src/pages/admin/news/components/MarkdownEditor.jsx -

5.2 复用策略

  1. 图片管理:完全复用 blog 的图片表结构,添加 module 字段区分来源
  2. 文件上传:复用上传逻辑,统一存储到 /uploads/news/
  3. 缩略图生成:复用 PIL 缩略图生成逻辑

6. 访客端展示

6.1 新闻列表页 (/news)

  • 顶部显示栏目筛选标签
  • 列表展示:封面图、标题、摘要、发布时间、浏览量
  • 支持分页加载

6.2 新闻详情页 (/news/:slug)

  • 文章标题、发布时间、栏目
  • 根据 content_type 渲染不同格式
  • Markdown: 使用 react-markdown + remark-gfm
  • HTML: 使用 dangerouslySetInnerHTML(需 XSS 过滤)

6.3 首页新闻模块联动

home_modules 表中 type=news 的模块,从 news_posts 表读取最新 N 条数据展示。


7. 实现步骤

Phase 1: 数据库与后端 API(预计 2-3 天)

  1. 创建数据库表(categories, posts, images)
  2. 实现栏目管理 API
  3. 实现资讯管理 API
  4. 复用/改造图片上传 API
  5. 编写 API 测试

Phase 2: 管理端前端(预计 3-4 天)

  1. 创建新闻模块路由和布局
  2. 实现栏目管理页面
  3. 实现 Markdown 编辑器组件
  4. 实现 HTML 编辑器组件(TinyMCE 集成)
  5. 实现资讯列表页
  6. 实现资讯编辑页(双编辑器切换)
  7. 实现图片管理页面

Phase 3: 访客端与联调(预计 2 天)

  1. 实现新闻列表页
  2. 实现新闻详情页(支持 Markdown/HTML 渲染)
  3. 联调首页新闻模块数据
  4. 顶部菜单"新闻动态"链接配置

Phase 4: 优化与测试(预计 1-2 天)

  1. 图片懒加载优化
  2. XSS 防护(HTML 内容过滤)
  3. 移动端适配
  4. 性能测试

8. 技术要点

8.1 XSS 防护

对于 HTML 格式的内容,必须做 XSS 过滤:

# 后端存储前过滤(可选)
from bleach import clean
allowed_tags = ['p', 'br', 'strong', 'em', 'u', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 
                'ul', 'ol', 'li', 'a', 'img', 'table', 'thead', 'tbody', 'tr', 'td', 'th']
allowed_attrs = {'a': ['href', 'title'], 'img': ['src', 'alt', 'width', 'height']}
cleaned_html = clean(raw_html, tags=allowed_tags, attributes=allowed_attrs)

8.2 图片存储规范

uploads/
├── news/                    # 新闻资讯图片
│   ├── 2024/01/            # 按年月组织
│   │   ├── xxx.jpg
│   │   └── thumbnails/     # 缩略图
│   └── ...
├── products/               # 产品图片
├── pages/                  # 页面图片
└── common/                 # 通用图片

8.3 slug 生成规则

def generate_slug(title: str) -> str:
    """将标题转换为 URL 友好的 slug"""
    # 1. 移除特殊字符
    # 2. 空格替换为连字符
    # 3. 转小写
    # 4. 处理重复(添加数字后缀)

9. 扩展性考虑

9.1 未来可扩展功能

  • 文章标签系统
  • 文章评论功能
  • 文章定时发布
  • 文章版本历史
  • 文章 SEO 元数据管理
  • 多语言支持

9.2 图片管理升级

当前作为新闻模块子功能,后续可提升为系统级资源中心,支持:

  • 图片分类/标签
  • 批量上传
  • 图片搜索
  • 在线编辑(裁剪、滤镜)

10. 参考资源

10.1 编辑器文档

10.2 代码参考

  • personal-blog Markdown 编辑实现
  • personal-blog 图片管理实现

文档版本: 1.0
创建时间: 2026-04-20
作者: nanobot