Files
mce/docs/development.md
2026-06-22 03:12:29 +08:00

195 lines
8.8 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.

# 开发记录 — MetaLab RC
> 最后更新2026-06-22 | 版本v0.1.0-rc1
## 一、架构总览
```
Web 适配器 (Gin Controller) → ISP Ports (interfaces.go)
Service 核心逻辑
Store Interfaces (repository.go) ← DB 适配器 (GORM Repo)
```
| 层次 | 职责 | 单文件上限 |
|------|------|-----------|
| Router | 路由映射 + 依赖注入 | ≤ 60 行 |
| Controller | 参数绑定 + 调用服务 + 返回 | ≤ 120 行 |
| Middleware | 认证/授权/安全头/限流 | ≤ 60 行 |
| Service | 业务逻辑 | ≤ 300 行 |
| Repository | 纯数据库操作 | ≤ 200 行 |
| Model | 纯结构体 | ≤ 80 行 |
## 二、已完成阶段
### Phase 1基础设施 + 用户认证
- PostgreSQL + AutoMigrate + 部分唯一索引(软删除用户邮箱复用)
- Gin + 模板渲染 + 静态资源哈希缓存破坏
- 用户注册/登录/登出 + bcrypt(12) 密码哈希
- 服务端 Session滑动窗口续期Redis + 内存 FallbackStore 自动降级
- 全局 `SecurityHeaders` 中间件CSP nonce、HSTS、X-Frame-Options、X-Content-Type-Options
- `InjectSiteInfo` 中间件注入站点品牌信息到所有 SSR 页面
- 角色系统user/moderator/admin/ownerOCP 可扩展)
- `BuildPageData()` / `BuildAdminPageData()` 统一模板数据注入
- CSRF Double Submit Cookie 保护
- 敏感操作限流(`SensitiveRateLimit`:改密/注销/签到)+ 登录限流(账户+IP 双维度滑动窗口)
- 维护模式(仅 owner 可访问,其余用户重定向登录页)
### Phase 2公告系统
- 公告 CRUD + 管理后台管理页面
- 前台首页公告区域
### Phase 3文章属性
- Post 模型Visibilitypublic/private、PostTypeoriginal/reprint、ReprintSource
- 创作声明7 种)、禁止转载标记
- 文章置顶category/global+ 管理后台 Pin/Unpin API
- 原创/转载:写文章页条件联动
- 模板函数 `declarationLabel()`
### Phase 4分类系统 + 标签系统
- Category 两级树形结构 + 管理后台页面
- Tag 系统 + 落地页 `/tags/{slug}`
- 写文章页分类选择 + 标签输入
### Phase 5定时发布
- Post 模型 `ScheduledAt` + 审核逻辑
- Scheduler goroutine 每分钟扫描发布到期文章
- 前端日期时间选择器min=now+30min
### Phase 6收尾与审计修复2026-06-22
**安全加固:**
| 项目 | 变更 |
|------|------|
| CSP | `'unsafe-inline'` 移除nonce 替代(`'unsafe-eval'` 保留供 Vditor |
| HSTS | 始终启用 `max-age=31536000; includeSubDomains; preload` |
| 密码强度 | 四级low/medium/high/very_high+ 连续字符检查 |
| 注册限流 | IP 维度 1min×5 次 |
| CSRF Token 日志 | 仅记录长度,不记明文 |
| DB 健康降级 | 5s ping + 全局 `dbHealthy` 标志 + 中间件拦截返回固定错误页 |
| 文件上传 | `image.Decode` 强制解码验证(替代 magic bytes |
**代码质量:**
| 项目 | 变更 |
|------|------|
| golangci-lint | 57 告警 → 0CI strict 模式零告警 |
| 包注释 | 16 个包全部添加 |
| 错误消息 | 全部小写开头 |
| errorlint | `==` 比较 → `errors.Is` |
| unused 代码 | `hasUnicode`/`energyStore`/`current`/`energyAdminUseCase` 移除 |
| gofumpt | 全量格式化 |
**架构重构:**
| 项目 | 变更 |
|------|------|
| `router/api.go` | 198 行拆为 7 个域文件auth/settings/posts/comments/reactions/social/studio |
| 管理后台站点设置 | 单页 310 行拆为 4 个子页brand/security/registration/content+ 子菜单,旧路由 301 重定向 |
| 前台用户设置 | 1201 行拆为 6 个独立模板 + 6 个独立 JS 文件 |
| Controller Exp 读取 | `common.GetGinExp()` 封装,不再直接读 context |
| UID 解析 | `common.ParseUIDParam()` 统一follow/admin controller 改用 |
| BaseModel 统一 | Post/Comment/Announcement/Category/Folder/FolderItem 嵌入 BaseModel`primaryKey``primarykey` |
| 时区 | `config.yaml server.timezone``time.Local` 初始化 |
**Footer 合规信息:**
- `site_settings.go` 扩展 8 个字段operator/ICP/公安/文网文/算法备案/隐私/条款)
- `footer.html` 渲染合规行(`safeHTML` 模板函数,空值跳过)
- 管理后台合规信息输入区
**注册准则控制:**
- 三层控制:`show_guidelines` / `force_guidelines` / `guidelines_timer`
- 管理后台注册设置区
## 三、文件清单
```text
mce/
├── cmd/server/main.go # 入口配置加载、DB/Redis、模板、路由、调度器
├── config.yaml # 默认配置
├── .golangci.yml # golangci-lint v2 配置
├── .gitea/workflows/ci.yml # CI 流水线strict 模式)
├── scripts/ci.sh # CI 脚本(支持 --strict
├── Makefile # fmt/lint/ci/test 命令
├── internal/
│ ├── common/ # 通用工具响应格式、Context 提取、模板数据构建、错误哨兵
│ ├── config/ # 配置加载 + SiteSettings DB 持久化内存缓存
│ ├── model/ # 所有数据模型25 个)
│ ├── repository/ # GORM 数据访问17 个 repo
│ ├── service/ # 业务逻辑18 个 service含 repository.go 接口定义)
│ ├── controller/ # Gin handler38 个 controller 文件)
│ │ └── admin/ # 管理后台 controller7 个)
│ ├── middleware/ # 中间件:认证/CSRF/安全头/限流/维护/DB健康
│ ├── router/ # 路由注册 + 依赖注入(按域拆分)
│ ├── session/ # 服务端 SessionRedis + Memory + Fallback
│ ├── scheduler/ # 定时发布调度器
│ ├── cache/ # 首页缓存
│ └── theme/ # 模板加载器 + safeHTML 函数
├── templates/
│ ├── MetaLab-2026/ # 前端主题
│ │ ├── html/ # Go 模板(按功能分目录)
│ │ └── static/ # CSS/JS/图片 + Vditor 编辑器
│ ├── admin/ # 管理后台模板
│ └── shared/ # 共享静态资源
└── docs/ # 设计文档
```
## 四、关键设计决策
| 决策 | 选择 | 原因 |
|------|------|------|
| Web 框架 | Gin | 性能好,生态成熟 |
| ORM | GORM v2 | AutoMigrate + 软删除 + 回调 |
| 数据库 | PostgreSQL | 社区级应用首选 |
| 会话 | 服务端 Session | 支持踢出设备、登录管理 |
| 存储 | Redis + Memory FallbackStore | Redis 不可达自动降级,恢复自动切回 |
| 模板 | Go html/template | 无前端框架依赖SSR 直出 |
| 编辑器 | Vditor v3.11.2(本地部署) | Markdown 所见即所得 |
| 图表 | Chart.js v4.4.0(本地化) | 趋势可视化 |
| 密码 | bcrypt(12) | 行业标准 |
| 架构 | 分层 + ISP 接口隔离 | 依赖倒置Controller 不依赖完整 Service |
| 重构 | 不向后兼容 | 全新项目,废弃旧代码不做兼容层 |
| Lint | golangci-lint v2.12.217 个 linter | CI strict 模式零告警 |
## 五、数据模型一览
| 模型 | BaseModel | 说明 |
|------|-----------|------|
| User | ✅ | 用户(邮箱/用户名/密码/角色/状态/经验) |
| Post | ✅ | 帖子/文章(标题/正文/状态/分类/标签/属性/计数器) |
| Comment | ✅ | 评论(含 is_deleted 自定义软删除) |
| AuditSubmission | ✅ | 审核记录 |
| Notification | ✅ | 通知 |
| Announcement | ✅ | 公告 |
| Category | ✅ | 文章分类(两级树形) |
| Folder | ✅ | 收藏夹 |
| FolderItem | ✅ | 收藏记录 |
| Tag | ❌ | 标签 |
| PostTag | ❌ | 文章-标签关联(联合主键) |
| PostLike | ❌ | 点赞(联合主键) |
| PostDislike | ❌ | 踩(联合主键) |
| UserFollow | ❌ | 关注关系(联合主键) |
| CommentMention | ❌ | @提及映射 |
| SiteSetting | ❌ | 站点设置Key-Value |
| EnergyLog / FundLog / PostEnergizeLog | ❌ | 域能/资金流日志 |
| UserCheckIn / UserTask | ✅ | 签到/任务 |
| DailyExpSummary / DailyLikeSummary | ❌ | 每日统计聚合 |
| PostReadLog / PostGuestReadLog | ❌ | 阅读日志 |
| CommunityFund | ❌ | 公户余额(单行表) |
| Level | ❌ | 等级配置(内存) |
## 六、待做事项
| 优先级 | 功能 | 状态 |
|--------|------|------|
| P2 | B8: BaseModel 主键列名不一致 | ✅ 已完成 |
| P3 | 集成测试 | ⬜ 暂缓 |
| P3 | `git tag v0.1.0-rc1` | ⬜ 暂缓 |
| — | 黑名单系统 | ⬜ 未来迭代 |
| — | 首页推荐算法 | ⬜ 未来迭代 |
| — | 模板审计修复 | ⬜ 未来迭代 |