优化斗鱼绑定状态同步
This commit is contained in:
@@ -334,6 +334,29 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind })
|
||||
return map;
|
||||
}, [tasks]);
|
||||
|
||||
const latestConfirmBindTaskByAccount = useMemo(() => {
|
||||
const map = new Map<number, DouyuTaskItem>();
|
||||
for (const task of tasks) {
|
||||
if (task.task_type !== 'confirm_bind') continue;
|
||||
if (!task.result) continue;
|
||||
const previous = map.get(task.account_id);
|
||||
if (!previous || task.id > previous.id) map.set(task.account_id, task);
|
||||
}
|
||||
return map;
|
||||
}, [tasks]);
|
||||
|
||||
const latestConfirmBindFailureByAccount = useMemo(() => {
|
||||
const map = new Map<number, DouyuTaskItem>();
|
||||
for (const task of tasks) {
|
||||
if (task.task_type !== 'confirm_bind') continue;
|
||||
if (!['failed', 'error'].includes(task.status)) continue;
|
||||
if (!(task.message || '').includes('待绑定游戏账号')) continue;
|
||||
const previous = map.get(task.account_id);
|
||||
if (!previous || task.id > previous.id) map.set(task.account_id, task);
|
||||
}
|
||||
return map;
|
||||
}, [tasks]);
|
||||
|
||||
const latestEsportsStateTaskByAccount = useMemo(() => {
|
||||
const map = new Map<number, DouyuTaskItem>();
|
||||
for (const task of tasks) {
|
||||
@@ -356,7 +379,7 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind })
|
||||
[tasks, activeQrTaskId],
|
||||
);
|
||||
|
||||
// 换绑时间:优先最近一次查询/拦截任务结果,回退账号落库字段
|
||||
// 换绑时间:优先最近一次查询/拦截/确认成功结果,回退账号落库字段
|
||||
const latestChangeWaitByAccount = useMemo(() => {
|
||||
const map = new Map<number, {
|
||||
wait: number | null; canChangeTime: number | null; text: string; taskId: number;
|
||||
@@ -364,9 +387,20 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind })
|
||||
for (const task of tasks) {
|
||||
const taskTypes = isEsportsHandbook
|
||||
? ['prepare_esports_bind', 'get_esports_bind_qr', 'query_esports_game_name', 'confirm_esports_bind']
|
||||
: ['query_change_bind_time', 'get_bind_qr'];
|
||||
: ['query_change_bind_time', 'get_bind_qr', 'confirm_bind'];
|
||||
if (!taskTypes.includes(task.task_type)) continue;
|
||||
if (!['success', 'failed'].includes(task.status)) continue;
|
||||
if (
|
||||
!isEsportsHandbook
|
||||
&& task.task_type === 'confirm_bind'
|
||||
&& (
|
||||
task.status !== 'success'
|
||||
|| !(
|
||||
resultFlag(task.result, 'bind_confirmed')
|
||||
|| resultFlag(task.result, 'is_bound_act')
|
||||
)
|
||||
)
|
||||
) continue;
|
||||
const wait = resultNumber(task.result, 'change_role_wait_time');
|
||||
const canChangeTime = resultNumber(task.result, 'can_change_time');
|
||||
// get_bind_qr 只有冷却拦截时才有 wait;无 wait 时跳过,避免覆盖
|
||||
@@ -644,6 +678,14 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind })
|
||||
for (const task of failedTasks) autoNotifiedConfirmFailedTaskIds.current.add(task.id);
|
||||
const latest = failedTasks[0];
|
||||
setConfirmFailTip({ taskId: latest.id, message: latest.message });
|
||||
setQrTaskIds((prev) => {
|
||||
const next = prev.filter((id) => {
|
||||
const task = visibleTasks.find((item) => item.id === id);
|
||||
return !task || task.account_id !== latest.account_id;
|
||||
});
|
||||
setActiveQrTaskId((cur) => (cur != null && !next.includes(cur) ? (next[next.length - 1] ?? null) : cur));
|
||||
return next;
|
||||
});
|
||||
}, [visibleTasks]);
|
||||
|
||||
// 弹窗倒计时自动关闭
|
||||
@@ -1019,32 +1061,76 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind })
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '游戏名', dataIndex: 'game_name', width: 130,
|
||||
title: '游戏名', dataIndex: 'game_name', width: 170,
|
||||
render: (_, record) => {
|
||||
const queryResult = (
|
||||
isEsportsHandbook
|
||||
? latestEsportsStateTaskByAccount.get(record.id)
|
||||
: latestQueryGameTaskByAccount.get(record.id)
|
||||
)?.result || null;
|
||||
// role_name = 当前已生效绑定角色;pending_role_name = 扫码后待确认的新角色
|
||||
const roleName = resultText(queryResult, 'role_name')
|
||||
|| (isEsportsHandbook ? record.esports_game_name : record.game_name);
|
||||
const pendingRoleName = resultText(queryResult, 'pending_role_name');
|
||||
const channel = (
|
||||
[resultText(queryResult, 'area_name'), resultText(queryResult, 'plat_name')]
|
||||
.filter(Boolean)
|
||||
.join(' / ')
|
||||
|| (isEsportsHandbook ? record.esports_game_channel : record.game_channel)
|
||||
const queryTask = isEsportsHandbook
|
||||
? latestEsportsStateTaskByAccount.get(record.id) || null
|
||||
: latestQueryGameTaskByAccount.get(record.id) || null;
|
||||
const confirmTask = isEsportsHandbook ? null : latestConfirmBindTaskByAccount.get(record.id) || null;
|
||||
const confirmSucceeded = Boolean(
|
||||
confirmTask
|
||||
&& confirmTask.status === 'success'
|
||||
&& (
|
||||
resultFlag(confirmTask.result, 'bind_confirmed')
|
||||
|| resultFlag(confirmTask.result, 'is_bound_act')
|
||||
),
|
||||
);
|
||||
return roleName ? (
|
||||
<Space direction="vertical" size={0}>
|
||||
<Text>{roleName}</Text>
|
||||
const stateTask = (
|
||||
confirmSucceeded
|
||||
&& (!queryTask || confirmTask!.id > queryTask.id)
|
||||
) ? confirmTask : queryTask;
|
||||
const confirmFailureTask = latestConfirmBindFailureByAccount.get(record.id);
|
||||
const clearPending = Boolean(
|
||||
!isEsportsHandbook
|
||||
&& confirmFailureTask
|
||||
&& stateTask
|
||||
&& confirmFailureTask.id > stateTask.id,
|
||||
);
|
||||
const stateResult = stateTask?.result || null;
|
||||
const stateRoleConfirmed = resultFlag(stateResult, 'is_bound_act') || resultFlag(stateResult, 'bind_confirmed');
|
||||
const stateRoleName = clearPending && !stateRoleConfirmed ? '' : resultText(stateResult, 'role_name');
|
||||
// role_name = 当前已生效绑定角色;pending_role_name = 扫码后待确认的新角色
|
||||
const roleName = stateRoleName
|
||||
|| (isEsportsHandbook ? record.esports_game_name : record.game_name);
|
||||
const stateChannel = clearPending && !stateRoleConfirmed
|
||||
? ''
|
||||
: [resultText(stateResult, 'area_name'), resultText(stateResult, 'plat_name')]
|
||||
.filter(Boolean)
|
||||
.join(' / ');
|
||||
const pendingRoleName = clearPending || confirmSucceeded ? '' : resultText(stateResult, 'pending_role_name');
|
||||
const channel = stateChannel || (isEsportsHandbook ? record.esports_game_channel : record.game_channel);
|
||||
const pendingChannel = clearPending || confirmSucceeded ? '' : [resultText(stateResult, 'pending_area_name'), resultText(stateResult, 'pending_plat_name')]
|
||||
.filter(Boolean)
|
||||
.join(' / ');
|
||||
if (!roleName && !pendingRoleName) return <Text type="secondary">未查</Text>;
|
||||
return (
|
||||
<Space direction="vertical" size={2} style={{ lineHeight: 1.35 }}>
|
||||
{roleName ? (
|
||||
<Space direction="vertical" size={0}>
|
||||
<Text ellipsis title={roleName}>
|
||||
{pendingRoleName ? `当前: ${roleName}` : roleName}
|
||||
</Text>
|
||||
{channel ? (
|
||||
<Text type="secondary" style={{ fontSize: 12 }} ellipsis title={channel}>
|
||||
{channel}
|
||||
</Text>
|
||||
) : null}
|
||||
</Space>
|
||||
) : null}
|
||||
{pendingRoleName ? (
|
||||
<Text type="warning" style={{ fontSize: 12 }}>待确认: {pendingRoleName}</Text>
|
||||
<Space direction="vertical" size={0}>
|
||||
<Text type="warning" style={{ fontSize: 12 }} ellipsis title={pendingRoleName}>
|
||||
待确认: {pendingRoleName}
|
||||
</Text>
|
||||
{pendingChannel ? (
|
||||
<Text type="warning" style={{ fontSize: 12 }} ellipsis title={pendingChannel}>
|
||||
{pendingChannel}
|
||||
</Text>
|
||||
) : null}
|
||||
</Space>
|
||||
) : null}
|
||||
{channel ? <Text type="secondary" style={{ fontSize: 12 }}>{channel}</Text> : null}
|
||||
</Space>
|
||||
) : <Text type="secondary">未查</Text>;
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user