Files
backend-go/README.md
2026-03-02 12:57:07 +08:00

401 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 浙江贝凡溯源管理平台 - 后端服务 (Go 版本)
这是一个使用 Go 语言开发的溯源管理平台后端服务,提供序列号生成、查询、管理等功能。
## 技术栈
- **Web 框架**: Gin (高性能 HTTP 框架)
- **ORM**: GORM (Go 对象关系映射)
- **数据库**:
- SQLite (默认,适用于开发和轻量级部署)
- PostgreSQL (生产环境推荐)
- **认证**: JWT (JSON Web Token) - golang-jwt/jwt/v5
- **密码加密**: bcrypt (golang.org/x/crypto)
- **二维码生成**: yeqown/go-qrcode/v2
- **API 文档**: Swagger/OpenAPI (swaggo/swag)
- **CORS**: gin-contrib/cors (跨域资源共享)
- **配置管理**:
- Viper (环境变量和配置文件)
- gotenv (.env 文件加载)
- **日志**: Zap (高性能结构化日志)
- **验证**: go-playground/validator
- **测试**: Testify (测试框架)
- **工具**: UUID (github.com/google/uuid)
## 项目结构
```
backend-go/
├── config/ # 配置管理
│ └── config.go # 配置加载和解析(支持 .env 文件和环境变量)
├── controllers/ # 控制器层,处理 HTTP 请求
│ ├── auth_controller.go # 认证相关接口
│ ├── companies_controller.go # 企业管理接口
│ ├── employees_controller.go # 员工赋码接口
│ ├── helper.go # 控制器通用辅助函数
│ └── serials_controller.go # 序列号管理接口
├── database/ # 数据库连接和操作
│ └── database.go # 数据库初始化、连接池配置
├── docs/ # Swagger API 文档(自动生成)
│ ├── docs.go # Swagger 文档定义
│ ├── swagger.json # Swagger JSON 格式文档
│ └── swagger.yaml # Swagger YAML 格式文档
├── logger/ # 日志管理
│ └── logger.go # 结构化日志(使用 Zap
├── middleware/ # 中间件层
│ └── auth.go # JWT 认证和权限检查
├── models/ # 数据模型和 DTO
│ └── models.go # User、Company、Serial 等模型定义
├── routes/ # 路由配置
│ └── routes.go # API 路由注册
├── services/ # 业务逻辑层
│ ├── auth_service.go # 认证业务逻辑
│ ├── companies_service.go # 企业管理业务逻辑
│ ├── employees_service.go # 员工赋码业务逻辑
│ ├── serials_service.go # 序列号业务逻辑
│ └── services_test.go # 服务层单元测试
├── tests/ # 集成测试
│ └── main_test.go # 端到端测试
├── data/ # 数据目录SQLite 数据库存储位置)
├── main.go # 应用程序入口
├── go.mod # Go 模块依赖
├── go.sum # Go 模块校验和
├── Makefile # 构建和开发任务
├── .env.example # 环境变量示例
├── .env # 环境变量配置(需手动创建)
├── .golangci.yml # 代码检查配置
└── .gitignore # Git 忽略文件
```
## 快速开始
### 1. 安装依赖
```bash
cd backend-go
go mod download
# 或使用 Makefile
make deps
```
### 2. 配置环境变量
复制 `.env.example` 文件为 `.env` 并根据需要修改:
```bash
cp .env.example .env
```
**重要**: 生产环境请务必修改 `JWT_SECRET` 环境变量!
### 3. 使用 Makefile推荐
```bash
# 启动开发服务器
make run
# 编译项目
make build
# 运行测试
make test
# 生成测试覆盖率报告
make test-coverage
# 代码质量检查
make quality
# 清理构建文件
make clean
```
### 4. 手动启动
```bash
go run main.go
```
服务器将在 http://localhost:3000 上运行。
### 5. 配置管理
项目采用 **YAML 结构化管理 + 环境变量动态覆盖** 的方案:
#### 配置文件优先级(从高到低)
1. **环境变量** (最高优先级) - 格式:`APP_配置项`
2. **.env 文件** - 本地开发环境配置
3. **config.yaml** - 默认配置文件
4. **内置默认值** (最低优先级)
#### 环境变量命名规则
所有环境变量使用 `APP_` 前缀,多级配置使用 `_` 连接:
```bash
# 示例
APP_SERVER_PORT=8080 # 覆盖 server.port
APP_DATABASE_DRIVER=postgres # 覆盖 database.driver
APP_DATABASE_POSTGRES_HOST=db.com # 覆盖 database.postgres.host
APP_JWT_SECRET=my-secret-key # 覆盖 jwt.secret
```
#### 常用配置项
| 环境变量 | 对应配置项 | 说明 | 默认值 |
|---------|-----------|------|--------|
| `APP_SERVER_PORT` | server.port | 服务器端口 | 3000 |
| `APP_SERVER_ENVIRONMENT` | server.environment | 运行环境 | development |
| `APP_DATABASE_DRIVER` | database.driver | 数据库驱动 | sqlite |
| `APP_DATABASE_SQLITE_PATH` | database.sqlite.path | SQLite 路径 | ./data/database.sqlite |
| `APP_DATABASE_POSTGRES_HOST` | database.postgres.host | PostgreSQL 主机 | localhost |
| `APP_DATABASE_POSTGRES_PORT` | database.postgres.port | PostgreSQL 端口 | 5432 |
| `APP_DATABASE_POSTGRES_USER` | database.postgres.user | PostgreSQL 用户名 | trace |
| `APP_DATABASE_POSTGRES_PASSWORD` | database.postgres.password | PostgreSQL 密码 | trace123 |
| `APP_DATABASE_POSTGRES_DBNAME` | database.postgres.dbname | PostgreSQL 数据库名 | trace |
| `APP_JWT_SECRET` | jwt.secret | JWT 签名密钥 | your-secret-key... |
| `APP_JWT_EXPIRE` | jwt.expire | JWT 过期时间(秒) | 7200 |
#### 快速配置示例
**开发环境(.env**:
```bash
# 使用 SQLite
APP_DATABASE_DRIVER=sqlite
APP_DATABASE_SQLITE_PATH=./data/dev.sqlite
```
**生产环境(环境变量)**:
```bash
# 使用 PostgreSQL
export APP_SERVER_PORT=8080
export APP_SERVER_ENVIRONMENT=production
export APP_DATABASE_DRIVER=postgres
export APP_DATABASE_POSTGRES_HOST=prod-db.example.com
export APP_DATABASE_POSTGRES_PASSWORD=secure-password
export APP_JWT_SECRET=your-production-secret-key
```
### 6. 测试 API
**健康检查**:
```bash
curl -X GET http://localhost:3000/api/health
```
**用户登录**:
```bash
curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"password123"}'
```
首次启动且用户表为空时,系统会自动创建默认管理员账号(请在生产环境立即修改密码):
- username: `admin`
- password: `Beifan@2026`
## API 文档
项目使用 Swagger 生成交互式 API 文档。
启动服务器后,访问以下地址查看完整的 API 文档:
```
http://localhost:3000/swagger/index.html
```
### Swagger 文档功能
- **交互式测试**: 直接在浏览器中测试 API 端点
- **请求/响应示例**: 查看每个接口的请求参数和响应格式
- **认证支持**: 支持 Bearer Token 认证,可以输入 JWT 令牌进行测试
- **按分组浏览**: API 按功能模块分组(认证、序列号管理、企业管理等)
### 重新生成 Swagger 文档
如果修改了代码中的 API 注解,需要重新生成 Swagger 文档:
```bash
# 确保已安装 swag 工具
go install github.com/swaggo/swag/cmd/swag@latest
# 生成文档
swag init -g main.go
# 文档将生成在 docs/ 目录下
```
### 认证路由
| 方法 | 路径 | 描述 | 需要认证 |
| ---- | --------------------------- | ----------------------- | -------- |
| POST | `/api/auth/login` | 用户登录,返回 JWT 令牌 | 否 |
| POST | `/api/auth/logout` | 用户登出 | 是 |
| GET | `/api/auth/profile` | 获取当前用户信息 | 是 |
| PUT | `/api/auth/profile` | 更新用户信息 | 是 |
| POST | `/api/auth/change-password` | 修改密码 | 是 |
> 错误提示已做用户友好化,例如登录失败统一返回:`用户名或密码不正确`。
### 序列号管理
| 方法 | 路径 | 描述 | 需要认证 | 角色 |
| ---- | ----------------------------------- | ---------------- | -------- | ------ |
| POST | `/api/serials/generate` | 生成序列号 | 是 | 管理员 |
| POST | `/api/serials/generate-with-prefix` | 带前缀生成序列号 | 是 | 管理员 |
| POST | `/api/serials/:serialNumber/qrcode` | 生成序列号二维码 | 是 | 任何 |
| GET | `/api/serials/:serialNumber/query` | 查询序列号信息 | 否 | 任何 |
| GET | `/api/serials` | 获取序列号列表 | 是 | 任何 |
| PATCH | `/api/serials/:serialNumber` | 更新序列号信息 | 是 | 管理员 |
| PUT | `/api/serials/:serialNumber` | 更新序列号信息 | 是 | 管理员 |
| POST | `/api/serials/:serialNumber/revoke` | 吊销序列号 | 是 | 管理员 |
### 企业管理
| 方法 | 路径 | 描述 | 需要认证 | 角色 |
| ------ | ----------------------------- | ------------ | -------- | ------ |
| GET | `/api/companies/stats/overview` | 获取企业统计概览 | 是 | 管理员 |
| GET | `/api/companies` | 获取企业列表 | 是 | 管理员 |
| GET | `/api/companies/:companyName` | 获取企业详情 | 是 | 管理员 |
| POST | `/api/companies` | 创建新企业 | 是 | 管理员 |
| PATCH | `/api/companies/:companyName` | 更新企业信息 | 是 | 管理员 |
| PUT | `/api/companies/:companyName` | 更新企业信息 | 是 | 管理员 |
| POST | `/api/companies/:companyName/revoke` | 吊销企业及序列号 | 是 | 管理员 |
| DELETE | `/api/companies/:companyName/serials/:serialNumber` | 删除企业下序列号 | 是 | 管理员 |
| DELETE | `/api/companies/:companyName` | 删除企业 | 是 | 管理员 |
### 员工赋码
| 方法 | 路径 | 描述 | 需要认证 | 角色 |
| ---- | -------------------------------------- | ------------------ | -------- | ------ |
| POST | `/api/employee-serials/generate` | 生成员工序列号 | 是 | 管理员 |
| GET | `/api/employee-serials` | 获取员工序列号列表 | 是 | 任何 |
| GET | `/api/employee-serials/:serialNumber/query` | 查询员工序列号信息 | 否 | 任何 |
| POST | `/api/employee-serials/:serialNumber/qrcode` | 生成员工二维码 | 是 | 任何 |
| PATCH | `/api/employee-serials/:serialNumber` | 更新员工序列号信息 | 是 | 管理员 |
| PUT | `/api/employee-serials/:serialNumber` | 更新员工序列号信息 | 是 | 管理员 |
| POST | `/api/employee-serials/:serialNumber/revoke` | 吊销员工序列号 | 是 | 管理员 |
### Node 对齐说明
- Go 版路由已与 `backend-node` 对齐(含 `PATCH` 更新接口、企业详情、企业吊销、删除企业下单个序列号)。
- 企业统计与企业详情接口统一返回 `{ message, data }` 结构。
- 序列号相关返回字段已对齐前端使用(如 `serialNumber``validUntil``createdBy``status`)。
**员工序列号特点**:
- 无有效期限制(与企业赋码不同)
- 包含部门department和员工姓名employeeName信息
- 序列号格式: `EMP26xxxxxx`EMP + 年份后两位 + 6位随机字符
## 测试
### 运行所有测试
```bash
# 运行所有测试
go test -v ./...
# 仅运行服务层单元测试
cd services && go test -v -cover
# 仅运行集成测试
go test -v ./tests/...
```
### 生成测试覆盖率报告
```bash
# 生成覆盖率报告
go test -v ./services/... -coverprofile=coverage.out
go tool cover -html=coverage.out
```
### 当前测试覆盖
- **services/**: 包含 AuthService、SerialsService、EmployeeSerialsService 和 CompaniesService 的完整单元测试
- 用户认证测试(登录、获取用户信息、修改密码、更新资料)
- 序列号管理测试(生成、查询、更新、吊销、分页列表)
- 员工赋码测试(生成、查询、更新、吊销、二维码生成)
- 企业统计测试(统计概览)
- **tests/**: 集成测试(健康检查、登录流程)
## 代码检查
使用 golangci-lint 进行代码检查:
```bash
golangci-lint run ./...
```
## 部署
### 编译为二进制文件
```bash
# Linux/Mac
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o trace-backend
# Windows
go build -o trace-backend.exe main.go
# macOS
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o trace-backend
```
### 运行
```bash
./trace-backend
```
## 数据库迁移
### SQLite 到 PostgreSQL 的迁移
修改 `.env` 文件中的数据库配置:
```bash
# 将数据库驱动改为 postgres
DATABASE_DRIVER=postgres
# PostgreSQL 配置
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=trace
POSTGRES_PASSWORD=trace123
POSTGRES_DB=trace
POSTGRES_SSLMODE=disable
```
然后重新启动应用即可:
```bash
./trace-backend
```
**注意**: 切换数据库后,原有 SQLite 中的数据不会自动迁移到 PostgreSQL。需要使用数据库迁移工具如 pgloader手动迁移数据。
## 贡献指南
1. 克隆项目
2. 创建新功能分支
3. 提交更改
4. 推送到远程仓库
5. 创建 Pull Request
### 代码风格要求
- 使用 gofmt 自动格式化代码
- 遵循 Go 官方编码规范
- 使用 golangci-lint 进行代码检查
- 保持代码简洁和高效
## 许可证
MIT License