mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-07-12 16:01:56 +08:00
fix(channels): add generic channel diagnostics
This commit is contained in:
@@ -219,6 +219,12 @@ export default {
|
||||
qqRepairBtn: _('一键修复', 'One-Click Repair', '一鍵修复'),
|
||||
qqFaqBtn: _('打开 QQ OpenClaw 常见问题', 'Open QQ OpenClaw FAQ', '開啟 QQ OpenClaw 常见問題'),
|
||||
qqDiagTitle: _('QQ 联通诊断', 'QQ Connectivity Diagnosis', 'QQ 聯通诊斷'),
|
||||
channelDiagTitle: _('{platform} 联通诊断', '{platform} Connectivity Diagnosis', '{platform} 聯通诊斷'),
|
||||
channelDiagAllPassed: _('配置侧检查已通过', 'Configuration checks passed', '設定側檢查已通過'),
|
||||
channelDiagHasFailed: _('存在需要处理的检查项', 'Some checks need attention', '存在需要處理的檢查項'),
|
||||
channelDiagPassed: _('通过', 'Passed', '通過'),
|
||||
channelDiagNeedsAction: _('需处理', 'Needs action', '需處理'),
|
||||
channelDiagNoChecks: _('暂无诊断结果', 'No diagnosis results yet', '暫無诊斷結果'),
|
||||
notes: _('说明', 'Notes', '說明'),
|
||||
processing: _('处理中...', 'Processing...', '處理中...'),
|
||||
repairDone: _('修复完成', 'Repair complete'),
|
||||
|
||||
@@ -1476,6 +1476,39 @@ function showQqDiagnoseModal(result, options = {}) {
|
||||
})
|
||||
}
|
||||
|
||||
function showChannelDiagnoseModal(result, options = {}) {
|
||||
const platformName = options.platformName || result?.platform || t('channels.channel')
|
||||
const checks = Array.isArray(result?.checks) ? result.checks : []
|
||||
const summaryOk = !!result?.overallReady
|
||||
const summary = summaryOk
|
||||
? `<div style="background:var(--success-muted);color:var(--success);padding:10px 14px;border-radius:var(--radius-md);margin-bottom:12px;font-size:var(--font-size-sm);line-height:1.5">${icon('check', 14)} ${t('channels.channelDiagAllPassed')}</div>`
|
||||
: `<div style="background:var(--warning-muted);color:var(--warning);padding:10px 14px;border-radius:var(--radius-md);margin-bottom:12px;font-size:var(--font-size-sm);line-height:1.5">${icon('alert-triangle', 14)} ${t('channels.channelDiagHasFailed')}</div>`
|
||||
const list = checks.map(c => {
|
||||
const ok = !!c.ok
|
||||
const tone = ok ? 'var(--success)' : 'var(--error)'
|
||||
const bg = ok ? 'var(--success-muted)' : 'var(--error-muted, rgba(220,38,38,0.1))'
|
||||
const label = ok ? t('channels.channelDiagPassed') : t('channels.channelDiagNeedsAction')
|
||||
return `<div style="border:1px solid ${bg};border-left:3px solid ${tone};padding:10px 12px;margin-bottom:8px;background:var(--bg-tertiary);border-radius:var(--radius-md)">
|
||||
<div style="display:flex;align-items:center;gap:8px;font-weight:600;color:var(--text-primary)">
|
||||
<span style="color:${tone};min-width:18px">${ok ? icon('check', 14) : icon('x', 14)}</span>
|
||||
<span>${escapeAttr(c.title || '')}</span>
|
||||
<span style="margin-left:auto;font-size:var(--font-size-xs);font-weight:600;color:${tone};background:${bg};padding:2px 8px;border-radius:999px;white-space:nowrap">${label}</span>
|
||||
</div>
|
||||
<div style="font-size:var(--font-size-sm);color:var(--text-secondary);margin-top:6px;line-height:1.55;white-space:pre-wrap">${escapeAttr(c.detail || '')}</div>
|
||||
</div>`
|
||||
}).join('')
|
||||
const hints = (result?.userHints || []).map(h =>
|
||||
`<li style="margin-bottom:8px;line-height:1.5">${escapeAttr(h)}</li>`
|
||||
).join('')
|
||||
const empty = `<div class="form-hint" style="padding:12px 0">${t('channels.channelDiagNoChecks')}</div>`
|
||||
|
||||
showContentModal({
|
||||
title: t('channels.channelDiagTitle', { platform: platformName }),
|
||||
content: `${summary}<div style="max-height:min(52vh,420px);overflow-y:auto;margin-bottom:12px;margin-top:12px">${list || empty}</div><div style="font-weight:600;margin-bottom:8px;font-size:var(--font-size-sm)">${t('channels.notes')}</div><ul style="padding-left:18px;font-size:var(--font-size-sm);color:var(--text-secondary);margin:0">${hints}</ul>`,
|
||||
width: 540,
|
||||
})
|
||||
}
|
||||
|
||||
async function runChannelTestForBinding(binding, btnEl) {
|
||||
const match = binding?.match || {}
|
||||
const channel = match.channel
|
||||
@@ -1489,30 +1522,18 @@ async function runChannelTestForBinding(binding, btnEl) {
|
||||
const prevHtml = btnEl?.innerHTML
|
||||
if (btnEl) {
|
||||
btnEl.disabled = true
|
||||
btnEl.textContent = channel === 'qqbot' ? t('channels.diagnosing') : t('channels.testing')
|
||||
btnEl.textContent = t('channels.diagnosing')
|
||||
}
|
||||
try {
|
||||
const result = await api.diagnoseChannel(platformId, accountId)
|
||||
if (channel === 'qqbot') {
|
||||
const result = await api.diagnoseChannel('qqbot', accountId)
|
||||
showQqDiagnoseModal(result, { accountId })
|
||||
return
|
||||
}
|
||||
const res = await api.readPlatformConfig(platformId, accountId)
|
||||
if (!res?.exists) {
|
||||
toast(t('channels.noCredentialsFound'), 'warning')
|
||||
return
|
||||
}
|
||||
const form = res.values || {}
|
||||
const out = await api.verifyBotToken(platformId, form)
|
||||
if (out.valid) {
|
||||
const details = (out.details || []).join(' · ')
|
||||
toast(`${t('channels.testPassed')}${details ? ': ' + details : ''}`, 'success')
|
||||
} else {
|
||||
const errs = (out.errors || [t('channels.verifyFailed')]).join('; ')
|
||||
toast(t('channels.testFailed') + ': ' + errs, 'error')
|
||||
}
|
||||
const platformName = PLATFORM_REGISTRY[platformId]?.label || CHANNEL_LABELS[platformId] || platformId
|
||||
showChannelDiagnoseModal(result, { platformName, accountId })
|
||||
} catch (e) {
|
||||
toast(humanizeError(e, channel === 'qqbot' ? t('channels.diagFailed') : t('channels.testFailed')), 'error')
|
||||
toast(humanizeError(e, t('channels.diagFailed')), 'error')
|
||||
} finally {
|
||||
if (btnEl) {
|
||||
btnEl.disabled = false
|
||||
|
||||
Reference in New Issue
Block a user