# 浙江贝凡溯源管理平台 - 后端服务 (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 - **配置管理**: - 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 # 企业管理接口 │ ├── helper.go # 控制器通用辅助函数 │ └── serials_controller.go # 序列号管理接口 ├── database/ # 数据库连接和操作 │ └── database.go # 数据库初始化、连接池配置 ├── 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 # 企业管理业务逻辑 │ ├── 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 DATABASE_DRIVER=sqlite DATABASE_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"}' ``` ## API 文档 ### 认证路由 | 方法 | 路径 | 描述 | 需要认证 | | ---- | --------------------------- | ----------------------- | -------- | | POST | `/api/auth/login` | 用户登录,返回 JWT 令牌 | 否 | | 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` | 获取序列号列表 | 是 | 任何 | | PUT | `/api/serials/:serialNumber` | 更新序列号信息 | 是 | 管理员 | | POST | `/api/serials/:serialNumber/revoke` | 吊销序列号 | 是 | 管理员 | ### 企业管理 | 方法 | 路径 | 描述 | 需要认证 | 角色 | | ------ | ----------------------------- | ------------ | -------- | ------ | | GET | `/api/companies` | 获取企业列表 | 是 | 任何 | | POST | `/api/companies` | 创建新企业 | 是 | 管理员 | | PUT | `/api/companies/:companyName` | 更新企业信息 | 是 | 管理员 | | DELETE | `/api/companies/:companyName` | 删除企业 | 是 | 管理员 | ## 测试 ### 运行所有测试 ```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 的完整单元测试 - 用户认证测试(登录、获取用户信息、修改密码、更新资料) - 序列号管理测试(生成、查询、更新、吊销、分页列表) - **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