195 lines
8.8 KiB
Markdown
195 lines
8.8 KiB
Markdown
# 开发记录 — 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/owner,OCP 可扩展)
|
||
- `BuildPageData()` / `BuildAdminPageData()` 统一模板数据注入
|
||
- CSRF Double Submit Cookie 保护
|
||
- 敏感操作限流(`SensitiveRateLimit`:改密/注销/签到)+ 登录限流(账户+IP 双维度滑动窗口)
|
||
- 维护模式(仅 owner 可访问,其余用户重定向登录页)
|
||
|
||
### Phase 2:公告系统
|
||
|
||
- 公告 CRUD + 管理后台管理页面
|
||
- 前台首页公告区域
|
||
|
||
### Phase 3:文章属性
|
||
|
||
- Post 模型:Visibility(public/private)、PostType(original/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 告警 → 0,CI 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 handler(38 个 controller 文件)
|
||
│ │ └── admin/ # 管理后台 controller(7 个)
|
||
│ ├── middleware/ # 中间件:认证/CSRF/安全头/限流/维护/DB健康
|
||
│ ├── router/ # 路由注册 + 依赖注入(按域拆分)
|
||
│ ├── session/ # 服务端 Session:Redis + 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.2(17 个 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` | ⬜ 暂缓 |
|
||
| — | 黑名单系统 | ⬜ 未来迭代 |
|
||
| — | 首页推荐算法 | ⬜ 未来迭代 |
|
||
| — | 模板审计修复 | ⬜ 未来迭代 |
|