2025-11-28 23:30:49 +08:00
|
|
|
|
# CarrotSkin Backend
|
|
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
一个功能完善的 Minecraft 皮肤站后端,基于 Go + Gin 构建,覆盖用户认证、材质管理、角色档案、审计日志等核心能力,并提供完整的 Swagger 文档与容器友好的环境变量配置。
|
|
|
|
|
|
|
|
|
|
|
|
## ✨ 功能亮点
|
|
|
|
|
|
|
|
|
|
|
|
- **账号体系**:注册 / 登录 / JWT 鉴权 / Yggdrasil 密码同步 / 用户积分
|
|
|
|
|
|
- **邮箱与验证码**:验证码发送频率控制、邮箱绑定与变更
|
|
|
|
|
|
- **材质中心**:皮肤/披风上传、搜索、收藏、下载统计、Hash 去重
|
|
|
|
|
|
- **角色档案**:Minecraft Profile 管理、RSA 密钥对生成、活跃档案切换
|
|
|
|
|
|
- **存储与上传**:RustFS/MinIO 预签名 URL,减轻服务器带宽压力
|
|
|
|
|
|
- **任务与日志**:登录日志、操作审计、材质下载记录、定时任务
|
|
|
|
|
|
- **权限体系**:Casbin RBAC,支持细粒度路线授权
|
|
|
|
|
|
- **配置管理**:100% 依赖环境变量,`SERVER_SWAGGER_ENABLED` 控制 Swagger
|
|
|
|
|
|
- **可观测性**:Zap 结构化日志、统一 API 响应模型
|
|
|
|
|
|
|
|
|
|
|
|
## 🛠 技术栈
|
|
|
|
|
|
|
|
|
|
|
|
| 类型 | 选型 |
|
|
|
|
|
|
| --- | --- |
|
|
|
|
|
|
| 语言 / 运行时 | Go 1.24+ |
|
|
|
|
|
|
| Web 框架 | Gin |
|
|
|
|
|
|
| ORM | GORM (PostgreSQL 驱动) |
|
|
|
|
|
|
| 数据库 | PostgreSQL 15+ |
|
|
|
|
|
|
| 缓存 / 消息 | Redis 6+ |
|
|
|
|
|
|
| 对象存储 | RustFS / MinIO(S3 兼容) |
|
|
|
|
|
|
| 权限控制 | Casbin |
|
|
|
|
|
|
| 配置 | Viper + `.env` |
|
|
|
|
|
|
| API 文档 | swaggo / Swagger UI |
|
|
|
|
|
|
| 日志 | Uber Zap |
|
|
|
|
|
|
|
|
|
|
|
|
## 📁 目录结构
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
backend/
|
2026-06-15 16:52:20 +08:00
|
|
|
|
├── cmd/server/ # 应用入口(main.go:极简 fx 装配)
|
2025-12-26 21:32:32 +08:00
|
|
|
|
├── internal/
|
2026-06-15 16:52:20 +08:00
|
|
|
|
│ ├── app/ # uber-go/fx 装配层(唯一依赖注入入口)
|
|
|
|
|
|
│ │ ├── module.go # 聚合根 Module
|
|
|
|
|
|
│ │ ├── infra_module.go # Logger/DB/Redis/Storage/Email/JWT/Casbin + Lifecycle
|
|
|
|
|
|
│ │ ├── container_module.go # Container 聚合 + 路由/HTTP/任务生命周期
|
|
|
|
|
|
│ │ ├── repository_module.go # Repository Provider(占位,Container 模式暂未启用)
|
|
|
|
|
|
│ │ ├── service_module.go # Service Provider(占位)
|
|
|
|
|
|
│ │ ├── handler_module.go # Handler Provider(占位)
|
|
|
|
|
|
│ │ ├── server_module.go # HTTP 服务器模块(占位)
|
|
|
|
|
|
│ │ └── task_module.go # 后台任务模块(占位)
|
|
|
|
|
|
│ ├── container/ # 过渡期手动 DI 容器(fx 迁移期的聚合层)
|
|
|
|
|
|
│ ├── handler/ # HTTP Handler 与 Swagger 注解
|
|
|
|
|
|
│ ├── service/ # 业务逻辑(接口 + 实现)
|
|
|
|
|
|
│ ├── repository/ # 数据访问(接口 + GORM 实现)
|
|
|
|
|
|
│ ├── model/ # GORM 数据模型与响应结构
|
|
|
|
|
|
│ ├── types/ # 请求/响应 DTO
|
|
|
|
|
|
│ ├── errors/ # 统一错误定义(apperrors)
|
|
|
|
|
|
│ ├── middleware/ # Gin 中间件
|
|
|
|
|
|
│ └── task/ # 定时任务与后台作业
|
|
|
|
|
|
├── pkg/ # 可复用组件(config、database、auth、logger、redis、storage、email、utils)
|
|
|
|
|
|
├── docs/ # swagger 生成产物(docs.go / swagger.json / swagger.yaml)
|
|
|
|
|
|
├── start.sh # 启动脚本(自动 swag init)
|
|
|
|
|
|
├── docker-compose.yml # 本地容器编排
|
|
|
|
|
|
├── .env.example # 环境变量示例
|
|
|
|
|
|
└── go.mod # Go Module 定义
|
2025-12-26 21:32:32 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## ✅ 前置要求
|
|
|
|
|
|
|
|
|
|
|
|
- Go 1.24+
|
|
|
|
|
|
- PostgreSQL 15+
|
|
|
|
|
|
- Redis 6+
|
|
|
|
|
|
- RustFS / MinIO(或其他兼容 S3 的对象存储,用于皮肤与头像)
|
|
|
|
|
|
|
|
|
|
|
|
## 🚀 快速开始
|
|
|
|
|
|
|
|
|
|
|
|
1. **克隆仓库**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
git clone <repo>
|
|
|
|
|
|
cd backend
|
|
|
|
|
|
```
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
|
|
|
|
|
2. **安装依赖**
|
2025-12-26 21:32:32 +08:00
|
|
|
|
```bash
|
|
|
|
|
|
go mod download
|
|
|
|
|
|
```
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
3. **配置环境变量**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cp .env.example .env
|
|
|
|
|
|
# 根据实际环境填写数据库、Redis、对象存储、邮件等信息
|
|
|
|
|
|
```
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
|
|
|
|
|
4. **初始化数据库**
|
2025-12-26 21:32:32 +08:00
|
|
|
|
```bash
|
|
|
|
|
|
createdb carrotskin
|
|
|
|
|
|
# 或 psql -c "CREATE DATABASE carrotskin;"
|
|
|
|
|
|
```
|
|
|
|
|
|
> 应用启动时会执行 `AutoMigrate`,自动创建 / 更新表结构。
|
|
|
|
|
|
|
|
|
|
|
|
5. **启动服务**
|
|
|
|
|
|
- **推荐**:`./start.sh`(自动 `swag init`,随后 `go run cmd/server/main.go`)
|
|
|
|
|
|
- **手动启动**:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
swag init -g cmd/server/main.go -o docs
|
|
|
|
|
|
go run cmd/server/main.go
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
6. **访问接口**
|
|
|
|
|
|
- API Root: `http://localhost:8080`
|
|
|
|
|
|
- Swagger: `http://localhost:8080/swagger/index.html`(需 `SERVER_SWAGGER_ENABLED=true`)
|
|
|
|
|
|
|
|
|
|
|
|
## ⚙️ 关键环境变量
|
|
|
|
|
|
|
|
|
|
|
|
| 变量 | 说明 | 示例 |
|
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
|
| `SERVER_PORT` | 服务监听端口 | `8080` |
|
|
|
|
|
|
| `SERVER_MODE` | Gin 模式(debug/release) | `debug` |
|
|
|
|
|
|
| `SERVER_SWAGGER_ENABLED` | 是否暴露 Swagger UI | `true` |
|
|
|
|
|
|
| `DATABASE_HOST` / `DATABASE_PORT` | PostgreSQL 地址 | `localhost` / `5432` |
|
|
|
|
|
|
| `DATABASE_USERNAME` / `DATABASE_PASSWORD` | 数据库凭据 | `postgres` |
|
|
|
|
|
|
| `DATABASE_NAME` | 数据库名称 | `carrotskin` |
|
|
|
|
|
|
| `REDIS_HOST` / `REDIS_PORT` | Redis 地址 | `localhost` / `6379` |
|
|
|
|
|
|
| `REDIS_PASSWORD` | Redis 密码(无可为空) | `` |
|
|
|
|
|
|
| `RUSTFS_ENDPOINT` | RustFS/MinIO 访问地址 | `127.0.0.1:9000` |
|
|
|
|
|
|
| `RUSTFS_ACCESS_KEY` / `RUSTFS_SECRET_KEY` | 对象存储凭据 | `minioadmin` |
|
|
|
|
|
|
| `RUSTFS_BUCKET_TEXTURES` / `RUSTFS_BUCKET_AVATARS` | 存储桶名称 | `carrotskin-textures` |
|
|
|
|
|
|
| `JWT_SECRET` | JWT 签名密钥 | `change-me` |
|
|
|
|
|
|
| `EMAIL_ENABLED` | 是否开启邮件服务 | `true` |
|
|
|
|
|
|
| `EMAIL_SMTP_HOST` / `EMAIL_SMTP_PORT` | SMTP 配置 | `smtp.example.com` / `587` |
|
2026-06-15 16:52:20 +08:00
|
|
|
|
| `ENVIRONMENT` | 应用环境(用于 service 层 `IsTestEnvironment()` 短路) | `production` |
|
|
|
|
|
|
| `SECURITY_ALLOWED_ORIGINS` | CORS 允许的来源(逗号分隔) | `*` |
|
|
|
|
|
|
| `SECURITY_ALLOWED_DOMAINS` | 头像/材质 URL 允许的域名(逗号分隔) | `localhost,127.0.0.1` |
|
2025-12-26 21:32:32 +08:00
|
|
|
|
|
|
|
|
|
|
更多变量请参考 `.env.example` 与 `.env.docker.example`。
|
|
|
|
|
|
|
|
|
|
|
|
## 🧪 常用命令
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2025-12-26 21:32:32 +08:00
|
|
|
|
# 运行单元测试
|
|
|
|
|
|
go test ./...
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
# 重新生成 swagger
|
|
|
|
|
|
swag init -g cmd/server/main.go -o docs
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
# 代码格式化 / 静态检查
|
|
|
|
|
|
gofmt -w .
|
|
|
|
|
|
golangci-lint run (若已安装)
|
2025-11-28 23:30:49 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
## 🧱 架构说明
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2026-06-15 16:52:20 +08:00
|
|
|
|
- **分层设计**:Handler → Service → Repository → Model,层次清晰、职责单一。
|
|
|
|
|
|
- Handler 不得直连 `*gorm.DB` 或 `*Repository`,必须通过 Service。
|
|
|
|
|
|
- Service 不得持有 `*gorm.DB`,所有数据访问通过 Repository 接口。
|
|
|
|
|
|
- **依赖注入(uber-go/fx)**:
|
|
|
|
|
|
- `internal/app/` 是唯一的依赖装配入口。每个基础设施 / 仓储 / 服务作为 `fx.Provider` 注册。
|
|
|
|
|
|
- **生命周期管理**:DB / Redis / Storage / Logger / HTTP Server / Task Runner 通过 `fx.Lifecycle` 的 `OnStart` / `OnStop` Hook 统一管理,彻底替代散落在 `main()` 的 `defer Close()` 链。
|
|
|
|
|
|
- **优雅关闭**:`fx.New(app.Module(cfg)).Run()` 监听 `SIGINT` / `SIGTERM`,按依赖逆序触发 `OnStop`,先关 HTTP Server(30s 超时),再关 Task Runner,最后关 DB/Redis。
|
|
|
|
|
|
- **Dev/Test 自动回退**:Redis 连接失败且环境为 `development` / `test` / `dev` / `USE_MINIREDIS=true` 时自动启用 `miniredis`。
|
|
|
|
|
|
- **启动时错误检查**:循环依赖、缺失 Provider、Provider 返回 error 全部在 `fx.New()` 阶段立即检测。
|
|
|
|
|
|
- **错误与响应统一**:
|
|
|
|
|
|
- 错误统一在 `internal/errors/`(别名 `apperrors`),通过 `errors.Is/As` 匹配。
|
|
|
|
|
|
- 响应统一使用 `model.Response` / `model.PaginationResponse` / `model.NewErrorResponse`。
|
|
|
|
|
|
- Middleware 错误响应也走 `model.NewErrorResponse`,不再使用裸 `gin.H`。
|
|
|
|
|
|
- **配置优先级**:`config.Load()` 读取 `.env` → 环境变量 → viper 默认值;`*config.Config` 由 `fx.Supply` 注入。
|
2025-12-26 21:32:32 +08:00
|
|
|
|
- **Swagger 注解**:所有 Handler、模型、DTO 均补齐 `@Summary` / `@Description` / `@Success`,可直接生成 OpenAPI 文档。
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
## 📝 Swagger 说明
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
- `start.sh` 会在启动前执行 `swag init -g cmd/server/main.go -o docs`
|
|
|
|
|
|
- 若手动运行,需要保证 `docs/` 下的 `docs.go`、`swagger.json`、`swagger.yaml` 与代码同步
|
|
|
|
|
|
- 通过 `SERVER_SWAGGER_ENABLED=false` 可在生产环境关闭 Swagger UI 暴露
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
## 🤝 贡献指南
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
1. Fork & Clone
|
|
|
|
|
|
2. 创建特性分支:`git checkout -b feature/xxx`
|
|
|
|
|
|
3. 编写代码并补全测试 / Swagger 注释
|
|
|
|
|
|
4. 提交时附上变更说明
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
## 📄 许可证
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
该项目未附带开源许可证,默认保留所有权利。若需对外使用,请先与作者确认协议。
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
---
|
2025-11-28 23:30:49 +08:00
|
|
|
|
|
2025-12-26 21:32:32 +08:00
|
|
|
|
如需了解业务细节或 API 调用示例,请参考 `docs/swagger.yaml` 或运行服务后访问 Swagger UI。祝编码愉快!🍀
|