fix(accounts): 完善手机号必绑与账号注销等登录异常分型识别

- 补充必须绑定手机号与账号注销/封禁/冻结等错误文案的识别规则
- 增加数据修正迁移 20261008_0052,回写历史账号和登录任务的失败分型
- 增加列表查询与导出时根据错误文案自动兜底细化 failure_kind 的逻辑
- 增加并完善相关分型单元测试
This commit is contained in:
yml2213
2026-10-08 11:26:19 +08:00
parent f8ad6e1777
commit 4eef45efe4
5 changed files with 122 additions and 10 deletions
@@ -0,0 +1,72 @@
"""同步历史重登失败分型:根据最新 classify_failure 规则刷正 accounts 和 login_tasks
## 背景
新增了「必须绑定手机号」与「账号注销/封禁」分型,历史已存在报错文案的账号需要回写正确的 failure_kind,
使「登录异常一键筛选」与列表角标统计准确。
"""
from __future__ import annotations
import sqlalchemy as sa
from alembic import op
from web.backend.services.login_failure import classify_failure
revision: str = "20261008_0052"
down_revision: str | None = "20261004_0051"
branch_labels: str | None = None
depends_on: str | None = None
def upgrade() -> None:
conn = op.get_bind()
# 1. 查询 accounts 中有 relogin_last_error 的记录
rows = conn.execute(
sa.text(
"SELECT id, relogin_last_error, relogin_failure_kind "
"FROM accounts "
"WHERE relogin_last_error IS NOT NULL AND relogin_last_error != ''"
)
).fetchall()
for row in rows:
acc_id, err_text, current_kind = row[0], row[1], row[2]
new_kind = classify_failure(err_text)
if new_kind and new_kind != current_kind:
conn.execute(
sa.text("UPDATE accounts SET relogin_failure_kind = :k WHERE id = :id"),
{"k": new_kind, "id": acc_id},
)
# 2. 查询 login_tasks 中有 message 的记录
# 检查 login_tasks 是否有 relogin_failure_kind 列
col_exists = conn.execute(
sa.text(
"SELECT COUNT(*) FROM information_schema.columns "
"WHERE table_schema = DATABASE() "
"AND table_name = 'login_tasks' AND column_name = 'relogin_failure_kind'"
)
).scalar()
if col_exists:
task_rows = conn.execute(
sa.text(
"SELECT id, message, relogin_failure_kind "
"FROM login_tasks "
"WHERE message IS NOT NULL AND message != ''"
)
).fetchall()
for row in task_rows:
task_id, msg, current_kind = row[0], row[1], row[2]
new_kind = classify_failure(msg)
if new_kind and new_kind != current_kind:
conn.execute(
sa.text(
"UPDATE login_tasks SET relogin_failure_kind = :k WHERE id = :id"
),
{"k": new_kind, "id": task_id},
)
def downgrade() -> None:
pass