8.8 KiB
8.8 KiB
开发记录 — 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 - 管理后台注册设置区
三、文件清单
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 |
⬜ 暂缓 |
| — | 黑名单系统 | ⬜ 未来迭代 |
| — | 首页推荐算法 | ⬜ 未来迭代 |
| — | 模板审计修复 | ⬜ 未来迭代 |