From dea3306b416e01312ba27dda078950e502c36d74 Mon Sep 17 00:00:00 2001 From: sunlei Date: Thu, 4 Jun 2026 03:32:04 +0800 Subject: [PATCH] =?UTF-8?q?fix(admin):=20=E4=BF=AE=E5=A4=8DQQBot=E7=BA=BF?= =?UTF-8?q?=E4=B8=8A=E4=BA=8C=E7=BB=B4=E7=A0=81=E7=BC=93=E5=AD=98=E8=BF=87?= =?UTF-8?q?=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/qqbot/account/list.tsx | 51 ++++++++++++++++--- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/apps/web-antdv-next/src/views/qqbot/account/list.tsx b/apps/web-antdv-next/src/views/qqbot/account/list.tsx index c0e83ac..d7e6e1b 100644 --- a/apps/web-antdv-next/src/views/qqbot/account/list.tsx +++ b/apps/web-antdv-next/src/views/qqbot/account/list.tsx @@ -43,6 +43,7 @@ export default defineComponent({ const router = useRouter(); const scanLoading = ref(false); const scanQrcodeImageFailed = ref(false); + const scanQrcodeRevision = ref(0); const scanQrcodeText = ref(''); const scanState = reactive<{ containerId?: string; @@ -67,10 +68,18 @@ export default defineComponent({ const qrcode = scanQrcodeText.value.trim(); if (!qrcode) return ''; if (!scanQrcodeImageFailed.value && isQrcodeImageCandidate(qrcode)) { - return normalizeQrcodeImageSrc(qrcode); + return normalizeQrcodeImageSrc(qrcode, scanQrcodeRevision.value); } return scanQrcode.value; }); + const scanQrcodeOpenHref = computed(() => { + const qrcode = scanQrcodeText.value.trim(); + if (!qrcode) return ''; + if (isQrcodeImageCandidate(qrcode)) { + return normalizeQrcodeImageSrc(qrcode, scanQrcodeRevision.value); + } + return qrcode; + }); let scanTimer: number | undefined; const [AccountForm, accountFormApi] = useVbenForm({ @@ -306,14 +315,18 @@ export default defineComponent({ scanLoading.value = true; try { if (mode === 'create') { - await applyScanResult(await startQqbotAccountScanCreate()); + await applyScanResult(await startQqbotAccountScanCreate(), { + reloadQrcode: true, + }); return; } if (!row) { message.warning('请选择需要更新登录的账号'); return; } - await applyScanResult(await startQqbotAccountScanRefresh(row.id)); + await applyScanResult(await startQqbotAccountScanRefresh(row.id), { + reloadQrcode: true, + }); } catch (error) { stopScanPolling(); scanState.status = 'error'; @@ -323,7 +336,10 @@ export default defineComponent({ } } - async function applyScanResult(result: QqbotApi.AccountScanResult) { + async function applyScanResult( + result: QqbotApi.AccountScanResult, + options: { reloadQrcode?: boolean } = {}, + ) { scanState.containerId = result.containerId; scanState.containerName = result.containerName; scanState.errorMessage = result.errorMessage; @@ -334,10 +350,15 @@ export default defineComponent({ scanState.status = result.status; scanState.webuiPort = result.webuiPort; const nextQrcode = result.qrcode || ''; - if (nextQrcode !== scanQrcodeText.value) { + const qrcodeChanged = nextQrcode !== scanQrcodeText.value; + if (qrcodeChanged) { scanQrcodeImageFailed.value = false; } scanQrcodeText.value = nextQrcode; + if (nextQrcode && (qrcodeChanged || options.reloadQrcode)) { + scanQrcodeRevision.value += 1; + scanQrcodeImageFailed.value = false; + } if (result.status === 'pending') { startScanPolling(); @@ -371,6 +392,7 @@ export default defineComponent({ try { await applyScanResult( await refreshQqbotAccountScanQrcode(scanState.sessionId), + { reloadQrcode: true }, ); } finally { scanLoading.value = false; @@ -404,6 +426,7 @@ export default defineComponent({ webuiPort: undefined, }); scanQrcodeImageFailed.value = false; + scanQrcodeRevision.value = 0; scanQrcodeText.value = ''; } @@ -454,13 +477,27 @@ export default defineComponent({ ); } - function normalizeQrcodeImageSrc(value: string) { + function normalizeQrcodeImageSrc(value: string, revision = 0) { if (isRawBase64Image(value)) { return `data:image/png;base64,${value}`; } + if (/^https?:\/\//i.test(value) && revision > 0) { + return appendQrcodeCacheBuster(value, revision); + } return value; } + function appendQrcodeCacheBuster(value: string, revision: number) { + try { + const url = new URL(value); + url.searchParams.set('_kt_qrcode_v', `${revision}`); + return url.toString(); + } catch { + const joiner = value.includes('?') ? '&' : '?'; + return `${value}${joiner}_kt_qrcode_v=${revision}`; + } + } + function isRawBase64Image(value: string) { const normalized = value.trim(); return ( @@ -777,7 +814,7 @@ export default defineComponent({ )} {scanQrcodeText.value ? ( - + 打开扫码链接 ) : null}