feat(frontend): wire pages to shadcn bridge and modular helpers

This commit is contained in:
Sagit
2026-02-19 05:15:26 +00:00
parent 12c50df6a7
commit 30c96a280d
27 changed files with 1077 additions and 1971 deletions
+94 -47
View File
@@ -1,3 +1,32 @@
import type {
BatchOperationResult,
ForwardDiagnosisApiData,
ForwardApiItem,
GroupPermissionApiItem,
NodeReleaseApiItem,
NodeApiItem,
SpeedLimitApiItem,
TunnelDiagnosisApiData,
TunnelGroupApiItem,
UserApiItem,
UserGroupApiItem,
UserListQuery,
UserPackageInfoApiData,
UserTunnelPermissionApiItem,
TunnelApiItem,
UserTunnelApiItem,
UserMutationPayload,
NodeMutationPayload,
TunnelMutationPayload,
UserTunnelAssignPayload,
UserTunnelListQuery,
UserTunnelRemovePayload,
ForwardMutationPayload,
SpeedLimitMutationPayload,
UpdatePasswordPayload,
BackupImportPayload,
} from "./types";
import axios from "axios";
import Network from "./network";
@@ -20,20 +49,25 @@ export const login = (data: LoginData) =>
Network.post<LoginResponse>("/user/login", data);
// 用户CRUD操作 - 全部使用POST请求
export const createUser = (data: any) => Network.post("/user/create", data);
export const getAllUsers = (pageData: any = {}) =>
Network.post("/user/list", pageData);
export const updateUser = (data: any) => Network.post("/user/update", data);
export const createUser = (data: UserMutationPayload) =>
Network.post("/user/create", data);
export const getAllUsers = (pageData: UserListQuery = {}) =>
Network.post<UserApiItem[]>("/user/list", pageData);
export const updateUser = (data: UserMutationPayload) =>
Network.post("/user/update", data);
export const deleteUser = (id: number) => Network.post("/user/delete", { id });
export const getUserPackageInfo = () => Network.post("/user/package");
export const getUserPackageInfo = () =>
Network.post<UserPackageInfoApiData>("/user/package");
// 节点CRUD操作 - 全部使用POST请求
export const createNode = (data: any) => Network.post("/node/create", data);
export const getNodeList = () => Network.post("/node/list");
export const updateNode = (data: any) => Network.post("/node/update", data);
export const createNode = (data: NodeMutationPayload) =>
Network.post("/node/create", data);
export const getNodeList = () => Network.post<NodeApiItem[]>("/node/list");
export const updateNode = (data: NodeMutationPayload) =>
Network.post("/node/update", data);
export const deleteNode = (id: number) => Network.post("/node/delete", { id });
export const getNodeInstallCommand = (id: number) =>
Network.post("/node/install", { id });
Network.post<string>("/node/install", { id });
export const updateNodeOrder = (data: {
nodes: Array<{ id: number; inx: number }>;
}) => Network.post("/node/update-order", data);
@@ -55,44 +89,50 @@ export const batchUpgradeNodes = (ids: number[], version?: string) =>
{ ids, version: version || "" },
{ timeout: 15 * 60 * 1000 },
);
export const getNodeReleases = () => Network.post("/node/releases");
export const getNodeReleases = () =>
Network.post<NodeReleaseApiItem[]>("/node/releases");
export const rollbackNode = (id: number) =>
Network.post("/node/rollback", { id });
// 隧道CRUD操作 - 全部使用POST请求
export const createTunnel = (data: any) => Network.post("/tunnel/create", data);
export const getTunnelList = () => Network.post("/tunnel/list");
export const createTunnel = (data: TunnelMutationPayload) =>
Network.post("/tunnel/create", data);
export const getTunnelList = () =>
Network.post<TunnelApiItem[]>("/tunnel/list");
export const getTunnelById = (id: number) =>
Network.post("/tunnel/get", { id });
export const updateTunnel = (data: any) => Network.post("/tunnel/update", data);
Network.post<TunnelApiItem>("/tunnel/get", { id });
export const updateTunnel = (data: TunnelMutationPayload) =>
Network.post("/tunnel/update", data);
export const deleteTunnel = (id: number) =>
Network.post("/tunnel/delete", { id });
export const diagnoseTunnel = (tunnelId: number) =>
Network.post("/tunnel/diagnose", { tunnelId });
Network.post<TunnelDiagnosisApiData>("/tunnel/diagnose", { tunnelId });
export const updateTunnelOrder = (data: {
tunnels: Array<{ id: number; inx: number }>;
}) => Network.post("/tunnel/update-order", data);
// 用户隧道权限管理操作 - 全部使用POST请求
export const assignUserTunnel = (data: any) =>
export const assignUserTunnel = (data: UserTunnelAssignPayload) =>
Network.post("/tunnel/user/assign", data);
export const batchAssignUserTunnel = (data: {
userId: number;
tunnels: Array<{ tunnelId: number; speedId?: number | null }>;
}) => Network.post("/tunnel/user/batch-assign", data);
export const getUserTunnelList = (queryData: any = {}) =>
Network.post("/tunnel/user/list", queryData);
export const removeUserTunnel = (params: any) =>
export const getUserTunnelList = (queryData: UserTunnelListQuery = {}) =>
Network.post<UserTunnelPermissionApiItem[]>("/tunnel/user/list", queryData);
export const removeUserTunnel = (params: UserTunnelRemovePayload) =>
Network.post("/tunnel/user/remove", params);
export const updateUserTunnel = (data: any) =>
export const updateUserTunnel = (data: UserTunnelAssignPayload) =>
Network.post("/tunnel/user/update", data);
export const userTunnel = () => Network.post("/tunnel/user/tunnel");
export const userTunnel = () =>
Network.post<UserTunnelApiItem[]>("/tunnel/user/tunnel");
// 转发CRUD操作 - 全部使用POST请求
export const createForward = (data: any) =>
export const createForward = (data: ForwardMutationPayload) =>
Network.post("/forward/create", data);
export const getForwardList = () => Network.post("/forward/list");
export const updateForward = (data: any) =>
export const getForwardList = () =>
Network.post<ForwardApiItem[]>("/forward/list");
export const updateForward = (data: ForwardMutationPayload) =>
Network.post("/forward/update", data);
export const deleteForward = (id: number) =>
Network.post("/forward/delete", { id });
@@ -107,7 +147,7 @@ export const resumeForwardService = (forwardId: number) =>
// 转发诊断操作
export const diagnoseForward = (forwardId: number) =>
Network.post("/forward/diagnose", { forwardId });
Network.post<ForwardDiagnosisApiData>("/forward/diagnose", { forwardId });
// 转发排序操作
export const updateForwardOrder = (data: {
@@ -115,16 +155,17 @@ export const updateForwardOrder = (data: {
}) => Network.post("/forward/update-order", data);
// 限速规则CRUD操作 - 全部使用POST请求
export const createSpeedLimit = (data: any) =>
export const createSpeedLimit = (data: SpeedLimitMutationPayload) =>
Network.post("/speed-limit/create", data);
export const getSpeedLimitList = () => Network.post("/speed-limit/list");
export const updateSpeedLimit = (data: any) =>
export const getSpeedLimitList = () =>
Network.post<SpeedLimitApiItem[]>("/speed-limit/list");
export const updateSpeedLimit = (data: SpeedLimitMutationPayload) =>
Network.post("/speed-limit/update", data);
export const deleteSpeedLimit = (id: number) =>
Network.post("/speed-limit/delete", { id });
// 修改密码接口
export const updatePassword = (data: any) =>
export const updatePassword = (data: UpdatePasswordPayload) =>
Network.post("/user/updatePassword", data);
// 重置流量接口
@@ -135,18 +176,19 @@ export const getUserGroups = (id: number) =>
Network.post<number[]>("/user/groups", { id });
// 网站配置相关接口
export const getConfigs = () => Network.post("/config/list");
export const getConfigs = () =>
Network.post<Record<string, string>>("/config/list");
export const getConfigByName = (name: string) =>
Network.post("/config/get", { name });
Network.post<{ name: string; value: string }>("/config/get", { name });
export const updateConfigs = (configMap: Record<string, string>) =>
Network.post("/config/update", configMap);
export const updateConfig = (name: string, value: string) =>
Network.post("/config/update-single", { name, value });
export const exportBackupData = () => Network.post("/backup/export");
export const importBackupData = (data: any) =>
export const importBackupData = (data: BackupImportPayload) =>
Network.post("/backup/import", data);
export const restoreBackupData = (data: any) =>
export const restoreBackupData = (data: BackupImportPayload) =>
Network.post("/backup/restore", data);
// 验证码相关接口
@@ -157,26 +199,27 @@ export const verifyCaptcha = (data: { captchaId: string; trackData: string }) =>
// 批量操作接口
export const batchDeleteForwards = (ids: number[]) =>
Network.post("/forward/batch-delete", { ids });
Network.post<BatchOperationResult>("/forward/batch-delete", { ids });
export const batchPauseForwards = (ids: number[]) =>
Network.post("/forward/batch-pause", { ids });
Network.post<BatchOperationResult>("/forward/batch-pause", { ids });
export const batchResumeForwards = (ids: number[]) =>
Network.post("/forward/batch-resume", { ids });
Network.post<BatchOperationResult>("/forward/batch-resume", { ids });
export const batchDeleteTunnels = (ids: number[]) =>
Network.post("/tunnel/batch-delete", { ids });
Network.post<BatchOperationResult>("/tunnel/batch-delete", { ids });
export const batchDeleteNodes = (ids: number[]) =>
Network.post("/node/batch-delete", { ids });
Network.post<BatchOperationResult>("/node/batch-delete", { ids });
export const batchRedeployForwards = (ids: number[]) =>
Network.post("/forward/batch-redeploy", { ids });
Network.post<BatchOperationResult>("/forward/batch-redeploy", { ids });
export const batchRedeployTunnels = (ids: number[]) =>
Network.post("/tunnel/batch-redeploy", { ids });
Network.post<BatchOperationResult>("/tunnel/batch-redeploy", { ids });
export const batchChangeTunnel = (data: {
forwardIds: number[];
targetTunnelId: number;
}) => Network.post("/forward/batch-change-tunnel", data);
}) => Network.post<BatchOperationResult>("/forward/batch-change-tunnel", data);
// 分组与权限分配接口
export const getTunnelGroupList = () => Network.post("/group/tunnel/list");
export const getTunnelGroupList = () =>
Network.post<TunnelGroupApiItem[]>("/group/tunnel/list");
export const createTunnelGroup = (data: { name: string; status?: number }) =>
Network.post("/group/tunnel/create", data);
export const updateTunnelGroup = (data: {
@@ -191,7 +234,8 @@ export const assignTunnelsToGroup = (data: {
tunnelIds: number[];
}) => Network.post("/group/tunnel/assign", data);
export const getUserGroupList = () => Network.post("/group/user/list");
export const getUserGroupList = () =>
Network.post<UserGroupApiItem[]>("/group/user/list");
export const createUserGroup = (data: { name: string; status?: number }) =>
Network.post("/group/user/create", data);
export const updateUserGroup = (data: {
@@ -207,7 +251,7 @@ export const assignUsersToGroup = (data: {
}) => Network.post("/group/user/assign", data);
export const getGroupPermissionList = () =>
Network.post("/group/permission/list");
Network.post<GroupPermissionApiItem[]>("/group/permission/list");
export const assignGroupPermission = (data: {
userGroupId: number;
tunnelGroupId: number;
@@ -216,7 +260,8 @@ export const removeGroupPermission = (id: number) =>
Network.post("/group/permission/remove", { id });
// 面板共享 (Federation) 接口
export const getPeerShareList = () => Network.post("/federation/share/list");
export const getPeerShareList = () =>
Network.post<Array<Record<string, unknown>>>("/federation/share/list");
export const createPeerShare = (data: {
name: string;
nodeId: number;
@@ -242,7 +287,9 @@ export const deletePeerShare = (id: number) =>
export const resetPeerShareFlow = (id: number) =>
Network.post("/federation/share/reset-flow", { id });
export const getPeerRemoteUsageList = () =>
Network.post("/federation/share/remote-usage/list");
Network.post<Array<Record<string, unknown>>>(
"/federation/share/remote-usage/list",
);
export const importRemoteNode = (data: { remoteUrl: string; token: string }) =>
Network.post("/federation/node/import", data);
@@ -288,7 +335,7 @@ export const exportBackup = async (types: string[] = []) => {
window.URL.revokeObjectURL(url);
};
export const importBackup = (data: { types: string[]; [key: string]: any }) =>
export const importBackup = (data: BackupImportPayload) =>
Network.post("/backup/import", data);
export interface AnnouncementData {
+38 -22
View File
@@ -1,6 +1,11 @@
import axios, { AxiosResponse } from "axios";
import {
extractApiErrorMessage,
isUnauthorizedError,
} from "@/api/error-message";
import { getPanelAddresses, isWebViewFunc } from "@/utils/panel";
import { clearSession, getToken } from "@/utils/session";
interface PanelAddress {
name: string;
@@ -37,7 +42,7 @@ export const reinitializeBaseURL = () => {
reinitializeBaseURL();
interface ApiResponse<T = any> {
interface ApiResponse<T = unknown> {
code: number;
msg: string;
data: T;
@@ -49,10 +54,7 @@ interface RequestOptions {
// 处理token失效的逻辑
function handleTokenExpired() {
// 清除localStorage中的token
window.localStorage.removeItem("token");
window.localStorage.removeItem("role_id");
window.localStorage.removeItem("name");
clearSession();
// 跳转到登录页面
if (window.location.pathname !== "/") {
@@ -61,7 +63,7 @@ function handleTokenExpired() {
}
// 检查响应是否为token失效
function isTokenExpired(response: ApiResponse) {
function isTokenExpired(response: ApiResponse<unknown>) {
return (
response &&
response.code === 401 &&
@@ -72,9 +74,9 @@ function isTokenExpired(response: ApiResponse) {
}
const Network = {
get: function <T = any>(
get: function <T = unknown>(
path: string = "",
data: any = {},
data: unknown = {},
options: RequestOptions = {},
): Promise<ApiResponse<T>> {
return new Promise(function (resolve) {
@@ -90,38 +92,45 @@ const Network = {
params: data,
timeout: options.timeout ?? 30000,
headers: {
Authorization: window.localStorage.getItem("token"),
Authorization: getToken(),
},
})
.then(function (response: AxiosResponse<ApiResponse<T>>) {
// 检查是否token失效
if (isTokenExpired(response.data)) {
handleTokenExpired();
return;
}
resolve(response.data);
})
.catch(function (error: any) {
.catch(function (error: unknown) {
const errorMessage = extractApiErrorMessage(error);
// 检查是否是401错误(token失效)
if (error.response && error.response.status === 401) {
if (isUnauthorizedError(error)) {
handleTokenExpired();
resolve({
code: 401,
msg: "未登录或token已过期",
data: null as T,
});
return;
}
resolve({
code: -1,
msg: error.message || "网络请求失败",
msg: errorMessage,
data: null as T,
});
});
});
},
post: function <T = any>(
post: function <T = unknown>(
path: string = "",
data: any = {},
data: unknown = {},
options: RequestOptions = {},
): Promise<ApiResponse<T>> {
return new Promise(function (resolve) {
@@ -136,7 +145,7 @@ const Network = {
.post(path, data, {
timeout: options.timeout ?? 30000,
headers: {
Authorization: window.localStorage.getItem("token"),
Authorization: getToken(),
"Content-Type": "application/json",
},
})
@@ -144,22 +153,29 @@ const Network = {
// 检查是否token失效
if (isTokenExpired(response.data)) {
handleTokenExpired();
return;
}
resolve(response.data);
})
.catch(function (error: any) {
.catch(function (error: unknown) {
const errorMessage = extractApiErrorMessage(error);
// 检查是否是401错误(token失效)
if (error.response && error.response.status === 401) {
if (isUnauthorizedError(error)) {
handleTokenExpired();
resolve({
code: 401,
msg: "未登录或token已过期",
data: null as T,
});
return;
}
resolve({
code: -1,
msg: error.message || "网络请求失败",
msg: errorMessage,
data: null as T,
});
});