合并本轮全部文档改动(原 5 个 docs 提交压成 1 个)。 口径与索引: - 新增 docs/README.md 文档总索引:三来源口径(91 + 快手 send-code = kuaishou-91)、 「一个订单 = 骨架 + 买家凭证 + 一个执行载体」、成本只改一处、文档状态机 - 过期阶段文档移入 docs/archive/2026-10-08/(保留内容,不删除) 分析报告: - docs/项目全量分析报告-2026-10-17.md:架构、五条业务链路、P0/P1/P2 风险与改进路线 - docs/载体判定与成本中心落地-复核与草案-2026-10-17.md:生产只读克隆量化、上一轮结论复核与 4 处修正 方案文档: - docs/成本中心与三块履约模型.md:三块执行载体、标准商品、成本版本与快照、人工支出登记 - docs/财务系统集成方案.md:复式记账模型、分录表、分期落地 - docs/影子总账说明.md:影子期与转正期的边界、对账与转正标准 SQL 草案(docs/drafts/,未接入迁移): - 载体判定与人工块量化.sql:量化查询、carrier_type 判定与回填、守恒校验 - 成本中心与销售事实-DDL草案.sql:product_catalog / channel_product_mappings / cost_items / cost_versions / cost_snapshots / cost_exceptions / sales_daily_facts - 人工支出登记-DDL草案.sql:manual_fulfillment_cases / manual_expense_records / manual_expense_events 业务口径确认(2026-10-17): - 收入 = 用户实付(orders.total_amount),与快手 paymentFen 数据核验 100% 一致 - 打手报酬 = 支出/成本(最终提现打款),按总额法 - 人工块以「支出可追溯」为先,SLA 监管延后 - 退款/仲裁暂未接入,先预留字段与反向冲正关系 三份草案已在一次性沙箱库按依赖顺序零错误应用(10 张新表、27 个 CHECK 约束)。
315 lines
13 KiB
Markdown
315 lines
13 KiB
Markdown
# order_site
|
||
|
||
多渠道订单履约、打手众包接单与寄卖仓库系统。
|
||
|
||
前后端分离架构:接收 `kuaishou-91`、`pdd`、`douyin-mashida` 三个来源的订单,按规则匹配自动发货或生成打手工单,提供统一领取/兑换链接,并支持平台配置、财务结算、审计与人工复核。
|
||
|
||
## 技术栈
|
||
|
||
| 层 | 技术 |
|
||
| --- | --- |
|
||
| 前端 | React 19、Vite 8、Ant Design 6、React Router 7、TanStack Query、TypeScript |
|
||
| 后端 | Node.js、Express 5、TypeScript、PostgreSQL、node-pg-migrate |
|
||
| 网关 | Caddy |
|
||
| 运行 | Docker Compose(开发 / 生产分离) |
|
||
|
||
## 目录结构
|
||
|
||
```text
|
||
apps/
|
||
backend/ 后端 API、任务编排、平台对接、数据库迁移
|
||
src/
|
||
db/migrations/ SQL 迁移(001 基线 + 后续渐进增量)
|
||
data/ 本地运行数据与平台配置(敏感,默认不提交)
|
||
frontend/ React 管理后台 + 用户领取页
|
||
deploy/
|
||
caddy/ Caddy 反向代理
|
||
docker/ 前后端 Dockerfile
|
||
mac-dev.sh / ubuntu-deploy.sh
|
||
docs/ 文档索引、架构分析、财务方案、平台接口、部署说明
|
||
docker-compose.dev.yml 本地 Docker 开发环境
|
||
docker-compose.yml 生产 / 服务器 Compose
|
||
```
|
||
|
||
## 来源模型(现行)
|
||
|
||
系统只有三个订单来源:
|
||
|
||
| sourceKey | 数据通道 | 说明 |
|
||
| --- | --- | --- |
|
||
| `kuaishou-91` | 91 回调 + 快手 send-code | **同一个来源的两条通道**:91 是订单骨架权威源,快手 send-code 是数据补全源与兜底源;共享店铺键空间与同一套匹配上下文 |
|
||
| `pdd` | 拼多多订单同步 | 两段式 `pdd_raw_orders → orders` |
|
||
| `douyin-mashida` | 抖音码速达推送 | 抖店订单、DYC 券、H5/兑换页 |
|
||
|
||
不要把 91 与快手 send-code 拆成两个来源或两个适配器。代码中的唯一来源键是 `kuaishou-91`(`apps/backend/src/services/product-match/types.ts`)。
|
||
|
||
## 业务边界(简图)
|
||
|
||
```text
|
||
kuaishou-91(91 回调 + 快手 send-code)
|
||
→ 本系统建单 / 匹配商品 / 创建履约任务
|
||
→ 返回统一 claimUrl
|
||
用户打开领取页
|
||
→ 可选:快手行业电子凭证自动核销
|
||
→ affiliate-dash / 人工 完成发货
|
||
后台
|
||
→ 订单任务、平台配置、审计、人工复核
|
||
接单平台(打手众包)
|
||
→ 工单发布到抢单大厅,打手抢单代练
|
||
→ 提交验收 / 问题单处置 / 任务时限超时自动判定
|
||
抖音码速达
|
||
→ 抖店订单推送 → 建单 → DYC 券 → 领取/兑换页 → 核销
|
||
```
|
||
|
||
更完整的链路说明见:`docs/履约配置/多发货平台与电子凭证整体链路.md`。
|
||
文档总索引见:`docs/README.md`。
|
||
|
||
## 本地开发
|
||
|
||
推荐直接用 Docker,本机不必单独装 Node / PostgreSQL。
|
||
|
||
```bash
|
||
cp .env.mac-docker.example .env
|
||
docker compose -f docker-compose.dev.yml up -d --build
|
||
```
|
||
|
||
常用入口:
|
||
|
||
| 入口 | 地址 |
|
||
| --- | --- |
|
||
| 前端 / 后台 / 领取页 | `http://localhost` |
|
||
| 后端健康检查 | `http://localhost/health` |
|
||
| 后端就绪检查 | `http://localhost/health/ready` |
|
||
| 后端 API 前缀 | `http://localhost/api/v1/...` |
|
||
|
||
常用命令:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.dev.yml ps
|
||
docker compose -f docker-compose.dev.yml logs -f backend
|
||
docker compose -f docker-compose.dev.yml logs -f frontend
|
||
docker compose -f docker-compose.dev.yml down
|
||
```
|
||
|
||
Mac 也可使用:
|
||
|
||
```bash
|
||
bash deploy/mac-dev.sh
|
||
```
|
||
|
||
## 开发验证
|
||
|
||
以容器内执行为准:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.dev.yml exec -T backend npm test
|
||
docker compose -f docker-compose.dev.yml exec -T backend npm run format:check
|
||
docker compose -f docker-compose.dev.yml exec -T backend npm run typecheck
|
||
docker compose -f docker-compose.dev.yml exec -T backend npm run build
|
||
docker compose -f docker-compose.dev.yml exec -T frontend npm test
|
||
docker compose -f docker-compose.dev.yml exec -T frontend npm run format:check
|
||
docker compose -f docker-compose.dev.yml exec -T frontend npm run typecheck
|
||
docker compose -f docker-compose.dev.yml exec -T frontend npm run build
|
||
```
|
||
|
||
### 本地推送检查
|
||
|
||
本项目不使用 Gitea Actions。需要在本机推送前自动执行前后端检查时,启用本地 Git hook:
|
||
|
||
```bash
|
||
bash scripts/install-git-hooks.sh
|
||
```
|
||
|
||
启用后,每次 `git push` 会依次执行 `apps/backend` 和 `apps/frontend` 的 `npm run check`。
|
||
仅临时跳过检查时使用:
|
||
|
||
```bash
|
||
SKIP_CHECKS=1 git push
|
||
```
|
||
|
||
## 数据库迁移
|
||
|
||
采用 **基线 + 渐进增量** 策略,由 `node-pg-migrate` 管理,记录表为 `schema_migrations`。
|
||
|
||
| 文件 | 含义 |
|
||
| --- | --- |
|
||
| `001_init.sql` | 空库基线,建立完整业务结构 |
|
||
| `002_xxx.sql` ~ `080_xxx.sql` | 后续结构变更的增量 SQL(接单平台 004~009,寄卖相关 077~080) |
|
||
|
||
约定:
|
||
|
||
1. **不要修改**已经应用到共享/生产环境的历史迁移文件。
|
||
2. 结构变更一律新增迁移文件,不要回写 `001_init.sql`。
|
||
3. 空库按序号依次执行 `001 → 002 → …`;已有库只执行尚未记录的增量。
|
||
4. 后端启动时自动 `up`;也可手动执行。
|
||
|
||
常用命令(容器内):
|
||
|
||
```bash
|
||
# 查看本地文件与数据库对齐状态
|
||
docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate:status
|
||
|
||
# 手动执行未应用迁移
|
||
docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate
|
||
|
||
# 创建下一份增量迁移(示例)
|
||
docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate:create -- add_task_priority
|
||
```
|
||
|
||
宿主机直连开发库(注意主机名):
|
||
|
||
```bash
|
||
cd apps/backend
|
||
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/order_site npm run db:migrate:status
|
||
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/order_site npm run db:migrate
|
||
```
|
||
|
||
本地需要清空数据重建库时(会丢开发数据):
|
||
|
||
```bash
|
||
docker compose -f docker-compose.dev.yml down
|
||
docker volume rm order_site_postgres_dev_data
|
||
docker compose -f docker-compose.dev.yml up -d --build
|
||
```
|
||
|
||
更多说明见 `docs/部署启动与数据库重建.md`。
|
||
|
||
## 环境变量
|
||
|
||
本地:
|
||
|
||
```bash
|
||
cp .env.mac-docker.example .env
|
||
```
|
||
|
||
生产:
|
||
|
||
```bash
|
||
cp .env.server.example .env
|
||
```
|
||
|
||
常用变量:
|
||
|
||
| 变量 | 说明 |
|
||
| --- | --- |
|
||
| `APP_DOMAIN` / `CADDY_SITE_ADDR` | 后台与领取页域名、Caddy 主站监听地址 |
|
||
| `WORKER_SITE_ADDR` | 打手端独立域名,如 `https://worker.khhao.com` |
|
||
| `CLAIM_BASE_URL` | 领取页完整前缀,如 `https://域名/#/claim` |
|
||
| `CLAIM_TOKEN_TTL_HOURS` | 领取链接有效期(小时);`0` 表示长期有效,正整数表示限时 |
|
||
| `DATABASE_URL` | PostgreSQL 连接串(容器内主机名用 `postgres`) |
|
||
| `ADMIN_SESSION_SECRET` | 后台登录态签名密钥 |
|
||
| `ADMIN_DEFAULT_USERS_JSON` | 默认后台用户 |
|
||
| `KAQUAN91_USER_ID` / `KAQUAN91_SECRET` | 91 卡券开放接口凭据 |
|
||
|
||
## 运行数据
|
||
|
||
| 环境 | 路径 / Volume |
|
||
| --- | --- |
|
||
| 本地后端配置与日志 | `apps/backend/data` |
|
||
| 本地 PostgreSQL | Docker volume `postgres_dev_data` |
|
||
| 生产后端数据 | `apps/backend/data`(与本地路径一致) |
|
||
| 生产 PostgreSQL | Docker volume `postgres_data` |
|
||
| 生产 Caddy | Docker volume `caddy_data` |
|
||
|
||
注意:`apps/backend/data/*.json` 可能含账号、Cookie、token 等敏感信息,默认不进仓库;只保留 `*.example.json` 模板。
|
||
|
||
## 生产部署
|
||
|
||
```bash
|
||
cp .env.server.example .env
|
||
# 编辑真实配置后:
|
||
mkdir -p apps/backend/data
|
||
sudo chown -R 1001:1001 apps/backend/data
|
||
docker compose up -d --build
|
||
```
|
||
|
||
Ubuntu 一键脚本:
|
||
|
||
```bash
|
||
bash deploy/ubuntu-deploy.sh
|
||
```
|
||
|
||
首次若无 `.env`,脚本会从示例生成模板并退出;填好后再执行一次即可。脚本会检查 Docker、占位配置、数据目录权限,构建启动并等待健康检查。
|
||
|
||
**按需重建**:脚本用 `.deploy-state` 记录上次成功部署的 commit 与 `.env` 指纹,再按 `git diff --name-only 上次..HEAD` 判断这次要重建哪一端 —— 只改 `apps/backend/**` 就只重建后端镜像,只改 `apps/frontend/**`(或 `deploy/caddy/**`)就只重建 Web 镜像,只改文档/部署脚本时两端镜像都不重建、容器保持运行;`.env` 变化、compose 文件变化或路径拿不准时两端都重建兜底。不需要重建的一侧既不跑 Docker 构建、也不重建容器。部署结束会打印各阶段耗时。
|
||
|
||
常用参数:
|
||
|
||
| 参数 | 说明 |
|
||
| --- | --- |
|
||
| (无) | 按 git 改动自动判断重建哪一端;本次改动不含 `apps/backend/src/db/migrations/**` 时自动跳过迁移前备份 |
|
||
| `--dry-run` | 只打印计划(改了什么、重建哪一端、要不要备份、基础镜像 digest)后退出,不做任何改动 |
|
||
| `--all` | 强制两端镜像都重建(忽略改动检测) |
|
||
| `--backend-only` / `--web-only` | 只重建指定的一端 |
|
||
| `--backup` | 强制迁移前备份(即使本次无 schema 变更) |
|
||
| `--skip-backup` | 无条件跳过部署前的数据库备份 |
|
||
| `--reset-db` | 删除 PostgreSQL 数据卷后按 migrations 全量重建(执行前会自动抓取最后一份备份) |
|
||
| `--yes` | 跳过 `--reset-db` 的交互确认(等价于 `RESET_DB_CONFIRM=1`) |
|
||
|
||
`--skip-backup` 也可用环境变量 `SKIP_BACKUP=true bash deploy/ubuntu-deploy.sh` 代替。备份与恢复的完整说明见 `docs/数据库备份与恢复.md`。
|
||
|
||
生产入口示例:
|
||
|
||
- 前端与领取页:`https://你的域名/`
|
||
- 健康检查:`https://你的域名/health`
|
||
- API:`https://你的域名/api/v1/...`
|
||
|
||
生产 Compose 会:启动 PostgreSQL → 后端自动迁移 → 初始化默认管理员 → 同步履约目录 → Caddy 暴露前端与 API。
|
||
|
||
## 主要模块
|
||
|
||
| 路径 | 职责 |
|
||
| --- | --- |
|
||
| `apps/backend/src/routes` | 开放接口 / 领取 / 后台 API |
|
||
| `apps/backend/src/routes/worker` | 打手端 API(抢单大厅、我的订单、验收) |
|
||
| `apps/backend/src/services/order` | 订单入库、商品匹配、任务同步 |
|
||
| `apps/backend/src/services/fulfillment` | 履约路由与执行器(cloud / feifei / 人工) |
|
||
| `apps/backend/src/services/worker-platform` | 接单平台业务(工单、等级、押金结算、超时扫描) |
|
||
| `apps/backend/src/services/platforms` | 外部平台对接 |
|
||
| `apps/backend/src/services/admin` | 后台鉴权、读写、配置 |
|
||
| `apps/backend/src/services/scheduler` | 定时任务(云账号健康检查、工单超时扫描) |
|
||
| `apps/backend/src/repositories` | 数据访问 |
|
||
| `apps/backend/src/db/migrations` | 数据库迁移 |
|
||
| `apps/frontend/src/pages/admin` | 管理后台页面 |
|
||
| `apps/frontend/src/pages/worker` | 打手端页面(大厅、我的订单、个人中心) |
|
||
| `apps/frontend/src/pages/claim` | 用户领取页 |
|
||
|
||
## 接单平台(打手众包)
|
||
|
||
用于将部分订单转为打手代练任务,与主履约流程解耦:
|
||
|
||
| 能力 | 说明 |
|
||
| --- | --- |
|
||
| 抢单大厅 | 打手按分类/关键词筛选,实时刷新、冻结押金抢单;拼单工单按份参与 |
|
||
| 我的订单 | 代练中 / 待验收 / 问题单流转,提交验收支持图片粘贴与拖拽 |
|
||
| 任务时限 | 工单可配置时限,超时由定时扫描 + 接口惰性判定双重处置(退回大厅 / 取消退押金 / 取消扣押金),并统计每个打手的超时订单数 |
|
||
| 等级权限 | VIP 等级体系:免押额度、最大同时接单量、大厅可见延迟 |
|
||
| 资金 | 押金冻结 / 退还 / 扣除流水,充值申请与提现审核 |
|
||
| 物品规则 | 按商品/SKU 匹配自动生成工单,可继承默认时限与拼单配置 |
|
||
| 管理后台 | 接单工单 CRUD、打手账号管理、问题单处置、定时任务管理,功能标签页记忆上次选择 |
|
||
|
||
说明:
|
||
|
||
- 打手通过**手机号验证码注册**并设置密码,注册后直接可用;登录使用手机号 + 密码。
|
||
- 短信默认 Mock 模式(验证码打印到服务日志),生产配置 `WORKER_SMS_PROVIDER=aliyun` + 阿里云凭据后走真实短信。
|
||
- 来源订单同步由物品规则驱动(`syncWorkerOrdersForSourceOrder`)。
|
||
- 工单状态机独立于主履约任务:`pending_material → unassigned → open → in_progress → pending_acceptance → accepted / cancelled`,另有 `problem`。
|
||
- 超时扫描定时任务默认 60 秒执行一次(配置见后台"平台配置 → 定时任务")。
|
||
|
||
## 提交前检查
|
||
|
||
```bash
|
||
docker compose -f docker-compose.dev.yml exec -T backend npm run check
|
||
docker compose -f docker-compose.dev.yml exec -T frontend npm run check
|
||
```
|
||
|
||
代码格式由仓库根目录的 Prettier 配置统一管理。修改代码后可在对应应用目录执行
|
||
`npm run format`,提交前使用 `npm run format:check` 只检查、不修改文件。
|
||
|
||
确认:
|
||
|
||
- 未提交真实账号、Cookie、token、手机号或生产配置
|
||
- `.env` 未入库
|
||
- **结构变更的 migration 与业务代码同 PR 提交**
|
||
- 领取链接相关改动已在 Docker 环境验证
|