diff --git a/package.json b/package.json index 7aa2b4c..66f7290 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "type-check": "vue-tsc --noEmit" }, "dependencies": { - "axios": "^1.8.4", + "axios": "1.15.0", "less": "^4.3.0", "echarts": "^6.0.0", "vue-echarts": "^8.0.1", @@ -19,7 +19,7 @@ "pinia": "^3.0.2", "tdesign-mobile-vue": "^1.13.2", "timi-tdesign-mobile": "0.0.9", - "timi-web": "0.0.15", + "timi-web": "0.0.16", "ts-node": "^10.9.2", "vue": "^3.5.16", "vue-router": "4.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 116df08..a3870e7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: axios: - specifier: ^1.8.4 - version: 1.14.0 + specifier: 1.15.0 + version: 1.15.0 echarts: specifier: ^6.0.0 version: 6.0.0 @@ -30,8 +30,8 @@ importers: specifier: 0.0.9 version: 0.0.9(typescript@5.8.3) timi-web: - specifier: 0.0.15 - version: 0.0.15 + specifier: 0.0.16 + version: 0.0.16 ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@24.12.0)(typescript@5.8.3) @@ -778,8 +778,8 @@ packages: axios@1.13.5: resolution: {integrity: sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==} - axios@1.14.0: - resolution: {integrity: sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==} + axios@1.15.0: + resolution: {integrity: sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1832,8 +1832,8 @@ packages: resolution: {integrity: sha512-SV8m/FsLsEabSmJ/NvI650fLyb/JCLz7JUNQrkWeoo5xICElsN4x39L3n4lTzu6ARidjpT6uA+XEmA4wnyQmuA==} engines: {node: '>=16.0.0'} - timi-web@0.0.15: - resolution: {integrity: sha512-j5CU8Byd9qdK7AWUGM5vgQ5Tix20m/WrD5Sv4h77aFV0G/rqdKi8uoRg1uUXUZLqsIy1zjI7kbIV3DnRplBYog==} + timi-web@0.0.16: + resolution: {integrity: sha512-Tyma/szWvAmPTq7HRtXtRA0Of+YI1Acko96wsosJFRyO+tN1gDEUrwMoY1l2Uw8Q1g6Yv7huS6E6DLd9fA28og==} engines: {node: '>=16.0.0'} tinycolor2@1.6.0: @@ -2743,7 +2743,7 @@ snapshots: transitivePeerDependencies: - debug - axios@1.14.0: + axios@1.15.0: dependencies: follow-redirects: 1.15.11 form-data: 4.0.5 @@ -3875,7 +3875,7 @@ snapshots: transitivePeerDependencies: - typescript - timi-web@0.0.15: + timi-web@0.0.16: dependencies: axios: 1.13.5 less: 4.5.1 diff --git a/src/api/FileAPI.ts b/src/api/FileAPI.ts index f6310ae..1e570e8 100644 --- a/src/api/FileAPI.ts +++ b/src/api/FileAPI.ts @@ -1,116 +1,27 @@ -import axios, { AxiosError } from "axios"; +import { axios } from "timi-web"; import type { ServerFile } from "@/types/File"; import { useSettingStore } from "@/store/settingStore"; -interface ApiResponse { - code?: number | string; - data?: T; - list?: T; - msg?: string; - message?: string; +async function list(pathSegments: string[]): Promise { + const settingStore = useSettingStore(); + const path = pathSegments.length ? `/${pathSegments.map((segment) => encodeURIComponent(segment)).join("/")}` : ""; + return await axios.get(`${settingStore.resolveBaseURL()}/system/file/list${path}`); } -export async function listServerFiles(pathSegments: string[]): Promise { - const response = await axios.get | ServerFile[]>(buildListURL(pathSegments), { - params: buildQueryParams(), - timeout: 15000 - }); - - return unwrapServerFileList(response.data); -} - -export function buildServerFileURL(path: string, action = "download"): string { - const normalizedPath = typeof path === "string" ? path.trim() : ""; +function buildURL(path: string, action = "download"): string { + const settingStore = useSettingStore(); + const normalizedPath = path.trim(); const segments = normalizedPath.split("/").filter((segment) => !!segment); const requestPath = segments.length ? `/${segments.map((segment) => encodeURIComponent(segment)).join("/")}` : ""; - const url = new URL(`${resolveBaseURL()}/system/file/${action}${requestPath}`); - const token = useSettingStore().connect.token.trim(); - + const url = new URL(`${settingStore.resolveBaseURL()}/system/file/${action}${requestPath}`); + const token = settingStore.connect.token.trim(); if (token) { url.searchParams.set("token", token); } - return url.toString(); } -export function resolveRequestErrorMessage(error: unknown): string { - if (error instanceof AxiosError) { - const message = resolveApiMessage(error.response?.data); - if (message) { - return message; - } - - if (error.message) { - return error.message; - } - } - - if (error instanceof Error && error.message) { - return error.message; - } - - return "请求失败,请稍后重试"; -} - -function buildListURL(pathSegments: string[]): string { - const path = pathSegments.length ? `/${pathSegments.map((segment) => encodeURIComponent(segment)).join("/")}` : ""; - return `${resolveBaseURL()}/system/file/list${path}`; -} - -function resolveBaseURL(): string { - const settingStore = useSettingStore(); - const connect = settingStore.connect; - const envBaseURL = typeof import.meta.env.VITE_API === "string" ? import.meta.env.VITE_API.trim() : ""; - - if (connect.host && connect.port) { - return `${connect.protocol}://${connect.host}:${connect.port}`; - } - - return envBaseURL.replace(/\/+$/, ""); -} - -function buildQueryParams(): Record { - const settingStore = useSettingStore(); - const token = settingStore.connect.token.trim(); - - if (!token) { - return {}; - } - - return { - token - }; -} - -function unwrapServerFileList(payload: ApiResponse | ServerFile[]): ServerFile[] { - if (Array.isArray(payload)) { - return payload; - } - - if (Array.isArray(payload.data)) { - return payload.data; - } - - if (Array.isArray(payload.list)) { - return payload.list; - } - - throw new Error(resolveApiMessage(payload) || "文件列表返回格式不正确"); -} - -function resolveApiMessage(payload: unknown): string { - if (!payload || typeof payload !== "object") { - return ""; - } - - const { msg, message } = payload as ApiResponse; - if (typeof msg === "string" && msg.trim()) { - return msg.trim(); - } - - if (typeof message === "string" && message.trim()) { - return message.trim(); - } - - return ""; -} +export default { + list, + buildURL +}; diff --git a/src/api/SystemAPI.ts b/src/api/SystemAPI.ts index 5425210..1412c8b 100644 --- a/src/api/SystemAPI.ts +++ b/src/api/SystemAPI.ts @@ -1,114 +1,29 @@ -import axios, { AxiosError } from "axios"; +import { axios, Text } from "timi-web"; import { useSettingStore } from "@/store/settingStore"; import type { SystemStatusHistoryView, SystemStatusSnapshotView } from "@/types/System"; -interface ApiResponse { - code?: number | string; - data?: T; - msg?: string; - message?: string; +async function getStatus(metrics?: string): Promise { + const settingStore = useSettingStore(); + return await axios.get(`${settingStore.resolveBaseURL()}/system/server/status?${Text.urlArgs({ + metrics, + })}`); } -export async function getSystemStatus(metrics?: string): Promise { - const response = await axios.get | SystemStatusSnapshotView>(`${resolveBaseURL()}/system/server/status`, { - params: { - ...buildQueryParams(), - ...(metrics ? { metrics } : {}) - }, - timeout: 15000 - }); - - return unwrapResponse(response.data); -} - -export async function getSystemStatusHistory(params?: { +async function getStatusHistory(params?: { window?: string; metrics?: string; }): Promise { - const response = await axios.get | SystemStatusHistoryView>(`${resolveBaseURL()}/system/server/status/history`, { + const settingStore = useSettingStore(); + return await axios.get(`${settingStore.resolveBaseURL()}/system/server/status/history`, { params: { - ...buildQueryParams(), ...(params?.window ? { window: params.window } : {}), ...(params?.metrics ? { metrics: params.metrics } : {}) }, timeout: 15000 }); - - return unwrapResponse(response.data); } -export function resolveSystemRequestErrorMessage(error: unknown): string { - if (error instanceof AxiosError) { - const message = resolveApiMessage(error.response?.data); - if (message) { - return message; - } - - if (error.message) { - return error.message; - } - } - - if (error instanceof Error && error.message) { - return error.message; - } - - return "请求失败,请稍后重试"; -} - -function unwrapResponse(payload: ApiResponse | T): T { - if (payload && typeof payload === "object" && "data" in payload) { - const data = (payload as ApiResponse).data; - if (data !== undefined) { - return data; - } - } - - if (payload && typeof payload === "object" && ("msg" in payload || "message" in payload)) { - throw new Error(resolveApiMessage(payload) || "接口返回为空"); - } - - return payload as T; -} - -function resolveBaseURL(): string { - const settingStore = useSettingStore(); - const connect = settingStore.connect; - const envBaseURL = typeof import.meta.env.VITE_API === "string" ? import.meta.env.VITE_API.trim() : ""; - - if (connect.host && connect.port) { - return `${connect.protocol}://${connect.host}:${connect.port}`; - } - - return envBaseURL.replace(/\/+$/, ""); -} - -function buildQueryParams(): Record { - const settingStore = useSettingStore(); - const token = settingStore.connect.token.trim(); - - if (!token) { - return {}; - } - - return { - token - }; -} - -function resolveApiMessage(payload: unknown): string { - if (!payload || typeof payload !== "object") { - return ""; - } - - const { msg, message } = payload as ApiResponse; - if (typeof msg === "string" && msg.trim()) { - return msg.trim(); - } - - if (typeof message === "string" && message.trim()) { - return message.trim(); - } - - return ""; -} +export default { + getStatus, + getStatusHistory +}; diff --git a/src/api/UpsAPI.ts b/src/api/UpsAPI.ts new file mode 100644 index 0000000..64b513c --- /dev/null +++ b/src/api/UpsAPI.ts @@ -0,0 +1,27 @@ +import { axios } from "timi-web"; +import type { UpsHistoryView, UpsStatusView } from "@/types/Ups"; +import { useSettingStore } from "@/store/settingStore"; + +async function getStatus(): Promise { + const settingStore = useSettingStore(); + return await axios.get(`${settingStore.resolveBaseURL()}/system/ups/status`, { + timeout: 15000 + }); +} + +async function getStatusHistory(params?: { + window?: string; +}): Promise { + const settingStore = useSettingStore(); + return await axios.get(`${settingStore.resolveBaseURL()}/system/ups/history`, { + params: { + ...(params?.window ? { window: params.window } : {}) + }, + timeout: 15000 + }); +} + +export default { + getStatus, + getStatusHistory +}; diff --git a/src/main.ts b/src/main.ts index cfd12c7..6d8f44b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,6 +8,25 @@ import "tdesign-mobile-vue/es/style/index.css"; import "timi-web/style.css"; import "timi-tdesign-mobile/style.css"; import "vue-virtual-scroller/dist/vue-virtual-scroller.css"; +import { axios } from "timi-web"; +import { useSettingStore } from "@/store/settingStore.ts"; + +axios.interceptors.request.use((config) => { + const settingStore = useSettingStore(); + const token = settingStore.connect.token.trim(); + if (token) { + if (config.method === "get") { + config.params = { + token, + ...config.params + }; + } + config.headers.set({ "Token": token }); + } + return config; +}, (error: any) => { + return Promise.reject(error); +}); export const pinia = createPinia(); diff --git a/src/pages/dashboard/ServerDashboard/ServerDashboard.vue b/src/pages/dashboard/ServerDashboard/ServerDashboard.vue index 0192615..2853498 100644 --- a/src/pages/dashboard/ServerDashboard/ServerDashboard.vue +++ b/src/pages/dashboard/ServerDashboard/ServerDashboard.vue @@ -119,11 +119,7 @@ import { GridComponent, LegendComponent, TooltipComponent } from "echarts/compon import VChart from "vue-echarts"; import { useRouter } from "vue-router"; import type { EChartsOption, SeriesOption } from "echarts"; -import { - getSystemStatus, - getSystemStatusHistory, - resolveSystemRequestErrorMessage -} from "@/api/SystemAPI"; +import SystemAPI from "@/api/SystemAPI"; import type { SystemStatusHistoryPoint, SystemStatusSnapshotView } from "@/types/System"; import type { DashboardHistoryMetric } from "@/store/settingStore"; import { useSettingStore } from "@/store/settingStore"; @@ -624,11 +620,11 @@ async function refreshSnapshot(): Promise { isSnapshotLoading.value = true; try { const metrics = settingStore.dashboard.server.snapshotMetrics.join(","); - snapshotView.value = await getSystemStatus(metrics); + snapshotView.value = await SystemAPI.getStatus(metrics); } catch (error) { Toast({ theme: "error", - message: resolveSystemRequestErrorMessage(error) + message: error instanceof Error ? error.message : "请求失败,请稍后重试" }); } finally { isSnapshotLoading.value = false; @@ -644,7 +640,7 @@ async function refreshHistory(): Promise { isHistoryLoading.value = true; try { const metrics = settingStore.dashboard.server.historyMetrics.join(","); - const historyView = await getSystemStatusHistory({ + const historyView = await SystemAPI.getStatusHistory({ window: "1h", metrics }); @@ -652,7 +648,7 @@ async function refreshHistory(): Promise { } catch (error) { Toast({ theme: "error", - message: resolveSystemRequestErrorMessage(error) + message: error instanceof Error ? error.message : "请求失败,请稍后重试" }); } finally { isHistoryLoading.value = false; diff --git a/src/pages/dashboard/ServerDashboard/ServerDetail.vue b/src/pages/dashboard/ServerDashboard/ServerDetail.vue index 903e523..eac0b13 100644 --- a/src/pages/dashboard/ServerDashboard/ServerDetail.vue +++ b/src/pages/dashboard/ServerDashboard/ServerDetail.vue @@ -28,7 +28,7 @@ + diff --git a/src/pages/file/FileExplorerPage.vue b/src/pages/file/FileExplorerPage.vue index 21bb8ab..e5100a2 100644 --- a/src/pages/file/FileExplorerPage.vue +++ b/src/pages/file/FileExplorerPage.vue @@ -25,7 +25,7 @@