# 目录结构与分层规范

## 总览

```
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/` 子包

```go
// ✅ 正确：瘦控制器
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` 放 BaseModel（ID/CreatedAt/UpdatedAt）
- `dto.go` 放请求/响应传输对象

### Middleware（中间件）

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

### Router（路由）

- 按路由组拆文件：`web.go`（页面）、`api.go`（API）、`admin.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/` 目录
