fix(plugins): propagate refresh failures to their owning callers
This commit is contained in:
1 parent
b561b398b4
commit
ae99b884c6
6 files changed
+233
-29
No files matched your search
@@ -44,14 +44,15 @@ onMounted(async () => {
|
||||
async function prepare() {
|
||||
await Promise.all([props.prepareMaintenance(), flushSettings()])
|
||||
}
|
||||
async function perform(label: string, action: () => Promise<void>) {
|
||||
async function perform(label: string, action: (version: number) => Promise<void>) {
|
||||
if (busy.value) return
|
||||
const version = user.getSessionVersion()
|
||||
busy.value = true; progress.value = label; error.value = ''; message.value = ''
|
||||
try {
|
||||
await prepare()
|
||||
user.assertSession(version)
|
||||
await action()
|
||||
await action(version)
|
||||
user.assertSession(version)
|
||||
if (mounted) {
|
||||
emit('changed'); last.value = (await getMaintenanceStatusApi()).data
|
||||
}
|
||||
@@ -85,8 +86,21 @@ async function exportMarkdown() {
|
||||
async function exportSystemLogs() {
|
||||
await perform('正在导出日志…', async () => download(await exportLogsApi(), 'rawmark-system-logs.zip'))
|
||||
}
|
||||
async function syncPreferences() {
|
||||
await loadSettings(); await reloadTheme(); await refreshPlugins()
|
||||
async function syncPreferences(completed: string, version: number) {
|
||||
try {
|
||||
user.assertSession(version)
|
||||
await loadSettings()
|
||||
user.assertSession(version)
|
||||
await reloadTheme()
|
||||
user.assertSession(version)
|
||||
await refreshPlugins()
|
||||
user.assertSession(version)
|
||||
} catch (cause) {
|
||||
user.assertSession(version)
|
||||
if (isCancel(cause)) throw cause
|
||||
throw new Error(`${completed},但同步失败:${cause instanceof Error ? cause.message : String(cause)}`, { cause })
|
||||
}
|
||||
message.value = completed
|
||||
}
|
||||
async function reset() {
|
||||
if (busy.value) return
|
||||
@@ -98,8 +112,8 @@ async function reset() {
|
||||
busy.value = false
|
||||
}
|
||||
if (!confirmed) return
|
||||
await perform('正在重置设置…', async () => {
|
||||
await resetSettingsApi(); await syncPreferences(); message.value = '设置已重置,原设置已备份'
|
||||
await perform('正在重置设置…', async (version) => {
|
||||
await resetSettingsApi(); await syncPreferences('设置已重置,原设置已备份', version)
|
||||
})
|
||||
}
|
||||
async function restore(kind: BackupKind, event: Event) {
|
||||
@@ -132,7 +146,7 @@ async function restore(kind: BackupKind, event: Event) {
|
||||
progress.value = kind === 'full' ? '正在恢复实例,请勿关闭页面…' : '正在导入设置…'
|
||||
if (kind === 'settings') {
|
||||
await importSettingsApi(id); submitted = true
|
||||
await syncPreferences(); message.value = '设置与资源已导入,原设置已备份'
|
||||
await syncPreferences('设置与资源已导入,原设置已备份', version)
|
||||
} else {
|
||||
await restoreBackupApi(id); submitted = true
|
||||
user.invalidate(version)
|
||||
|
||||
@@ -9,7 +9,6 @@ import { pluginsPaused, settingTabs } from '@@/plugins/registry'
|
||||
import { confirmAction } from '@@/utils/confirm'
|
||||
import { isCancel } from 'axios'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { ApiError } from '@/http/axios'
|
||||
|
||||
const busy = ref(false)
|
||||
const error = ref('')
|
||||
@@ -18,17 +17,16 @@ const selected = ref('')
|
||||
const currentTab = computed(() => settingTabs.get(selected.value))
|
||||
const labels: Record<string, string> = { loading: '加载中', active: '运行中', error: '故障停用', disabled: '已停用', paused: '临时跳过' }
|
||||
|
||||
async function perform(operation?: () => Promise<unknown>, confirmation?: string) {
|
||||
async function perform(operation: () => Promise<unknown> = refreshPlugins, confirmation?: string) {
|
||||
if (busy.value) return
|
||||
busy.value = true
|
||||
error.value = ''
|
||||
try {
|
||||
if (confirmation && !await confirmAction(confirmation)) return
|
||||
if (operation) await operation()
|
||||
await refreshPlugins()
|
||||
await operation()
|
||||
} catch (err) {
|
||||
if (isCancel(err)) return
|
||||
error.value = err instanceof ApiError ? err.message : '插件操作失败,请检查连接后重试'
|
||||
error.value = err instanceof Error ? err.message : String(err)
|
||||
} finally {
|
||||
busy.value = false
|
||||
}
|
||||
@@ -39,15 +37,21 @@ async function install(event: Event) {
|
||||
const file = input.files?.[0]
|
||||
input.value = ''
|
||||
if (!file) return
|
||||
await perform(() => installPluginApi(file), '插件在页面内拥有完整权限,可读取和修改全部笔记及账户数据。仅安装你信任的插件。确认安装?')
|
||||
await perform(async () => {
|
||||
await installPluginApi(file); await refreshPlugins()
|
||||
}, '插件在页面内拥有完整权限,可读取和修改全部笔记及账户数据。仅安装你信任的插件。确认安装?')
|
||||
}
|
||||
|
||||
async function remove(plugin: InstalledPlugin) {
|
||||
await perform(() => uninstallPluginApi(plugin.id), `卸载插件“${plugin.name}”?将停用并删除插件文件,保留插件数据。`)
|
||||
await perform(async () => {
|
||||
await uninstallPluginApi(plugin.id); await refreshPlugins()
|
||||
}, `卸载插件“${plugin.name}”?将停用并删除插件文件,保留插件数据。`)
|
||||
}
|
||||
|
||||
function toggle(plugin: InstalledPlugin) {
|
||||
void perform(() => togglePluginApi({ id: plugin.id, enabled: !plugin.enabled }))
|
||||
void perform(async () => {
|
||||
await togglePluginApi({ id: plugin.id, enabled: !plugin.enabled }); await refreshPlugins()
|
||||
})
|
||||
}
|
||||
onMounted(() => perform())
|
||||
</script>
|
||||
@@ -93,7 +97,7 @@ onMounted(() => perform())
|
||||
<!-- @vue-generic {InstalledPlugin} -->
|
||||
<el-table-column label="操作" width="130">
|
||||
<template #default="{ row: plugin }">
|
||||
<el-button v-if="plugin.enabled && pluginState.status[plugin.id]?.phase === 'error'" text :disabled="busy || pluginsPaused" @click="retryPlugin(plugin.id)">
|
||||
<el-button v-if="plugin.enabled && pluginState.status[plugin.id]?.phase === 'error'" text :disabled="busy || pluginsPaused" @click="perform(() => retryPlugin(plugin.id))">
|
||||
重试
|
||||
</el-button><el-button text type="danger" :disabled="busy" @click="remove(plugin)">
|
||||
卸载
|
||||
|
||||
Reference in new issue
Block a user