fix(douyu): 已绑定账号生成二维码不再立即成功, 正常等待扫码换绑

- 后端: get_xpd_bind_qr 生成二维码前记录绑定前状态(before_bound/
  before_role_name); 轮询判断改为 —— 未绑定: 检测到 bind_role=1 成功;
  已绑定(换绑): 角色名变化才算成功, 角色不变继续等待
- 前端: 弹窗保留二维码与角色信息; 轮询期间显示"当前绑定: 原角色",
  换绑成功显示新角色; 确认绑定维持手动(小程序内人工确认)
This commit is contained in:
yml2213
2026-08-06 18:28:06 +08:00
parent ee097e1fda
commit 86459a1bd0
2 changed files with 51 additions and 27 deletions
+21 -3
View File
@@ -1086,7 +1086,7 @@ class DouyuBatchRunner:
cookie: str, cookie: str,
config: dict, config: dict,
): ):
"""生成和平小店绑定二维码并轮询等待微信扫码绑定完成。""" """生成和平小店绑定二维码并轮询等待微信扫码绑定/换绑完成。"""
client = self._client(cookie) client = self._client(cookie)
act_alias = str(config.get("xpd_act_alias") or "").strip() act_alias = str(config.get("xpd_act_alias") or "").strip()
if not act_alias: if not act_alias:
@@ -1096,6 +1096,16 @@ class DouyuBatchRunner:
account.xpd_bind_status = "xpd_bind_qr_ready" account.xpd_bind_status = "xpd_bind_qr_ready"
account.updated_at = datetime.now(timezone.utc) account.updated_at = datetime.now(timezone.utc)
db.commit() db.commit()
# 记录绑定前状态:已绑定账号生成二维码后必须等扫码换绑,不能立即成功
try:
before = client.xpd_bind_info(act_alias=act_alias)
result["before_bound"] = bool(before.get("bind_role"))
result["before_role_name"] = str(before.get("role_name") or "")
result["before_area_name"] = str(before.get("area_name") or "")
result["before_plat_name"] = str(before.get("plat_name") or "")
except Exception:
result["before_bound"] = False
result["before_role_name"] = ""
result["bind_polling"] = True result["bind_polling"] = True
self._update_task_progress( self._update_task_progress(
db, db,
@@ -1134,7 +1144,13 @@ class DouyuBatchRunner:
act_alias: str, act_alias: str,
result: dict, result: dict,
) -> bool: ) -> bool:
"""轮询 bindInfo,检测到绑定角色即回写账号并返回 True。""" """轮询 bindInfo 等待绑定/换绑完成。
- 绑定前未绑定:检测到 bind_role=1 即绑定成功
- 绑定前已绑定(换绑):检测到角色名变化才算换绑成功,角色不变继续等
"""
before_bound = bool(result.get("before_bound"))
before_role_name = str(result.get("before_role_name") or "")
deadline = time.monotonic() + DOUYU_XPD_BIND_POLL_SECONDS deadline = time.monotonic() + DOUYU_XPD_BIND_POLL_SECONDS
poll_count = 0 poll_count = 0
while not self._stop.is_set() and time.monotonic() <= deadline: while not self._stop.is_set() and time.monotonic() <= deadline:
@@ -1144,7 +1160,9 @@ class DouyuBatchRunner:
result["bind_poll_count"] = poll_count result["bind_poll_count"] = poll_count
result["bind_polling"] = True result["bind_polling"] = True
role_name = str(info.get("role_name") or "") role_name = str(info.get("role_name") or "")
if info.get("bind_role") and role_name: bound_now = bool(info.get("bind_role"))
changed = before_bound and bool(role_name) and role_name != before_role_name
if (not before_bound and bound_now and role_name) or changed:
result.update({key: value for key, value in info.items() if key != "raw"}) result.update({key: value for key, value in info.items() if key != "raw"})
result["bind_polling"] = False result["bind_polling"] = False
result["xpd_bound"] = True result["xpd_bound"] = True
+30 -24
View File
@@ -1064,30 +1064,36 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind })
const qrRoleName = resultText(qrRoleSourceResult, 'pending_role_name') || resultText(qrRoleSourceResult, 'role_name'); const qrRoleName = resultText(qrRoleSourceResult, 'pending_role_name') || resultText(qrRoleSourceResult, 'role_name');
const qrAreaName = resultText(qrRoleSourceResult, 'pending_area_name') || resultText(qrRoleSourceResult, 'area_name'); const qrAreaName = resultText(qrRoleSourceResult, 'pending_area_name') || resultText(qrRoleSourceResult, 'area_name');
const qrPlatName = resultText(qrRoleSourceResult, 'pending_plat_name') || resultText(qrRoleSourceResult, 'plat_name'); const qrPlatName = resultText(qrRoleSourceResult, 'pending_plat_name') || resultText(qrRoleSourceResult, 'plat_name');
const qrCurrentRoleName = qrQueryRoleName const qrCurrentRoleName = isXpdBindTask
|| resultText(qrResult, 'current_role_name') ? resultText(qrResult, 'before_role_name')
|| ( : (qrQueryRoleName
resultFlag(qrResult, 'is_bound_act') || resultText(qrResult, 'current_role_name')
? resultText(qrResult, 'role_name') || (
: '' resultFlag(qrResult, 'is_bound_act')
) ? resultText(qrResult, 'role_name')
|| (qrQueryIsBoundAct ? qrQueryRoleName : ''); : ''
const qrCurrentAreaName = resultText(qrQueryResult, 'area_name') )
|| resultText(qrResult, 'current_area_name') || (qrQueryIsBoundAct ? qrQueryRoleName : ''));
|| ( const qrCurrentAreaName = isXpdBindTask
resultFlag(qrResult, 'is_bound_act') ? resultText(qrResult, 'before_area_name')
? resultText(qrResult, 'area_name') : (resultText(qrQueryResult, 'area_name')
: '' || resultText(qrResult, 'current_area_name')
) || (
|| (qrQueryIsBoundAct ? resultText(qrQueryResult, 'area_name') : ''); resultFlag(qrResult, 'is_bound_act')
const qrCurrentPlatName = resultText(qrQueryResult, 'plat_name') ? resultText(qrResult, 'area_name')
|| resultText(qrResult, 'current_plat_name') : ''
|| ( )
resultFlag(qrResult, 'is_bound_act') || (qrQueryIsBoundAct ? resultText(qrQueryResult, 'area_name') : ''));
? resultText(qrResult, 'plat_name') const qrCurrentPlatName = isXpdBindTask
: '' ? resultText(qrResult, 'before_plat_name')
) : (resultText(qrQueryResult, 'plat_name')
|| (qrQueryIsBoundAct ? resultText(qrQueryResult, 'plat_name') : ''); || resultText(qrResult, 'current_plat_name')
|| (
resultFlag(qrResult, 'is_bound_act')
? resultText(qrResult, 'plat_name')
: ''
)
|| (qrQueryIsBoundAct ? resultText(qrQueryResult, 'plat_name') : ''));
const qrRoleLine = qrBindReady const qrRoleLine = qrBindReady
? [qrPlatName, qrAreaName, qrRoleName].filter(Boolean).join(' - ') ? [qrPlatName, qrAreaName, qrRoleName].filter(Boolean).join(' - ')
: ''; : '';