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

291 lines
9.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 内容系统设计文档
> **状态**: 计划中 | **优先级**: 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 定义)
```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 定义)
```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` | 直接可见 |
**审核操作对应状态变更**:
| 操作 | 状态变更 | 条件 |
|------|---------|------|
| 提交审核 | `draft``pending` | 仅作者本人 |
| 审核通过 | `pending``approved` | admin+ |
| 退回 | `pending`/`approved``rejected` | admin+,需填写理由 |
| 退回+锁定 | `pending`/`approved``locked` | 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
```