feat: implement automatic refresh logic for expired WeChat Claw Bot QR codes

This commit is contained in:
jxxghp
2026-05-10 22:45:21 +08:00
parent 9703b2dbee
commit a2b2e8cd94

View File

@@ -83,6 +83,18 @@ interface WechatClawBotStatus {
base_url?: string | null base_url?: string | null
} }
interface WechatClawBotStatusFetchOptions {
autoGenerateQrcode?: boolean
silent?: boolean
autoRefreshExpired?: boolean
showErrorToast?: boolean
}
interface WechatClawBotRefreshOptions {
silent?: boolean
showToast?: boolean
}
function ensureWechatConfigDefaults(notification: NotificationConf) { function ensureWechatConfigDefaults(notification: NotificationConf) {
if (notification.type !== 'wechat') { if (notification.type !== 'wechat') {
return return
@@ -117,6 +129,7 @@ const wechatClawBotLoading = ref(false)
const wechatClawBotActionLoading = ref(false) const wechatClawBotActionLoading = ref(false)
const wechatClawBotStatus = ref<WechatClawBotStatus | null>(null) const wechatClawBotStatus = ref<WechatClawBotStatus | null>(null)
const wechatClawBotQrImage = ref('') const wechatClawBotQrImage = ref('')
const wechatClawBotExpiredRefreshAttempted = ref(false)
let wechatClawBotTimer: number | null = null let wechatClawBotTimer: number | null = null
function isImageSource(value?: string | null) { function isImageSource(value?: string | null) {
@@ -201,7 +214,10 @@ function openNotificationInfoDialog() {
ensureWechatClawBotConfigDefaults(notificationInfo.value) ensureWechatClawBotConfigDefaults(notificationInfo.value)
notificationInfoDialog.value = true notificationInfoDialog.value = true
if (notificationInfo.value.type === 'wechatclawbot') { if (notificationInfo.value.type === 'wechatclawbot') {
fetchWechatClawBotStatus(true) fetchWechatClawBotStatus({
autoGenerateQrcode: true,
autoRefreshExpired: true,
})
} }
} }
@@ -240,16 +256,27 @@ function scheduleWechatClawBotRefresh() {
const pendingStatus = ['waiting', 'scanned'].includes((wechatClawBotStatus.value?.qrcode_status || '').toLowerCase()) const pendingStatus = ['waiting', 'scanned'].includes((wechatClawBotStatus.value?.qrcode_status || '').toLowerCase())
if (connected || pendingStatus) { if (connected || pendingStatus) {
wechatClawBotTimer = window.setTimeout(() => { wechatClawBotTimer = window.setTimeout(() => {
fetchWechatClawBotStatus(false) fetchWechatClawBotStatus({
silent: true,
autoRefreshExpired: true,
})
}, connected ? 10000 : 3000) }, connected ? 10000 : 3000)
} }
} }
async function fetchWechatClawBotStatus(autoGenerateQrcode = false) { async function fetchWechatClawBotStatus(options: WechatClawBotStatusFetchOptions = {}) {
const {
autoGenerateQrcode = false,
silent = false,
autoRefreshExpired = false,
showErrorToast = true,
} = options
if (notificationInfo.value.type !== 'wechatclawbot' || !notificationInfo.value.name) { if (notificationInfo.value.type !== 'wechatclawbot' || !notificationInfo.value.name) {
return return
} }
wechatClawBotLoading.value = true if (!silent) {
wechatClawBotLoading.value = true
}
try { try {
const result: { [key: string]: any } = await api.get('notification/wechatclawbot/status', { const result: { [key: string]: any } = await api.get('notification/wechatclawbot/status', {
params: getWechatClawBotRequestParams({ auto_generate_qrcode: autoGenerateQrcode }), params: getWechatClawBotRequestParams({ auto_generate_qrcode: autoGenerateQrcode }),
@@ -257,27 +284,53 @@ async function fetchWechatClawBotStatus(autoGenerateQrcode = false) {
if (result.success) { if (result.success) {
wechatClawBotStatus.value = result.data wechatClawBotStatus.value = result.data
await updateWechatClawBotQrImage(result.data) await updateWechatClawBotQrImage(result.data)
const status = (result.data?.qrcode_status || '').toLowerCase()
if (status !== 'expired') {
wechatClawBotExpiredRefreshAttempted.value = false
}
if (
autoRefreshExpired &&
!result.data?.connected &&
status === 'expired' &&
!wechatClawBotExpiredRefreshAttempted.value
) {
wechatClawBotExpiredRefreshAttempted.value = true
await refreshWechatClawBotQrcode({
silent: true,
showToast: false,
})
return
}
scheduleWechatClawBotRefresh() scheduleWechatClawBotRefresh()
} else { } else {
wechatClawBotStatus.value = null wechatClawBotStatus.value = null
wechatClawBotQrImage.value = '' wechatClawBotQrImage.value = ''
clearWechatClawBotTimer() clearWechatClawBotTimer()
$toast.error(result.message || t('notification.wechatclawbot.statusLoadFailed')) if (showErrorToast) {
$toast.error(result.message || t('notification.wechatclawbot.statusLoadFailed'))
}
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
clearWechatClawBotTimer() clearWechatClawBotTimer()
$toast.error(t('notification.wechatclawbot.statusLoadFailed')) if (showErrorToast) {
$toast.error(t('notification.wechatclawbot.statusLoadFailed'))
}
} finally { } finally {
wechatClawBotLoading.value = false if (!silent) {
wechatClawBotLoading.value = false
}
} }
} }
async function refreshWechatClawBotQrcode() { async function refreshWechatClawBotQrcode(options: WechatClawBotRefreshOptions = {}) {
const { silent = false, showToast = true } = options
if (!notificationInfo.value.name) { if (!notificationInfo.value.name) {
return return
} }
wechatClawBotActionLoading.value = true if (!silent) {
wechatClawBotActionLoading.value = true
}
try { try {
const result: { [key: string]: any } = await api.post('notification/wechatclawbot/refresh', null, { const result: { [key: string]: any } = await api.post('notification/wechatclawbot/refresh', null, {
params: getWechatClawBotRequestParams(), params: getWechatClawBotRequestParams(),
@@ -285,16 +338,25 @@ async function refreshWechatClawBotQrcode() {
if (result.success) { if (result.success) {
wechatClawBotStatus.value = result.data wechatClawBotStatus.value = result.data
await updateWechatClawBotQrImage(result.data) await updateWechatClawBotQrImage(result.data)
wechatClawBotExpiredRefreshAttempted.value = false
scheduleWechatClawBotRefresh() scheduleWechatClawBotRefresh()
$toast.success(t('notification.wechatclawbot.qrcodeRefreshSuccess')) if (showToast) {
$toast.success(t('notification.wechatclawbot.qrcodeRefreshSuccess'))
}
} else { } else {
$toast.error(result.message || t('notification.wechatclawbot.qrcodeRefreshFailed')) if (showToast) {
$toast.error(result.message || t('notification.wechatclawbot.qrcodeRefreshFailed'))
}
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
$toast.error(t('notification.wechatclawbot.qrcodeRefreshFailed')) if (showToast) {
$toast.error(t('notification.wechatclawbot.qrcodeRefreshFailed'))
}
} finally { } finally {
wechatClawBotActionLoading.value = false if (!silent) {
wechatClawBotActionLoading.value = false
}
} }
} }
@@ -309,7 +371,10 @@ async function logoutWechatClawBot() {
}) })
if (result.success) { if (result.success) {
$toast.success(result.message || t('notification.wechatclawbot.logoutSuccess')) $toast.success(result.message || t('notification.wechatclawbot.logoutSuccess'))
await fetchWechatClawBotStatus(true) await fetchWechatClawBotStatus({
autoGenerateQrcode: true,
autoRefreshExpired: true,
})
} else { } else {
$toast.error(result.message || t('notification.wechatclawbot.logoutFailed')) $toast.error(result.message || t('notification.wechatclawbot.logoutFailed'))
} }
@@ -381,6 +446,7 @@ watch(notificationInfoDialog, value => {
if (!value) { if (!value) {
clearWechatClawBotTimer() clearWechatClawBotTimer()
wechatClawBotQrImage.value = '' wechatClawBotQrImage.value = ''
wechatClawBotExpiredRefreshAttempted.value = false
} }
}) })
</script> </script>
@@ -642,7 +708,7 @@ watch(notificationInfoDialog, value => {
size="small" size="small"
variant="tonal" variant="tonal"
:loading="wechatClawBotLoading" :loading="wechatClawBotLoading"
@click.stop="fetchWechatClawBotStatus(true)" @click.stop="fetchWechatClawBotStatus({ autoGenerateQrcode: true, autoRefreshExpired: true })"
> >
{{ t('common.refresh') }} {{ t('common.refresh') }}
</VBtn> </VBtn>