Files
AstrBot/dashboard/src/main.ts
2026-02-06 02:38:58 +08:00

174 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import { router } from "./router";
import vuetify from "./plugins/vuetify";
import confirmPlugin from "./plugins/confirmPlugin";
import { setupI18n } from "./i18n/composables";
import "@/scss/style.scss";
import VueApexCharts from "vue3-apexcharts";
import print from "vue3-print-nb";
import { loader } from "@guolao/vue-monaco-editor";
import axios from "axios";
// 1. 定义加载配置的函数
async function loadAppConfig() {
try {
// 加上时间戳防止浏览器缓存 config.json
const response = await fetch(`/config.json?t=${new Date().getTime()}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.warn("Failed to load config.json, falling back to default.", error);
return {};
}
}
function mountApp(app: any, pinia: any) {
app.mount("#app");
// 挂载后同步 Vuetify 主题
import("./stores/customizer").then(({ useCustomizerStore }) => {
const customizer = useCustomizerStore(pinia);
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;
["PurpleTheme", "PurpleThemeDark"].forEach((name) => {
const theme = themes[name];
if (!theme?.colors) return;
if (storedPrimary) theme.colors.primary = storedPrimary;
if (storedSecondary) theme.colors.secondary = storedSecondary;
if (storedPrimary && theme.colors.darkprimary)
theme.colors.darkprimary = storedPrimary;
if (storedSecondary && theme.colors.darksecondary)
theme.colors.darksecondary = storedSecondary;
});
}
});
}
async function initApp() {
// 等待配置加载
const config = await loadAppConfig();
const configApiUrl = config.apiBaseUrl || "";
const presets = config.presets || [];
// 优先使用 localStorage 中的配置,其次是 config.json最后是空字符串
const localApiUrl = localStorage.getItem("apiBaseUrl");
const apiBaseUrl = localApiUrl !== null ? localApiUrl : configApiUrl;
if (apiBaseUrl) {
console.log(
`API Base URL set to: ${apiBaseUrl} (Local: ${localApiUrl}, Config: ${configApiUrl})`,
);
}
// 配置 Axios 全局 Base URL
axios.defaults.baseURL = apiBaseUrl;
axios.interceptors.request.use((config) => {
const token = localStorage.getItem("token");
if (token) {
config.headers["Authorization"] = `Bearer ${token}`;
}
return config;
});
// Keep fetch() calls consistent with axios by automatically attaching the JWT.
// Some parts of the UI use fetch directly; without this, those requests will 401.
// Also handle apiBaseUrl for fetch
const _origFetch = window.fetch.bind(window);
window.fetch = (input: RequestInfo | URL, init?: RequestInit) => {
let url = input;
// 动态获取当前的 Base URL (可能已被 Store 修改)
const currentBaseUrl = axios.defaults.baseURL;
// 如果是字符串路径且以 /api 开头,并且配置了 Base URL则拼接
if (
typeof input === "string" &&
input.startsWith("/api") &&
currentBaseUrl
) {
// 移除 apiBaseUrl 尾部的斜杠
const cleanBase = currentBaseUrl.replace(/\/+$/, "");
// 移除 input 开头的斜杠
const cleanPath = input.replace(/^\/+/, "");
url = `${cleanBase}/${cleanPath}`;
}
const token = localStorage.getItem("token");
// 如果没有 token但有 apiBaseUrl 修改,仍需使用新 url
if (!token) return _origFetch(url, init);
const headers = new Headers(
init?.headers ||
(typeof input !== "string" && "headers" in input
? (input as Request).headers
: undefined),
);
if (!headers.has("Authorization")) {
headers.set("Authorization", `Bearer ${token}`);
}
return _origFetch(url, { ...init, headers });
};
loader.config({
paths: {
vs: "https://cdn.jsdelivr.net/npm/monaco-editor@0.54.0/min/vs",
},
});
// 初始化新的i18n系统等待完成后再挂载应用
setupI18n()
.then(async () => {
console.log("🌍 新i18n系统初始化完成");
const app = createApp(App);
app.use(router);
const pinia = createPinia();
app.use(pinia);
// Initialize API Store with presets
const { useApiStore } = await import("@/stores/api");
const apiStore = useApiStore(pinia);
apiStore.setPresets(presets);
app.use(print);
app.use(VueApexCharts);
app.use(vuetify);
app.use(confirmPlugin);
mountApp(app, pinia);
})
.catch(async (error) => {
console.error("❌ 新i18n系统初始化失败:", error);
// 即使i18n初始化失败也要挂载应用使用回退机制
const app = createApp(App);
app.use(router);
const pinia = createPinia();
app.use(pinia);
// Initialize API Store with presets
const { useApiStore } = await import("@/stores/api");
const apiStore = useApiStore(pinia);
apiStore.setPresets(presets);
app.use(print);
app.use(VueApexCharts);
app.use(vuetify);
app.use(confirmPlugin);
mountApp(app, pinia);
});
}
// 启动应用
initApp();