Files
mce/docs/structure.md
Victor_Jay c3dec09dae feat(settings): 个人资料编辑 + 头像上传/裁切 + 自定义裁切弹窗
**新增功能:**

用户名编辑:输入框替换静态文本,白名单验证(中文/英文/数字/下划线/连字符),前端计数器(n/16),utf8对齐PG VARCHAR,XSS防控。

个性签名编辑:Textarea,128字符上限,实时计数器。

头像上传管线:校验→解码→裁切→CatmullRom缩放→WebP二分编码≤100KB→原子写入(.tmp→os.Rename)。限制5MB,128-3840px,JPEG/PNG/WebP。输出512x512 WebP。文件名 {uid}_{timestamp}.webp。清理旧头像。

自定义裁切弹窗:浅色主题,固定裁切框+图片平移/缩放(1×-3×滚轮),box-shadow遮罩,三等分网格。坐标映射pan/zoom→原图像素→subImage。

CSP修复:img-src允许data:URI(FileReader预览)。

**文件变更:**
修改: README, docs/{development,structure}.md, go.{mod,sum}, cmd/server/main.go, controller/settings, middleware/security, router, templates/settings/{index.html,css}
新增: internal/service/avatar_service.go, docs/settings.md
2026-05-27 01:03:16 +08:00

5.5 KiB
Raw Blame History

目录结构与分层规范

总览

METAZONE.FAN/
├── cmd/server/main.go              # 入口:初始化→启动,只做编排,不写业务
├── internal/                        # 内部包(不可外部 import
│   ├── config/                      # 配置加载(结构体 + yaml/file
│   ├── router/                      # 路由注册(按路由组拆文件)
│   ├── controller/                  # 控制器(瘦)— 接参数 → 调服务 → 返回
│   │   ├── interfaces.go            # 控制器层接口定义ISP
│   │   └── admin/                   # 后台子包(功能多,独立拆)
│   ├── service/                     # 业务逻辑(厚)— 核心逻辑、校验、编排
│   │   ├── repository.go           # Service 层仓储接口定义ISP
│   │   └── avatar_service.go       # 头像上传处理管线
│   ├── repository/                  # 数据访问DAO— 纯数据库操作
│   ├── model/                       # 数据模型 — 纯结构体 + DTO
│   ├── middleware/                  # 中间件 — 每个中间件一个文件
│   ├── theme/                       # 模板/主题管理 — 加载、切换、静态资源
│   └── common/                      # 公共工具 — 响应格式、分页、校验、错误码
├── templates/                       # 前端模板 — 多主题支持
│   ├── MetaLab-2026/                # 当前主题
│   │   ├── theme.json               # 主题元信息
│   │   ├── guidelines.html          # 准则等长文本(非模板,纯内容文件)
│   │   ├── html/                    # 页面模板
│   │   │   ├── layout/              # 布局组件header/nav/footer
│   │   │   ├── home/ post/ comment/ user/ topic/ settings/
│   │   │   └── partials/            # 可复用组件(卡片/分页/侧栏)
│   │   └── static/                  # 静态资源css/js/img
│   │       ├── css/
│   │       │   ├── common.css       # 全局样式 + 导航
│   │       │   ├── home.css auth.css settings.css
│   │       └── js/
│   ├── MetaLab-2027/                # 未来主题(相同结构)
│   └── system/                      # 系统模板email 等,与主题无关)
├── storage/                         # 运行时数据(.gitignore
│   ├── uploads/avatars/             # 用户头像WebP
│   └── logs/
└── docs/                            # 项目文档

各层职责与边界

Controller控制器

  • 只做三件事:绑定请求参数 → 调用 Service → 返回响应
  • 不允许直接调用 Repository
  • 不允许写 if-else 业务分支逻辑
  • 单文件 ≤ 120 行
  • 每个领域实体一个文件,后台独立 admin/ 子包
// ✅ 正确:瘦控制器
func (c *PostController) Detail(ctx *gin.Context) {
    id := ctx.Param("id")
    post, err := c.postService.GetDetail(ctx, id)
    if err != nil {
        common.Error(ctx, common.ErrNotFound, "帖子不存在")
        return
    }
    common.Ok(ctx, post)
}

Service业务逻辑

  • 承载所有业务规则:权限校验、数据组装、事务编排
  • 可以调用多个 Repository
  • 单文件 ≤ 300 行
  • 方法命名语义化:Create/Update/Delete/GetDetail/ListByTopic

Repository数据访问

  • 纯数据库操作:增删改查,不含业务逻辑
  • 单文件 ≤ 200 行
  • 不引用 Controller 或 Service 层

Model模型

  • 纯结构体定义 + DTO
  • 单文件 ≤ 80 行
  • common.go 放 BaseModelID/CreatedAt/UpdatedAt
  • dto.go 放请求/响应传输对象

Middleware中间件

  • 每个中间件一个文件,≤ 60 行
  • 按关注点注册到路由组上,不要逐个路由单独加

Router路由

  • 按路由组拆文件:web.go(页面)、api.goAPIadmin.go(后台)
  • 只做路由映射,不写 handler 逻辑

Theme主题管理

  • loader.go:模板文件加载、内容文件读取
  • manager.go:主题扫描、切换、获取当前
  • resolver.go:静态资源路径解析(/static/ → 当前主题 static 目录)
  • theme.go:主题接口定义 + ThemeMeta 结构体

Common公共工具

  • response.go:统一 JSON 响应格式
  • error_code.go:错误码常量
  • validator.go:参数校验
  • pagination.go:分页工具

import 规则

允许的依赖方向(从上到下,不可反向):

controller → service → repository → model
controller → common
service    → common + repository + model
middleware → common + service可选
router     → controller + middleware
theme      → 无(独立工具包)
  • Controller 不可 import Repository
  • Controller 不可 import 另一个 Controller
  • Service 不可 import Controller
  • Repository 不可 import Service

模板目录规范

  • 每个主题 templates/{主题名}/ 下有独立完整的 html/static/
  • 主题之间互不引用、互不依赖
  • 长文本内容(准则、关于页面等)放主题根目录(guidelines.html),不在 html/
  • 这些内容文件不是模板(不含 {{}} 语法),由 Controller 读取后注入
  • 系统级模板email 等)放 templates/system/,与主题无关
  • 切换主题时Gin 引擎重新指向新主题的 html/ 目录