mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-15 17:30:13 +08:00
fix(dashboard): resolve missing translations and autocomplete warnings
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -84,3 +84,4 @@ dashboard/src/assets/mdi-subset/*.woff
|
||||
dashboard/src/assets/mdi-subset/*.woff2
|
||||
.planning
|
||||
*cache
|
||||
node_modules
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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": "Настройки сервера"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
"username": "用户名",
|
||||
"password": "密码",
|
||||
"defaultHint": "默认用户名和密码为 astrbot,请在登录后立即修改以确保安全。",
|
||||
"autoTheme": "自动切换主题",
|
||||
"addPreset": "添加预设",
|
||||
"shareLink": "分享配置链接",
|
||||
"presetName": "预设名称",
|
||||
"presetUrl": "预设 URL",
|
||||
"linkCopied": "链接已复制到剪贴板",
|
||||
"linkCopyFailed": "复制链接失败",
|
||||
"logo": {
|
||||
"title": "AstrBot WebUI",
|
||||
"subtitle": "欢迎使用"
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user