Files

210 lines
7.2 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 + 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 签名密钥 | 开发默认值 |
| `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` |
## 开放接口(皮肤源头对接)
项目有两套外部 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/main.go # 入口
│ └── internal/
│ ├── config/ # 配置加载
│ ├── handler/ # HTTP 处理器
│ ├── middleware/ # JWT 认证、签名验证
│ ├── model/ # 数据模型
│ ├── pkg/ # 工具包
│ ├── router/ # 路由
│ └── service/ # 业务逻辑
├── frontend/src/
│ ├── api/ # API 调用
│ ├── pages/ # 页面组件
│ ├── layouts/ # 布局
│ └── types/ # 类型定义
├── docker-compose.yml # 容器编排
├── Makefile # 常用命令
└── start.sh # 开发一键启动
```