fix(dashboard): resolve missing translations and autocomplete warnings

This commit is contained in:
LIghtJUNction
2026-04-04 18:37:05 +08:00
parent b4f3718413
commit 607735e55b
10 changed files with 983 additions and 728 deletions

1
.gitignore vendored
View File

@@ -84,3 +84,4 @@ dashboard/src/assets/mdi-subset/*.woff
dashboard/src/assets/mdi-subset/*.woff2
.planning
*cache
node_modules

View File

@@ -3,6 +3,13 @@
"username": "Username",
"password": "Password",
"defaultHint": "Default credentials: astrbot / astrbot",
"autoTheme": "Auto switch theme",
"addPreset": "Add preset",
"shareLink": "Share config link",
"presetName": "Preset Name",
"presetUrl": "Preset URL",
"linkCopied": "Link copied to clipboard",
"linkCopyFailed": "Failed to copy link",
"logo": {
"title": "AstrBot Dashboard",
"subtitle": "Welcome"

View File

@@ -3,6 +3,13 @@
"username": "Имя пользователя",
"password": "Пароль",
"defaultHint": "Учетные данные по умолчанию: astrbot / astrbot",
"autoTheme": "Автоматическая смена темы",
"addPreset": "Добавить пресет",
"shareLink": "Поделиться ссылкой",
"presetName": "Имя пресета",
"presetUrl": "URL пресета",
"linkCopied": "Ссылка скопирована в буфер обмена",
"linkCopyFailed": "Не удалось скопировать ссылку",
"logo": {
"title": "Панель управления AstrBot",
"subtitle": "Добро пожаловать"
@@ -22,4 +29,4 @@
"cancel": "Отмена",
"tooltip": "Настройки сервера"
}
}
}

View File

@@ -3,6 +3,13 @@
"username": "用户名",
"password": "密码",
"defaultHint": "默认用户名和密码为 astrbot请在登录后立即修改以确保安全。",
"autoTheme": "自动切换主题",
"addPreset": "添加预设",
"shareLink": "分享配置链接",
"presetName": "预设名称",
"presetUrl": "预设 URL",
"linkCopied": "链接已复制到剪贴板",
"linkCopyFailed": "复制链接失败",
"logo": {
"title": "AstrBot WebUI",
"subtitle": "欢迎使用"

View File

@@ -7,7 +7,6 @@ import VerticalHeaderVue from "./vertical-header/VerticalHeader.vue";
import MigrationDialog from "@/components/shared/MigrationDialog.vue";
import ReadmeDialog from "@/components/shared/ReadmeDialog.vue";
import Chat from "@/components/chat/Chat.vue";
import ReactorBg from "@/components/shared/ReactorBg.vue";
import { useCustomizerStore } from "@/stores/customizer";
import { useRouterLoadingStore } from "@/stores/routerLoading";
import { useI18n } from "@/i18n/composables";
@@ -18,9 +17,6 @@ const customizer = useCustomizerStore();
const { locale } = useI18n();
const route = useRoute();
const routerLoadingStore = useRouterLoadingStore();
const isCurrentChatRoute = computed(
() => route.path === "/chat" || route.path.startsWith("/chat/"),
);
const isChatPage = computed(() => {
return route.path.startsWith("/chat");
@@ -54,10 +50,7 @@ const checkMigration = async (): Promise<boolean> => {
return true;
}
} catch (error) {
console.warn(
"Failed to check migration status (backend may not be running):",
error,
);
console.error("Failed to check migration status:", error);
}
return false;
};
@@ -83,10 +76,7 @@ const maybeShowFirstNotice = async () => {
localStorage.setItem(FIRST_NOTICE_SEEN_KEY, "1");
} catch (error) {
console.warn(
"Failed to load first notice (backend may not be running):",
error,
);
console.error("Failed to load first notice:", error);
}
};
@@ -117,7 +107,6 @@ onMounted(() => {
customizer.inputBg ? 'inputWithbg' : '',
]"
>
<ReactorBg />
<v-progress-linear
v-if="routerLoadingStore.isLoading"
:model-value="routerLoadingStore.progress"
@@ -138,7 +127,7 @@ onMounted(() => {
<v-container
fluid
class="page-wrapper"
:class="{ 'chat-mode-container': isCurrentChatRoute }"
:class="{ 'chat-mode-container': showChatPage }"
:style="{
height: showChatPage ? '100%' : 'calc(100% - 8px)',
padding: isChatPage || showChatPage ? '0' : undefined,

File diff suppressed because it is too large Load Diff

View File

@@ -45,10 +45,16 @@ async function mountApp(app: any, pinia: any, waitForRouter = true) {
}
app.mount("#app");
// 挂载后同步 Vuetify 主题
const customizer = useCustomizerStore(pinia);
vuetify.theme.global.name.value = customizer.uiTheme;
const storedPrimary = localStorage.getItem("themePrimary");
// 挂载后同步 Vuetify 主题
const customizer = useCustomizerStore(pinia);
// @ts-ignore
if (typeof vuetify.theme.change === "function") {
// @ts-ignore
vuetify.theme.change(customizer.uiTheme);
} else {
vuetify.theme.global.name.value = customizer.uiTheme;
}
const storedPrimary = localStorage.getItem("themePrimary");
const storedSecondary = localStorage.getItem("themeSecondary");
if (storedPrimary || storedSecondary) {
const themes = vuetify.theme.themes.value;

View File

@@ -1,14 +1,12 @@
import { defineStore } from "pinia";
import { router } from "@/router";
import axios from "axios";
import axios from "@/utils/request";
import { createLoginProof, type LoginChallenge } from "@/utils/authLoginProof";
export const useAuthStore = defineStore({
id: "auth",
export const useAuthStore = defineStore("auth", {
state: () => ({
// @ts-ignore
username: "",
returnUrl: null,
returnUrl: null as string | null,
}),
actions: {
async login(username: string, password: string): Promise<void> {
@@ -20,7 +18,6 @@ export const useAuthStore = defineStore({
}
let res;
// @ts-ignore
if (challenge.algorithm === "argon2") {
res = await axios.post("/api/auth/login", {
username: username,

View File

@@ -3,7 +3,7 @@ import { md5 } from 'js-md5';
export type LoginChallenge = {
challenge_id: string;
nonce: string;
algorithm: 'pbkdf2_sha256' | 'legacy_md5';
algorithm: 'pbkdf2_sha256' | 'legacy_md5' | 'argon2';
iterations?: number;
salt?: string;
};

View File

@@ -68,6 +68,7 @@ async function validate(_values: any, { setErrors }: any) {
variant="outlined"
prepend-inner-icon="mdi-account"
:disabled="loading"
autocomplete="username"
/>
<v-text-field
@@ -81,6 +82,7 @@ async function validate(_values: any, { setErrors }: any) {
class="pwd-input"
prepend-inner-icon="mdi-lock"
:disabled="loading"
autocomplete="current-password"
@click:append="show1 = !show1"
/>