公告中心(前台公告列表/详情)此前完全没有站点概念,分站访客只能看到主站公告。 本次按「默认继承主站、站长可切仅本站」的口径支持分站自定义。 数据与口径: - 新增 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 与跨站防护、公告来源开关校验与非法值容错
893 lines
38 KiB
Markdown
893 lines
38 KiB
Markdown
# 分销网管理后台设计方案
|
||
|
||
> 状态:草案 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` 移动端卡片副标题),
|
||
在分销后台「品牌装修 → 首页文案」编辑;字段留空或整段为空时回落到前台内置默认文案。
|