Procházet zdrojové kódy

文档:净亏邀请记录说明并入后台接口

记录名单、中文列名与获券展示并入《净亏邀请-后台接口》“记录查询”一节,
删除单独的记录说明;交付副本同步券包已使用券不显示的变更,更新目录、清单与校验值。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
doge před 21 hodinami
rodič
revize
0f8ffbda5f

+ 3 - 2
docs/前端交付/README.md

@@ -4,8 +4,9 @@
 
 ## 记录列表展示增补(2026-11-02)
 
-- [净亏邀请记录-中文字段与名单展示](bot-28/后台/独立活动/净亏邀请记录-中文字段与名单展示.md):给管理后台前端,包含新增返回字段、两类记录的中文标签、ID/账号及获券的列表展示方式。
-- 本次新增 1 份独立说明,当前来源文件合计 24 份;下方旧批次范围保留。
+- [净亏邀请-后台接口](bot-28/后台/独立活动/净亏邀请-后台接口.md):配置表单与记录合并为一份完整文档。“记录查询”一节包含申请、发奖、已发优惠券三个列表的中文列名,以及新增的奖励方式、邀请人与被邀请人 ID/账号、获券档位和张数。原单独的《净亏邀请记录-中文字段与名单展示》已并入,不再单独发送。
+- [优惠券券包-会员接口](melbet_sport-api/前台/独立活动/优惠券券包-会员接口.md):已使用的券不再出现在“不可用”列表和数量中。
+- 合并后当前来源文件合计 23 份;下方旧批次范围保留。
 
 ## 2026-10-31 增补
 

+ 1 - 2
docs/前端交付/bot-28/后台/README.md

@@ -4,13 +4,12 @@
 
 | 功能 | 文档 |
 |---|---|
-| 净亏邀请:记录中文、邀请人与被邀请人账号及获券 | [净亏邀请记录-中文字段与名单展示](独立活动/净亏邀请记录-中文字段与名单展示.md) |
 | 实时推送:Laravel Echo + Reverb、频道授权、表格更新、断线补发(2026-10-31 增补) | [后台实时推送-前端接入](后台实时推送-前端接入.md) |
 | 公告:多语言、展示平台、发布时段、启停和日志 | [公告系统-后台接口](公告系统-后台接口.md) |
 | 信息:发送对象、多语言、定时发送、撤回和日志 | [信息管理-后台接口](信息管理-后台接口.md) |
 | 维护:整站与游戏分类、平台、时区、起止时间、开关和日志 | [整站与游戏维护-后台接口](整站与游戏维护-后台接口.md) |
 | 三个独立活动的公共约定和目录 | [独立活动-后台接口](独立活动-后台接口.md) |
-| 净亏邀请配置与记录 | [净亏邀请-后台接口](独立活动/净亏邀请-后台接口.md) |
+| 净亏邀请:平铺配置表单、现金/优惠券模式、申请/发奖/已发券记录(含中文列名、名单与获券) | [净亏邀请-后台接口](独立活动/净亏邀请-后台接口.md) |
 | 首充奖励配置与记录 | [首充奖励-后台接口](独立活动/首充奖励-后台接口.md) |
 | 转盘任务、概率配置与记录 | [转盘活动-后台接口](独立活动/转盘活动-后台接口.md) |
 | 报表页面修正:移除三个入口,统一有效会员条件 | [报表页面调整-移除三个入口](报表页面调整-移除三个入口.md) |

+ 1 - 1
docs/前端交付/bot-28/后台/独立活动-后台接口.md

@@ -12,4 +12,4 @@
 
 新增按钮与新增类型下拉使用 `GET /admin/promotion/options` 返回的 `create_types`,当前只有首充奖励(`value=8`)。`types` 仍提供三种类型用于筛选。固定活动从列表读取现有 `id` 后编辑保存;净亏邀请改为单页平铺表单,直接用 `GET /admin/promotion/detail?type=7` 读取,不再经过列表。
 
-申请记录、发奖记录的中文标签、被邀请人账号及获券列表接入见[净亏邀请记录-中文字段与名单展示](独立活动/净亏邀请记录-中文字段与名单展示.md)。
+净亏邀请的申请记录、发奖记录、已发优惠券(中文列名、邀请人与被邀请人账号及获券)已并入[净亏邀请-后台接口](独立活动/净亏邀请-后台接口.md)的“记录查询”一节。

+ 178 - 13
docs/前端交付/bot-28/后台/独立活动/净亏邀请-后台接口.md

@@ -160,25 +160,190 @@
    - 奖励记录 `amount` 为本次发出的券抵扣总额,状态为 `paid`;记录页直接展示,会员钱包不增加现金。
 7. 券只能在 F1 自有游戏(F1体育、F1彩票)下注时使用;退款后的可用状态以券包接口返回为准。
 
-## 参与、发奖与优惠券记录
+## 记录查询:申请、发奖、已发优惠券
 
-`GET /admin/promotion/records?activity_id=1&kind=accounts&page=1&limit=20` 查看申请记录,`kind=rewards` 查看奖金,可追加会员 ID `user_id`(使用会员列表返回的 `id`)。返回 `total/data`。
+记录区为只读展示,返回的字段不要提交给保存接口。三个列表共用一个接口,`activity_id` 取 `detail` 返回的 `id`。申请记录 ID 和发奖记录 ID 都不是活动 ID。
 
-申请记录包含 `applied_at/application_snapshot`;奖金有 `reserved/locked/paid` 状态和资金流水关联(优惠券模式无流水)。没有有效申请前不允许领奖,重复领取不会重复入账或发券。停止活动使用下架,不删除参与历史。
+| 页签 | 请求 |
+|---|---|
+| 申请记录 | `GET /admin/promotion/records?activity_id=1&kind=accounts&page=1&limit=20` |
+| 发奖记录 | `GET /admin/promotion/records?activity_id=1&kind=rewards&page=1&limit=20` |
+| 已发优惠券 | `GET /admin/promotion/records?activity_id=1&kind=coupons&page=1&limit=20` |
+
+- 返回:成功 `code=0`,列表在 `data.data`,总数在 `data.total`。总数按申请或发奖记录计算,不是被邀请人数或券张数。
+- `limit` 最大 100。
+- `user_id` 按会员筛选,取会员列表返回的 `id`:
+  - 申请、发奖列表:筛选该邀请人。
+  - 已发券列表:匹配持券人或邀请人。
+- `status=unused/used` 仅已发券列表支持。申请、发奖列表不提供奖励状态筛选。
+
+所有列名使用中文,嵌套对象和 JSON 字段不要按原文渲染。会员 ID 与账号按文本展示,不套用金额格式,保留账号可能有的前导零。
+
+### 申请记录 `kind=accounts`
+
+| 字段 | 中文列名 | 展示建议 |
+|---|---|---|
+| id | 申请记录 ID | 显示 |
+| activity_id | 活动 ID | 可隐藏(页面已在本活动内) |
+| user_id | 申请会员 ID | 与 `inviter.account` 合并显示为"ID / 账号" |
+| round_no | 参与轮次 | 固定为 1,隐藏 |
+| spins | 剩余抽奖次数 | 转盘专用,隐藏 |
+| applied_at | 申请时间 | 为空时显示"未申请" |
+| application_snapshot | 申请时规则 | 按下方摘要展示,不显示原始 JSON |
+| reward_mode | 奖励方式 | `cash` 现金 / `coupon` 优惠券;`null` 显示"—" |
+| reward_id | 关联发奖记录 ID | 未发奖时为 `null`,显示"—" |
+| reward_status | 发奖状态 | 枚举同发奖记录 `status`;`null` 显示"暂无发奖记录" |
+| inviter / invitees | 邀请人、被邀请人及获券 | 见下方[名单与获券](#名单与获券申请发奖共用) |
+| created_at / updated_at | 创建时间 / 更新时间 | 显示 |
+
+`application_snapshot` 目前是 JSON 字符串,先解析再展示,也要兼容已是对象的情况:
+
+| 解析后字段 | 中文名称 |
+|---|---|
+| loss | 申请时净亏 |
+| from | 统计开始时间 |
+| rules.loss_amount | 申请所需净亏 |
+| rules.invite_count | 需邀请有效会员数 |
+| rules.reward_amount | 现金奖励金额 / 邀请人券总额上限,按奖励方式显示 |
+| rules.turnover_ratio | 解冻投注倍数,仅现金模式展示 |
+
+摘要示例:"申请时净亏 550、申请门槛 500、需邀请 3 人、现金奖励 500"。`policy`、`invite_user_cursor` 为内部核对字段,不展示。
+
+### 发奖记录 `kind=rewards`
 
-`kind=coupons` 查看已发优惠券,可加 `user_id`(匹配持券人或邀请人)和 `status=unused/used`:
+| 字段 | 中文列名 | 展示建议 |
+|---|---|---|
+| id | 发奖记录 ID | 显示 |
+| activity_id | 活动 ID | 可隐藏 |
+| user_id | 领奖会员 ID(邀请人) | 与 `inviter.account` 合并显示 |
+| account_id | 关联申请记录 ID | 对应申请记录的 `id` |
+| round_no | 发奖轮次 | 固定为 1,隐藏 |
+| amount | 现金奖励金额 / 优惠券抵扣总额 | 列名随本行 `reward_mode` 切换 |
+| required_flow | 解冻所需有效投注额 | 现金模式为 0 时显示"无需解冻";券模式隐藏 |
+| status | 发奖状态 | 见下表 |
+| credited_log_id | 奖励入账流水 ID | 券模式隐藏;无值显示"—" |
+| unlocked_log_id | 解冻流水 ID | 无值显示"—" |
+| unlocked_at | 解冻时间 | 无值显示"—" |
+| rule_snapshot | 发奖时规则 | 不显示原始 JSON;名单和获券使用新增字段 |
+| flow_snapshot | 流水统计快照 | 内部字段,隐藏 |
+| reward_mode | 奖励方式 | 同申请记录 |
+| inviter / invitees | 邀请人、被邀请人及获券 | 见下方名单与获券 |
+| created_at / updated_at | 创建时间 / 更新时间 | 显示;`created_at` 不要改称"实际发奖时间" |
+
+| status / reward_status | 中文 |
+|---|---|
+| reserved | 待发放 |
+| locked | 待解冻(已入冻结余额) |
+| paid | 已发放 |
+
+即使金额为 0 或无需解冻,也按 `status` 展示状态,不要当作已发放。每名会员只能领取一次,重复领取不会重复入账或发券。停止活动用下架,参与历史不会删除。
+
+### 名单与获券(申请、发奖共用)
+
+净亏邀请(类型 7)的申请、发奖记录每行附带下面这组名单字段,其他活动类型不返回:
 
 | 字段 | 含义 |
 |---|---|
-| id / activity_id / reward_id | 券ID、活动、来源奖励记录 |
-| user_id / member_id | 持券会员 |
-| role | `inviter` 邀请人券 / `invitee` 被邀请人券 |
-| inviter_user_id | 发起邀请的会员 |
-| min_amount / discount | 使用门槛、抵扣金额 |
-| categories | 可用游戏数组 |
-| valid_from / valid_until | 可用时间 |
-| status | `unused` 未使用 / `used` 已使用 |
-| used_source / used_stake / used_at | 使用的注单类型、下注毛额、使用时间 |
+| inviter.id / inviter.account | 邀请人会员 ID / 账号 |
+| inviter.coupons | 邀请人本次获得的券 |
+| invitees[] | 本次关联的被邀请人,每项 `id / account / coupons` |
+
+`coupons` 为数组,按档位合并,每项字段如下:
+
+| 字段 | 中文名称 | 类型 |
+|---|---|---|
+| min_amount | 使用门槛 | 金额字符串 |
+| discount | 抵扣金额 | 金额字符串 |
+| quantity | 本次发放张数 | 整数 |
+
+建议在申请、发奖两个列表中都增加以下列:
+
+| 列名 | 展示示例 |
+|---|---|
+| 奖励方式 | 现金 / 优惠券 |
+| 邀请人(ID / 账号) | `164 / demo164` |
+| 邀请人获得的券 | `满100抵50 × 2张;满200抵100 × 1张` |
+| 被邀请人及获券 | 每人一行:`168 / demo168:满100抵100 × 1张` |
+
+各情况的展示:
+
+| 情况 | 返回 | 显示 |
+|---|---|---|
+| 现金记录 | `invitees` 为发奖时达标的会员,双方 `coupons=[]` | 列出名单,获券显示"本次未发券";不要把被邀请人显示成现金收款人 |
+| 优惠券记录 | `invitees` 为本次计入发券的会员 | 列出每人账号与获券 |
+| 尚未发奖的申请 | `reward_id=null`、`reward_status=null`、`invitees=[]` | 显示"尚未生成发奖名单"(不代表没有下级或邀请数为 0) |
+| 账号未设置或会员已删除 | `account=null`,ID 保留 | 账号显示"—" |
+| 被邀请人未配置券 | 该人 `coupons=[]` | 显示"本次未发券" |
+
+- 会员 ID 对应记录的 `user_id`,不是会员编号 `member_id`。
+- 账号取会员当前账号,不是发奖时的快照。
+- `quantity` 是实际发出的张数,券已使用或已过期仍计入,不等于当前可用张数。
+- 每行只包含这笔发奖的券。获券摘要直接用本行数据,不要用"已发优惠券"分页数据拼总数,也不要按活动当前配置推算档位。
+- 历史记录缺少奖励方式时按现金兼容,不要用活动当前配置覆盖旧记录的奖励方式和券档位。
+
+优惠券模式发奖记录示例(账号为示例值):
+
+```json
+{
+  "code": 0,
+  "data": {
+    "total": 1,
+    "data": [
+      {
+        "id": 3003,
+        "activity_id": 1,
+        "user_id": 164,
+        "account_id": 20001,
+        "amount": "500",
+        "status": "paid",
+        "reward_mode": "coupon",
+        "inviter": {
+          "id": 164,
+          "account": "demo164",
+          "coupons": [
+            {"min_amount": "100", "discount": "50", "quantity": 2},
+            {"min_amount": "200", "discount": "100", "quantity": 1}
+          ]
+        },
+        "invitees": [
+          {"id": 168, "account": "demo168", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]},
+          {"id": 169, "account": "demo169", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]},
+          {"id": 170, "account": "demo170", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]}
+        ]
+      }
+    ]
+  }
+}
+```
+
+### 已发优惠券 `kind=coupons`
+
+每行是一张券:
+
+| 字段 | 中文名称 |
+|---|---|
+| id | 券 ID |
+| activity_id / reward_id | 活动 ID / 来源发奖记录 ID |
+| user_id / account | 持券会员 ID / 账号 |
+| member_id | 持券会员编号(内部关联用,可隐藏) |
+| inviter_user_id / inviter_account | 邀请人 ID / 账号 |
+| role | `inviter` 邀请人奖励券 / `invitee` 被邀请人奖励券 |
+| seq | 发放序号,内部字段,隐藏 |
+| min_amount / discount | 使用门槛 / 抵扣金额,显示为"满 X 抵 Y" |
+| categories | 可用游戏:`self:sport` F1体育、`self:lottery` F1彩票 |
+| valid_from / valid_until | 可用时间(UTC+8) |
+| status | `unused` 未使用 / `used` 已使用;未使用不代表仍在可用时间内 |
+| used_source | 使用的注单类型:`sport_order` 体育、`sport_game_order` 足球小游戏、`lhc_order` 彩票 |
+| used_stake / used_at | 使用时的下注金额 / 使用时间;未使用为空,显示"—" |
+| created_at / updated_at | 发放时间 / 更新时间 |
+
+### 记录页验收
+
+- 列名全为中文;不展示 `spins`、固定轮次和内部快照字段。
+- 现金记录显示邀请人和达标会员的 ID、账号,获券显示"本次未发券"。
+- 优惠券记录在同一行显示邀请人和每名被邀请人的 ID、账号、满减档位和张数。
+- 未发奖的申请显示"尚未生成发奖名单";账号缺失显示"—",保留会员 ID。
+- 券使用或过期后,记录页获得张数不变;分页总数仍为主记录数。
 
 ## 权限
 

+ 0 - 197
docs/前端交付/bot-28/后台/独立活动/净亏邀请记录-中文字段与名单展示.md

@@ -1,197 +0,0 @@
-# 净亏邀请记录:中文字段、被邀请人及获券展示
-
-面向**管理后台前端**,用于改造“申请记录”“发奖记录”和“已发优惠券”列表及详情。本次沿用现有接口,增加名单、账号和获券展示数据;不补发历史奖励。
-
-记录页面为只读展示,新增字段不要提交给活动配置保存接口。
-
-## 1. 现有截图中的三个人在哪里
-
-截图发奖记录 `id=3`、领奖会员 `user_id=164`、关联申请 `account_id=11865`。其规则中有 `qualified_invitees=[168,169,170]`,这就是发奖时达标的三名会员。
-
-这条历史记录的规则未指定优惠券模式,按兼容规则属于**现金奖励**,并有奖励入账流水 `credited_log_id=20800`。500 是邀请人 164 的现金奖励。三名被邀请人用于满足领取条件,这条记录没有给他们发券。
-
-更新接口后,前端直接使用新增的 `inviter`、`invitees` 显示 ID、账号和各自获券,无需再从规则快照解析名单或逐人查询账号。
-
-## 2. 请求和返回位置
-
-在 bot-28 后台 API 主机请求,沿用管理员请求头 `Authorization: Bearer <token>`。
-
-| 页面 | 请求 |
-| --- | --- |
-| 申请记录 | `GET /admin/promotion/records?activity_id=1&kind=accounts&page=1&limit=20` |
-| 发奖记录 | `GET /admin/promotion/records?activity_id=1&kind=rewards&page=1&limit=20` |
-| 已发优惠券 | `GET /admin/promotion/records?activity_id=1&kind=coupons&page=1&limit=20` |
-
-成功 `code=0`,列表位于 `data.data`,总记录数位于 `data.total`;失败展示 `msg`。可传 `user_id`:申请、发奖列表筛选该邀请人;已发券列表匹配持券人或邀请人。`limit` 最大 100。
-
-示例中的 `activity_id=1` 替换为当前页面的活动 ID。申请记录 ID、发奖记录 ID 均不是活动 ID;记录详情使用本行返回数据展开。
-
-只有已发优惠券列表支持 `status=unused/used` 筛选。申请、发奖列表暂不提供奖励状态筛选参数。
-
-下述申请、发奖列表新增字段用于净亏邀请(活动类型 `7`),不改变原分页、筛选和原有字段。其他活动类型不增加这组名单字段。
-
-## 3. 新增字段及列表列名
-
-| 返回字段 | 中文名称 / 用法 |
-| --- | --- |
-| `reward_mode` | 奖励方式:`cash` 现金、`coupon` 优惠券;尚无规则时为 `null`,显示“—” |
-| `inviter.id` | 邀请人会员 ID;申请列表可标“申请会员 ID”,发奖列表可标“领奖会员 ID” |
-| `inviter.account` | 邀请人账号 |
-| `inviter.coupons` | 邀请人本次获得的券,按满减档位合并 |
-| `invitees` | 本次关联的被邀请人列表 |
-| `invitees[].id` | 被邀请人会员 ID |
-| `invitees[].account` | 被邀请人账号 |
-| `invitees[].coupons` | 该被邀请人本次获得的券,按满减档位合并 |
-| `reward_id` | 仅申请记录新增:关联发奖记录 ID;未生成发奖记录时为 `null` |
-| `reward_status` | 仅申请记录新增:关联发奖状态;未生成时为 `null`,其余枚举同发奖记录的 `status` |
-
-建议两张列表都增加以下列,不要把嵌套对象直接渲染成原始 JSON:
-
-| 列名 | 展示示例 |
-| --- | --- |
-| 邀请人(ID / 账号) | `164 / demo164` |
-| 邀请人获得的券 | `满100抵50 × 2张;满200抵100 × 1张` |
-| 被邀请人及获券 | 每人一行,例如 `168 / demo168:满100抵100 × 1张`,其余会员继续列出 |
-| 奖励方式 | 现金 / 优惠券 |
-
-现金记录也返回达标会员的 ID 和账号,但双方 `coupons=[]`,显示“本次未发券”。不要把三名达标会员渲染成三笔现金收款记录。
-
-尚未发奖的申请返回 `reward_id=null`、`reward_status=null`、`invitees=[]`,显示“尚未生成发奖名单”。这不表示没有下级,也不表示当前有效邀请人数为 0;这里展示的是与发奖记录关联的历史名单,不是实时邀请进度。
-
-账号取当前可查询的会员账号,不是发奖时的账号快照。账号未设置或会员记录已不存在时,ID 仍保留,`account=null`,显示“—”。这里的会员 ID 对应原记录的 `user_id`,不要当成会员编号 `member_id`。
-
-## 4. 获券数组格式
-
-`inviter.coupons` 和 `invitees[].coupons` 中的每一项:
-
-| 字段 | 中文名称 | 类型 |
-| --- | --- | --- |
-| `min_amount` | 使用门槛 | 金额字符串 |
-| `discount` | 抵扣金额 | 金额字符串 |
-| `quantity` | 本次发放张数 | 整数 |
-
-前端显示“满 `min_amount` 抵 `discount` × `quantity` 张”。金额沿用活动接口的展示格式:整数不带 `.00`,有小数时保留两位。会员 ID 和账号不套用金额格式;账号按文本展示,保留可能存在的前导零。
-
-数量来自实际发出的券,已使用、已过期的券仍计入**获得张数**。不要把它当成当前可用张数,也不要根据活动当前配置自行生成券档位。没有给被邀请人配置券或该人未获券时,其 `coupons` 为空。
-
-现金记录展示发奖时的达标名单;优惠券记录展示本次计入发券的名单,并包含实际获券人。历史快照中其他达标会员不自动变成本次收券人。
-
-以下为优惠券模式的响应片段,仅演示结构;账号为示例,**不代表截图中的历史现金记录被改成了券奖励**:
-
-```json
-{
-  "code": 0,
-  "data": {
-    "total": 1,
-    "data": [
-      {
-        "id": 3003,
-        "activity_id": 1,
-        "user_id": 164,
-        "account_id": 20001,
-        "amount": "500",
-        "status": "paid",
-        "reward_mode": "coupon",
-        "inviter": {
-          "id": 164,
-          "account": "demo164",
-          "coupons": [
-            {"min_amount": "100", "discount": "50", "quantity": 2},
-            {"min_amount": "200", "discount": "100", "quantity": 1}
-          ]
-        },
-        "invitees": [
-          {"id": 168, "account": "demo168", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]},
-          {"id": 169, "account": "demo169", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]},
-          {"id": 170, "account": "demo170", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]}
-        ]
-      }
-    ]
-  }
-}
-```
-
-列表总数仍是申请或发奖记录数,不是被邀请人人数或券张数。每条记录只展示属于这笔发奖的券,不会混入该会员其他发奖记录的券。
-
-## 5. 申请记录:原有英文字段中文名
-
-| 字段 | 中文名称 | 净亏邀请页面建议 |
-| --- | --- | --- |
-| `id` | 申请记录 ID | 显示 |
-| `activity_id` | 活动 ID | 显示或隐藏在活动页上下文中 |
-| `user_id` | 申请会员 ID | 账号使用 `inviter.account` |
-| `round_no` | 参与轮次 | 净亏邀请固定为 1,隐藏 |
-| `spins` | 剩余抽奖次数 | 仅转盘使用,净亏邀请隐藏 |
-| `applied_at` | 申请时间 | 显示;为空时显示“未申请” |
-| `application_snapshot` | 申请时规则 | 不直接显示原始 JSON,按下表展示摘要 |
-| `created_at` | 创建时间 | 显示 |
-| `updated_at` | 更新时间 | 显示 |
-
-`application_snapshot` 当前是 JSON 字符串,展示摘要时先解析;兼容已经解析成对象的数据:
-
-| 解析后的字段 | 中文名称 |
-| --- | --- |
-| `loss` | 申请时净亏 |
-| `from` | 统计开始时间 |
-| `rules.loss_amount` | 申请所需净亏 |
-| `rules.invite_count` | 需邀请有效会员数 |
-| `rules.reward_amount` | 申请时现金奖励金额 / 邀请人券总额上限,按奖励方式显示 |
-| `rules.turnover_ratio` | 解冻投注倍数,仅现金模式需要时展示 |
-
-截图可整理为“申请时净亏 550、申请门槛 500、需邀请 3 人、现金奖励 500”,不要把整段申请规则挤在一行。`application_snapshot.policy`、`application_snapshot.invite_user_cursor` 属于内部核对信息,不作为业务详情展示。
-
-## 6. 发奖记录:原有英文字段中文名
-
-| 字段 | 中文名称 | 展示建议 |
-| --- | --- | --- |
-| `id` | 发奖记录 ID | 显示 |
-| `activity_id` | 活动 ID | 依页面上下文决定是否重复显示 |
-| `user_id` | 领奖会员 ID(邀请人) | 账号使用 `inviter.account` |
-| `account_id` | 关联申请记录 ID | 对应申请记录的 `id` |
-| `round_no` | 发奖轮次 | 净亏邀请固定为 1,隐藏 |
-| `amount` | 现金奖励金额 / 优惠券抵扣总额 | 按本行 `reward_mode` 显示对应列名 |
-| `required_flow` | 解冻所需有效投注额 | 现金模式为 0 时可显示“无需解冻”;券模式隐藏 |
-| `status` | 发奖状态 | 按下表翻译 |
-| `credited_log_id` | 奖励入账流水 ID | 券模式隐藏;无值显示“—” |
-| `unlocked_log_id` | 解冻流水 ID | 无值显示“—” |
-| `rule_snapshot` | 发奖时规则 | 不直接显示原始 JSON;名单和获券使用新增字段 |
-| `flow_snapshot` | 流水统计快照 | 内部字段,隐藏,不展开其中内容 |
-| `unlocked_at` | 解冻时间 | 无值显示“—” |
-| `created_at` | 创建时间 | 不改称“实际发奖时间” |
-| `updated_at` | 更新时间 | 显示 |
-
-| `status` / `reward_status` | 中文 |
-| --- | --- |
-| `reserved` | 待发放 |
-| `locked` | 待解冻(已入冻结余额) |
-| `paid` | 已发放 |
-| `null` | 暂无发奖记录,仅申请记录适用 |
-
-金额为 0 或无需解冻不代表已经发放,仍按状态字段展示。历史记录缺少奖励模式时,接口按现金模式兼容;不要使用活动现在的配置去覆盖旧记录的奖励方式和券档位。
-
-## 7. 已发优惠券列表的账号补充
-
-`kind=coupons` 每条券记录新增 `account`(持券会员账号)、`inviter_account`(邀请人账号),原有字段保留:
-
-| 字段 | 中文名称 |
-| --- | --- |
-| `id` | 券 ID |
-| `reward_id` | 来源发奖记录 ID |
-| `user_id` / `account` | 持券会员 ID / 账号 |
-| `inviter_user_id` / `inviter_account` | 邀请人 ID / 账号 |
-| `role=inviter` | 邀请人奖励券 |
-| `role=invitee` | 被邀请人奖励券 |
-| `min_amount` / `discount` | 使用门槛 / 抵扣金额 |
-| `status=unused` | 未使用;不表示一定在可用时间内 |
-| `status=used` | 已使用 |
-
-发奖列表中的获券摘要使用本行 `inviter.coupons`、`invitees[].coupons` 即可。不要用某一页“已发优惠券”的数据自行拼出获券总数,分页可能只包含部分券。
-
-## 8. 前端验收
-
-- 所有列名使用中文;净亏邀请不展示 `spins`、固定轮次或内部统计快照。
-- 截图历史现金记录显示邀请人 164、三名达标会员及各自账号;双方获券显示“本次未发券”。
-- 优惠券模式同一行显示邀请人及每名被邀请人的 ID、账号、满减档位和获得张数。
-- 未发奖申请显示“尚未生成发奖名单”;账号缺失显示“—”,保留会员 ID。
-- 券使用或过期后,记录页的获得张数保持不变;分页总数仍是主记录数。
-- 更新接口后再启用这些列;历史奖励方式和金额保持原样。

+ 5 - 5
docs/前端交付/melbet_sport-api/前台/独立活动/优惠券券包-会员接口.md

@@ -13,7 +13,7 @@
 | Tab | 请求 | 内容 |
 |---|---|---|
 | 可用 | `GET /api/coupon/list?tab=usable&category=<当前游戏分类>` | 未使用、在可用时间内、可用于当前游戏的券 |
-| 不可用 | `GET /api/coupon/list?tab=unusable&category=<当前游戏分类>` | 已使用、已过期、未到时间、不适用当前游戏的券 |
+| 不可用 | `GET /api/coupon/list?tab=unusable&category=<当前游戏分类>` | 已过期、未到时间、不适用当前游戏的券(已使用的券不显示) |
 
 Tab 上的数量用 `GET /api/coupon/count?category=<当前游戏分类>`。
 
@@ -71,10 +71,10 @@ Tab 上的数量用 `GET /api/coupon/count?category=<当前游戏分类>`。
 | min_amount / discount | 显示为"满 min_amount 抵 discount" |
 | categories / category_names | 可用游戏 |
 | valid_from / valid_until | 可用时间(UTC+8) |
-| status | `unused` / `used` |
+| status | 列表中均为 `unused`,已使用的券不返回 |
 | usable | 在本次 `category` 条件下是否可用 |
-| unusable_reason | `used` 已使用、`expired` 已过期、`not_started` 未到可用时间、`category` 不适用当前游戏;可用时为 `null` |
-| used_at / used_stake | 使用时间、使用时的下注金额 |
+| unusable_reason | `expired` 已过期、`not_started` 未到可用时间、`category` 不适用当前游戏;可用时为 `null` |
+| used_at / used_stake | 列表中均为 `null`,无需展示 |
 
 ### GET /api/coupon/count
 
@@ -96,7 +96,7 @@ Tab 上的数量用 `GET /api/coupon/count?category=<当前游戏分类>`。
 
 - 一张券只能用一次。根级 `coupon_id` 的接口,一次请求最多用一张券;F1体育每一注可各带一张,同一张券不能用在两注上。
 - 门槛按下注**总额**判断:根级券看整张注单所有号码/投注项金额合计,F1体育看该注金额。
-- 扣款 = 下注总额 − 抵扣金额。下注成功后该券进入"不可用"(`used`)。
+- 扣款 = 下注总额 − 抵扣金额。下注成功后该券标记为 `used`,不再出现在券包的可用和不可用列表中。
 - 券不可用时:
   - 根级 `coupon_id` 的接口整单失败,不扣款,`msg` 为原因。
   - F1体育只有该注进入返回的 `failure` 列表(带 `msg`),其他注照常成功。

+ 18 - 17
docs/前端交付/交付清单.json

@@ -26,8 +26,8 @@
       "role": "后台",
       "kind": "目录",
       "git_status": "M",
-      "source_sha256": "98322b197addd5a9c55385121b5d5a4bf363fc5ed8810faeeb1903301f9bfb68",
-      "delivery_sha256": "436f4f7c80155474d5ce0b9282ef2a0e2f9d4890b557fbb01e9e8d4194039754",
+      "source_sha256": "3be44c953c2677c131a424179f629e8fa0af2cb97d6dd9358f34ba6f0d17b45c",
+      "delivery_sha256": "1eff1aab9ba98b0b8a6340d826c09d1c33fc13284e2c0f41652306f48ec6f543",
       "revised_on": "2026-11-02"
     },
     {
@@ -37,8 +37,8 @@
       "role": "后台",
       "kind": "正文",
       "git_status": "M",
-      "source_sha256": "93f83870d5fce3372d40dada0b4e02f4a7d17aed8e682ef7b83aa439cc4773e9",
-      "delivery_sha256": "93f83870d5fce3372d40dada0b4e02f4a7d17aed8e682ef7b83aa439cc4773e9",
+      "source_sha256": "a15115b1144e65c867737ab2c7c1c4619c12609f803cfda1f7b014a68ee6c93f",
+      "delivery_sha256": "a15115b1144e65c867737ab2c7c1c4619c12609f803cfda1f7b014a68ee6c93f",
       "revised_on": "2026-11-02"
     },
     {
@@ -265,19 +265,8 @@
       "role": "前台",
       "kind": "正文",
       "git_status": "??",
-      "source_sha256": "e750345f581a4854d2cdd2555000d21ae34a5b49c8593a219a56ef6cfb413eff",
-      "delivery_sha256": "e750345f581a4854d2cdd2555000d21ae34a5b49c8593a219a56ef6cfb413eff",
-      "revised_on": "2026-11-02"
-    },
-    {
-      "project": "bot-28",
-      "source_path": "docs/总后台/独立活动/净亏邀请记录-中文字段与名单展示.md",
-      "delivery_path": "bot-28/后台/独立活动/净亏邀请记录-中文字段与名单展示.md",
-      "role": "后台",
-      "kind": "正文",
-      "git_status": "??",
-      "source_sha256": "f0aaed63c5a765e927462ac7b56086ca6c448a0f3b89e7f1898aaea178c4350a",
-      "delivery_sha256": "f0aaed63c5a765e927462ac7b56086ca6c448a0f3b89e7f1898aaea178c4350a",
+      "source_sha256": "ff9a70b0fff9cea5b95a6bed0938dba8137ea5b7b50527c39ab47822bbbdc99c",
+      "delivery_sha256": "ff9a70b0fff9cea5b95a6bed0938dba8137ea5b7b50527c39ab47822bbbdc99c",
       "revised_on": "2026-11-02"
     }
   ],
@@ -329,6 +318,12 @@
       "source_path": "docs/后端/报表内部核对与诊断-接口.md",
       "git_status": "??",
       "reason": "后端内部维护合同,明确不接入报表菜单、按钮或弹窗"
+    },
+    {
+      "project": "bot-28",
+      "source_path": "docs/总后台/独立活动/净亏邀请记录-中文字段与名单展示.md",
+      "git_status": "D",
+      "reason": "已并入净亏邀请-后台接口“记录查询”一节"
     }
   ],
   "revisions": [
@@ -429,6 +424,12 @@
       "project": "bot-28",
       "branch": "master",
       "description": "新增管理后台净亏邀请记录字段中文与名单展示说明;申请、发奖记录增加邀请人及被邀请人的ID、账号和实际获券档位/张数,券记录增加账号字段;同步交付副本、目录与校验值。"
+    },
+    {
+      "date": "2026-11-02",
+      "project": "bot-28 / melbet_sport-api",
+      "branch": "master",
+      "description": "净亏邀请后台文档重新整理:记录名单与中文列名说明并入《净亏邀请-后台接口》“记录查询”,删除单独的记录说明;券包文档同步已使用券不显示的变更;更新目录、清单及校验值。"
     }
   ]
 }

+ 1 - 1
docs/前端交付/交付清单.md

@@ -8,7 +8,6 @@
 
 | 项目 | 来源路径 | 状态 | 交付文件 | 类型 |
 |---|---|---|---|---|
-| bot-28 | `docs/总后台/独立活动/净亏邀请记录-中文字段与名单展示.md` | 新增(2026-11-02) | [净亏邀请记录-中文字段与名单展示](bot-28/后台/独立活动/净亏邀请记录-中文字段与名单展示.md) | 正文 |
 | bot-28 | `docs/总后台/后台实时推送-前端接入.md` | ??(2026-10-31 增补) | [后台实时推送-前端接入.md](bot-28/后台/后台实时推送-前端接入.md) | 正文 |
 | bot-28 | `docs/总后台/独立活动-后台接口.md` | M | [独立活动-后台接口.md](bot-28/后台/独立活动-后台接口.md) | 目录 |
 | bot-28 | `docs/总后台/独立活动/净亏邀请-后台接口.md` | M | [净亏邀请-后台接口.md](bot-28/后台/独立活动/净亏邀请-后台接口.md) | 正文 |
@@ -45,5 +44,6 @@
 | bot-28 | `docs/后端/报表统计口径与数据补录.md` | 后端实现与部署说明,不是前端接口接入文档 |
 | bot-28 | `docs/后端/报表内部核对与诊断-接口.md` | 后端内部维护合同,不接入报表菜单、按钮或弹窗 |
 | melbet_sport-api | `docs/返佣列表-前端接入文档.md` | 仅空白格式变化,接口正文/合约没有增量 |
+| bot-28 | `docs/总后台/独立活动/净亏邀请记录-中文字段与名单展示.md` | 2026-11-02 已并入《净亏邀请-后台接口》的“记录查询”一节,原文件删除 |
 
 `M` 为修改,`??` 为未跟踪,`D` 为删除;“基准已有(补充)”对应JSON中的 `git_status=unchanged`,表示按用户要求额外交付的已有文档。`交付清单.json` 记录完整基准与来源/副本SHA-256,便于核对。

+ 1 - 1
docs/总后台/独立活动-后台接口.md

@@ -12,4 +12,4 @@
 
 新增按钮与新增类型下拉使用 `GET /admin/promotion/options` 返回的 `create_types`,当前只有首充奖励(`value=8`)。`types` 仍提供三种类型用于筛选。固定活动从列表读取现有 `id` 后编辑保存;净亏邀请改为单页平铺表单,直接用 `GET /admin/promotion/detail?type=7` 读取,不再经过列表。
 
-申请记录、发奖记录的中文标签、被邀请人账号及获券列表接入见[净亏邀请记录-中文字段与名单展示](独立活动/净亏邀请记录-中文字段与名单展示.md)。
+净亏邀请的申请记录、发奖记录、已发优惠券(中文列名、邀请人与被邀请人账号及获券)已并入[净亏邀请-后台接口](独立活动/净亏邀请-后台接口.md)的“记录查询”一节。

+ 178 - 13
docs/总后台/独立活动/净亏邀请-后台接口.md

@@ -160,25 +160,190 @@
    - 奖励记录 `amount` 为本次发出的券抵扣总额,状态为 `paid`;记录页直接展示,会员钱包不增加现金。
 7. 券只能在 F1 自有游戏(F1体育、F1彩票)下注时使用;退款后的可用状态以券包接口返回为准。
 
-## 参与、发奖与优惠券记录
+## 记录查询:申请、发奖、已发优惠券
 
-`GET /admin/promotion/records?activity_id=1&kind=accounts&page=1&limit=20` 查看申请记录,`kind=rewards` 查看奖金,可追加会员 ID `user_id`(使用会员列表返回的 `id`)。返回 `total/data`。
+记录区为只读展示,返回的字段不要提交给保存接口。三个列表共用一个接口,`activity_id` 取 `detail` 返回的 `id`。申请记录 ID 和发奖记录 ID 都不是活动 ID。
 
-申请记录包含 `applied_at/application_snapshot`;奖金有 `reserved/locked/paid` 状态和资金流水关联(优惠券模式无流水)。没有有效申请前不允许领奖,重复领取不会重复入账或发券。停止活动使用下架,不删除参与历史。
+| 页签 | 请求 |
+|---|---|
+| 申请记录 | `GET /admin/promotion/records?activity_id=1&kind=accounts&page=1&limit=20` |
+| 发奖记录 | `GET /admin/promotion/records?activity_id=1&kind=rewards&page=1&limit=20` |
+| 已发优惠券 | `GET /admin/promotion/records?activity_id=1&kind=coupons&page=1&limit=20` |
+
+- 返回:成功 `code=0`,列表在 `data.data`,总数在 `data.total`。总数按申请或发奖记录计算,不是被邀请人数或券张数。
+- `limit` 最大 100。
+- `user_id` 按会员筛选,取会员列表返回的 `id`:
+  - 申请、发奖列表:筛选该邀请人。
+  - 已发券列表:匹配持券人或邀请人。
+- `status=unused/used` 仅已发券列表支持。申请、发奖列表不提供奖励状态筛选。
+
+所有列名使用中文,嵌套对象和 JSON 字段不要按原文渲染。会员 ID 与账号按文本展示,不套用金额格式,保留账号可能有的前导零。
+
+### 申请记录 `kind=accounts`
+
+| 字段 | 中文列名 | 展示建议 |
+|---|---|---|
+| id | 申请记录 ID | 显示 |
+| activity_id | 活动 ID | 可隐藏(页面已在本活动内) |
+| user_id | 申请会员 ID | 与 `inviter.account` 合并显示为"ID / 账号" |
+| round_no | 参与轮次 | 固定为 1,隐藏 |
+| spins | 剩余抽奖次数 | 转盘专用,隐藏 |
+| applied_at | 申请时间 | 为空时显示"未申请" |
+| application_snapshot | 申请时规则 | 按下方摘要展示,不显示原始 JSON |
+| reward_mode | 奖励方式 | `cash` 现金 / `coupon` 优惠券;`null` 显示"—" |
+| reward_id | 关联发奖记录 ID | 未发奖时为 `null`,显示"—" |
+| reward_status | 发奖状态 | 枚举同发奖记录 `status`;`null` 显示"暂无发奖记录" |
+| inviter / invitees | 邀请人、被邀请人及获券 | 见下方[名单与获券](#名单与获券申请发奖共用) |
+| created_at / updated_at | 创建时间 / 更新时间 | 显示 |
+
+`application_snapshot` 目前是 JSON 字符串,先解析再展示,也要兼容已是对象的情况:
+
+| 解析后字段 | 中文名称 |
+|---|---|
+| loss | 申请时净亏 |
+| from | 统计开始时间 |
+| rules.loss_amount | 申请所需净亏 |
+| rules.invite_count | 需邀请有效会员数 |
+| rules.reward_amount | 现金奖励金额 / 邀请人券总额上限,按奖励方式显示 |
+| rules.turnover_ratio | 解冻投注倍数,仅现金模式展示 |
+
+摘要示例:"申请时净亏 550、申请门槛 500、需邀请 3 人、现金奖励 500"。`policy`、`invite_user_cursor` 为内部核对字段,不展示。
+
+### 发奖记录 `kind=rewards`
 
-`kind=coupons` 查看已发优惠券,可加 `user_id`(匹配持券人或邀请人)和 `status=unused/used`:
+| 字段 | 中文列名 | 展示建议 |
+|---|---|---|
+| id | 发奖记录 ID | 显示 |
+| activity_id | 活动 ID | 可隐藏 |
+| user_id | 领奖会员 ID(邀请人) | 与 `inviter.account` 合并显示 |
+| account_id | 关联申请记录 ID | 对应申请记录的 `id` |
+| round_no | 发奖轮次 | 固定为 1,隐藏 |
+| amount | 现金奖励金额 / 优惠券抵扣总额 | 列名随本行 `reward_mode` 切换 |
+| required_flow | 解冻所需有效投注额 | 现金模式为 0 时显示"无需解冻";券模式隐藏 |
+| status | 发奖状态 | 见下表 |
+| credited_log_id | 奖励入账流水 ID | 券模式隐藏;无值显示"—" |
+| unlocked_log_id | 解冻流水 ID | 无值显示"—" |
+| unlocked_at | 解冻时间 | 无值显示"—" |
+| rule_snapshot | 发奖时规则 | 不显示原始 JSON;名单和获券使用新增字段 |
+| flow_snapshot | 流水统计快照 | 内部字段,隐藏 |
+| reward_mode | 奖励方式 | 同申请记录 |
+| inviter / invitees | 邀请人、被邀请人及获券 | 见下方名单与获券 |
+| created_at / updated_at | 创建时间 / 更新时间 | 显示;`created_at` 不要改称"实际发奖时间" |
+
+| status / reward_status | 中文 |
+|---|---|
+| reserved | 待发放 |
+| locked | 待解冻(已入冻结余额) |
+| paid | 已发放 |
+
+即使金额为 0 或无需解冻,也按 `status` 展示状态,不要当作已发放。每名会员只能领取一次,重复领取不会重复入账或发券。停止活动用下架,参与历史不会删除。
+
+### 名单与获券(申请、发奖共用)
+
+净亏邀请(类型 7)的申请、发奖记录每行附带下面这组名单字段,其他活动类型不返回:
 
 | 字段 | 含义 |
 |---|---|
-| id / activity_id / reward_id | 券ID、活动、来源奖励记录 |
-| user_id / member_id | 持券会员 |
-| role | `inviter` 邀请人券 / `invitee` 被邀请人券 |
-| inviter_user_id | 发起邀请的会员 |
-| min_amount / discount | 使用门槛、抵扣金额 |
-| categories | 可用游戏数组 |
-| valid_from / valid_until | 可用时间 |
-| status | `unused` 未使用 / `used` 已使用 |
-| used_source / used_stake / used_at | 使用的注单类型、下注毛额、使用时间 |
+| inviter.id / inviter.account | 邀请人会员 ID / 账号 |
+| inviter.coupons | 邀请人本次获得的券 |
+| invitees[] | 本次关联的被邀请人,每项 `id / account / coupons` |
+
+`coupons` 为数组,按档位合并,每项字段如下:
+
+| 字段 | 中文名称 | 类型 |
+|---|---|---|
+| min_amount | 使用门槛 | 金额字符串 |
+| discount | 抵扣金额 | 金额字符串 |
+| quantity | 本次发放张数 | 整数 |
+
+建议在申请、发奖两个列表中都增加以下列:
+
+| 列名 | 展示示例 |
+|---|---|
+| 奖励方式 | 现金 / 优惠券 |
+| 邀请人(ID / 账号) | `164 / demo164` |
+| 邀请人获得的券 | `满100抵50 × 2张;满200抵100 × 1张` |
+| 被邀请人及获券 | 每人一行:`168 / demo168:满100抵100 × 1张` |
+
+各情况的展示:
+
+| 情况 | 返回 | 显示 |
+|---|---|---|
+| 现金记录 | `invitees` 为发奖时达标的会员,双方 `coupons=[]` | 列出名单,获券显示"本次未发券";不要把被邀请人显示成现金收款人 |
+| 优惠券记录 | `invitees` 为本次计入发券的会员 | 列出每人账号与获券 |
+| 尚未发奖的申请 | `reward_id=null`、`reward_status=null`、`invitees=[]` | 显示"尚未生成发奖名单"(不代表没有下级或邀请数为 0) |
+| 账号未设置或会员已删除 | `account=null`,ID 保留 | 账号显示"—" |
+| 被邀请人未配置券 | 该人 `coupons=[]` | 显示"本次未发券" |
+
+- 会员 ID 对应记录的 `user_id`,不是会员编号 `member_id`。
+- 账号取会员当前账号,不是发奖时的快照。
+- `quantity` 是实际发出的张数,券已使用或已过期仍计入,不等于当前可用张数。
+- 每行只包含这笔发奖的券。获券摘要直接用本行数据,不要用"已发优惠券"分页数据拼总数,也不要按活动当前配置推算档位。
+- 历史记录缺少奖励方式时按现金兼容,不要用活动当前配置覆盖旧记录的奖励方式和券档位。
+
+优惠券模式发奖记录示例(账号为示例值):
+
+```json
+{
+  "code": 0,
+  "data": {
+    "total": 1,
+    "data": [
+      {
+        "id": 3003,
+        "activity_id": 1,
+        "user_id": 164,
+        "account_id": 20001,
+        "amount": "500",
+        "status": "paid",
+        "reward_mode": "coupon",
+        "inviter": {
+          "id": 164,
+          "account": "demo164",
+          "coupons": [
+            {"min_amount": "100", "discount": "50", "quantity": 2},
+            {"min_amount": "200", "discount": "100", "quantity": 1}
+          ]
+        },
+        "invitees": [
+          {"id": 168, "account": "demo168", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]},
+          {"id": 169, "account": "demo169", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]},
+          {"id": 170, "account": "demo170", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]}
+        ]
+      }
+    ]
+  }
+}
+```
+
+### 已发优惠券 `kind=coupons`
+
+每行是一张券:
+
+| 字段 | 中文名称 |
+|---|---|
+| id | 券 ID |
+| activity_id / reward_id | 活动 ID / 来源发奖记录 ID |
+| user_id / account | 持券会员 ID / 账号 |
+| member_id | 持券会员编号(内部关联用,可隐藏) |
+| inviter_user_id / inviter_account | 邀请人 ID / 账号 |
+| role | `inviter` 邀请人奖励券 / `invitee` 被邀请人奖励券 |
+| seq | 发放序号,内部字段,隐藏 |
+| min_amount / discount | 使用门槛 / 抵扣金额,显示为"满 X 抵 Y" |
+| categories | 可用游戏:`self:sport` F1体育、`self:lottery` F1彩票 |
+| valid_from / valid_until | 可用时间(UTC+8) |
+| status | `unused` 未使用 / `used` 已使用;未使用不代表仍在可用时间内 |
+| used_source | 使用的注单类型:`sport_order` 体育、`sport_game_order` 足球小游戏、`lhc_order` 彩票 |
+| used_stake / used_at | 使用时的下注金额 / 使用时间;未使用为空,显示"—" |
+| created_at / updated_at | 发放时间 / 更新时间 |
+
+### 记录页验收
+
+- 列名全为中文;不展示 `spins`、固定轮次和内部快照字段。
+- 现金记录显示邀请人和达标会员的 ID、账号,获券显示"本次未发券"。
+- 优惠券记录在同一行显示邀请人和每名被邀请人的 ID、账号、满减档位和张数。
+- 未发奖的申请显示"尚未生成发奖名单";账号缺失显示"—",保留会员 ID。
+- 券使用或过期后,记录页获得张数不变;分页总数仍为主记录数。
 
 ## 权限
 

+ 0 - 197
docs/总后台/独立活动/净亏邀请记录-中文字段与名单展示.md

@@ -1,197 +0,0 @@
-# 净亏邀请记录:中文字段、被邀请人及获券展示
-
-面向**管理后台前端**,用于改造“申请记录”“发奖记录”和“已发优惠券”列表及详情。本次沿用现有接口,增加名单、账号和获券展示数据;不补发历史奖励。
-
-记录页面为只读展示,新增字段不要提交给活动配置保存接口。
-
-## 1. 现有截图中的三个人在哪里
-
-截图发奖记录 `id=3`、领奖会员 `user_id=164`、关联申请 `account_id=11865`。其规则中有 `qualified_invitees=[168,169,170]`,这就是发奖时达标的三名会员。
-
-这条历史记录的规则未指定优惠券模式,按兼容规则属于**现金奖励**,并有奖励入账流水 `credited_log_id=20800`。500 是邀请人 164 的现金奖励。三名被邀请人用于满足领取条件,这条记录没有给他们发券。
-
-更新接口后,前端直接使用新增的 `inviter`、`invitees` 显示 ID、账号和各自获券,无需再从规则快照解析名单或逐人查询账号。
-
-## 2. 请求和返回位置
-
-在 bot-28 后台 API 主机请求,沿用管理员请求头 `Authorization: Bearer <token>`。
-
-| 页面 | 请求 |
-| --- | --- |
-| 申请记录 | `GET /admin/promotion/records?activity_id=1&kind=accounts&page=1&limit=20` |
-| 发奖记录 | `GET /admin/promotion/records?activity_id=1&kind=rewards&page=1&limit=20` |
-| 已发优惠券 | `GET /admin/promotion/records?activity_id=1&kind=coupons&page=1&limit=20` |
-
-成功 `code=0`,列表位于 `data.data`,总记录数位于 `data.total`;失败展示 `msg`。可传 `user_id`:申请、发奖列表筛选该邀请人;已发券列表匹配持券人或邀请人。`limit` 最大 100。
-
-示例中的 `activity_id=1` 替换为当前页面的活动 ID。申请记录 ID、发奖记录 ID 均不是活动 ID;记录详情使用本行返回数据展开。
-
-只有已发优惠券列表支持 `status=unused/used` 筛选。申请、发奖列表暂不提供奖励状态筛选参数。
-
-下述申请、发奖列表新增字段用于净亏邀请(活动类型 `7`),不改变原分页、筛选和原有字段。其他活动类型不增加这组名单字段。
-
-## 3. 新增字段及列表列名
-
-| 返回字段 | 中文名称 / 用法 |
-| --- | --- |
-| `reward_mode` | 奖励方式:`cash` 现金、`coupon` 优惠券;尚无规则时为 `null`,显示“—” |
-| `inviter.id` | 邀请人会员 ID;申请列表可标“申请会员 ID”,发奖列表可标“领奖会员 ID” |
-| `inviter.account` | 邀请人账号 |
-| `inviter.coupons` | 邀请人本次获得的券,按满减档位合并 |
-| `invitees` | 本次关联的被邀请人列表 |
-| `invitees[].id` | 被邀请人会员 ID |
-| `invitees[].account` | 被邀请人账号 |
-| `invitees[].coupons` | 该被邀请人本次获得的券,按满减档位合并 |
-| `reward_id` | 仅申请记录新增:关联发奖记录 ID;未生成发奖记录时为 `null` |
-| `reward_status` | 仅申请记录新增:关联发奖状态;未生成时为 `null`,其余枚举同发奖记录的 `status` |
-
-建议两张列表都增加以下列,不要把嵌套对象直接渲染成原始 JSON:
-
-| 列名 | 展示示例 |
-| --- | --- |
-| 邀请人(ID / 账号) | `164 / demo164` |
-| 邀请人获得的券 | `满100抵50 × 2张;满200抵100 × 1张` |
-| 被邀请人及获券 | 每人一行,例如 `168 / demo168:满100抵100 × 1张`,其余会员继续列出 |
-| 奖励方式 | 现金 / 优惠券 |
-
-现金记录也返回达标会员的 ID 和账号,但双方 `coupons=[]`,显示“本次未发券”。不要把三名达标会员渲染成三笔现金收款记录。
-
-尚未发奖的申请返回 `reward_id=null`、`reward_status=null`、`invitees=[]`,显示“尚未生成发奖名单”。这不表示没有下级,也不表示当前有效邀请人数为 0;这里展示的是与发奖记录关联的历史名单,不是实时邀请进度。
-
-账号取当前可查询的会员账号,不是发奖时的账号快照。账号未设置或会员记录已不存在时,ID 仍保留,`account=null`,显示“—”。这里的会员 ID 对应原记录的 `user_id`,不要当成会员编号 `member_id`。
-
-## 4. 获券数组格式
-
-`inviter.coupons` 和 `invitees[].coupons` 中的每一项:
-
-| 字段 | 中文名称 | 类型 |
-| --- | --- | --- |
-| `min_amount` | 使用门槛 | 金额字符串 |
-| `discount` | 抵扣金额 | 金额字符串 |
-| `quantity` | 本次发放张数 | 整数 |
-
-前端显示“满 `min_amount` 抵 `discount` × `quantity` 张”。金额沿用活动接口的展示格式:整数不带 `.00`,有小数时保留两位。会员 ID 和账号不套用金额格式;账号按文本展示,保留可能存在的前导零。
-
-数量来自实际发出的券,已使用、已过期的券仍计入**获得张数**。不要把它当成当前可用张数,也不要根据活动当前配置自行生成券档位。没有给被邀请人配置券或该人未获券时,其 `coupons` 为空。
-
-现金记录展示发奖时的达标名单;优惠券记录展示本次计入发券的名单,并包含实际获券人。历史快照中其他达标会员不自动变成本次收券人。
-
-以下为优惠券模式的响应片段,仅演示结构;账号为示例,**不代表截图中的历史现金记录被改成了券奖励**:
-
-```json
-{
-  "code": 0,
-  "data": {
-    "total": 1,
-    "data": [
-      {
-        "id": 3003,
-        "activity_id": 1,
-        "user_id": 164,
-        "account_id": 20001,
-        "amount": "500",
-        "status": "paid",
-        "reward_mode": "coupon",
-        "inviter": {
-          "id": 164,
-          "account": "demo164",
-          "coupons": [
-            {"min_amount": "100", "discount": "50", "quantity": 2},
-            {"min_amount": "200", "discount": "100", "quantity": 1}
-          ]
-        },
-        "invitees": [
-          {"id": 168, "account": "demo168", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]},
-          {"id": 169, "account": "demo169", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]},
-          {"id": 170, "account": "demo170", "coupons": [{"min_amount": "100", "discount": "100", "quantity": 1}]}
-        ]
-      }
-    ]
-  }
-}
-```
-
-列表总数仍是申请或发奖记录数,不是被邀请人人数或券张数。每条记录只展示属于这笔发奖的券,不会混入该会员其他发奖记录的券。
-
-## 5. 申请记录:原有英文字段中文名
-
-| 字段 | 中文名称 | 净亏邀请页面建议 |
-| --- | --- | --- |
-| `id` | 申请记录 ID | 显示 |
-| `activity_id` | 活动 ID | 显示或隐藏在活动页上下文中 |
-| `user_id` | 申请会员 ID | 账号使用 `inviter.account` |
-| `round_no` | 参与轮次 | 净亏邀请固定为 1,隐藏 |
-| `spins` | 剩余抽奖次数 | 仅转盘使用,净亏邀请隐藏 |
-| `applied_at` | 申请时间 | 显示;为空时显示“未申请” |
-| `application_snapshot` | 申请时规则 | 不直接显示原始 JSON,按下表展示摘要 |
-| `created_at` | 创建时间 | 显示 |
-| `updated_at` | 更新时间 | 显示 |
-
-`application_snapshot` 当前是 JSON 字符串,展示摘要时先解析;兼容已经解析成对象的数据:
-
-| 解析后的字段 | 中文名称 |
-| --- | --- |
-| `loss` | 申请时净亏 |
-| `from` | 统计开始时间 |
-| `rules.loss_amount` | 申请所需净亏 |
-| `rules.invite_count` | 需邀请有效会员数 |
-| `rules.reward_amount` | 申请时现金奖励金额 / 邀请人券总额上限,按奖励方式显示 |
-| `rules.turnover_ratio` | 解冻投注倍数,仅现金模式需要时展示 |
-
-截图可整理为“申请时净亏 550、申请门槛 500、需邀请 3 人、现金奖励 500”,不要把整段申请规则挤在一行。`application_snapshot.policy`、`application_snapshot.invite_user_cursor` 属于内部核对信息,不作为业务详情展示。
-
-## 6. 发奖记录:原有英文字段中文名
-
-| 字段 | 中文名称 | 展示建议 |
-| --- | --- | --- |
-| `id` | 发奖记录 ID | 显示 |
-| `activity_id` | 活动 ID | 依页面上下文决定是否重复显示 |
-| `user_id` | 领奖会员 ID(邀请人) | 账号使用 `inviter.account` |
-| `account_id` | 关联申请记录 ID | 对应申请记录的 `id` |
-| `round_no` | 发奖轮次 | 净亏邀请固定为 1,隐藏 |
-| `amount` | 现金奖励金额 / 优惠券抵扣总额 | 按本行 `reward_mode` 显示对应列名 |
-| `required_flow` | 解冻所需有效投注额 | 现金模式为 0 时可显示“无需解冻”;券模式隐藏 |
-| `status` | 发奖状态 | 按下表翻译 |
-| `credited_log_id` | 奖励入账流水 ID | 券模式隐藏;无值显示“—” |
-| `unlocked_log_id` | 解冻流水 ID | 无值显示“—” |
-| `rule_snapshot` | 发奖时规则 | 不直接显示原始 JSON;名单和获券使用新增字段 |
-| `flow_snapshot` | 流水统计快照 | 内部字段,隐藏,不展开其中内容 |
-| `unlocked_at` | 解冻时间 | 无值显示“—” |
-| `created_at` | 创建时间 | 不改称“实际发奖时间” |
-| `updated_at` | 更新时间 | 显示 |
-
-| `status` / `reward_status` | 中文 |
-| --- | --- |
-| `reserved` | 待发放 |
-| `locked` | 待解冻(已入冻结余额) |
-| `paid` | 已发放 |
-| `null` | 暂无发奖记录,仅申请记录适用 |
-
-金额为 0 或无需解冻不代表已经发放,仍按状态字段展示。历史记录缺少奖励模式时,接口按现金模式兼容;不要使用活动现在的配置去覆盖旧记录的奖励方式和券档位。
-
-## 7. 已发优惠券列表的账号补充
-
-`kind=coupons` 每条券记录新增 `account`(持券会员账号)、`inviter_account`(邀请人账号),原有字段保留:
-
-| 字段 | 中文名称 |
-| --- | --- |
-| `id` | 券 ID |
-| `reward_id` | 来源发奖记录 ID |
-| `user_id` / `account` | 持券会员 ID / 账号 |
-| `inviter_user_id` / `inviter_account` | 邀请人 ID / 账号 |
-| `role=inviter` | 邀请人奖励券 |
-| `role=invitee` | 被邀请人奖励券 |
-| `min_amount` / `discount` | 使用门槛 / 抵扣金额 |
-| `status=unused` | 未使用;不表示一定在可用时间内 |
-| `status=used` | 已使用 |
-
-发奖列表中的获券摘要使用本行 `inviter.coupons`、`invitees[].coupons` 即可。不要用某一页“已发优惠券”的数据自行拼出获券总数,分页可能只包含部分券。
-
-## 8. 前端验收
-
-- 所有列名使用中文;净亏邀请不展示 `spins`、固定轮次或内部统计快照。
-- 截图历史现金记录显示邀请人 164、三名达标会员及各自账号;双方获券显示“本次未发券”。
-- 优惠券模式同一行显示邀请人及每名被邀请人的 ID、账号、满减档位和获得张数。
-- 未发奖申请显示“尚未生成发奖名单”;账号缺失显示“—”,保留会员 ID。
-- 券使用或过期后,记录页的获得张数保持不变;分页总数仍是主记录数。
-- 更新接口后再启用这些列;历史奖励方式和金额保持原样。