Files
affiliate_dash/README.md
T
yml2213 14d297a591 docs: 补充项目分析并更新 README 目录结构
- 新增 docs/项目分析.md:项目定位、架构、数据模型、业务流、工程质量、
  两轮优化记录(含验证证据)与遗留问题清单
- README 目录结构同步现有包(cmd/*、internal/database、testdb、store 等),
  并说明 service 包按 delivery_*/rock_*/merchant_*/provider_* 前缀成组
2026-10-06 19:43:51 +08:00

233 lines
9.4 KiB
Markdown
Raw 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 + React 的游戏皮肤分销管理平台,支持分销商管理、订单追踪、上游皮肤源头对接。
## 技术栈
| 层级 | 技术 |
|------|------|
| 后端 | Go 1.26 + Gin + GORM |
| 数据库 | PostgreSQL 16 |
| 前端 | React 19 + TypeScript + Ant Design |
| 构建 | Vite + Docker Compose |
| 反向代理 | Caddy |
## 本地开发
### 环境要求
- Go 1.26+
- Node.js 22+
- Docker / Docker Compose(用于自动启动 PostgreSQL 开发服务)
### 快速启动
```bash
# 1. 复制配置文件
cp .env.example .env
# 按需修改 .env 中的密钥
# 2. 一键启动(后端 + 前端 + PostgreSQL)
make dev
# 或直接
./start.sh
```
`make dev` 会通过 Docker Compose 启动 `affiliate_dash/postgres`,后端和前端仍在宿主机运行,方便热更新。首次从旧版 `affiliate_dash_postgres_dev` 开发容器迁移时,脚本会停止旧容器并优先复用旧数据卷。
启动后:
- 前端:`http://localhost:15173`
- 后端:`http://localhost:18080`
按 `Ctrl+C` 停止所有服务。
### 手动启动
```bash
# 安装依赖
make install
# 分别启动
make backend # 后端 :18080
make frontend # 前端 :15173
```
## Docker 生产部署
### 配置
```bash
cp .env.example .env
# 编辑 .env,确保以下变量已配置:
# JWT_SECRET — 生产环境务必修改
# OPEN_API_KEY — 皮肤源头对接 API Key
# OPEN_API_SECRET — 签名密钥
# POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB — PostgreSQL 初始化配置
```
> 国内服务器可在 `.env` 中取消 `GOPROXY`、`ALPINE_MIRROR`、`NPM_REGISTRY` 等镜像加速源的注释。
> Docker 后端容器默认使用 `postgres` 作为数据库主机;只有连接外部数据库时才需要设置 `DOCKER_DATABASE_URL`。
### 启动服务
```bash
# 构建并启动全部服务(PostgreSQL + 后端 + Caddy)
make docker-up
# 或
docker compose up -d --build
```
服务端口(默认值已避开常见端口,避免与其他项目冲突;均可在 `.env` 中覆盖):
- `:80` — 前端页面 + API(Caddy 统一入口,可通过 `HTTP_PORT`/`HTTPS_PORT` 调整)
- `:18080` — 后端 API(直接访问,调试用,可通过 `PORT` 调整)
- `:15432` — PostgreSQL(本地开发/调试用,可通过 `POSTGRES_PORT` 调整)
### 常用命令
```bash
make docker-logs # 查看日志
make docker-ps # 查看容器状态
make docker-down # 停止并移除
```
### 自定义域名
`Caddyfile` 默认同时支持本地 `:80` 和示例域名 `skin.khhao.com`。生产部署时把 `skin.khhao.com` 改为你的域名,重新构建即可。
## 环境变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `PORT` | 后端端口 | `18080` |
| `FRONTEND_PORT` | 前端开发端口 | `15173` |
| `HTTP_PORT` / `HTTPS_PORT` | Caddy 对外 HTTP/HTTPS 端口 | `80` / `443` |
| `JWT_SECRET` | JWT 签名密钥 | 开发默认值 |
| `DATA_ENCRYPTION_KEY` | 加密落库的 API/回调密钥;留空会回退到 `JWT_SECRET` 并在启动日志告警 | 回退到 `JWT_SECRET` |
| `DATABASE_URL` | PostgreSQL 连接串 | 本地开发默认值 |
| `DOCKER_DATABASE_URL` | Docker 后端容器内 PostgreSQL 连接串,通常无需设置 | Compose 内置默认值 |
| `POSTGRES_PORT` | PostgreSQL 映射到宿主机的端口 | `15432` |
| `COMPOSE_PROJECT_NAME` | Docker Compose 项目名 | `affiliate_dash` |
| `POSTGRES_DATA_VOLUME` | PostgreSQL 数据卷名 | `affiliate_dash_postgres_data` |
| `GIN_MODE` | Gin 运行模式 | `debug` |
| `OPEN_API_KEY` | 开放接口 ApiKey | 需修改 |
| `OPEN_API_SECRET` | 开放接口签名密钥 | 需修改 |
| `OPEN_SIGN_SKEW` | 签名时间戳偏差(秒) | `300` |
| `OPEN_API_DEBUG` | 开放接口调试日志 | debug 模式默认开启 |
| `LOG_FILE` | 日志文件路径(按天分割为 `app-YYYYMMDD.log`) | `logs/app.log` |
| `LOG_RETAIN_DAYS` | 日志文件保留天数,到期自动清理 | `30` |
| `CORS_ALLOWED_ORIGINS` | 跨域来源白名单(逗号分隔);生产同域部署无需配置,为空时仅放行本地开发端口,不支持 `*` | 空 |
| `FULFILLMENT_PROCESSING_TIMEOUT_MINUTES` | 发货中订单自动标记失败的超时分钟数,<=0 关闭 | `30` |
| `FULFILLMENT_TIMEOUT_SCAN_INTERVAL_SECONDS` | 发货超时巡检间隔秒数 | `60` |
> **安全提示**:`JWT_SECRET` 与 `DATA_ENCRYPTION_KEY` 必须各自生成随机值(`openssl rand -hex 48` / `openssl rand -hex 32`),
> 不能沿用 `.env.example` 中的示例值,也不能两者相同。服务启动时会自动体检并打印
> `[CONFIG] 安全告警: ...`。轮换方法见 [`docs/密钥轮换说明.md`](docs/密钥轮换说明.md)。
## 开放接口(皮肤源头对接)
项目有两套外部 API,请先区分调用方:
- 商户侧 `/api/client/v1`:商户系统创建订单、查询订单和钱包,使用商户专属 `X-App-Key`。
- 源头侧 `/api/open/v1`:上游发货平台查询订单并回传发货结果,使用平台配置的 `X-Api-Key`。
源头侧 `ship_notify` 当前只使用 `success` / `failed`,速查见 [`docs/发货通知约定.md`](docs/发货通知约定.md),完整关系图见 [`docs/API对接关系.md`](docs/API对接关系.md)。两套 API 的签名算法不同,不能混用鉴权头或签名串。
### 状态速查
| 订单状态 | 含义 | 是否可发货 |
|----------|------|------------|
| `paid` | 已支付/已扣款,待发货 | 是 |
| `delivering` | 发货中 | 否 |
| `delivered` | 已交付 | 否 |
| `ship_failed` | 发货失败,可重试 | 是 |
| `cancelled` | 已取消并退款 | 否 |
上游皮肤源头系统调用源头侧接口时,需携带签名头 `X-Api-Key`、`X-Timestamp`、`X-Nonce`、`X-Sign`。
### 1. 查询订单(发货前置)
```
GET /api/open/v1/orders/:order_no
```
返回订单状态、商品信息、是否可发货。
### 2. 发货结果通知
```
POST /api/open/v1/orders/ship-notify
```
上游发货完成后推送结果,请求体:
```json
{
"order_no": "O202607241200000012",
"ship_status": "success",
"provider_order_no": "上游单号",
"shipped_at": "2026-07-24T16:00:00+08:00",
"fail_reason": "",
"game_channel": "IOS-微信",
"game_uid": "550e8400-e29b-41d4-a716-446655440000",
"role_name": "玩家名",
"pay_score": 100
}
```
| 字段 | 必填 | 说明 |
|------|------|------|
| `order_no` | 是 | 系统订单号 |
| `ship_status` | 是 | 仅 `success` / `failed` |
| `provider_order_no` | 否 | 上游单号 |
| `shipped_at` | 否 | 发货时间,RFC3339 格式 |
| `fail_reason` | 失败时是 | `failed` 时必填,填写详细失败原因 |
| `game_channel` | 否 | 账号区服(安卓/IOS-微信/QQ) |
| `game_uid` | 否 | 游戏角色 UUID |
| `role_name` | 否 | 角色名 |
| `pay_score` | 否 | 消耗积分 |
## 管理端
管理员登录后可访问商品管理、订单管理、用户管理、发货日志等功能。后台默认地址 `/`。
## 目录结构
```
├── backend/
│ ├── cmd/
│ │ ├── server/ # 服务入口
│ │ ├── reencrypt_secrets/ # 密钥轮换:重加密落库密文
│ │ ├── cache_images/ # 商品图本地缓存工具
│ │ └── sync_product_images/ # 商品图同步工具
│ └── internal/
│ ├── config/ # 配置加载 + 启动安全体检
│ ├── database/ # 显式 SQL 迁移(embed + checksum)
│ │ └── migrations/ # 001~012 迁移脚本,已执行版本不可修改
│ ├── handler/ # HTTP 处理器:merchant_* / open_* / recharge / rock …
│ ├── middleware/ # JWT / 商户签名 / 源头签名 / 功能与权限门禁
│ ├── model/ # 数据模型:merchant / recharge / rock / models
│ ├── pkg/ # 工具包:applog / openlog / jwt / response / timeutil / lewan
│ ├── router/ # 路由注册与请求日志
│ ├── service/ # 业务逻辑
│ │ ├── fulfillment* # 订单状态机、下单幂等、超时巡检
│ │ ├── delivery* # 提货页 BFF:查询 / 绑定 / 提交 / 链接
│ │ ├── provider* # 履约渠道接口与路由(DLC / 乐玩 / Rock)
│ │ ├── rock_* # Rock 库存池、UID 强一致门禁、绑错追溯
│ │ ├── merchant* # 商户、商品目录、成员与角色
│ │ └── recharge / callback / user / tenant
│ └── testdb/ # 集成测试用 PostgreSQL 临时 schema
├── frontend/src/
│ ├── api/ # API 调用
│ ├── pages/ # 页面组件(platformRock/ 为 Rock 大屏拆出的子组件)
│ ├── layouts/ # 布局
│ ├── store/ # 登录态与租户上下文
│ └── types/ # 类型定义
├── docs/ # 对接文档、实施方案与项目分析
├── docker-compose.yml # 容器编排
├── Makefile # 常用命令(dev / test / lint / fmt / docker-*)
└── start.sh # 开发一键启动
```
> `service` 包按 `delivery_*` / `rock_*` / `merchant_*` / `provider_*` 前缀成组,
> 单个文件保持在 300 行以内,便于按业务域定位。