This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/docs/content-system.md
Victor_Jay fc65872882 docs: 内容系统改用 ID 链接,细化审核状态流转
- 链接格式 slug → /posts/{id}
- 状态重定义: draft/pending/approved/rejected/locked
- 新增 rejected 退回状态(可重提)+ locked 锁定状态(禁止编辑)
- 支持退回+锁定(严重违规/侵权场景)
- 新增解除锁定、提交审核等 API
2026-05-27 18:03:57 +08:00

9.0 KiB
Raw Blame History

内容系统设计文档

状态: 计划中 | 优先级: MVP


1. 内容模型

Post帖子/文章)

字段 类型 说明
id uint (PK) 自增主键
title varchar(200) 标题,非空
body text Markdown 原文
body_html text 渲染后 HTML写时缓存
user_id uint (FK → users) 作者
status varchar(20) draft / pending / approved / rejected / locked
reject_reason varchar(500) 退回理由(管理员填写)
allow_comment bool 是否允许评论MVP 预留)
deleted_at gorm.DeletedAt 软删除
created_at / updated_at timestamp

链接格式: /posts/{id}(如 /posts/42

状态说明:

状态 含义 公开可见 可编辑
draft 草稿,未被审核或审核已关闭 否(作者本人可见)
pending 待审,已提交等待管理员操作
approved 审核通过,公开发布
rejected 退回,审核未通过,可修改后重提
locked 锁定,禁止编辑只能删除

状态流转:

创建 → draft ──(提交/审核开启)──→ pending
                                    ├──(通过)──→ approved ──(撤回)──→ rejected
                                    │                │
                                    ├──(退回)──→ rejected           │
                                    │                │              │
                                    └──(退回+锁定)──→ locked ←──────┘
                                                             ←(任意状态锁定)

rejected ──(修改后重提)──→ pending
locked ──(解锁)──→ 回到锁定前状态

任何状态均可软删除(→ deleted_at

锁定场景:

  • 审核退回+锁定: 严重违规/侵权内容,无修改空间,禁止再次提交
  • 审核通过后退回+锁定: 已发布内容被撤回并禁止再次编辑/提交
  • 直接锁定: 任何时候管理员可锁定任意帖子

2. 分层结构

对齐现有四层架构:

internal/
├── model/post.go              # Post + 状态常量
├── repository/post_repo.go    # DB CRUD
├── service/post_service.go    # 业务逻辑 (依赖 postRepository 接口)
├── controller/
│   ├── post_controller.go     # SSR 页面 + API
│   └── interfaces.go          # 新增 postUseCase 接口
├── router/                    # 注册路由

依赖方向: router → controller → service → repository → model
接口定义: service 层定义 repository 接口controller 层定义 service 接口ISP
控制器位置: 放在 controller 根包,与 auth/settings 并列


3. 接口定义

Repository 接口service/repository.go 定义)

type postRepository interface {
    Create(post *model.Post) error
    FindByID(id uint) (*model.Post, error)
    FindPageable(keyword string, status string, page, pageSize int) ([]model.Post, int64, error)
    Update(post *model.Post) error
    SoftDelete(id uint) error
}

Service 接口controller/interfaces.go 定义)

type postUseCase interface {
    Create(userID uint, title, body string) (*model.Post, error)
    GetByID(id uint) (*model.Post, error)
    List(keyword string, page, pageSize int) ([]model.Post, int64, error)
    Update(userID uint, postID uint, title, body string) error
    Delete(userID uint, postID uint) error
    SubmitForAudit(postID uint) error        // 草稿 → 待审
    Approve(postID uint) error               // 审核通过
    Reject(postID uint, reason string) error // 退回
    Lock(postID uint) error                  // 锁定(禁止编辑)
    Unlock(postID uint) error                // 解锁
}

4. Service 业务逻辑

发帖流程

用户提交 → 
  1. 鉴权(中间件 authMdw.Required
  2. 校验标题/正文非空
  3. body → body_htmlGoldmark 渲染)
  4. 检查审核开关:
     - 审核关闭 → status = approved直接可见
     - 审核开启 → status = pending创建 AuditSubmission
  5. Save → 返回

列表

  • 仅返回 status = approved
  • keyword 标题模糊搜索
  • 分页默认 page_size=20
  • 排序: created_at DESC
  • 每条附带作者用户名

详情

  • 通过 ID 查找
  • 公开: 仅 approved
  • 作者本人 + admin+: 可预览 draft / pending / rejected / locked
  • 已渲染的 body_html 直接输出(带 XSS 防护)

编辑 / 删除

  • 权限: 作者本人 或 admin+
  • 状态约束: pending / locked 禁止编辑
  • rejected 状态编辑后自动重置为 draft
  • 删除: 软删除,任何状态均可

5. 路由设计

SSR 页面frontend

GET  /posts              列表页
GET  /posts/:id          详情页
GET  /posts/new          编辑器(需登录)
GET  /posts/:id/edit     编辑页(作者/adminlocked 状态禁止)

APIapi

POST   /api/posts              发帖
PUT    /api/posts/:id           编辑
DELETE /api/posts/:id           删除
POST   /api/posts/:id/submit   草稿提交审核
GET    /api/posts               列表 JSON
GET    /api/posts/:id           详情 JSON
POST   /api/posts/preview       Markdown 预览

管理后台admin

GET   /admin/posts                所有帖子(全状态)
POST  /admin/posts/:id/approve    审核通过
POST  /admin/posts/:id/reject     退回(需填写理由)
POST  /admin/posts/:id/lock       锁定(禁止编辑)
POST  /admin/posts/:id/unlock     解锁
POST  /admin/posts/:id/restore    恢复软删除

6. 模板设计

templates/MetaLab-2026/html/posts/
├── index.html            列表(卡片式: 标题+作者+时间+摘要)
├── show.html             详情Markdown 渲染 → 主题 CSS
├── new.html              编辑器EasyMDE + 实时预览)
└── edit.html             复用 new.html注入现有内容

templates/admin/html/posts/
└── index.html            管理列表(全量状态 + 操作按钮)
  • 列表摘要: body 前 200 字符纯文本剥离
  • 详情样式: 代码高亮、响应式图片、表格自适应
  • 编辑器: EasyMDE + marked.js + DOMPurify

7. Markdown 安全策略

层级 措施
服务端渲染 Goldmark (Go) + html.EscapeString
客户端预览 marked.js + DOMPurify
外部链接 rel="nofollow noopener noreferrer"
图片 限制域名白名单 + CSS max-width: 100%

8. 审核集成

复用现有 AuditSubmission 表,新增 type = "post":

用户角色 发帖后状态 如何可见
user审核开启 pending → AuditSubmission 审核通过 → approved
moderator+ approved 直接可见
user审核关闭 approved 直接可见

审核操作对应状态变更:

操作 状态变更 条件
提交审核 draftpending 仅作者本人
审核通过 pendingapproved admin+
退回 pending/approvedrejected admin+,需填写理由
退回+锁定 pending/approvedlocked admin+,严重违规/侵权

9. 管理后台扩展

侧边栏新增 "内容管理" 入口admin+

  • 全状态列表: 标题 / 作者 / 状态 / 时间 / 退回理由
  • 操作: 通过 / 退回 / 锁定 / 解锁 / 恢复
  • 状态标签: draft/ pending/ approved绿/ rejected/ locked

10. MVP vs 后续

维度 MVP 后续
内容 帖子 CRUD 评论系统
编辑器 EasyMDE + 实时预览 图片拖拽上传
列表 卡片 + 分页 分类 / 标签 / 置顶
审核 复用 Audit 表 编辑也走审核
管理 列表 + 基本操作 批量操作 / 搜索
通知 审核通过 / 新评论通知

11. 预计新增/修改文件

新增(~12:

internal/model/post.go
internal/repository/post_repo.go
internal/service/post_service.go
internal/controller/post_controller.go
templates/MetaLab-2026/html/posts/index.html
templates/MetaLab-2026/html/posts/show.html
templates/MetaLab-2026/html/posts/new.html
templates/admin/html/posts/index.html
templates/MetaLab-2026/static/css/posts.css
templates/admin/static/css/posts.css
templates/MetaLab-2026/static/js/editor.js
templates/admin/static/js/posts.js

修改(~6:

internal/controller/interfaces.go    + postUseCase
internal/service/repository.go       + postRepository (接口)
internal/router/frontend.go          + post SSR 路由
internal/router/api.go               + post API 路由
internal/router/admin.go             + admin post 路由
templates/admin/html/layout/base.html + 侧边栏
cmd/server/main.go                   + AutoMigrate Post