mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-05-06 20:02:49 +08:00
feat(about): Hermes config/upgrade/uninstall use modal dialogs with logs
配置按钮: 弹出模态框显示当前 Hermes 配置(Provider/URL/Key/Model), 带"前往配置向导"按钮跳转 setup 页面 升级按钮: 确认模态框 → 进度条+实时日志(监听 hermes-install-log 事件) 卸载按钮: 两步确认(是否卸载 → 是否清除配置) → 进度条+日志 所有操作完成后自动刷新 Hermes 卡片数据 新增 6 个 i18n 键
This commit is contained in:
@@ -31,6 +31,11 @@ export default {
|
||||
hermesUninstallCleanConfig: _('是否同时清除配置文件?(选「取消」保留配置)', 'Also remove config files? (Cancel to keep)', '是否同時清除配置文件?(選「取消」保留配置)'),
|
||||
hermesUninstallOk: _('Hermes Agent 已卸载', 'Hermes Agent uninstalled', 'Hermes Agent 已卸載'),
|
||||
hermesUninstallFail: _('卸载失败: {error}', 'Uninstall failed: {error}', '卸載失敗: {error}'),
|
||||
hermesConfigFile: _('配置文件', 'Config file', '配置文件', '設定ファイル', '설정 파일'),
|
||||
hermesGoSetup: _('前往配置向导', 'Go to Setup Wizard', '前往配置嚮導'),
|
||||
hermesUpgradeConfirm: _('确定要升级 Hermes Agent 吗?将从 GitHub 重新安装最新版本。', 'Are you sure you want to upgrade Hermes Agent? This will reinstall the latest version from GitHub.', '確定要升級 Hermes Agent 嗎?將從 GitHub 重新安裝最新版本。'),
|
||||
hermesUninstallCleanConfigHint: _('同时清除配置文件和虚拟环境', 'Also removing config files and virtual environment', '同時清除配置文件和虛擬環境'),
|
||||
notSet: _('未设置', 'Not set', '未設置', '未設定', '미설정'),
|
||||
aheadOfRecommended: _('当前版本高于推荐稳定版: {ver}', 'Current version is ahead of recommended stable: {ver}', '目前版本高於推薦穩定版: {ver}'),
|
||||
rollbackToRecommended: _('回退到推荐版', 'Rollback to recommended', '回退到推薦版'),
|
||||
recommendedStable: _('推荐稳定版: {ver}', 'Recommended stable: {ver}', '推薦穩定版: {ver}', '推奨安定版: {ver}', '권장 안정 버전: {ver}'),
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
import { api } from '../lib/tauri-api.js'
|
||||
import { toast } from '../components/toast.js'
|
||||
import { showUpgradeModal, showConfirm } from '../components/modal.js'
|
||||
import { showUpgradeModal, showConfirm, showContentModal } from '../components/modal.js'
|
||||
import { setUpgrading } from '../lib/app-state.js'
|
||||
import { icon, statusIcon } from '../lib/icons.js'
|
||||
import { t, getLang } from '../lib/i18n.js'
|
||||
@@ -107,7 +107,7 @@ async function loadHermesData(page) {
|
||||
${model ? `<span style="color:var(--text-secondary)">${t('engine.dashModel')}: ${esc(model)}</span>` : ''}
|
||||
${!installed ? `<a class="btn btn-primary btn-sm" href="#/h/setup" style="${btnSm}">${t('about.hermesSetup')}</a>` : ''}
|
||||
${installed ? `
|
||||
<a class="btn btn-secondary btn-sm" href="#/h/setup" style="${btnSm}">${t('about.hermesConfig')}</a>
|
||||
<button class="btn btn-secondary btn-sm" id="btn-hermes-config" style="${btnSm}">${t('about.hermesConfig')}</button>
|
||||
<button class="btn btn-secondary btn-sm" id="btn-hermes-upgrade" style="${btnSm}">${t('about.hermesUpgrade')}</button>
|
||||
<button class="btn btn-danger btn-sm" id="btn-hermes-uninstall" style="${btnSm}">${t('about.hermesUninstall')}</button>
|
||||
` : ''}
|
||||
@@ -122,45 +122,102 @@ async function loadHermesData(page) {
|
||||
|
||||
// Hermes 管理按钮事件
|
||||
if (installed) {
|
||||
const upgradeBtn = cards.querySelector('#btn-hermes-upgrade')
|
||||
const uninstallBtn = cards.querySelector('#btn-hermes-uninstall')
|
||||
|
||||
if (upgradeBtn) {
|
||||
upgradeBtn.onclick = async () => {
|
||||
upgradeBtn.disabled = true
|
||||
upgradeBtn.textContent = t('about.upgrading')
|
||||
try {
|
||||
const ver = await api.updateHermes()
|
||||
toast(t('about.hermesUpgradeOk', { version: ver || '' }), 'success')
|
||||
loadHermesData(page)
|
||||
} catch (e) {
|
||||
toast(t('about.hermesUpgradeFail', { error: e.message || e }), 'error')
|
||||
} finally {
|
||||
upgradeBtn.disabled = false
|
||||
upgradeBtn.textContent = t('about.hermesUpgrade')
|
||||
}
|
||||
// --- 配置模态框 ---
|
||||
cards.querySelector('#btn-hermes-config')?.addEventListener('click', async () => {
|
||||
try {
|
||||
const cfg = await api.hermesReadConfig()
|
||||
const maskedKey = cfg.api_key ? cfg.api_key.slice(0, 6) + '••••' + cfg.api_key.slice(-4) : t('about.notSet')
|
||||
const overlay = showContentModal({
|
||||
title: `Hermes Agent ${t('about.hermesConfig')}`,
|
||||
width: 480,
|
||||
content: `
|
||||
<div style="display:grid;gap:12px;font-size:13px;line-height:1.6">
|
||||
<div style="display:flex;gap:8px"><span style="color:var(--text-tertiary);min-width:90px">${t('engine.configProvider')}:</span><span style="word-break:break-all">${esc(cfg.provider || '-')}</span></div>
|
||||
<div style="display:flex;gap:8px"><span style="color:var(--text-tertiary);min-width:90px">Base URL:</span><span style="word-break:break-all">${esc(cfg.base_url || '-')}</span></div>
|
||||
<div style="display:flex;gap:8px"><span style="color:var(--text-tertiary);min-width:90px">API Key:</span><span style="font-family:monospace">${esc(maskedKey)}</span></div>
|
||||
<div style="display:flex;gap:8px"><span style="color:var(--text-tertiary);min-width:90px">${t('engine.configModel')}:</span><span style="word-break:break-all">${esc(cfg.model_raw || cfg.model || '-')}</span></div>
|
||||
<div style="display:flex;gap:8px"><span style="color:var(--text-tertiary);min-width:90px">${t('about.hermesConfigFile')}:</span><span style="color:${cfg.config_exists ? 'var(--success)' : 'var(--warning)'}">${cfg.config_exists ? '✓' : '✗'}</span></div>
|
||||
</div>
|
||||
`,
|
||||
buttons: [
|
||||
{ label: t('about.hermesGoSetup'), className: 'btn btn-primary btn-sm', id: 'btn-goto-setup' },
|
||||
],
|
||||
})
|
||||
overlay.querySelector('#btn-goto-setup')?.addEventListener('click', () => {
|
||||
overlay.close()
|
||||
window.location.hash = '#/h/setup'
|
||||
})
|
||||
} catch (e) {
|
||||
toast(t('common.loadFailed') + ': ' + (e.message || e), 'error')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (uninstallBtn) {
|
||||
uninstallBtn.onclick = async () => {
|
||||
const confirmed = confirm(t('about.hermesUninstallConfirm'))
|
||||
if (!confirmed) return
|
||||
const cleanConfig = confirm(t('about.hermesUninstallCleanConfig'))
|
||||
uninstallBtn.disabled = true
|
||||
uninstallBtn.textContent = t('about.uninstalling')
|
||||
try {
|
||||
await api.uninstallHermes(cleanConfig)
|
||||
toast(t('about.hermesUninstallOk'), 'success')
|
||||
loadHermesData(page)
|
||||
} catch (e) {
|
||||
toast(t('about.hermesUninstallFail', { error: e.message || e }), 'error')
|
||||
} finally {
|
||||
uninstallBtn.disabled = false
|
||||
uninstallBtn.textContent = t('about.hermesUninstall')
|
||||
}
|
||||
// --- 升级模态框(带实时日志) ---
|
||||
cards.querySelector('#btn-hermes-upgrade')?.addEventListener('click', async () => {
|
||||
const confirmed = await showConfirm(t('about.hermesUpgradeConfirm'))
|
||||
if (!confirmed) return
|
||||
|
||||
const modal = showUpgradeModal(t('about.hermesUpgrade') + ' Hermes Agent')
|
||||
modal.setProgressLabels({
|
||||
preparing: t('about.upgrading'),
|
||||
downloading: t('about.upgrading'),
|
||||
installing: t('about.upgrading'),
|
||||
done: t('about.hermesUpgradeOk', { version: '' }),
|
||||
})
|
||||
modal.setProgress(10)
|
||||
|
||||
let unlisten = null
|
||||
try {
|
||||
const { listen } = await import('@tauri-apps/api/event')
|
||||
unlisten = await listen('hermes-install-log', (e) => {
|
||||
modal.appendLog(String(e.payload))
|
||||
})
|
||||
} catch (_) {}
|
||||
|
||||
modal.setProgress(20)
|
||||
try {
|
||||
const ver = await api.updateHermes()
|
||||
modal.setProgress(100)
|
||||
modal.setDone(t('about.hermesUpgradeOk', { version: ver || '' }))
|
||||
modal.onClose(() => loadHermesData(page))
|
||||
} catch (e) {
|
||||
modal.appendLog(`❌ ${e.message || e}`)
|
||||
modal.setError(t('about.hermesUpgradeFail', { error: e.message || e }))
|
||||
modal.onClose(() => loadHermesData(page))
|
||||
} finally {
|
||||
if (unlisten) unlisten()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// --- 卸载模态框(确认 + 实时日志) ---
|
||||
cards.querySelector('#btn-hermes-uninstall')?.addEventListener('click', async () => {
|
||||
const confirmed = await showConfirm(t('about.hermesUninstallConfirm'))
|
||||
if (!confirmed) return
|
||||
const cleanConfig = await showConfirm(t('about.hermesUninstallCleanConfig'))
|
||||
|
||||
const modal = showUpgradeModal(t('about.hermesUninstall') + ' Hermes Agent')
|
||||
modal.setProgressLabels({
|
||||
preparing: t('about.uninstalling'),
|
||||
downloading: t('about.uninstalling'),
|
||||
installing: t('about.uninstalling'),
|
||||
done: t('about.hermesUninstallOk'),
|
||||
})
|
||||
modal.appendLog('🗑️ ' + t('about.uninstalling'))
|
||||
if (cleanConfig) modal.appendLog('📁 ' + t('about.hermesUninstallCleanConfigHint'))
|
||||
modal.setProgress(30)
|
||||
|
||||
try {
|
||||
const result = await api.uninstallHermes(cleanConfig)
|
||||
modal.appendLog('✅ ' + (result || t('about.hermesUninstallOk')))
|
||||
modal.setProgress(100)
|
||||
modal.setDone(t('about.hermesUninstallOk'))
|
||||
modal.onClose(() => loadHermesData(page))
|
||||
} catch (e) {
|
||||
modal.appendLog(`❌ ${e.message || e}`)
|
||||
modal.setError(t('about.hermesUninstallFail', { error: e.message || e }))
|
||||
modal.onClose(() => loadHermesData(page))
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch {
|
||||
cards.innerHTML = `<div class="stat-card"><div class="stat-card-label">${t('common.loadFailed')}</div></div>`
|
||||
|
||||
Reference in New Issue
Block a user