Files
hfb_sys/docs/分销网管理后台设计方案.md
T
yml2213 2a76d59a30 feat(distribution): 公告中心支持分站自定义
公告中心(前台公告列表/详情)此前完全没有站点概念,分站访客只能看到主站公告。
本次按「默认继承主站、站长可切仅本站」的口径支持分站自定义。

数据与口径:
- 新增 announcements.distribution_site_id(0=主站),前台按站点隔离
- 新增 distribution_sites.announcement_mode:inherit(默认,主站+本站)/ own_only(仅本站)

后端:
- 公告模块新增 ResolvePublicSiteScope:主站 [0]、inherit [0, siteID]、own_only [siteID],
  站点编码无效/已停用回落主站;列表与详情都按该范围过滤,详情不再允许跨站按 ID 读取
- 管理端公告列表支持按站点筛选(site_id:不传=全部,0=主站,>0=分站)并带出站点名
- 分销模块新增本站公告 CRUD(distribution/announcement.go):强制 distribution_site_id=本站,
  先过 ensureSiteAccess,跨站更新/删除/上下架一律 ErrAnnouncementNotFound
- UpdateSiteBranding 支持 announcement_mode 切换(非法值报错,读侧非法历史值回落 inherit)
- 新增权限 distribution:announcement_view|manage 并授予 super_admin/ops/finance,
  站长开通时继承 ops 角色即自动获得
- 路由:站长侧 /api/distribution/announcements*,平台侧 /api/admin/distribution/announcements*

前端:
- 分销后台新增「公告中心」页:来源开关(继承主站+本站 / 仅本站)、本站公告列表与
  新建/编辑/发布/下架/归档/恢复/删除,空态按来源模式给出引导
- 平台后台公告页新增「站点」列与筛选,新建公告可选择归属站点(主站或指定分站代发)
- 前台 PC/移动无需改动:请求已带 X-Distribution-Site-Code,后端按站点隔离,页面已有空态

测试:
- 公告模块:主站/继承/仅本站三种可见范围、跨站详情拦截、无效站点回落、管理端站点筛选
- 分销模块:本站公告 CRUD 与跨站防护、公告来源开关校验与非法值容错
2026-10-01 10:02:31 +08:00

893 lines
38 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.
# 分销网管理后台设计方案
> 状态:草案 v0.8
> 更新时间:2026-09-15
> v0.8 变更:通道手续费改由主站承担、不再计入提价利润基数,第 2、7.5、7.8、14、16 节与代码实现(`distribution/pricing.go`)对齐。
> 适用范围:分销网站正常租赁订单管理、订单分账、分销客服与支付配置
## 1. 文档目的
本文档记录分销网管理后台的产品计划、领域模型、分账口径、接口边界、部署方案和实施顺序。
本文档是持续维护的设计基线。业务规则尚未确认的部分使用“待确认”标记,进入开发前必须补齐;已创建的订单必须使用规则和金额快照,不能因后续规则变更而重算历史账目。
## 2. 现有系统基础
当前 HFB Sys 是 Go + Gin + GORM + MySQL + Redis 后端,Vue 3 + Element Plus 用户端/运营后台前端,生产通过 Caddy 托管静态文件并反代单个 backend 服务。
可复用的现有领域:
- 用户:`users`、实名认证、用户状态。
- 商品和账号:`rental_listings`、`game_accounts`、账号资产快照。
- 正常订单:`rental_orders`、交接、归还、结账、退款和订单过程事件。
- 订单来源:`rental_orders` 的正常租赁交易;分销网只处理卖家和租客都在网站内完成的正常订单。
- 资金:`wallet_accounts`、`wallet_ledger`、`withdrawal_requests`。
- 支付:`payment_merchant_configs`、支付单、退款单和支付配置使用日志。
- 客服:`chat_conversations`、`chat_messages`、客服组和二维码池。
- 管理权限:`admin_users`、`roles`、`permissions`、角色权限关联和审计日志。
现有系统的价格快照包含 `seller_ratio`、`buyer_ratio`、`seller_total_price`、`buyer_total_price` 和 `platform_markup_amount`:
- **主站提价逻辑**:收号时录入卖家底价 `seller_total_price` 与回收比例 `seller_ratio`,主站定价引擎通过固定加价(小额)或减比例加价(大额)算得面向买家的挂牌比例 `buyer_ratio` 与买家价 `buyer_total_price`。两者的差额即为**主站提价利润**(`platform_markup_amount = buyer_total_price - seller_total_price`)。
- **分销分账本质**:分账**分的是主站提价多出来的利润**,按收号方 35% / 卖出方 40% / 平台服务费 25% 切分;号主底价作为本金成本 100% 归号主,不参与分账。支付通道手续费由主站承担,不计入提价利润基数,只落库供对账(见 7.5)。
- **分站自主加价**:分站货架可在主站挂牌价基础上进一步自主提价;**分站自己提价多挣的钱 100% 属于分站自己**,不进入三方分成池。
- **挂牌比例定义**:挂牌比例语义为「1 元兑换多少万哈夫币」,`价格 = 哈夫币万数 / 比例`,比例越小售价越贵(加价是调小比例)。分销分成的 35% / 40% / 25% 是利润分成百分比,不能与兑换比例混淆。
## 3. 总体架构
### 3.1 独立前端、复用后端
分销网管理后台独立为新的前端工程,推荐 React + TypeScript + Vite + Ant Design。现有 Vue + Element Plus 用户端和运营后台保持不变。
```text
主站:https://hao858.com/
现有运营后台:https://hao858.com/manage-xxx
分销后台:暂定使用主域名下的独立子域名,例如 `distribution.hao858.com`
```
分销后台通过独立域名提供静态资源,`/api/*` 反代到现有 Go backend:
```text
distribution.hao858.com(暂定)
├── / 独立 Ant Design 静态资源
└── /api/* reverse_proxy backend:8080
```
这样可以避免在同一个 Vue 应用中同时引入 Element Plus 和 Ant Design,也避免跨域 Cookie 和 CORS 配置。
### 3.2 后端暂不拆服务
第一阶段不新建独立分销后端服务。分销模块继续使用现有 MySQL、Redis、钱包、订单、支付、客服和权限体系,以便在同一事务中处理支付、退款、分成、税费和钱包流水。
建议新增后端目录:
```text
backend/internal/modules/distribution/
```
建议文件:
```text
dto.go
handler.go
service.go
repository.go
query.go
mutation.go
pricing.go
settlement.go
payment.go
qrcode.go
chat.go
presenter.go
audit.go
```
## 4. 业务目标与后台功能
### 4.1 分销后台功能
第一版需要覆盖(仅限正常租赁订单):
1. 显示正常订单中已售出账号的详情。
2. 显示分销网站自己通过正常订单收购/接收的账号详情(卖家在分销网站上架,租客完成交易)。
3. 配置分销网站在正常订单中的收号分成百分比;主站卖出百分比统一或按规则版本管理(默认收号 35% / 卖出 40% / 服务费 25%)。
4. 分销网站使用指定客服组和指定二维码池的拉群码。
5. 查看通道手续费、服务费(利润的 25%)、货架兑换比例、税费、分成和结算金额。
6. 配置分销网站是否展示账号,并可单独关闭某个账号。
7. 配置分销网站可使用的一个或多个收款支付渠道。
8. 分销客服只读订单信息和过程记录,并可按权限处理客服消息。
9. 主站查看所有分销网站的收售订单、收款金额和结算数据。
### 4.2 建议页面
```text
仪表盘
分销网站管理
正常订单售出账号
分销收售订单
佣金/分成明细
结算管理
比例与税费规则
支付通道
客服组与二维码
账号展示管理
报表
操作日志
```
## 5. 业务主体和权限
### 5.1 分销网站
建议使用独立主体表 `distribution_sites`。分销网站不是普通用户,也不直接等同于平台管理员。
分销网站至少需要保存:
- 编码、名称、域名和状态。
- 联系人信息。
- 是否允许自动展示账号。
- 默认客服组和专属二维码池。
- 税费开关和税率。
- 创建、停用和更新时间。
### 5.2 分销网站成员
建议使用 `distribution_site_members` 将现有 `admin_users` 映射到一个或多个分销网站。
成员类型建议包括:
- `operator`:查看业务和账号展示。
- `finance`:查看分成、结算和收款金额。
- `customer_service`:查看订单、过程记录和客服消息。
分销网站成员只能看到所属站点的数据。前端传入的 `site_id` 不能扩大数据范围,后端必须从当前管理员成员关系中推导并校验。
### 5.3 权限码
建议新增:
```text
distribution:site_view
distribution:site_manage
distribution:account_view
distribution:account_display
distribution:order_view
distribution:process_view
distribution:finance_view
distribution:settlement_view
distribution:settlement_manage
distribution:rule_view
distribution:rule_manage
distribution:payment_view
distribution:payment_manage
distribution:qrcode_view
distribution:qrcode_manage
distribution:chat_view
distribution:chat_send
distribution:all_view
```
分销客服默认只拥有:
```text
distribution:order_view
distribution:process_view
distribution:chat_view
distribution:chat_send
```
客服禁止修改比例、支付配置、展示状态、退款、订单状态和结算结果。
## 6. 订单和账号展示
### 6.1 售出账号详情
分销后台需要显示:
- 订单号、商品编号、账号基本信息和账号快照。
- 分销网站、收号方、售出方和租客。
- 收号 35%、卖出 40%、服务费 25%、该站 1 元兑换哈夫币比例、销售价和实际支付金额。
- 退款、手续费、服务费、税费、各方收入和结算状态。
- 交接、租用、归还、结账、退款、仲裁等过程事件。
账号密码、实名信息等敏感字段必须按照现有后台脱敏和权限规则返回。是否允许分销成员查看完整登录信息:待确认。
### 6.2 分销网站正常订单收号详情
分销网的收号不是线下提号记录,而是正常租赁订单中的一方角色:卖家在分销网站上架账号,租客在分销网站完成支付、交接、租用和归还。该类记录应从 `rental_orders` 及分销订单参与方快照查询,不能使用 `admin_pickups` 作为数据来源。
正常订单需要保存分销站点和参与方快照,例如:
```text
distribution_site_id
seller_party_id
renter_party_id
receive_ratio
receive_amount_cent
rule_version
```
不新增独立的线下收号流程;如需展示“分销网收号记录”,通过正常订单中的 `distributor_receive` 角色和订单状态筛选实现。
### 6.3 账号展示开关
网站级配置:
```text
distribution_sites.display_account_enabled
```
账号级配置:
```text
distribution_site_accounts.display_status
```
账号状态建议为:
```text
enabled
disabled
sold
offline
```
关闭展示不删除账号、不影响历史订单,只阻止新展示或新订单,并写入审计日志。
#### 6.3.1 货源与自动铺货(已实现)
所有站点与主站共用同一套货源(`rental_listings` / `game_accounts`),分站货架不是独立商品库,
而是「同一批已审核商品在本站的展示关系 + 本站加价」。据此确定铺货规则:
- 商品变为 `published + approved`(审核通过、后台直接上架、免审上架、编辑后重新上架)时,
自动为所有 `status='active' AND display_account_enabled=true` 的站点写入/恢复货架行
(`listing.Approve` → `distribution.EnsureListingShelvedTx`),不需要站长手动「一键同步主站商品」。
- `display_account_enabled` 的语义是「本站是否参与自动铺货」:关闭后该站不自动接新货,
仍可由站长手动同步与选品。
- 新增行加价 `shelf_ratio_delta = 0`(等于主站原价),站长可在货架页自主加价;
自动铺货不会覆盖已有加价。
- 站长人工下架是选品决策,自动铺货与手动同步都不会覆盖;因此
`distribution_site_accounts.display_disabled_by` 记录下架来源
(`operator` = 站长人工、`system` = 系统自动、空 = 展示中或历史数据)。
- 分站前台/搜索只要求 `published + approved` 且货架行 `enabled`;商品暂时下架、出租、
待审核都不需要改动货架行(前台条件本身就会隐藏),否则商品重新在售后会永久从分站消失。
- 「一键同步主站商品」保留为兜底与修复入口:补全缺失货架行、恢复系统下架/历史无标记的行,
`clean_stale_listings` 只清理「商品记录已被删除」的孤儿货架行。
货源归属与展示归属是两个概念:`rental_listings.distribution_site_id` 表示「这条货是谁收的」
(唯一),而 `distribution_site_accounts` 表示「这条货在哪些站的货架上卖」(可多站)。
具体分成口径由 `resolveDistributionMode` 按「买入站 × 货源站」判定
(同站自卖 / 主站收号分站卖 / 分站收号主站卖 / 三方跨站),避免重复出售与归因冲突。
#### 6.3.2 公告中心(分站可自定义)
公告中心(前台「公告」页的列表/详情)按站点隔离,不再无条件继承主站:
- `announcements.distribution_site_id` 标记归属站点(`0` = 主站)。
- `distribution_sites.announcement_mode` 决定分站来源:
`inherit`(默认)= 主站公告 + 本站公告;`own_only` = 仅本站公告。
- 前台可见范围由请求站点(`X-Distribution-Site-Code` / `?distribution_site_code`)解析:
主站 `[0]`、inherit `[0, siteID]`、own_only `[siteID]`;站点编码无效/已停用回落主站。
详情接口同样按该范围校验,避免跨站按 ID 读取。
- 维护方:**站长在分销后台「公告中心」自助维护**本站公告
(`/api/admin/distribution/announcements` + `distribution:announcement_view|manage`,
站点由 `?site_id=` 解析并校验成员权限,跨站 ID 一律视为不存在);
平台后台的公告管理可按站点筛选、并为指定分站代发。
- 权限:新站点开通时站长继承 `ops` 角色,自动获得上述权限;超管/财务同样授予,便于代管。
### 6.4 不纳入分销网的业务
以下业务不属于分销网正常订单,不进入分销订单分账:
- 平台或管理员线下提号(`admin_pickups`)。
- 平台代管账号及线下交接、线下结算。
- 撞车商品及撞车订单(`mohong`/`crash`)。
- 分销网站之外的外部导入、私下交易或人工补录订单。
分销网订单必须同时满足:订单来源站点是分销网站、卖家和租客均属于该正常订单链路、支付和订单状态在平台系统内可追踪。
## 7. 比例、费用和分账口径
### 7.1 卖出后主站提价利润的百分比分成(已确认 v0.7)
口头常说的 3.5 / 4 / 2.5,统一写成 **35% / 40% / 25%**。这是卖出完成后的主站提价利润分成,三方合计 100%。不是挂牌定价比例(不是 1:3.5 / 1:4),文档、字段、后台和代码都只写百分比,不再写「成」。
| 分成 | 角色 | 说明 |
| --- | --- | --- |
| 35% | 收号 / 上架方 | 货源归属方分得主站提价利润的 35% |
| 40% | 卖出方 | 促成订单的销售站点分得主站提价利润的 40% |
| 25% | 平台服务费 | 主站平台收取主站提价利润的 25% 服务费 |
| 合计 100% | 切完主站提价利润 | 四舍五入尾差除外,全部分配完毕 |
```text
某方提价分成 = round_half_up(主站提价利润基数 × 百分比 / 100)
```
规则字段存 `35` / `40` / `25`,计算一律 `× 百分比 / 100`。
**核心业务口径(v0.7 锁定,v0.8 修订通道手续费口径)**:
1. **号主底价本金保底**:号主应得走订单原有 `owner_rent_amount_cent`(对应 `seller_total_price`),属于履约本金,不参与任何分销分成,100% 结算给号主。
2. **分账分的是提价的部分**:分销分账的标的是**主站收号定价多出来的利润**(即 `platform_markup_amount = buyer_total_price - seller_total_price`)。该利润全额构成供三方切分的提价利润基数;**支付通道手续费由主站承担,不从基数中扣除**,只落库供对账(见 7.5)。
3. **分站自主加价溢价 100% 归分站自己**:若分站在货架上自主加价(或调比例加价),该加价溢价**完全属于卖出分站自己**,不进入 35/40/25 的三方分成池(详见 7.6 节)。
默认角色模式(可按站点、模式出新规则版本,历史订单用快照):
| 模式 | 参与方 | 初始提价分成 |
| --- | --- | --- |
| 两方-分销网收号 | 分销网收号、主站卖出 | 分销网 35%,主站 40%,服务费 25% |
| 两方-主站收号 | 分销网卖出、主站收号 | 分销网 40%,主站 35%,服务费 25% |
| 三方 | 主站服务费、分销 A 上架、分销 B 卖出 | 主站服务费 25%,分销 A 35%,分销 B 40% |
规则字段按参与方角色命名(`distributor_receive_ratio` 等)。后台文案写「35% / 40% / 25%」。
默认值必须通过迁移或初始化数据写入,不写死在结算公式里。新订单读取当前生效规则并写入快照,历史订单不跟随后台修改。
提价利润基数计算:
```text
主站提价总额 = base_price_cent - owner_rent_amount_cent (= platform_markup_amount)
有效加价 = min(shelf_markup_cent, max(净支付额 - owner_rent_amount_cent, 0))
提价利润基数 = max(净支付额 - owner_rent_amount_cent - 有效加价, 0)
```
通道手续费不进此式:由主站承担,只记录对账(见 7.5)。
### 7.2 必须确认的口径
v0.7 已锁定 7.1 的提价分成和 7.6 的分站自主加价独享。其余待确认项:
| 项目 | 状态 |
| --- | --- |
| 35% / 40% / 25% 的含义 | **已确认**:主站收号提价利润的百分比分成;口头 3.5/4/2.5 不再使用 |
| 服务费 25% | **已确认**:主站提价利润的 25%,与收号、卖出同一基数 |
| 分站自主加价归属 | **已确认**:分站自己加比例/加价多挣的钱 100% 属于分站自己,见 7.6 |
| 两方/三方角色 | **已确认**:收号/上架 35%,卖出 40%,服务费 25% |
| 利润是否扣号主、是否按结账消耗重算 | **已确认**:号主底价作为本金扣除,分账只切提价部分 |
| 分销网站收号百分比上下限 | 待确认 |
| 三方亏损承担 | 待确认 |
| 税费税基 | 待确认:各方分成后毛利,还是利润基数 |
| 退款处理 | 待确认:重算剩余分成,还是生成反向冲正流水 |
| 四舍五入尾差 | 待确认:统一归主站还是按最大分成方承担 |
### 7.3 后台调整要求
后台调整规则时必须:
1. 只允许具备 `distribution:rule_manage` 权限的管理员操作。
2. 新增规则版本,不直接覆盖已生效版本的历史内容。
3. 支持按分销网站、交易模式配置收号百分比、卖出百分比、服务费百分比、通道手续费和税费开关;三方百分比之和必须为 100。
4. 支持设置生效时间;同一站点同一模式同一时刻只能有一个生效版本。
5. 修改前展示影响范围和新旧值,确认后写入审计日志。
6. 已创建、已支付或已结算订单继续使用其规则快照。
7. 比例、费率和金额必须由后端校验范围,前端输入不能绕过校验。
### 7.4 推荐的金额模型
两套「比例」不能混用,快照里必须分开存:
```text
挂牌兑换比例:1 元 = X 万哈夫币(主站 publish_ratio / buyer_ratio)
分成百分比:35 / 40 / 25(用于提价利润切分,字段存百分数不是 3.5)
分站加价溢价:shelf_markup_cent(分站自主加价金额,独立核算)
```
最终结算全部以整数分为准。每笔订单保存:
```text
split_percent_snapshot # 各方分成 35 / 40 / 25
shelf_markup_snapshot # 分站自主加价溢价(分)
amount_snapshot
rule_version
```
建议所有金额字段使用 `*_cent BIGINT`。通道手续费、税率继续用基点 `*_bps INT`:
```text
0.5% = 50 bps
1% = 100 bps
分成 35% 存 35,计算用 × 35 / 100;不要存 3.5
```
### 7.5 通道手续费与平台服务费
支付通道手续费和平台服务费不是同一层。
通道手续费:按退款后的实际支付金额计算,费率 0.5%,四舍五入;**由主站承担,不从提价利润基数中扣除**,只落库 `payment_fee_cent` 供对账。
```text
净支付额 = 支付金额 - 成功退款金额
通道手续费 = round_half_up(净支付额 × 50 / 10000) # 主站承担,不进分成基数
主站提价总额 = base_price_cent - owner_rent_amount_cent
有效加价 = min(shelf_markup_cent, max(净支付额 - owner_rent_amount_cent, 0))
提价利润基数 = max(净支付额 - owner_rent_amount_cent - 有效加价, 0)
平台服务费 = round_half_up(提价利润基数 × 25 / 100) # 25%
收号/上架分成 = round_half_up(提价利润基数 × 35 / 100) # 35%
卖出方提价分成 = round_half_up(提价利润基数 × 40 / 100) # 40%
分站自主加价溢价 = shelf_markup_cent # 100% 独享归卖出分站
```
`payment_fee` 与 `service_fee` 必须分字段。服务费是提价利润的 25%,不是通道手续费,不是固定元,也不是 `实付/2.5`。
通道手续费由主站自行承担:平台净收益 = 提价利润基数 × 25% + 四舍五入尾差 − 通道手续费,不向其他参与方回收。
### 7.6 分站货架自主提价(分站独享溢价,已确认 v0.7)
分站货架提价是分销商根据自身经营策略自主制定的加价:
1. **加价多挣的钱属于分站自己**:
分站在货架上自主提价所产生的差价收益(`shelf_markup_cent = site_price_cent - base_price_cent`),**100% 归属于卖出该商品的分站**。
分站自主提价溢价不参与 35/40/25 切分,平台与收号方不得切分该部分收益。
2. **兑换比例与提价方向**:
- 比例语义:「1 元兑换多少万哈夫币」,`价格 = 哈夫币万数 / 比例`。
- **比例越小,1 元换到的哈夫币越少,同样币数售价越高(提价)**;反之比例越大越便宜(打折)。
- 若通过调整兑换比例加价,必须是减小兑换比例(`site_ratio = base_ratio - ratio_delta`),使得 `site_price_cent >= base_price_cent`。
- 系统支持直接按元设置加价金额(`shelf_markup_cent`),或通过减比例自动换算为加价金额。
3. **卖出分站总收入**:
$$\text{卖出分站总收入} = \text{分站自主加价溢价 (shelf\_markup\_cent)} + \text{卖出方提价分成 (40\%)}$$
约束:
1. 自主加价保存在 `distribution_site_accounts` 上,只影响该站货架和该站订单。
2. 主站挂牌价、主站订单、号主回收底价不因分站加价而变。
3. 下单时将主站基础价快照 `base_price_cent` 与分站加价快照 `shelf_markup_cent` 写入订单,历史订单不受事后调价影响。
### 7.7 税费
计划要求对分销所得利益按毛利的 1% 计税,并支持开关和可调税率;每个主体承担自己的分成税费。
推荐配置:
```text
tax_enabled
tax_rate_bps
```
推荐公式:
```text
毛利 = 该主体收入 - 该主体收号成本 - 该主体承担的费用
税额 = round_half_up(毛利 × tax_rate_bps / 10000)
```
每个主体分别计算税费,主站、分销 A、分销 B 不合并税基。毛利为负时税额暂按 0 处理,亏损如何结转:待确认。
### 7.8 账务不变量与结算恒等式(已确认 v0.7,v0.8 修订)
每笔分销订单的结算必须满足:
```text
净支付租金 (net_paid_amount_cent)
= 号主底价 (owner_rent_amount_cent)
+ 分站自主提价溢价 (shelf_markup_cent) [100% 归卖出分站]
+ 提价利润基数 (split_base_amount_cent)
通道手续费 (payment_fee_cent) 不参与上式:由主站承担,只记录对账
提价利润基数
= 收号/上架 35%
+ 卖出 40%
+ 平台服务费 25%
+ 四舍五入尾差 (rounding_adjustment_cent)
```
**各方收益结算**:
- **号主**:得到完整的 `owner_rent_amount_cent`。
- **收号方**:分得 `提价利润基数 × 35%`。
- **卖出方(分站)**:获得 `分站自主加价溢价 (shelf_markup_cent) + (提价利润基数 × 40%)`。
- **平台**:获得 `提价利润基数 × 25% + 四舍五入尾差`,并自行承担通道手续费(`payment_fee_cent` 只作记录,不从各方分成中回收)。
税费若开启,从各方分成中计,不破坏上面 100% 切完利润的关系;具体税基见 7.2。
退款、拒付、仲裁和结算撤销必须生成反向明细,不能直接覆盖原结算记录。
## 8. 建议数据模型
### 8.1 分销网站
```text
distribution_sites
```
建议字段:
```text
id, site_code, site_name, domain, status
display_account_enabled
default_support_group_id
tax_enabled, tax_rate_bps
created_at, updated_at
```
### 8.2 成员关系
```text
distribution_site_members
```
```text
id, site_id, admin_user_id, member_type, status, data_scope
created_at, updated_at
```
### 8.3 账号展示关系
```text
distribution_site_accounts
```
```text
id, site_id, account_id, listing_id, display_status
shelf_ratio_delta # 该站加价:增加的 1 元兑换哈夫币比例点数,不是人民币
display_started_at, display_ended_at
created_at, updated_at
```
### 8.4 规则版本
```text
distribution_rules
distribution_rule_versions
```
规则需要保存:
```text
site_id
mode: two_party / three_party
platform_receive_ratio # 百分比,默认 35
platform_sell_ratio # 百分比,默认 40
distributor_receive_ratio # 百分比,默认 35
distributor_sell_ratio # 百分比,默认 40
distributor_a_ratio # 百分比,默认 35
distributor_b_ratio # 百分比,默认 40
service_fee_value # 百分比,默认 25
service_fee_unit: percent # 只表示百分数;禁止 fixed_amount / 金额÷value
payment_fee_bps
tax_enabled
tax_rate_bps
effective_from, effective_to
version, status
```
同一规则里收号 + 卖出 + 服务费必须等于 100。首批默认规则按第 7.1 节初始化:
```text
two_party_distributor_receive: distributor_receive_ratio=35, platform_sell_ratio=40, service_fee_value=25
two_party_platform_receive: platform_receive_ratio=35, distributor_sell_ratio=40, service_fee_value=25
three_party: distributor_a_ratio=35, distributor_b_ratio=40, service_fee_value=25
```
字段按参与方角色命名。库里存百分数 35 / 40 / 25,计算一律 `× 百分比 / 100`。已写入的 3.5 / 4 / 2.5 不能当百分数用,迁移时换算成 35 / 40 / 25。默认规则必须通过迁移或初始化数据写入,不写死在结算代码中。
### 8.5 订单参与方
```text
distribution_order_parties
```
```text
order_id, site_id, party_role, user_id
ratio, base_amount_cent, markup_amount_cent
gross_amount_cent, fee_amount_cent, tax_amount_cent
net_amount_cent, status
```
`party_role` 建议支持:
```text
platform
distributor_a
distributor_b
distributor_receive
seller
buyer
```
### 8.6 订单财务快照
```text
distribution_order_financials
```
```text
order_id UNIQUE
gross_paid_amount_cent
refund_amount_cent
net_paid_amount_cent
payment_fee_bps, payment_fee_cent
service_fee_bps, service_fee_cent
markup_amount_cent
tax_enabled, tax_rate_bps, tax_amount_cent
split_base_amount_cent
settlement_status
rule_version
created_at, settled_at
```
### 8.7 结算批次和明细
```text
distribution_settlements
distribution_settlement_items
```
结算批次保存周期、状态、审核人、付款时间和失败原因;明细保存每个站点、参与方、收入、成本、毛利、手续费、税费和钱包流水关联。
### 8.8 支付配置绑定
```text
distribution_site_payment_configs
```
一个分销网站可以绑定一个或多个现有 `payment_merchant_configs`。支付下单时保存 `site_id` 和 `payment_config_id` 快照,回调不重新依赖当前配置。
### 8.9 二维码和客服组
建议给二维码池或关联表增加:
```text
distribution_site_id
support_group_id
```
取码优先匹配“分销网站 + 客服组”的专属二维码池。站点已配置专属池时,不回退到其他站点二维码。
## 9. API 规划
### 9.1 平台管理员
```text
GET /api/admin/distribution/sites
POST /api/admin/distribution/sites
GET /api/admin/distribution/sites/:id
PUT /api/admin/distribution/sites/:id
POST /api/admin/distribution/sites/:id/enable
POST /api/admin/distribution/sites/:id/disable
GET /api/admin/distribution/sold-orders
GET /api/admin/distribution/sold-orders/:id
GET /api/admin/distribution/receive-orders
GET /api/admin/distribution/receive-orders/:id
GET /api/admin/distribution/rules
POST /api/admin/distribution/rules
PUT /api/admin/distribution/rules/:id
GET /api/admin/distribution/settlements
GET /api/admin/distribution/settlements/:id
POST /api/admin/distribution/settlements/:id/approve
POST /api/admin/distribution/settlements/:id/reject
GET /api/admin/distribution/reports/summary
GET /api/admin/distribution/reports/orders
GET /api/admin/distribution/reports/finance
```
### 9.2 分销网站成员
```text
GET /api/admin/distribution/me
GET /api/admin/distribution/orders
GET /api/admin/distribution/orders/:id
GET /api/admin/distribution/receive-orders
GET /api/admin/distribution/chats
GET /api/admin/distribution/chats/:id/messages
POST /api/admin/distribution/chats/:id/messages
```
同一套后端接口通过成员关系限制 `site_id`。平台管理员可以显式选择站点或查看全部;分销成员不能自行传入其他站点 ID。
## 10. 支付和域名上下文
生产环境建议通过请求 Host 解析分销网站:
```text
请求域名 -> 服务端解析 site_id -> 校验站点状态 -> 选择绑定支付配置
```
开发环境可以临时使用 `site_code`,但生产支付下单不能完全信任前端提交的站点参数。
支付配置选择规则:
1. 只读取当前站点启用的支付配置。
2. 支持一个或多个配置,按优先级或健康状态选择。
3. 支付单保存站点和支付配置快照。
4. 回调、查询和退款使用支付单快照,不因后台配置变更而切换通道。
## 11. 独立前端工程
建议目录:
```text
distribution-admin/
├── package.json
├── vite.config.ts
├── tsconfig.json
├── Dockerfile
└── src/
├── main.tsx
├── router/
├── layouts/
├── stores/
├── services/
├── types/
└── features/
├── dashboard/
├── sites/
├── sold-orders/
├── receive-orders/
├── settlements/
├── payment-configs/
├── qrcodes/
├── chats/
└── reports/
```
建议继续复用现有 API 响应格式:
```json
{
"code": "ok",
"message": "ok",
"data": {}
}
```
独立后台第一阶段可复用现有管理员登录接口和 HttpOnly Cookie,但不与现有前端共享 localStorage。是否建设分销员独立登录:待确认;如果分销员不是平台管理员,应新增独立主体和认证体系。
## 12. 部署方案
新增独立前端构建单元:
```text
distribution-admin/Dockerfile
```
Caddy 增加独立子域名站点。子域名名称暂定,最终以 DNS、证书和运营规划确认的名称为准:
```text
distribution.hao858.com {
handle /api/* {
reverse_proxy backend:8080
}
handle {
root * /srv/distribution-admin
try_files {path} /index.html
file_server
}
}
```
主站、现有运营后台和分销后台分别构建、分别发布。数据库迁移仍由现有生产发布流程执行,后端和前端发布需要保持兼容窗口。
## 13. 实施阶段
### 阶段 0:确认业务口径
- ~~确认 3.5、4、2.5 的单位和方向。~~ **已确认(v0.6)**:卖出后利润分成 35% / 40% / 25%,文档与字段只写百分比。
- ~~确认加价形态。~~ **已确认(v0.6)**:分站加价增加该站「1 元兑换哈夫币」比例,不是叠加人民币。
- 确认两方、三方亏损承担。
- 确认结账后利润是否按实际消耗重切。
- 确认税费毛利计算口径。
- 确认退款采用重算还是冲正。
- 确认分销员和分销客服的身份模型。
- 确认账号是否允许多站点展示。
### 阶段 1:数据库和计算引擎
新增 Goose 迁移,建议从 `000062_distribution_init.sql` 开始,包含站点、成员、展示关系、默认规则版本、订单参与方、财务快照、结算、支付绑定、二维码绑定和权限初始化。默认分账值先按第 7.1 节写入,后续通过后台规则页面调整。
先完成纯函数计算和单元测试,不接真实订单。
### 阶段 2:订单生命周期接入
接入:
```text
支付成功
退款成功
订单完成
订单仲裁
订单取消
```
要求支付回调、退款回调、订单完成和结算操作幂等;规则修改不影响已有订单;钱包流水和分销结算明细金额一致。
### 阶段 3:后台 API
完成站点、售出订单、正常订单收号记录、比例规则、结算、支付通道、二维码客服和账号展示接口,并补齐站点数据隔离测试。
### 阶段 4:Ant Design 前端
开发顺序:登录和权限、仪表盘、售出订单、正常订单收号记录、站点配置、规则、结算、支付、客服二维码、报表。
### 阶段 5:独立生产部署
接入独立子域名、DNS、Caddy 配置、前端镜像和发布脚本,完成健康检查、登录、订单查询、支付配置和客服消息冒烟测试。
## 14. 测试和验收标准
### 权限隔离
- 分销网站 A 不能查询分销网站 B。
- 分销客服不能修改比例、支付配置、订单状态和结算。
- 主站财务可查看全部站点资金数据。
- 超级管理员可管理全部站点。
### 账务正确性
- 通道手续费按退款后的实际支付金额计算,0.5%,四舍五入,以分保存。
- 号主应得先扣,得到利润基数后再切 35% / 40% / 25%;通道手续费由主站承担,不计入利润基数。
- 收号 35%、卖出 40%、服务费 25%;字段存 35/40/25,禁止存 3.5/4/2.5 再当百分数乘。
- 分站加价改该站 1 元兑换哈夫币比例,不叠加人民币;历史订单用下单时的比例快照。
- 各主体独立计算税费。
- 重复支付、退款和结算请求不会重复入账。
- 分销结算明细与钱包流水一致。
- 同一订单同一参与方只允许一条结算明细(唯一键 `uk_distribution_settlement_item_party`):自动释放与手工批次并发时以唯一键冲突为准跳过该参与方,不重复入账。
- 订单累计退款额取「本次回调金额与已退款成功流水合计」的较大值,多笔退款与退款结果重复回调都不会把口径写小;分销重算与仲裁回冲均按此累计额计算。
- 关单(`AdminClose` / `AdminSeal` / `AdminRejectRefund` 的 close 分支)属于可释放终态,会补写 `release_at`,避免不退款关单的订单永远不被自动结算。
### 业务正确性
- 售出订单和正常订单收号记录均可查询。
- 线下提号、平台代管和撞车订单不会进入分销订单列表或分账。
- 账号关闭展示后不影响历史订单。
- 规则修改只影响新订单。
- 支付只使用当前分销网站绑定的通道。
- 分销网站使用指定客服组和二维码池。
- 客服消息按站点隔离。
### 发布标准
- `./scripts/check.sh` 通过。
- 新迁移具备 Up/Down 并通过 SQL 门禁。
- 金额、退款、分账、税费和状态机变更包含回归测试。
- 生产环境完成独立域名、后台登录、订单查询和支付配置冒烟验证。
## 15. 待确认清单
以下问题确认后,更新本文档版本并进入详细表结构和 API 契约设计:
1. 分销网站是平台合作方,还是普通用户下的分销身份?
2. 分销客服是否使用现有 `admin_users`?
3. ~~3.5、4、2.5 的确切单位和计算方向是什么?~~ **已确认**:利润分成 35% / 40% / 25%,只写百分比,见 7.1。
4. ~~服务费和支付手续费是否都按实际支付净额计算?~~ **已确认**:通道手续费按实付净额 0.5%;服务费是利润的 25%。
5. ~~加价是否计入服务费、税费和退款基数?~~ **已确认加价形态**:改兑换比例,不是人民币;利润仍按 7.1 切 35% / 40% / 25%。
6. 税费是否只对正毛利计提?亏损是否结转?
7. 退款后佣金是重算剩余金额,还是追加负向冲正?
8. 一个账号能否同时展示在多个分销网站?
9. 分销后台子域名最终使用哪个名称(当前暂定 `distribution.hao858.com`)?
10. 分销网站是否需要独立登录入口和独立账号体系?
11. 分销网站是否能查看完整账号登录资料?
---
后续每次确认业务规则后,优先更新第 7、15 节,再同步更新第 8、9、13、14 节,确保规则、数据、接口、实施和验收标准保持一致。
## 16. 当前实现基线(v0.8)
本分支已落地第一批可运行功能,主站域名为 `https://hao858.com/`,独立后台工程位于 `distribution-admin/`,子域名暂定 `https://distribution.hao858.com/`:
- Go 后端已实现 `distribution_sites`、成员、账号货架、规则版本、订单财务快照、订单参与方、结算批次/明细、支付通道绑定表。
- `rental_orders` 增加分销站点、模式和规则版本字段,并具备 `base_price_cent`(主站基准价)与 `shelf_markup_cent`(分站自主加价溢价)快照。
- 分账计算引擎与口径全面对齐 v0.8:
1. 利润分成百分比使用 35%(收号/上架)、40%(卖出方)、25%(平台服务费);
2. 号主底价成本(`owner_rent_amount_cent`)保底归号主,不参与任何分成;
3. 分账标的为主站收号提价利润(`platform_markup_amount = base_price - owner_rent`),全额按 35/40/25 切分;通道手续费由主站承担,不从基数中扣除;
4. 分站货架自主提价溢价(`shelf_markup_cent`)100% 独享归卖方分站,不参与三方切分;
5. 兑换比例提价语义明确(比例越小售价越高,提价使分站售价增加)。
- 管理 API 覆盖站点、规则、售出/收号订单查询、财务快照、账号展示开关、支付通道绑定和结算批次。
- 货架铺货与展示口径(详见 6.3.1):商品变为 `published + approved` 时自动铺到所有开启自动展示的站点货架,
不再依赖站长手动同步;`distribution_site_accounts.display_disabled_by` 记录下架来源,自动铺货不覆盖站长人工下架;
`clean_stale_listings` 只清理商品记录已删除的孤儿货架行。
- 生产与测试口径一致:结算批次入账、站点提现与冷却期自动释放不再按 `APP_ENV` 冻结(原 `liveMoneyMovementEnabled` 生产保护已移除)。
- 新建站点的默认结算冷却天数由系统配置 `distribution.default_settlement_hold_days` 统一控制(默认 7 天,0=立即释放,最大 365),管理端可在系统配置页调整;站点级 `settlement_hold_days` 仍可单独覆盖。
- `distribution-admin` 基于 React + TypeScript + Vite + Ant Design,覆盖经营大盘、双视图资产管理、选品货架、订单中心、品牌装修与钱包明细。
- 分站前台统一按「一手独立商城」呈现:不向顾客暴露分销身份(无「官方分销」标识),
登录/注册页与首页品牌区的站名、Logo 均取自站点配置。
- 公告中心按站点隔离并可自定义(详见 6.3.2):`announcements.distribution_site_id` + 站点 `announcement_mode`
(`inherit` 继承主站+本站 / `own_only` 仅本站),站长在分销后台自助维护本站公告。
- 首页文案支持站长自定义:`distribution_sites.storefront_text_json`
(`tagline` 头部副标题 / `hero_badge` 主视觉徽标 / `hero_desc` 主视觉描述 / `card_sub` 移动端卡片副标题),
在分销后台「品牌装修 → 首页文案」编辑;字段留空或整段为空时回落到前台内置默认文案。