diff --git a/docs/content-system.md b/docs/content-system.md new file mode 100644 index 0000000..cec5c1f --- /dev/null +++ b/docs/content-system.md @@ -0,0 +1,251 @@ +# 内容系统设计文档 + +> **状态**: 计划中 | **优先级**: MVP + +--- + +## 1. 内容模型 + +### Post(帖子/文章) + +| 字段 | 类型 | 说明 | +|------|------|------| +| `id` | uint (PK) | 自增主键 | +| `title` | varchar(200) | 标题,非空 | +| `slug` | varchar(200), unique | URL 友好标识,标题自动生成,去重追加数字 | +| `body` | text | Markdown 原文 | +| `body_html` | text | 渲染后 HTML(写时缓存,避免重复解析) | +| `user_id` | uint (FK → users) | 作者 | +| `status` | varchar(20) | `draft` / `published` / `pending`(审核中)/ `hidden` | +| `allow_comment` | bool | 是否允许评论(MVP 预留字段) | +| `deleted_at` | gorm.DeletedAt | 软删除 | +| `created_at` / `updated_at` | timestamp | | + +**状态流转**: +``` +draft ──→ pending ──(审核通过)──→ published + | + (管理隐藏)──→ hidden + | + (作者删除)──→ 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 + FindBySlug(slug string) (*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) + GetBySlug(slug string) (*model.Post, error) + List(keyword string, page, pageSize int) ([]model.Post, int64, error) + Update(userID, role uint, title, body string) error + Delete(userID uint, id uint) error + AdminHide(id uint) error + AdminPublish(id uint) error +} +``` + +--- + +## 4. Service 业务逻辑 + +### 发帖流程 + +``` +用户提交 → + 1. 鉴权(中间件 authMdw.Required) + 2. 校验标题/正文非空 + 3. 生成 unique slug(标题 → URL 安全 → 查重追加数字后缀) + 4. body → body_html(Goldmark 渲染) + 5. 检查审核开关: + - IsRegistrationEnabled = false → status = published + - IsAuditEnabled = true → status = pending,创建 AuditSubmission + 6. Save → 返回 +``` + +### 列表 + +- 仅返回 `status = published` +- keyword 标题模糊搜索 +- 分页默认 page_size=20 +- 排序: created_at DESC +- 每条附带作者用户名 + +### 详情 + +- 通过 slug 查找 +- 公开: 仅 `published` +- 作者本人 + admin+: 可预览 `draft` / `pending` +- 已渲染的 body_html 直接输出(带 XSS 防护) + +### 编辑 / 删除 + +- 权限: 作者本人 或 admin+ +- 编辑: 更新 title / body / body_html,重新生成 slug(若标题变更) +- 删除: 软删除 + +--- + +## 5. 路由设计 + +### SSR 页面(frontend) + +``` +GET /posts 列表页 +GET /posts/:slug 详情页 +GET /posts/new 编辑器(需登录) +GET /posts/:slug/edit 编辑页(作者/admin) +``` + +### API(api) + +``` +POST /api/posts 发帖 +PUT /api/posts/:slug 编辑 +DELETE /api/posts/:slug 删除 +GET /api/posts 列表 JSON +GET /api/posts/:slug 详情 JSON +GET /api/posts/:slug/preview Markdown 预览 +``` + +### 管理后台(admin) + +``` +GET /admin/posts 所有帖子(含草稿/审核中/隐藏) +POST /admin/posts/:slug/hide 隐藏 +POST /admin/posts/:slug/publish 强制发布 +POST /admin/posts/:slug/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 | 审核通过 → published | +| moderator+ | `published` | 直接可见 | +| user(审核关闭) | `published` | 直接可见 | + +--- + +## 9. 管理后台扩展 + +侧边栏新增 "内容管理" 入口(admin+): + +- 全状态列表: 标题 / 作者 / 状态 / 时间 +- 操作: 隐藏 / 强制发布 / 恢复 +- 状态标签: draft(灰)/ pending(黄)/ published(绿)/ hidden(红) + +--- + +## 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 +```