实现虎牙查询兑换记录

This commit is contained in:
yml2213
2026-07-05 00:15:10 +08:00
parent 5513b5a313
commit d5ecfb1c89
4 changed files with 284 additions and 1 deletions
+62
View File
@@ -211,6 +211,65 @@ class HuyaBatchRunner:
account.updated_at = datetime.now(timezone.utc)
self._mark_task(worker_db, task, "success", f"积分: {points}", result)
def _execute_query_exchange_records(
self,
worker_db: Session,
task: HuyaTask,
account: HuyaAccount,
account_info: dict,
config_info: dict,
):
sid = str(self.payload.get("sid") or config_info.get("sid") or "").strip()
if not sid:
self._mark_task(worker_db, task, "failed", "请先配置虎牙活动 SID")
return
sid_int = self._to_int(sid)
if not sid_int:
self._mark_task(worker_db, task, "failed", f"虎牙活动 SID 无效: {sid}")
return
uid = self._resolve_uid(account_info)
if not uid:
self._mark_task(worker_db, task, "failed", "无法从账号或 Cookie 解析 yyuid")
return
cookie = account_info.get("cookie") or ""
if not cookie:
self._mark_task(worker_db, task, "failed", "账号 Cookie 为空")
return
client = HuyaHttpClient(logger=lambda msg: self._push_log("info", f"[{uid}] {msg}"))
response = client.get_user_prize_records(uid=uid, cookie=cookie, sid=sid_int)
if response is None:
self._mark_task(worker_db, task, "error", "虎牙兑换记录接口无响应")
return
result = response.to_dict()
result["sid"] = sid_int
if response.status != 200:
self._mark_task(
worker_db,
task,
"failed",
response.msg or f"虎牙兑换记录查询失败: {response.status}",
result,
)
return
records = result.get("records", [])
for index, item in enumerate(records, start=1):
item["index"] = index
item["exchange_time_text"] = self._format_local_time(int(item.get("exchange_time") or 0))
if item.get("score") is not None:
item["score_text"] = f"{int(item.get('score') or 0)}积分"
account.status = "exchange_records_queried"
account.updated_at = datetime.now(timezone.utc)
count = len(records)
message = f"兑换记录 {count}" if count else "暂无兑换记录"
self._mark_task(worker_db, task, "success", message, result)
def _execute_refresh_goods(
self,
worker_db: Session,
@@ -955,6 +1014,7 @@ class HuyaBatchRunner:
"get_bind_qr",
"confirm_bind",
"query_game_name",
"query_exchange_records",
"refresh_goods",
"refresh_recharge_goods",
"create_recharge_order",
@@ -978,6 +1038,8 @@ class HuyaBatchRunner:
self._execute_confirm_bind(worker_db, task, account, account_info, config_info)
elif self.task_type == "query_game_name":
self._execute_query_game_name(worker_db, task, account, account_info, config_info)
elif self.task_type == "query_exchange_records":
self._execute_query_exchange_records(worker_db, task, account, account_info, config_info)
worker_db.refresh(task)
if task.status == "success":
self._push_log("success", f"[{current}] {name} {task.message}")
+88 -1
View File
@@ -153,6 +153,7 @@ export default function HuyaTasksPage() {
const [batchId, setBatchId] = useState<string | null>(null);
const [qrTask, setQrTask] = useState<HuyaTaskItem | null>(null);
const [payTask, setPayTask] = useState<HuyaTaskItem | null>(null);
const [exchangeRecordsTask, setExchangeRecordsTask] = useState<HuyaTaskItem | null>(null);
const autoOpenedQrTaskIds = useRef<Set<number>>(new Set());
const autoOpenQrReady = useRef(false);
const autoOpenedPayTaskIds = useRef<Set<number>>(new Set());
@@ -422,6 +423,14 @@ export default function HuyaTasksPage() {
const payAccountName = payTask
? payTask.account_nickname || payTask.account_uid || `#${payTask.account_id}`
: '';
const exchangeRecordsResult = exchangeRecordsTask?.result || null;
const exchangeRecordsRaw = exchangeRecordsResult?.records;
const exchangeRecords = Array.isArray(exchangeRecordsRaw)
? exchangeRecordsRaw.filter((item) => item && typeof item === 'object') as Record<string, unknown>[]
: [];
const exchangeRecordsAccountName = exchangeRecordsTask
? exchangeRecordsTask.account_nickname || exchangeRecordsTask.account_uid || `#${exchangeRecordsTask.account_id}`
: '';
const renderTaskResult = (value: Record<string, unknown> | null, record: HuyaTaskItem) => {
const bindQrImage = resultText(value, 'mini_qrcode_image');
@@ -463,6 +472,18 @@ export default function HuyaTasksPage() {
if (value?.is_bound === false) return <Tag></Tag>;
return <Text type="secondary">-</Text>;
}
if (record.task_type === 'query_exchange_records') {
const recordCount = value?.record_count;
if (typeof recordCount === 'number' && recordCount > 0) {
return (
<Button size="small" icon={<FieldTimeOutlined />} onClick={() => setExchangeRecordsTask(record)}>
</Button>
);
}
if (typeof recordCount === 'number') return <Tag> {recordCount} </Tag>;
return <Text type="secondary">-</Text>;
}
if (record.task_type === 'refresh_goods') {
const goodsCount = value?.goods_count;
if (typeof goodsCount === 'number') return <Tag color="green"> {goodsCount} </Tag>;
@@ -603,6 +624,49 @@ export default function HuyaTasksPage() {
},
];
const exchangeRecordColumns: TableProps<Record<string, unknown>>['columns'] = [
{
title: '序号',
width: 70,
align: 'center',
render: (_: unknown, record, index) => String(record.index || index + 1),
},
{
title: '消耗',
width: 110,
render: (_: unknown, record) => {
const scoreText = record.score_text;
if (typeof scoreText === 'string' && scoreText) return scoreText;
const score = record.score;
return typeof score === 'number' ? `${score}积分` : <Text type="secondary">-</Text>;
},
},
{
title: '奖品名称',
dataIndex: 'prize_name',
ellipsis: true,
render: (value: unknown) => typeof value === 'string' && value ? value : <Text type="secondary">-</Text>,
},
{
title: '兑换状态',
width: 110,
align: 'center',
render: (_: unknown, record) => {
const label = typeof record.status_label === 'string' ? record.status_label : '';
const color = label === '已发放' ? 'green' : 'orange';
return label ? <Tag color={color}>{label}</Tag> : <Text type="secondary">-</Text>;
},
},
{
title: '兑换时间',
width: 170,
render: (_: unknown, record) => {
const text = record.exchange_time_text;
return typeof text === 'string' && text ? text : <Text type="secondary">-</Text>;
},
},
];
return (
<div style={{ height: '100%', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<div style={{ flexShrink: 0, marginBottom: 12, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12 }}>
@@ -838,7 +902,7 @@ export default function HuyaTasksPage() {
))}
</div>
<Text type="secondary" style={{ fontSize: 12 }}>
</Text>
</div>
</Card>
@@ -872,6 +936,29 @@ export default function HuyaTasksPage() {
style={{ marginTop: 4 }}
/>
<Modal
title="兑换记录"
open={!!exchangeRecordsTask}
onCancel={() => setExchangeRecordsTask(null)}
footer={null}
width={760}
>
<Space direction="vertical" size={10} style={{ width: '100%' }}>
<Text type="secondary">
{exchangeRecordsAccountName}{exchangeRecordsResult?.sid ? ` / SID ${String(exchangeRecordsResult.sid)}` : ''}
</Text>
<Table
columns={exchangeRecordColumns}
dataSource={exchangeRecords}
rowKey={(record) => String(record.record_id || record.order_id || record.index)}
size="small"
pagination={false}
scroll={{ y: 360 }}
locale={{ emptyText: '暂无兑换记录' }}
/>
</Space>
</Modal>
<Modal
title="绑定小程序码"
open={!!qrTask}