diff --git a/astrbot/cli/commands/cmd_init.py b/astrbot/cli/commands/cmd_init.py index 6c0c34b99..0adbf3288 100644 --- a/astrbot/cli/commands/cmd_init.py +++ b/astrbot/cli/commands/cmd_init.py @@ -34,8 +34,13 @@ async def initialize_astrbot(astrbot_root: Path) -> None: for name, path in paths.items(): path.mkdir(parents=True, exist_ok=True) click.echo(f"{'Created' if not path.exists() else 'Directory exists'}: {path}") - - await check_dashboard(astrbot_root / "data") + if click.confirm( + "是否需要集成式 WebUI?(个人电脑推荐,服务器不推荐)", + default=True, + ): + await check_dashboard(astrbot_root / "data") + else: + click.echo("你可以使用在线面版(v4.14.4+),填写后端地址的方式来控制。") @click.command() diff --git a/astrbot/cli/commands/cmd_run.py b/astrbot/cli/commands/cmd_run.py index 6952ba323..6039d2eff 100644 --- a/astrbot/cli/commands/cmd_run.py +++ b/astrbot/cli/commands/cmd_run.py @@ -15,7 +15,8 @@ async def run_astrbot(astrbot_root: Path): from astrbot.core import LogBroker, LogManager, db_helper, logger from astrbot.core.initial_loader import InitialLoader - await check_dashboard(astrbot_root / "data") + if os.environ.get("DASHBOARD_ENABLE") == "True": + await check_dashboard(astrbot_root / "data") log_broker = LogBroker() LogManager.set_queue_handler(logger, log_broker) diff --git a/astrbot/dashboard/routes/static_file.py b/astrbot/dashboard/routes/static_file.py index 3d3d0ca51..7e7592e9b 100644 --- a/astrbot/dashboard/routes/static_file.py +++ b/astrbot/dashboard/routes/static_file.py @@ -5,6 +5,9 @@ class StaticFileRoute(Route): def __init__(self, context: RouteContext) -> None: super().__init__(context) + if "index" in self.app.view_functions: + return + index_ = [ "/", "/auth/login", diff --git a/dashboard/src/stores/api.ts b/dashboard/src/stores/api.ts index 57ab3c495..b664c1d95 100644 --- a/dashboard/src/stores/api.ts +++ b/dashboard/src/stores/api.ts @@ -11,11 +11,30 @@ export const useApiStore = defineStore({ state: () => ({ // 优先从 localStorage 读取用户手动设置的地址 apiBaseUrl: localStorage.getItem("apiBaseUrl") || "", - presets: [] as ApiPreset[], + configPresets: [] as ApiPreset[], + customPresets: JSON.parse( + localStorage.getItem("customPresets") || "[]", + ) as ApiPreset[], }), + getters: { + presets: (state): ApiPreset[] => [ + ...state.configPresets, + ...state.customPresets, + ], + }, actions: { setPresets(presets: ApiPreset[]) { - this.presets = presets; + this.configPresets = presets; + }, + + addPreset(preset: ApiPreset) { + this.customPresets.push(preset); + localStorage.setItem("customPresets", JSON.stringify(this.customPresets)); + }, + + removePreset(name: string) { + this.customPresets = this.customPresets.filter((p) => p.name !== name); + localStorage.setItem("customPresets", JSON.stringify(this.customPresets)); }, /** diff --git a/dashboard/src/views/Settings.vue b/dashboard/src/views/Settings.vue index ff6ff1b28..20a5c1e8e 100644 --- a/dashboard/src/views/Settings.vue +++ b/dashboard/src/views/Settings.vue @@ -22,9 +22,60 @@
+
+
+ Quick Select Preset +
+ + mdi-plus + +
+ + +
+ + + Add Preset +
+
+ {{ preset.name }} @@ -178,6 +231,25 @@ const apiStore = useApiStore(); const apiBaseUrl = ref(apiStore.apiBaseUrl); +const showAddPreset = ref(false); +const newPresetName = ref(""); +const newPresetUrl = ref(""); + +const savePreset = () => { + if (!newPresetName.value || !newPresetUrl.value) return; + apiStore.addPreset({ + name: newPresetName.value, + url: newPresetUrl.value, + }); + showAddPreset.value = false; + newPresetName.value = ""; + newPresetUrl.value = ""; +}; + +const isCustomPreset = (name) => { + return apiStore.customPresets.some((p) => p.name === name); +}; + const saveApiUrl = () => { apiStore.setApiBaseUrl(apiBaseUrl.value); window.location.reload(); diff --git a/dashboard/src/views/authentication/auth/LoginPage.vue b/dashboard/src/views/authentication/auth/LoginPage.vue index ac6f512fd..b659eae27 100644 --- a/dashboard/src/views/authentication/auth/LoginPage.vue +++ b/dashboard/src/views/authentication/auth/LoginPage.vue @@ -20,12 +20,31 @@ const theme = useTheme(); const serverConfigDialog = ref(false); const apiUrl = ref(apiStore.apiBaseUrl); +const showAddPreset = ref(false); +const newPresetName = ref(""); +const newPresetUrl = ref(""); + function saveApiUrl() { apiStore.setApiBaseUrl(apiUrl.value); serverConfigDialog.value = false; window.location.reload(); } +function savePreset() { + if (!newPresetName.value || !newPresetUrl.value) return; + apiStore.addPreset({ + name: newPresetName.value, + url: newPresetUrl.value, + }); + showAddPreset.value = false; + newPresetName.value = ""; + newPresetUrl.value = ""; +} + +function isCustomPreset(name: string) { + return apiStore.customPresets.some((p) => p.name === name); +} + // 主题切换函数 function toggleTheme() { const newTheme = @@ -136,12 +155,60 @@ onMounted(() => {
-
- {{ t("serverConfig.presetLabel") }} +
+
+ {{ t("serverConfig.presetLabel") }} +
+ + mdi-plus +
+ + +
+ + + Add Preset +
+
+ { @click="apiUrl = preset.url" :variant="apiUrl === preset.url ? 'flat' : 'tonal'" :color="apiUrl === preset.url ? 'primary' : undefined" + :closable="isCustomPreset(preset.name)" + @click:close="apiStore.removePreset(preset.name)" > {{ preset.name }}