Files
live-hub-py/tests
yml2213 6b5271c983 feat(account): 一键查询补上「角色绑定状态」—— 以前从来没人查过,97% 显示"未知"
## 问题(用户:"这个做了吗?我看好像都是未知")

**只做了一半**:

- 列的拆分做了(S6):三列存在、写入收敛到 set_bind_status、迁移映射与运行时对齐
- 但**没有任何一处真的去查绑定状态**(grep -c bind_info douyu_runner_overview.py = 0)

那三列的值从来不是查来的,而是 S6 迁移时从旧的垃圾场列 bind_status
**能推的推、推不出的留 unknown**。只把明确陈述了绑定事实的旧值映射过来
(bind_confirmed → bound、bind_qr_generated → pending、game_not_bound → unbound),
其余一律 unknown —— 因为旧列被"查限兑商品""送礼物"这类**无关动作**覆盖过,
从无关动作推绑定状态就是造假。当时留 unknown 是对的,但结果是:

真实生产分布(15182 个账号)
  精英 unknown 14683 (96.7%)   电竞 14730 (97.0%)   小店 15045 (99.1%)

## 修法:真的去查,用唯一写入者写回

一键查询新增三个绑定查询(接口都已存在,活动别名走后台配置):
bind_info / esports_bind_info / xpd_bind_info。

新增 derive_from_bind_info() 把返回推导成 4 态,**并做了实测校准**:

  账号  列值(旧)   is_bound_role   角色名            推导
  51    unknown     False           (空)              unbound
  60    unknown     True            唉清静的一生      bound
  61    unknown     True            柿子洋音          bound
  62    unknown     True            FatalistIc        bound

**4 个里 3 个其实已绑定,全被 unknown 盖住了。**

两个刻意的设计:

1. **推导不出来时返回 None,且不动原值** —— "没查到"和"没绑定"必须分开,
   写 unbound 就是编造结论(小店未开通、返回里没有标志时实测就是这种情况)
2. **不产出 pending** —— 它描述"正在绑定/待确认"这种**进行中的动作**
   (如刚生成过二维码),那是一次查询的副作用,不是查询能观测到的状态
3. need_bind_role **不是**"未绑定"的信号:实测**已绑定**的账号上它也是 1,
   拿它当判据会把这 3 个已绑定的判成未绑

端到端实测(账号 51):

  查询前: 精英=unknown  电竞=unknown  小店=unknown
  查询后: 精英=unbound  电竞=unbound  小店=unknown  ← 推不出来,正确保持原值

## 显示:把"没查过"和"查了推不出"分开

三处都改了(用户要求):全 unknown 时不再显示「精? 电? 店?」,
而是 **未查询**(点一键查询就有了)/ **未能判定**(斗鱼这次没给结论)。

## 验证(本地)

TZ=Asia/Shanghai **615 passed / 6 skipped**;ruff 全绿;前端 build 通过、lint 0 errors。
新增 9 条用例(含"need_bind_role 不是信号"的反向回归)。
2026-10-04 20:22:54 +08:00
..
2026-08-31 10:55:44 +08:00