feat: 添加 WebUI 迁移助手以及相关迁移方法 (#2477)
This commit is contained in:
@@ -34,7 +34,6 @@ from astrbot.core.platform_message_history_mgr import PlatformMessageHistoryMana
|
||||
from astrbot.core.astrbot_config_mgr import AstrBotConfigManager
|
||||
from astrbot.core.star.star_handler import star_handlers_registry, EventType
|
||||
from astrbot.core.star.star_handler import star_map
|
||||
from astrbot.core.db.migration.helper import do_migration_v4
|
||||
|
||||
|
||||
class AstrBotCoreLifecycle:
|
||||
@@ -72,11 +71,6 @@ class AstrBotCoreLifecycle:
|
||||
|
||||
await self.db.initialize()
|
||||
|
||||
try:
|
||||
await do_migration_v4(self.db, {}, self.astrbot_config)
|
||||
except Exception as e:
|
||||
logger.error(f"迁移到 v4.0.0 新版本数据格式失败: {e}")
|
||||
|
||||
# 初始化 AstrBot 配置管理器
|
||||
self.astrbot_config_mgr = AstrBotConfigManager(
|
||||
default_config=self.astrbot_config, sp=sp
|
||||
|
||||
@@ -43,14 +43,14 @@ async def do_migration_v4(
|
||||
# 执行会话表迁移
|
||||
await migration_conversation_table(db_helper, platform_id_map)
|
||||
|
||||
# 执行平台统计表迁移
|
||||
await migration_platform_table(db_helper, platform_id_map)
|
||||
# 执行人格数据迁移
|
||||
await migration_persona_data(db_helper, astrbot_config)
|
||||
|
||||
# 执行 WebChat 数据迁移
|
||||
await migration_webchat_data(db_helper, platform_id_map)
|
||||
|
||||
# 执行人格数据迁移
|
||||
await migration_persona_data(db_helper, astrbot_config)
|
||||
# 执行平台统计表迁移
|
||||
await migration_platform_table(db_helper, platform_id_map)
|
||||
|
||||
# 标记迁移完成
|
||||
await db_helper.insert_preference_or_update("migration_done_v4", "true")
|
||||
|
||||
@@ -7,8 +7,11 @@ from astrbot import logger
|
||||
DEFAULT_PERSONALITY = Personality(
|
||||
prompt="You are a helpful and friendly assistant.",
|
||||
name="default",
|
||||
begin_dialogs=[],
|
||||
mood_imitation_dialogs=[],
|
||||
tools=None,
|
||||
_begin_dialogs_processed=[],
|
||||
_mood_imitation_dialogs_processed="",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from astrbot.core.db import BaseDatabase
|
||||
from astrbot.core.config import VERSION
|
||||
from astrbot.core.utils.io import get_dashboard_version
|
||||
from astrbot.core import DEMO_MODE
|
||||
from astrbot.core.db.migration.helper import check_migration_needed_v4
|
||||
|
||||
|
||||
class StatRoute(Route):
|
||||
@@ -59,6 +60,8 @@ class StatRoute(Route):
|
||||
)
|
||||
|
||||
async def get_version(self):
|
||||
need_migration = await check_migration_needed_v4(self.core_lifecycle.db)
|
||||
|
||||
return (
|
||||
Response()
|
||||
.ok(
|
||||
@@ -66,6 +69,7 @@ class StatRoute(Route):
|
||||
"version": VERSION,
|
||||
"dashboard_version": await get_dashboard_version(),
|
||||
"change_pwd_hint": self.is_default_cred(),
|
||||
"need_migration": need_migration,
|
||||
}
|
||||
)
|
||||
.__dict__
|
||||
|
||||
@@ -7,6 +7,7 @@ from astrbot.core import logger, pip_installer
|
||||
from astrbot.core.utils.io import download_dashboard, get_dashboard_version
|
||||
from astrbot.core.config.default import VERSION
|
||||
from astrbot.core import DEMO_MODE
|
||||
from astrbot.core.db.migration.helper import do_migration_v4, check_migration_needed_v4
|
||||
|
||||
|
||||
class UpdateRoute(Route):
|
||||
@@ -23,11 +24,27 @@ class UpdateRoute(Route):
|
||||
"/update/do": ("POST", self.update_project),
|
||||
"/update/dashboard": ("POST", self.update_dashboard),
|
||||
"/update/pip-install": ("POST", self.install_pip_package),
|
||||
"/update/migration": ("POST", self.do_migration),
|
||||
}
|
||||
self.astrbot_updator = astrbot_updator
|
||||
self.core_lifecycle = core_lifecycle
|
||||
self.register_routes()
|
||||
|
||||
async def do_migration(self):
|
||||
need_migration = await check_migration_needed_v4(self.core_lifecycle.db)
|
||||
if not need_migration:
|
||||
return Response().ok(None, "不需要进行迁移。").__dict__
|
||||
try:
|
||||
data = await request.json
|
||||
pim = data.get("platform_id_map", {})
|
||||
await do_migration_v4(
|
||||
self.core_lifecycle.db, pim, self.core_lifecycle.astrbot_config
|
||||
)
|
||||
return Response().ok(None, "迁移成功。").__dict__
|
||||
except Exception as e:
|
||||
logger.error(f"迁移失败: {traceback.format_exc()}")
|
||||
return Response().error(f"迁移失败: {str(e)}").__dict__
|
||||
|
||||
async def check_update(self):
|
||||
type_ = request.args.get("type", None)
|
||||
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
<template>
|
||||
<v-dialog v-model="isOpen" persistent max-width="600" max-height="80vh" scrollable>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
{{ t('features.migration.dialog.title') }}
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text class="pa-6">
|
||||
<p class="mb-4">{{ t('features.migration.dialog.warning') }}</p>
|
||||
|
||||
|
||||
<div v-if="migrationCompleted" class="text-center py-8">
|
||||
<v-icon size="64" color="success" class="mb-4">mdi-check-circle</v-icon>
|
||||
<h3 class="mb-4">{{ t('features.migration.dialog.completed') }}</h3>
|
||||
{{ migrationResult?.message || t('features.migration.dialog.success') }}
|
||||
</div>
|
||||
|
||||
<div v-else-if="migrating" class="migration-in-progress">
|
||||
<div class="text-center py-4">
|
||||
<v-progress-circular indeterminate color="primary" class="mb-4"></v-progress-circular>
|
||||
<h3 class="mb-4">{{ t('features.migration.dialog.migrating') }}</h3>
|
||||
<p class="mb-4">{{ t('features.migration.dialog.migratingSubtitle') }}</p>
|
||||
</div>
|
||||
<div class="console-container">
|
||||
<ConsoleDisplayer ref="consoleDisplayer" :showLevelBtns="false" style="height: 300px;" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="loading" class="text-center py-8">
|
||||
<v-progress-circular indeterminate color="primary" class="mb-4"></v-progress-circular>
|
||||
<p>{{ t('features.migration.dialog.loading') }}</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="error" class="text-center py-4">
|
||||
<v-alert type="error" variant="tonal" class="mb-4">
|
||||
<template v-slot:prepend>
|
||||
<v-icon>mdi-alert</v-icon>
|
||||
</template>
|
||||
{{ error }}
|
||||
</v-alert>
|
||||
<v-btn color="primary" @click="loadPlatforms">
|
||||
{{ t('features.migration.dialog.retry') }}
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div v-if="platformGroups.length === 0" class="text-center py-4">
|
||||
<v-alert type="info" variant="tonal">
|
||||
<template v-slot:prepend>
|
||||
<v-icon>mdi-information</v-icon>
|
||||
</template>
|
||||
{{ t('features.migration.dialog.noPlatforms') }}
|
||||
</v-alert>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div v-for="group in platformGroups" :key="group.type" class="mb-6">
|
||||
<v-card variant="outlined" v-if="group.platforms.length > 1">
|
||||
<v-card-subtitle class="py-2">
|
||||
{{ group.type }}
|
||||
</v-card-subtitle>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-text style="padding: 16px;">
|
||||
<small>请选择该平台类型下您主要使用的平台适配器。</small>
|
||||
<v-radio-group v-model="selectedPlatforms[group.type]" :key="group.type"
|
||||
hide-details>
|
||||
<v-radio v-for="platform in group.platforms" :key="platform.id"
|
||||
:value="platform.id" :label="getPlatformLabel(platform)" color="primary"
|
||||
class="mb-1"></v-radio>
|
||||
</v-radio-group>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions class="px-6 py-4">
|
||||
<v-spacer></v-spacer>
|
||||
<template v-if="migrationCompleted">
|
||||
<v-btn color="primary" variant="elevated" @click="handleClose">
|
||||
{{ t('core.common.confirm') }}
|
||||
</v-btn>
|
||||
</template>
|
||||
<template v-else>
|
||||
<v-btn color="grey" variant="text" @click="handleCancel" :disabled="migrating">
|
||||
{{ t('core.common.cancel') }}
|
||||
</v-btn>
|
||||
<v-btn color="primary" variant="elevated" @click="handleMigration" :disabled="!canMigrate || migrating"
|
||||
:loading="migrating">
|
||||
{{ t('features.migration.dialog.startMigration') }}
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import axios from 'axios'
|
||||
import { useI18n } from '@/i18n/composables'
|
||||
import ConsoleDisplayer from './ConsoleDisplayer.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const isOpen = ref(false)
|
||||
const loading = ref(false)
|
||||
const error = ref('')
|
||||
const migrating = ref(false)
|
||||
const migrationCompleted = ref(false)
|
||||
const migrationResult = ref(null)
|
||||
const platforms = ref([])
|
||||
const selectedPlatforms = ref({})
|
||||
|
||||
let resolvePromise = null
|
||||
|
||||
// 计算属性:将平台按类型分组
|
||||
const platformGroups = computed(() => {
|
||||
const groups = {}
|
||||
platforms.value.forEach(platform => {
|
||||
const type = platform.platform_type || platform.type
|
||||
if (!groups[type]) {
|
||||
groups[type] = {
|
||||
type,
|
||||
platforms: []
|
||||
}
|
||||
}
|
||||
groups[type].platforms.push(platform)
|
||||
})
|
||||
return Object.values(groups)
|
||||
})
|
||||
|
||||
// 计算属性:检查是否可以开始迁移
|
||||
const canMigrate = computed(() => {
|
||||
return platformGroups.value.every(group => selectedPlatforms.value[group.type])
|
||||
})
|
||||
|
||||
// 监听 isOpen 变化,当对话框打开时加载平台列表
|
||||
watch(isOpen, (newVal) => {
|
||||
if (newVal) {
|
||||
loadPlatforms()
|
||||
} else {
|
||||
// 重置状态
|
||||
platforms.value = []
|
||||
selectedPlatforms.value = {}
|
||||
error.value = ''
|
||||
migrating.value = false
|
||||
migrationCompleted.value = false
|
||||
migrationResult.value = null
|
||||
}
|
||||
})
|
||||
|
||||
// 加载平台列表
|
||||
const loadPlatforms = async () => {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
|
||||
try {
|
||||
const response = await axios.get('/api/config/platform/list')
|
||||
if (response.data.status === 'ok') {
|
||||
platforms.value = response.data.data.platforms || []
|
||||
|
||||
// 为每个平台类型初始化默认选择(选择第一个)
|
||||
platformGroups.value.forEach(group => {
|
||||
if (group.platforms.length > 0) {
|
||||
selectedPlatforms.value[group.type] = group.platforms[0].id
|
||||
}
|
||||
})
|
||||
} else {
|
||||
error.value = response.data.message || t('features.migration.dialog.loadError')
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load platforms:', err)
|
||||
error.value = t('features.migration.dialog.loadError')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 执行迁移
|
||||
const handleMigration = async () => {
|
||||
migrating.value = true
|
||||
|
||||
try {
|
||||
// 构建 platform_id_map
|
||||
const platformIdMap = {}
|
||||
|
||||
Object.entries(selectedPlatforms.value).forEach(([type, platformId]) => {
|
||||
const selectedPlatform = platforms.value.find(p => p.id === platformId)
|
||||
if (selectedPlatform) {
|
||||
platformIdMap[type] = {
|
||||
platform_id: platformId,
|
||||
platform_type: type
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
console.log('Migration platform_id_map:', platformIdMap)
|
||||
|
||||
const response = await axios.post('/api/update/migration', {
|
||||
platform_id_map: platformIdMap
|
||||
})
|
||||
|
||||
if (response.data.status === 'ok') {
|
||||
migrationCompleted.value = true
|
||||
migrationResult.value = {
|
||||
success: true,
|
||||
message: response.data.message || t('features.migration.dialog.success')
|
||||
}
|
||||
} else {
|
||||
throw new Error(response.data.message || t('features.migration.dialog.migrationError'))
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Migration failed:', err)
|
||||
error.value = err.message || t('features.migration.dialog.migrationError')
|
||||
} finally {
|
||||
migrating.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 取消操作
|
||||
const handleCancel = () => {
|
||||
isOpen.value = false
|
||||
if (resolvePromise) {
|
||||
resolvePromise({ success: false, cancelled: true })
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭已完成的迁移对话框
|
||||
const handleClose = () => {
|
||||
isOpen.value = false
|
||||
if (resolvePromise) {
|
||||
resolvePromise(migrationResult.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 获取平台显示标签
|
||||
const getPlatformLabel = (platform) => {
|
||||
const name = platform.name || platform.id || 'Unknown'
|
||||
return `${name}`
|
||||
}
|
||||
|
||||
// 打开对话框的方法
|
||||
const open = () => {
|
||||
isOpen.value = true
|
||||
|
||||
return new Promise((resolve) => {
|
||||
resolvePromise = resolve
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.v-radio-group {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.migration-in-progress {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.console-container {
|
||||
border: 1px solid var(--v-theme-border);
|
||||
border-radius: 8px;
|
||||
margin-top: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -53,6 +53,7 @@ export class I18nLoader {
|
||||
{ name: 'features/alkaid/knowledge-base', path: 'features/alkaid/knowledge-base.json' },
|
||||
{ name: 'features/alkaid/memory', path: 'features/alkaid/memory.json' },
|
||||
{ name: 'features/persona', path: 'features/persona.json' },
|
||||
{ name: 'features/migration', path: 'features/migration.json' },
|
||||
|
||||
// 消息模块
|
||||
{ name: 'messages/errors', path: 'messages/errors.json' },
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"dialog": {
|
||||
"title": "Database Migration Assistant",
|
||||
"warning": "A database migration is required.",
|
||||
"loading": "Loading platform list...",
|
||||
"loadError": "Failed to load platform list, please retry",
|
||||
"noPlatforms": "No available platform configurations found",
|
||||
"retry": "Retry",
|
||||
"startMigration": "Start Migration",
|
||||
"migrating": "Migrating...",
|
||||
"migratingSubtitle": "Please wait patiently, do not close this window during migration",
|
||||
"migrationError": "Migration failed",
|
||||
"success": "Migration completed successfully!",
|
||||
"completed": "Migration Completed"
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,11 @@
|
||||
"title": "Restart",
|
||||
"subtitle": "Restart AstrBot",
|
||||
"button": "Restart"
|
||||
},
|
||||
"migration": {
|
||||
"title": "Data Migration to v4.0.0",
|
||||
"subtitle": "If you encounter data compatibility issues, you can manually start the database migration assistant",
|
||||
"button": "Start Migration Assistant"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"dialog": {
|
||||
"title": "数据迁移助手",
|
||||
"warning": "👋 欢迎升级到 v4.0.0。我们在新版本对数据格式进行了优化,检测到需要进行数据库迁移。",
|
||||
"loading": "正在加载平台列表...",
|
||||
"loadError": "加载平台列表失败,请重试",
|
||||
"noPlatforms": "未找到可用的平台配置",
|
||||
"retry": "重试",
|
||||
"startMigration": "开始迁移",
|
||||
"migrating": "正在迁移中...",
|
||||
"migratingSubtitle": "请耐心等待,迁移过程中请勿关闭此窗口",
|
||||
"migrationError": "迁移失败",
|
||||
"success": "迁移成功完成!",
|
||||
"completed": "迁移已完成"
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,11 @@
|
||||
"title": "重启",
|
||||
"subtitle": "重启 AstrBot",
|
||||
"button": "重启"
|
||||
},
|
||||
"migration": {
|
||||
"title": "数据迁移到 v4.0.0 格式",
|
||||
"subtitle": "如果您遇到数据兼容性问题,可以手动启动数据库迁移助手",
|
||||
"button": "启动迁移助手"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import zhCNAlkaidIndex from './locales/zh-CN/features/alkaid/index.json';
|
||||
import zhCNAlkaidKnowledgeBase from './locales/zh-CN/features/alkaid/knowledge-base.json';
|
||||
import zhCNAlkaidMemory from './locales/zh-CN/features/alkaid/memory.json';
|
||||
import zhCNPersona from './locales/zh-CN/features/persona.json';
|
||||
import zhCNMigration from './locales/zh-CN/features/migration.json';
|
||||
|
||||
import zhCNErrors from './locales/zh-CN/messages/errors.json';
|
||||
import zhCNSuccess from './locales/zh-CN/messages/success.json';
|
||||
@@ -56,6 +57,7 @@ import enUSAlkaidIndex from './locales/en-US/features/alkaid/index.json';
|
||||
import enUSAlkaidKnowledgeBase from './locales/en-US/features/alkaid/knowledge-base.json';
|
||||
import enUSAlkaidMemory from './locales/en-US/features/alkaid/memory.json';
|
||||
import enUSPersona from './locales/en-US/features/persona.json';
|
||||
import enUSMigration from './locales/en-US/features/migration.json';
|
||||
|
||||
import enUSErrors from './locales/en-US/messages/errors.json';
|
||||
import enUSSuccess from './locales/en-US/messages/success.json';
|
||||
@@ -91,7 +93,8 @@ export const translations = {
|
||||
'knowledge-base': zhCNAlkaidKnowledgeBase,
|
||||
memory: zhCNAlkaidMemory
|
||||
},
|
||||
persona: zhCNPersona
|
||||
persona: zhCNPersona,
|
||||
migration: zhCNMigration
|
||||
},
|
||||
messages: {
|
||||
errors: zhCNErrors,
|
||||
@@ -127,7 +130,8 @@ export const translations = {
|
||||
'knowledge-base': enUSAlkaidKnowledgeBase,
|
||||
memory: enUSAlkaidMemory
|
||||
},
|
||||
persona: enUSPersona
|
||||
persona: enUSPersona,
|
||||
migration: enUSMigration
|
||||
},
|
||||
messages: {
|
||||
errors: enUSErrors,
|
||||
|
||||
@@ -1,9 +1,40 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterView } from 'vue-router';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import axios from 'axios';
|
||||
import VerticalSidebarVue from './vertical-sidebar/VerticalSidebar.vue';
|
||||
import VerticalHeaderVue from './vertical-header/VerticalHeader.vue';
|
||||
import MigrationDialog from '@/components/shared/MigrationDialog.vue';
|
||||
import { useCustomizerStore } from '@/stores/customizer';
|
||||
|
||||
const customizer = useCustomizerStore();
|
||||
const migrationDialog = ref(null);
|
||||
|
||||
// 检查是否需要迁移
|
||||
const checkMigration = async () => {
|
||||
try {
|
||||
const response = await axios.get('/api/stat/version');
|
||||
if (response.data.status === 'ok' && response.data.data.need_migration) {
|
||||
// 需要迁移,显示迁移对话框
|
||||
if (migrationDialog.value) {
|
||||
const result = await migrationDialog.value.open();
|
||||
if (result.success) {
|
||||
// 迁移成功,可以显示成功消息
|
||||
console.log('Migration completed successfully:', result.message);
|
||||
// 可以考虑刷新页面或显示成功通知
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to check migration status:', error);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 页面加载时检查是否需要迁移
|
||||
setTimeout(checkMigration, 1000); // 延迟1秒执行,确保页面完全加载
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -20,6 +51,9 @@ const customizer = useCustomizerStore();
|
||||
</div>
|
||||
</v-container>
|
||||
</v-main>
|
||||
|
||||
<!-- Migration Dialog -->
|
||||
<MigrationDialog ref="migrationDialog" />
|
||||
</v-app>
|
||||
</v-locale-provider>
|
||||
</template>
|
||||
|
||||
@@ -14,35 +14,48 @@
|
||||
<v-list-item :subtitle="tm('system.restart.subtitle')" :title="tm('system.restart.title')">
|
||||
<v-btn style="margin-top: 16px;" color="error" @click="restartAstrBot">{{ tm('system.restart.button') }}</v-btn>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :subtitle="tm('system.migration.subtitle')" :title="tm('system.migration.title')">
|
||||
<v-btn style="margin-top: 16px;" color="primary" @click="startMigration">{{ tm('system.migration.button') }}</v-btn>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
</div>
|
||||
|
||||
<WaitingForRestart ref="wfr"></WaitingForRestart>
|
||||
<MigrationDialog ref="migrationDialog"></MigrationDialog>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import WaitingForRestart from '@/components/shared/WaitingForRestart.vue';
|
||||
import ProxySelector from '@/components/shared/ProxySelector.vue';
|
||||
import MigrationDialog from '@/components/shared/MigrationDialog.vue';
|
||||
import { useModuleI18n } from '@/i18n/composables';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WaitingForRestart,
|
||||
ProxySelector,
|
||||
},
|
||||
setup() {
|
||||
const { tm } = useModuleI18n('features/settings');
|
||||
return { tm };
|
||||
},
|
||||
methods: {
|
||||
restartAstrBot() {
|
||||
axios.post('/api/stat/restart-core').then(() => {
|
||||
this.$refs.wfr.check();
|
||||
})
|
||||
const { tm } = useModuleI18n('features/settings');
|
||||
|
||||
const wfr = ref(null);
|
||||
const migrationDialog = ref(null);
|
||||
|
||||
const restartAstrBot = () => {
|
||||
axios.post('/api/stat/restart-core').then(() => {
|
||||
wfr.value.check();
|
||||
})
|
||||
}
|
||||
|
||||
const startMigration = async () => {
|
||||
if (migrationDialog.value) {
|
||||
try {
|
||||
const result = await migrationDialog.value.open();
|
||||
if (result.success) {
|
||||
console.log('Migration completed successfully:', result.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Migration dialog error:', error);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user