1.前端的后端配置页面新增新增按钮,允许新增后端,自由切换后端。2.一些必要的改进,比如astrbot init初始化时候询问是否下载前端,可选择不下载,使用--backend-only选项时候,不再提示要下载前端

This commit is contained in:
LIghtJUNction
2026-02-06 03:47:53 +08:00
parent 68b8a1a01c
commit d68ccfcc96
6 changed files with 178 additions and 9 deletions
+7 -2
View File
@@ -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()
+2 -1
View File
@@ -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)
+3
View File
@@ -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",
+21 -2
View File
@@ -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));
},
/**
+73 -1
View File
@@ -22,9 +22,60 @@
<v-row class="mt-2" dense>
<v-col cols="12" sm="6">
<div
v-if="apiStore.presets && apiStore.presets.length > 0"
v-if="
(apiStore.presets && apiStore.presets.length > 0) ||
apiStore.customPresets
"
class="mb-2"
>
<div class="d-flex justify-space-between align-center mb-2">
<div class="text-caption text-medium-emphasis">
Quick Select Preset
</div>
<v-btn
size="x-small"
variant="text"
icon
@click="showAddPreset = !showAddPreset"
>
<v-icon>mdi-plus</v-icon>
</v-btn>
</div>
<v-expand-transition>
<div
v-if="showAddPreset"
class="mb-2 pa-2 bg-grey-lighten-4 rounded border"
>
<v-text-field
v-model="newPresetName"
label="Name"
density="compact"
hide-details
class="mb-2"
variant="outlined"
bg-color="white"
></v-text-field>
<v-text-field
v-model="newPresetUrl"
label="URL"
density="compact"
hide-details
class="mb-2"
variant="outlined"
bg-color="white"
></v-text-field>
<v-btn
size="small"
block
color="primary"
variant="flat"
@click="savePreset"
>Add Preset</v-btn
>
</div>
</v-expand-transition>
<v-chip-group column>
<v-chip
v-for="preset in apiStore.presets"
@@ -33,6 +84,8 @@
@click="apiBaseUrl = preset.url"
:variant="apiBaseUrl === preset.url ? 'flat' : 'tonal'"
:color="apiBaseUrl === preset.url ? 'primary' : undefined"
:closable="isCustomPreset(preset.name)"
@click:close="apiStore.removePreset(preset.name)"
>
{{ preset.name }}
</v-chip>
@@ -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();
@@ -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(() => {
</div>
<div
v-if="apiStore.presets && apiStore.presets.length > 0"
v-if="
(apiStore.presets && apiStore.presets.length > 0) ||
apiStore.customPresets
"
class="mb-4"
>
<div class="text-caption text-medium-emphasis mb-2">
{{ t("serverConfig.presetLabel") }}
<div class="d-flex justify-space-between align-center mb-2">
<div class="text-caption text-medium-emphasis">
{{ t("serverConfig.presetLabel") }}
</div>
<v-btn
size="x-small"
variant="text"
icon
@click="showAddPreset = !showAddPreset"
>
<v-icon>mdi-plus</v-icon>
</v-btn>
</div>
<v-expand-transition>
<div
v-if="showAddPreset"
class="mb-2 pa-2 bg-grey-lighten-4 rounded border"
>
<v-text-field
v-model="newPresetName"
label="Name"
density="compact"
hide-details
class="mb-2"
variant="outlined"
bg-color="white"
></v-text-field>
<v-text-field
v-model="newPresetUrl"
label="URL"
density="compact"
hide-details
class="mb-2"
variant="outlined"
bg-color="white"
></v-text-field>
<v-btn
size="small"
block
color="primary"
variant="flat"
@click="savePreset"
>Add Preset</v-btn
>
</div>
</v-expand-transition>
<v-chip-group column>
<v-chip
v-for="preset in apiStore.presets"
@@ -150,6 +217,8 @@ onMounted(() => {
@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 }}
</v-chip>