@go-wind/admin-react 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +74 -2
- package/dist/access/access-control.d.ts +39 -0
- package/dist/access/field-permission.d.ts +11 -0
- package/dist/access/index.d.ts +4 -0
- package/dist/access/use-access.d.ts +50 -0
- package/dist/admin-react.css +2 -0
- package/dist/admin-react.js +36561 -0
- package/dist/admin-react.js.map +1 -0
- package/dist/auth-gateway.d.ts +54 -0
- package/dist/components/ListTable/ResizableHeaderCell.d.ts +31 -0
- package/dist/components/ListTable/TableSkeleton.d.ts +25 -0
- package/dist/components/ListTable/index.d.ts +20 -0
- package/dist/components/Loading/index.d.ts +22 -0
- package/dist/constants.d.ts +30 -0
- package/dist/env.d.ts +5 -0
- package/dist/hooks/useClipboard.d.ts +3 -0
- package/dist/hooks/useEcharts.d.ts +10 -0
- package/dist/hooks/useKeyStroke.d.ts +13 -0
- package/dist/hooks/usePageFullscreen.d.ts +9 -0
- package/dist/hooks/useProTableScrollY.d.ts +22 -0
- package/dist/hooks/useTime.d.ts +6 -0
- package/dist/hooks/useTitle.d.ts +1 -0
- package/dist/hooks/useTokenRefresh.d.ts +26 -0
- package/dist/hooks/useWatermark.d.ts +20 -0
- package/dist/i18n/components/LocaleSwitcher/index.d.ts +1 -0
- package/dist/i18n/components/index.d.ts +1 -0
- package/dist/i18n/config/i18n.d.ts +18 -0
- package/dist/i18n/hooks/index.d.ts +2 -0
- package/dist/i18n/hooks/useI18n.d.ts +96 -0
- package/dist/i18n/hooks/useLocaleSync.d.ts +4 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/utils/detector.d.ts +26 -0
- package/dist/i18n/utils/formatter.d.ts +38 -0
- package/dist/i18n/utils/index.d.ts +3 -0
- package/dist/i18n/utils/sync.d.ts +27 -0
- package/dist/index.d.ts +41 -0
- package/dist/locales/en-US/index.d.ts +2 -0
- package/dist/locales/index.d.ts +10 -0
- package/dist/locales/zh-CN/index.d.ts +2 -0
- package/dist/nprogress-CwfUlis6.js +159 -0
- package/dist/nprogress-CwfUlis6.js.map +1 -0
- package/dist/preferences/components/PreferencesPanel/AppearancePanel.d.ts +3 -0
- package/dist/preferences/components/PreferencesPanel/GeneralPanel.d.ts +3 -0
- package/dist/preferences/components/PreferencesPanel/LayoutPanel.d.ts +3 -0
- package/dist/preferences/components/PreferencesPanel/ShortcutKeyPanel.d.ts +3 -0
- package/dist/preferences/components/PreferencesPanel/index.d.ts +8 -0
- package/dist/preferences/components/ThemeProvider/index.d.ts +9 -0
- package/dist/preferences/components/index.d.ts +2 -0
- package/dist/preferences/config/constants.d.ts +24 -0
- package/dist/preferences/config/darkTheme.d.ts +32 -0
- package/dist/preferences/config/default.d.ts +3 -0
- package/dist/preferences/config/index.d.ts +4 -0
- package/dist/preferences/config/lightTheme.d.ts +33 -0
- package/dist/preferences/hooks/index.d.ts +3 -0
- package/dist/preferences/hooks/useLocale.d.ts +23 -0
- package/dist/preferences/hooks/usePreferences.d.ts +31 -0
- package/dist/preferences/hooks/useThemeConfig.d.ts +2 -0
- package/dist/preferences/index.d.ts +5 -0
- package/dist/preferences/store/index.d.ts +24 -0
- package/dist/preferences/theme-transition.d.ts +17 -0
- package/dist/preferences/types/app.d.ts +238 -0
- package/dist/preferences/types/index.d.ts +4 -0
- package/dist/preferences/types/layout.d.ts +78 -0
- package/dist/preferences/types/preferences-root.d.ts +48 -0
- package/dist/preferences/types/theme.d.ts +29 -0
- package/dist/preferences/utils/diff.d.ts +7 -0
- package/dist/preferences/utils/merge.d.ts +9 -0
- package/dist/query-client.d.ts +9 -0
- package/dist/rolldown-runtime-BbCBk-LD.js +19 -0
- package/dist/router/factory.d.ts +7 -0
- package/dist/router/generators/generate-menus.d.ts +13 -0
- package/dist/router/generators/generate-routes-backend.d.ts +12 -0
- package/dist/router/generators/generate-routes-frontend.d.ts +17 -0
- package/dist/router/generators/index.d.ts +3 -0
- package/dist/router/index.d.ts +5 -0
- package/dist/router/routes-context.d.ts +8 -0
- package/dist/router/types/index.d.ts +207 -0
- package/dist/router/utils/index.d.ts +8 -0
- package/dist/router/utils/inject-redirect.d.ts +6 -0
- package/dist/router/utils/lazy.d.ts +11 -0
- package/dist/router/utils/loader.d.ts +14 -0
- package/dist/router/utils/menu.d.ts +5 -0
- package/dist/router/utils/merge-route-modules.d.ts +23 -0
- package/dist/router/utils/reset-routes.d.ts +18 -0
- package/dist/router/utils/sort-routes.d.ts +5 -0
- package/dist/router/utils/transform-meta-to-handle.d.ts +11 -0
- package/dist/storage/index.d.ts +2 -0
- package/dist/storage/storage.class.d.ts +125 -0
- package/dist/storage/storage.types.d.ts +199 -0
- package/dist/stores/auth.d.ts +56 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/user.d.ts +32 -0
- package/dist/transport/rest/captcha-headers.d.ts +2 -0
- package/dist/transport/rest/index.d.ts +8 -0
- package/dist/transport/rest/modules/downloader.d.ts +9 -0
- package/dist/transport/rest/modules/interceptor.d.ts +9 -0
- package/dist/transport/rest/modules/uploader.d.ts +10 -0
- package/dist/transport/rest/pagination.d.ts +73 -0
- package/dist/transport/rest/preset-interceptors.d.ts +25 -0
- package/dist/transport/rest/request-api.d.ts +6 -0
- package/dist/transport/rest/request-client.d.ts +87 -0
- package/dist/transport/rest/types.d.ts +38 -0
- package/dist/transport/rest/utils.d.ts +16 -0
- package/dist/transport/sse/event.d.ts +44 -0
- package/dist/transport/sse/index.d.ts +5 -0
- package/dist/transport/sse/sse_client.d.ts +76 -0
- package/dist/transport/sse/types.d.ts +27 -0
- package/dist/types.d.ts +44 -0
- package/dist/utils/color.d.ts +27 -0
- package/dist/utils/date.d.ts +5 -0
- package/dist/utils/diff.d.ts +6 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/inference.d.ts +111 -0
- package/dist/utils/merge.d.ts +17 -0
- package/dist/utils/nprogress.d.ts +11 -0
- package/dist/utils/tree.d.ts +27 -0
- package/dist/utils/url.d.ts +11 -0
- package/dist/utils/utils.d.ts +37 -0
- package/package.json +77 -3
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type StoreApi } from 'zustand';
|
|
2
|
+
import { type AdminLoginParams } from '../auth-gateway';
|
|
3
|
+
import type { AdminUserInfo } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* 令牌载荷
|
|
6
|
+
*/
|
|
7
|
+
export interface TokenPayload {
|
|
8
|
+
/**
|
|
9
|
+
* 令牌值
|
|
10
|
+
*/
|
|
11
|
+
value: string;
|
|
12
|
+
/**
|
|
13
|
+
* 令牌过期时间
|
|
14
|
+
*/
|
|
15
|
+
expiresAt?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface AuthState {
|
|
18
|
+
accessToken: string | null;
|
|
19
|
+
accessTokenExpireAt: number | null;
|
|
20
|
+
userInfo: AdminUserInfo | null;
|
|
21
|
+
mfaOperationId: string | null;
|
|
22
|
+
loginLoading: boolean;
|
|
23
|
+
error: string | null;
|
|
24
|
+
login: (params: AdminLoginParams, onSuccess?: () => void, captcha?: {
|
|
25
|
+
id: string;
|
|
26
|
+
value: string;
|
|
27
|
+
}) => Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* 完成 MFA 挑战:用 operation_id + TOTP 码调后端验证,通过则后端返回真 token,
|
|
30
|
+
* 复用登录成功流程(存 token / 拉用户信息 / 跳首页)。失败抛错。
|
|
31
|
+
*/
|
|
32
|
+
completeMfaChallenge: (totpCode: string, onSuccess?: () => void) => Promise<void>;
|
|
33
|
+
/** 完成 OIDC SSO 登录:code+state 换令牌,复用登录成功流程;失败抛错 */
|
|
34
|
+
completeSsoLogin: (code: string, state: string, onSuccess?: () => void) => Promise<void>;
|
|
35
|
+
logout: (redirect?: boolean) => Promise<void>;
|
|
36
|
+
refreshToken: () => Promise<string>;
|
|
37
|
+
reauthenticate: () => void;
|
|
38
|
+
/** 强制登出:纯前端清除认证状态 + 跳转登录页,不调后端接口(用于 token 已失效场景) */
|
|
39
|
+
forceLogout: () => void;
|
|
40
|
+
setUserInfo: (info: AdminUserInfo) => void;
|
|
41
|
+
clearError: () => void;
|
|
42
|
+
$reset: () => void;
|
|
43
|
+
}
|
|
44
|
+
export declare const useAuthStore: import("zustand").UseBoundStore<Omit<StoreApi<AuthState>, "setState" | "persist"> & {
|
|
45
|
+
setState(partial: AuthState | Partial<AuthState> | ((state: AuthState) => AuthState | Partial<AuthState>), replace?: false | undefined): unknown;
|
|
46
|
+
setState(state: AuthState | ((state: AuthState) => AuthState), replace: true): unknown;
|
|
47
|
+
persist: {
|
|
48
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<AuthState, {}, unknown>>) => void;
|
|
49
|
+
clearStorage: () => void;
|
|
50
|
+
rehydrate: () => Promise<void>;
|
|
51
|
+
hasHydrated: () => boolean;
|
|
52
|
+
onHydrate: (fn: (state: AuthState) => void) => () => void;
|
|
53
|
+
onFinishHydration: (fn: (state: AuthState) => void) => () => void;
|
|
54
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<AuthState, {}, unknown>>;
|
|
55
|
+
};
|
|
56
|
+
}>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AdminUserBasic } from '../types';
|
|
2
|
+
export interface UserState {
|
|
3
|
+
userInfo: AdminUserBasic | null;
|
|
4
|
+
userRoles: string[];
|
|
5
|
+
accessCodes: string[];
|
|
6
|
+
hiddenFields: string[];
|
|
7
|
+
tenantId: string | null;
|
|
8
|
+
isLoggedIn: boolean;
|
|
9
|
+
setUserInfo: (info: AdminUserBasic | null) => void;
|
|
10
|
+
setUserRoles: (roles: string[]) => void;
|
|
11
|
+
setAccessCodes: (codes: string[]) => void;
|
|
12
|
+
setHiddenFields: (fields: string[]) => void;
|
|
13
|
+
isTenantUser: () => boolean;
|
|
14
|
+
$reset: () => void;
|
|
15
|
+
}
|
|
16
|
+
export declare const useUserStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<UserState>, "setState" | "persist"> & {
|
|
17
|
+
setState(partial: UserState | Partial<UserState> | ((state: UserState) => UserState | Partial<UserState>), replace?: false | undefined): unknown;
|
|
18
|
+
setState(state: UserState | ((state: UserState) => UserState), replace: true): unknown;
|
|
19
|
+
persist: {
|
|
20
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<UserState, {
|
|
21
|
+
userInfo: AdminUserBasic | null;
|
|
22
|
+
}, unknown>>) => void;
|
|
23
|
+
clearStorage: () => void;
|
|
24
|
+
rehydrate: () => Promise<void>;
|
|
25
|
+
hasHydrated: () => boolean;
|
|
26
|
+
onHydrate: (fn: (state: UserState) => void) => () => void;
|
|
27
|
+
onFinishHydration: (fn: (state: UserState) => void) => () => void;
|
|
28
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<UserState, {
|
|
29
|
+
userInfo: AdminUserBasic | null;
|
|
30
|
+
}, unknown>>;
|
|
31
|
+
};
|
|
32
|
+
}>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AxiosRequestConfig } from 'axios';
|
|
2
|
+
import type { RequestClient } from '../request-client';
|
|
3
|
+
import type { RequestResponse } from '../types';
|
|
4
|
+
declare class FileDownloader {
|
|
5
|
+
private client;
|
|
6
|
+
constructor(client: RequestClient);
|
|
7
|
+
download(url: string, config?: AxiosRequestConfig): Promise<RequestResponse<Blob>>;
|
|
8
|
+
}
|
|
9
|
+
export { FileDownloader };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AxiosInstance } from 'axios';
|
|
2
|
+
import type { RequestInterceptorConfig, ResponseInterceptorConfig } from '../types';
|
|
3
|
+
declare class InterceptorManager {
|
|
4
|
+
private axiosInstance;
|
|
5
|
+
constructor(instance: AxiosInstance);
|
|
6
|
+
addRequestInterceptor({ fulfilled, rejected, }?: RequestInterceptorConfig): void;
|
|
7
|
+
addResponseInterceptor<T = any>({ fulfilled, rejected, }?: ResponseInterceptorConfig<T>): void;
|
|
8
|
+
}
|
|
9
|
+
export { InterceptorManager };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
|
+
import type { RequestClient } from '../request-client';
|
|
3
|
+
declare class FileUploader {
|
|
4
|
+
private client;
|
|
5
|
+
constructor(client: RequestClient);
|
|
6
|
+
upload(url: string, data: {
|
|
7
|
+
file: Blob | File;
|
|
8
|
+
} & Record<string, any>, config?: AxiosRequestConfig): Promise<AxiosResponse>;
|
|
9
|
+
}
|
|
10
|
+
export { FileUploader };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export declare class PaginationQuery {
|
|
2
|
+
paging?: {
|
|
3
|
+
page?: number;
|
|
4
|
+
pageSize?: number;
|
|
5
|
+
};
|
|
6
|
+
formValues?: Record<string, unknown> | null;
|
|
7
|
+
fieldMask?: string | string[] | null;
|
|
8
|
+
orderBy?: string[] | null;
|
|
9
|
+
isTenantUser: boolean;
|
|
10
|
+
constructor(data?: Partial<PaginationQuery>);
|
|
11
|
+
/**
|
|
12
|
+
* 移除对象中的 null 和 undefined 值
|
|
13
|
+
* @param obj - 需要清理的对象
|
|
14
|
+
* @returns 清理后的对象
|
|
15
|
+
*/
|
|
16
|
+
private static removeNullUndefined;
|
|
17
|
+
/**
|
|
18
|
+
* key 末段是否已是 go-crud 支持的查询操作符(created_at__gte、type__not 等)。
|
|
19
|
+
* 这类 key 不能再叠加 __contains:go-crud 会把 `a__gte__contains`
|
|
20
|
+
* 解析成 `a CONTAINS value`,对时间/布尔列直接 SQL 报错(500),
|
|
21
|
+
* "排除"等语义也可能被静默反转。
|
|
22
|
+
*
|
|
23
|
+
* 下表与 go-crud `filter/operator_converter.go` 的 operatorMap 别名集
|
|
24
|
+
* 逐字对齐(含 i_* 前缀变体、数值比较长拼写/连字符拼写、is_not_null
|
|
25
|
+
* 拼写族、json_contains/array_contains/exists/search/exact/iexact)。
|
|
26
|
+
* 后端映射表变更时须同步此表;匹配前做小写归一(后端同)。此表缺项
|
|
27
|
+
* 会让对应后缀键被追加 __contains 而语义反转或 500(2026-09-13 修复的缺口)。
|
|
28
|
+
*/
|
|
29
|
+
private static hasOperatorSuffix;
|
|
30
|
+
/**
|
|
31
|
+
* 创建列表查询 JSON 过滤字符串
|
|
32
|
+
*
|
|
33
|
+
* 后端 go-crud 的裸 `{"field": value}` 走 EQ 精确匹配;搜索框输入部分关键词
|
|
34
|
+
* 必须使用 `field__contains` 才是模糊匹配。这里约定:字符串值统一转
|
|
35
|
+
* `__contains`(contains 是完整值精确匹配的超集,对下拉枚举等完整值查询
|
|
36
|
+
* 结果一致),非字符串(数字/布尔)保持 EQ 精确语义。
|
|
37
|
+
* @param formValues - 查询表单值
|
|
38
|
+
* @param needCleanTenant - 是否需要清理租户字段
|
|
39
|
+
* @returns JSON 字符串或 undefined
|
|
40
|
+
*/
|
|
41
|
+
private static makeQueryString;
|
|
42
|
+
/**
|
|
43
|
+
* 创建排序字符串
|
|
44
|
+
* @param orderBy - 排序字段数组
|
|
45
|
+
* @returns JSON 字符串或 undefined
|
|
46
|
+
*/
|
|
47
|
+
private static makeOrderBy;
|
|
48
|
+
get noPaging(): boolean;
|
|
49
|
+
get orderByString(): string | undefined;
|
|
50
|
+
get queryString(): string | undefined;
|
|
51
|
+
private get formattedFieldMask();
|
|
52
|
+
toRawParams(): {
|
|
53
|
+
page: number | undefined;
|
|
54
|
+
pageSize: number | undefined;
|
|
55
|
+
noPaging: boolean;
|
|
56
|
+
fieldMask: string | undefined;
|
|
57
|
+
orderBy: string | undefined;
|
|
58
|
+
query: string | undefined;
|
|
59
|
+
sorting: undefined;
|
|
60
|
+
offset: undefined;
|
|
61
|
+
limit: undefined;
|
|
62
|
+
token: undefined;
|
|
63
|
+
filter: undefined;
|
|
64
|
+
filterExpr: undefined;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 分页查询结果类型
|
|
69
|
+
*/
|
|
70
|
+
export type PaginationResult<T> = {
|
|
71
|
+
items: T[];
|
|
72
|
+
total: number;
|
|
73
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { RequestClient } from './request-client';
|
|
2
|
+
import type { MakeErrorMessageFn, ResponseInterceptorConfig } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* 认证响应拦截器:处理 401 错误,支持自动刷新 token 和重新认证
|
|
5
|
+
* @param client 请求客户端实例
|
|
6
|
+
* @param doReAuthenticate 重新认证函数,返回 Promise<void>
|
|
7
|
+
* @param doRefreshToken 刷新 token 函数,返回 Promise<string>,成功时返回新的 token
|
|
8
|
+
* @param enableRefreshToken 是否启用刷新 token 功能
|
|
9
|
+
* @param formatToken 格式化 token 的函数,接受原始 token 字符串,返回格式化后的 token 字符串(如添加 "Bearer " 前缀),如果返回 null 则不设置 Authorization 头
|
|
10
|
+
* @returns 响应拦截器配置对象
|
|
11
|
+
*/
|
|
12
|
+
export declare const authenticateResponseInterceptor: ({ client, doReAuthenticate, doRefreshToken, enableRefreshToken, formatToken, }: {
|
|
13
|
+
client: RequestClient;
|
|
14
|
+
doReAuthenticate: () => Promise<void>;
|
|
15
|
+
doRefreshToken: () => Promise<string>;
|
|
16
|
+
enableRefreshToken: boolean;
|
|
17
|
+
formatToken: (token: string) => null | string;
|
|
18
|
+
}) => ResponseInterceptorConfig;
|
|
19
|
+
/**
|
|
20
|
+
* 错误消息拦截器:提取错误文本并回调
|
|
21
|
+
* @param makeErrorMessage 错误消息回调函数
|
|
22
|
+
* @param getErrorMsg 获取错误消息函数,默认为 getDefaultErrorMsg
|
|
23
|
+
* @returns 响应拦截器配置对象
|
|
24
|
+
*/
|
|
25
|
+
export declare const errorMessageResponseInterceptor: (makeErrorMessage?: MakeErrorMessageFn, getErrorMsg?: (error: unknown) => string) => ResponseInterceptorConfig;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { AxiosRequestConfig } from 'axios';
|
|
2
|
+
import { FileDownloader } from './modules/downloader';
|
|
3
|
+
import { InterceptorManager } from './modules/interceptor';
|
|
4
|
+
import { FileUploader } from './modules/uploader';
|
|
5
|
+
import type { RequestClientCallbacks, RequestClientOptions } from './types';
|
|
6
|
+
declare class RequestClient {
|
|
7
|
+
private readonly instance;
|
|
8
|
+
/**
|
|
9
|
+
* 错误消息提取函数(由应用层注入,接入 i18n;未注入时回退到 getDefaultErrorMsg)。
|
|
10
|
+
* 仅基于 reason 翻译,不返回后端 message。
|
|
11
|
+
*/
|
|
12
|
+
private readonly getErrorMsg;
|
|
13
|
+
addRequestInterceptor: InterceptorManager['addRequestInterceptor'];
|
|
14
|
+
addResponseInterceptor: InterceptorManager['addResponseInterceptor'];
|
|
15
|
+
download: FileDownloader['download'];
|
|
16
|
+
isRefreshing: boolean;
|
|
17
|
+
refreshTokenQueue: ((token: string) => void)[];
|
|
18
|
+
upload: FileUploader['upload'];
|
|
19
|
+
private static _instance;
|
|
20
|
+
/**
|
|
21
|
+
* 初始化全局单例(在 bootstrap 时调用一次)
|
|
22
|
+
*/
|
|
23
|
+
static init(baseURL: string, callbacks: RequestClientCallbacks): void;
|
|
24
|
+
/**
|
|
25
|
+
* 获取全局单例
|
|
26
|
+
*/
|
|
27
|
+
static getInstance(): RequestClient;
|
|
28
|
+
/**
|
|
29
|
+
* 构造函数,创建 Axios 实例并注册拦截器
|
|
30
|
+
* @param options - Axios 请求配置
|
|
31
|
+
* @param callbacks - 业务回调接口(token、认证、错误处理),由应用层注入
|
|
32
|
+
*/
|
|
33
|
+
constructor(options?: RequestClientOptions, callbacks?: RequestClientCallbacks);
|
|
34
|
+
/**
|
|
35
|
+
* 格式化令牌
|
|
36
|
+
*/
|
|
37
|
+
private formatToken;
|
|
38
|
+
/**
|
|
39
|
+
* 注册所有内置拦截器
|
|
40
|
+
*/
|
|
41
|
+
private setupInterceptors;
|
|
42
|
+
/**
|
|
43
|
+
* 请求拦截器:注入 Authorization Token
|
|
44
|
+
*/
|
|
45
|
+
private useTokenInterceptor;
|
|
46
|
+
/**
|
|
47
|
+
* 请求拦截器:注入 X-Request-ID 和 XMLHttpRequest 标识
|
|
48
|
+
*/
|
|
49
|
+
private useRequestIdInterceptor;
|
|
50
|
+
/**
|
|
51
|
+
* 请求拦截器:注入 Accept-Language
|
|
52
|
+
*/
|
|
53
|
+
private useLocaleInterceptor;
|
|
54
|
+
/**
|
|
55
|
+
* 响应拦截器:解构响应数据(只返回 data 部分)
|
|
56
|
+
*/
|
|
57
|
+
private useResponseDataInterceptor;
|
|
58
|
+
/**
|
|
59
|
+
* 401 认证拦截器:自动刷新 Token 或跳转登录页
|
|
60
|
+
*/
|
|
61
|
+
private useAuthInterceptor;
|
|
62
|
+
/**
|
|
63
|
+
* 统一错误消息拦截器:提取错误文本并回调
|
|
64
|
+
*/
|
|
65
|
+
private useErrorMessageInterceptor;
|
|
66
|
+
/**
|
|
67
|
+
* DELETE请求方法
|
|
68
|
+
*/
|
|
69
|
+
delete<T = never>(url: string, config?: AxiosRequestConfig): Promise<T>;
|
|
70
|
+
/**
|
|
71
|
+
* GET请求方法
|
|
72
|
+
*/
|
|
73
|
+
get<T = never>(url: string, config?: AxiosRequestConfig): Promise<T>;
|
|
74
|
+
/**
|
|
75
|
+
* POST请求方法
|
|
76
|
+
*/
|
|
77
|
+
post<T = never>(url: string, data?: never, config?: AxiosRequestConfig): Promise<T>;
|
|
78
|
+
/**
|
|
79
|
+
* PUT请求方法
|
|
80
|
+
*/
|
|
81
|
+
put<T = never>(url: string, data?: never, config?: AxiosRequestConfig): Promise<T>;
|
|
82
|
+
/**
|
|
83
|
+
* 通用的请求方法
|
|
84
|
+
*/
|
|
85
|
+
request<T>(url: string, config: AxiosRequestConfig): Promise<T>;
|
|
86
|
+
}
|
|
87
|
+
export { RequestClient };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AxiosResponse, CreateAxiosDefaults, InternalAxiosRequestConfig } from 'axios';
|
|
2
|
+
type RequestResponse<T = any> = AxiosResponse<T>;
|
|
3
|
+
type RequestContentType = 'application/json;charset=utf-8' | 'application/octet-stream;charset=utf-8' | 'application/x-www-form-urlencoded;charset=utf-8' | 'multipart/form-data;charset=utf-8';
|
|
4
|
+
type RequestClientOptions = CreateAxiosDefaults;
|
|
5
|
+
interface RequestInterceptorConfig {
|
|
6
|
+
fulfilled?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig<any> | Promise<InternalAxiosRequestConfig<any>>;
|
|
7
|
+
rejected?: (error: any) => any;
|
|
8
|
+
}
|
|
9
|
+
interface ResponseInterceptorConfig<T = any> {
|
|
10
|
+
fulfilled?: (response: AxiosResponse<T>) => AxiosResponse | Promise<AxiosResponse>;
|
|
11
|
+
rejected?: (error: any) => any;
|
|
12
|
+
}
|
|
13
|
+
type MakeErrorMessageFn = (message: string, error: any) => void;
|
|
14
|
+
interface HttpResponse {
|
|
15
|
+
code: number;
|
|
16
|
+
reason: string;
|
|
17
|
+
message: string;
|
|
18
|
+
metadata: object;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 请求客户端回调接口
|
|
22
|
+
* 由应用层(bootstrap)注入具体实现,基础设施层不感知业务逻辑
|
|
23
|
+
*/
|
|
24
|
+
interface RequestClientCallbacks {
|
|
25
|
+
/** 获取当前 access token */
|
|
26
|
+
getToken: () => string | null;
|
|
27
|
+
/** 获取当前语言标识(如 zh-CN、en-US) */
|
|
28
|
+
getLocale?: () => string;
|
|
29
|
+
/** 刷新 token,返回新的 access token */
|
|
30
|
+
refreshToken: () => Promise<string>;
|
|
31
|
+
/** Token 彻底失效时的处理(登出 + 跳转登录页) */
|
|
32
|
+
onReAuthenticate: (redirect?: boolean) => Promise<void>;
|
|
33
|
+
/** 错误消息处理(弹窗、toast 等) */
|
|
34
|
+
onError?: (message: string) => void;
|
|
35
|
+
/** 从错误对象中提取用户友好的错误消息(可接入 i18n) */
|
|
36
|
+
getErrorMsg?: (error: unknown) => string;
|
|
37
|
+
}
|
|
38
|
+
export type { RequestClientCallbacks, HttpResponse, MakeErrorMessageFn, RequestClientOptions, RequestContentType, RequestInterceptorConfig, RequestResponse, ResponseInterceptorConfig, };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 创建更新掩码字符串
|
|
3
|
+
* @param keys - 字段键名数组
|
|
4
|
+
* @returns 逗号分隔的字符串
|
|
5
|
+
*/
|
|
6
|
+
export declare function makeUpdateMask(keys: string[]): string;
|
|
7
|
+
/**
|
|
8
|
+
* 默认的请求 ID 生成器
|
|
9
|
+
*/
|
|
10
|
+
export declare function defaultIdGenerator(): string;
|
|
11
|
+
/**
|
|
12
|
+
* 默认的错误消息提取(不依赖 i18n,纯逻辑 fallback)
|
|
13
|
+
* 仅基于 reason;不再回退到后端 message 字段(该字段后续将被移除)。
|
|
14
|
+
* 如需 i18n 翻译,通过 RequestClientCallbacks.getErrorMsg 注入。
|
|
15
|
+
*/
|
|
16
|
+
export declare function getDefaultErrorMsg(error: unknown): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE 事件名注册表(react 端副本)。
|
|
3
|
+
*
|
|
4
|
+
* 真相源是后端 `backend/pkg/sseevent/sseevent.go`:它把常量写进帧的 `event:` 行,
|
|
5
|
+
* 这里按同名注册回调,中间没有编译期检查(`SSEEventName` 带 `| string`,等于不约束)。
|
|
6
|
+
* 新增事件要两边同时改;已发布事件的取值不可改——改名等于对线上前端静默断流。
|
|
7
|
+
*/
|
|
8
|
+
export declare const SSE_EVENT: {
|
|
9
|
+
/**
|
|
10
|
+
* 站内信收件行推送。
|
|
11
|
+
*
|
|
12
|
+
* data 为 `InternalMessageRecipient` 的 protojson:camelCase 键(`messageId` /
|
|
13
|
+
* `recipientUserId` / `createdAt`),`status` 是枚举名字符串(`RECEIVED` / `READ`),
|
|
14
|
+
* 与 REST 收件箱接口返回的形状一致。
|
|
15
|
+
*/
|
|
16
|
+
readonly Notification: "notification";
|
|
17
|
+
/**
|
|
18
|
+
* AI 对话流式片段推送。
|
|
19
|
+
*
|
|
20
|
+
* data 为 `ChatChunkEvent` 的 protojson:camelCase 键(`conversationId` /
|
|
21
|
+
* `seq` / `delta`)。一次对话产生多个 chunk 帧,按 conversationId 归组、
|
|
22
|
+
* seq 顺序累积渲染;POST /admin/v1/ai/chat/completions 的同步响应携带
|
|
23
|
+
* 完整回复,以响应为准校正累积文本。
|
|
24
|
+
*/
|
|
25
|
+
readonly AIChatChunk: "ai_chat_chunk";
|
|
26
|
+
/**
|
|
27
|
+
* AI 对话的工具调用可见化推送。
|
|
28
|
+
*
|
|
29
|
+
* data 为 `ChatToolEvent` 的 protojson:camelCase 键(`conversationId` /
|
|
30
|
+
* `name` / `arguments` / `result`)。模型每发起一次本地工具调用并执行完成
|
|
31
|
+
* 后推一帧;工具轮不进消息落库(落库的 assistant 消息只有最终答案),
|
|
32
|
+
* 本事件是前端展示"模型正在调工具"的唯一信息源(尽力而为,丢帧可容忍)。
|
|
33
|
+
*/
|
|
34
|
+
readonly AIChatTool: "ai_chat_tool";
|
|
35
|
+
/**
|
|
36
|
+
* AI Agent 试运行实时推送。
|
|
37
|
+
*
|
|
38
|
+
* data 为 `AgentRunEvent` 的 protojson:camelCase 键(`runId` / `appId` /
|
|
39
|
+
* `seq` / `phase`(node_start|node_end|error|done) / `nodeId` / `summary` /
|
|
40
|
+
* `status`)。一次试运行产生多帧;Run 同步响应携带完整 trace 与终态,
|
|
41
|
+
* 以响应为准校正(尽力而为,丢帧可容忍)。streamId 与对话同为发起用户流。
|
|
42
|
+
*/
|
|
43
|
+
readonly AgentRun: "ai_agent_run";
|
|
44
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { SSEClientConfig, SSEConnectionStatus, SSEEventHandler, SSEEventName } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* SSE客户端
|
|
4
|
+
*/
|
|
5
|
+
export declare class SSEClient {
|
|
6
|
+
private abortController;
|
|
7
|
+
private config;
|
|
8
|
+
private eventSource;
|
|
9
|
+
private handlers;
|
|
10
|
+
private status;
|
|
11
|
+
private readonly transport;
|
|
12
|
+
constructor(config: SSEClientConfig);
|
|
13
|
+
/**
|
|
14
|
+
* 解析数据(自动处理 JSON 格式)
|
|
15
|
+
* @param rawData
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
private parseData;
|
|
19
|
+
/**
|
|
20
|
+
* 触发事件监听器
|
|
21
|
+
* @param eventName
|
|
22
|
+
* @param data
|
|
23
|
+
* @param event
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
private triggerHandler;
|
|
27
|
+
/**
|
|
28
|
+
* 通过 EventSource 建立 SSE 连接
|
|
29
|
+
* @param url 连接 URL
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
_connectByEventSource(url: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* 通过 fetchEventSource 建立 SSE 连接(支持更灵活的配置和控制)
|
|
35
|
+
* @param url 连接 URL
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
_connectByFetchEventSource(url: string): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* 关闭 SSE 连接
|
|
41
|
+
*/
|
|
42
|
+
close(): void;
|
|
43
|
+
/**
|
|
44
|
+
* 建立 SSE 连接
|
|
45
|
+
* @param url 可选连接 URL,默认为配置中的 URL
|
|
46
|
+
*/
|
|
47
|
+
connect(url?: string): Error | null;
|
|
48
|
+
/**
|
|
49
|
+
* 获取当前连接状态
|
|
50
|
+
*/
|
|
51
|
+
getStatus(): SSEConnectionStatus;
|
|
52
|
+
/**
|
|
53
|
+
* 移除事件监听器
|
|
54
|
+
* @param eventName
|
|
55
|
+
* @param handler
|
|
56
|
+
*/
|
|
57
|
+
off<T = unknown>(eventName: SSEEventName, handler?: SSEEventHandler<T>): void;
|
|
58
|
+
/**
|
|
59
|
+
* 注册事件监听器(支持泛型指定数据类型)
|
|
60
|
+
* @param eventName
|
|
61
|
+
* @param handler
|
|
62
|
+
*/
|
|
63
|
+
on<T = unknown>(eventName: SSEEventName, handler: SSEEventHandler<T>): void;
|
|
64
|
+
/**
|
|
65
|
+
* 关闭当前连接并使用新的 URL / headers 重新连接
|
|
66
|
+
* 适用于 token 刷新后需要携带新凭证的场景
|
|
67
|
+
* @param url 可选的新连接 URL,默认沿用配置中的 URL
|
|
68
|
+
*/
|
|
69
|
+
reconnect(url?: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* 动态设置/更新请求头(不会影响正在进行中的连接,下次 connect 时生效)
|
|
72
|
+
* 注意:EventSource 模式不支持自定义请求头,此方法仅对 fetch-event-source 模式生效
|
|
73
|
+
* @param headers 键值对,会浅合并到当前 headers 配置中
|
|
74
|
+
*/
|
|
75
|
+
setHeaders(headers: Record<string, string>): void;
|
|
76
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE 事件类型(区分默认事件和自定义事件)
|
|
3
|
+
*/
|
|
4
|
+
export type SSEEventName = 'error' | 'message' | 'open' | string;
|
|
5
|
+
/**
|
|
6
|
+
* SSE 事件回调函数类型(T 为数据类型)
|
|
7
|
+
*/
|
|
8
|
+
export type SSEEventHandler<T = unknown> = (data: T, event: MessageEvent) => void;
|
|
9
|
+
/**
|
|
10
|
+
* SSE 连接实现方式
|
|
11
|
+
*/
|
|
12
|
+
export type SSETransport = 'event-source' | 'fetch-event-source';
|
|
13
|
+
/**
|
|
14
|
+
* SSE 客户端配置
|
|
15
|
+
*/
|
|
16
|
+
export interface SSEClientConfig {
|
|
17
|
+
url: string;
|
|
18
|
+
withCredentials?: boolean;
|
|
19
|
+
reconnectDelay?: number;
|
|
20
|
+
autoParseJson?: boolean;
|
|
21
|
+
headers?: Record<string, string>;
|
|
22
|
+
transport?: SSETransport;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* SSE 连接状态
|
|
26
|
+
*/
|
|
27
|
+
export type SSEConnectionStatus = 'connected' | 'connecting' | 'disconnected' | 'error';
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 包内基础类型(自 go-wind-admin 的 src/types/global.d.ts 迁入)。
|
|
3
|
+
*
|
|
4
|
+
* 宿主应用保留自己的全局 `UserInfo`/`BasicUserInfo` 声明即可——它们与本包的
|
|
5
|
+
* AdminUserInfo 结构兼容(宿主接口字段为必填,赋给本包可选字段类型天然可赋值),
|
|
6
|
+
* 无需 declaration merging。
|
|
7
|
+
*/
|
|
8
|
+
/** 用户信息基础形状(与宿主 BasicUserInfo 对齐) */
|
|
9
|
+
export interface AdminUserBasic {
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
/** 头像 */
|
|
12
|
+
avatar: string;
|
|
13
|
+
/** 用户id(后端 uint64,proto3 JSON 下为字符串) */
|
|
14
|
+
id: string;
|
|
15
|
+
/** 用户昵称 */
|
|
16
|
+
nickname: string;
|
|
17
|
+
/** 用户实名 */
|
|
18
|
+
realname: string;
|
|
19
|
+
/** 用户角色 */
|
|
20
|
+
roles?: string[];
|
|
21
|
+
/** 租户id(后端 uint64,proto3 JSON 下为字符串) */
|
|
22
|
+
tenantId: string;
|
|
23
|
+
/** 用户名 */
|
|
24
|
+
username: string;
|
|
25
|
+
}
|
|
26
|
+
/** 包内认证/用户 store 消费的用户信息形状 */
|
|
27
|
+
export interface AdminUserInfo extends AdminUserBasic {
|
|
28
|
+
/** 用户描述 */
|
|
29
|
+
description?: string;
|
|
30
|
+
/** 首页地址 */
|
|
31
|
+
homePath?: string;
|
|
32
|
+
/** accessToken */
|
|
33
|
+
token?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* React Router 路由 handle 元数据类型。
|
|
37
|
+
* 用于 useMatches() 获取路由附加信息(自宿主全局声明迁入)。
|
|
38
|
+
*/
|
|
39
|
+
export interface RouteHandle {
|
|
40
|
+
title?: string;
|
|
41
|
+
icon?: string;
|
|
42
|
+
authority?: string[];
|
|
43
|
+
[key: string]: any;
|
|
44
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 生成基于字符串的固定随机色(HSL模式,保证饱和度和明度适中)
|
|
3
|
+
*
|
|
4
|
+
* 浅底色(l=85):只能配深色墨(最差色相对深色墨仍 ≥11:1),配白字不可读。
|
|
5
|
+
* @param str
|
|
6
|
+
*/
|
|
7
|
+
export declare const getRandomColor: (str: string) => string;
|
|
8
|
+
/**
|
|
9
|
+
* 根据首字母生成固定随机色(头像实底色,前景固定近白)
|
|
10
|
+
*
|
|
11
|
+
* 明度取 28% 是量出来的:本函数的产物一律配 antd/EP 头像的白字,而 hsl 同饱和度下
|
|
12
|
+
* 45% 明度是"两种墨都不合格"的死区(360 个色相里最差 white 2.03 / dark 2.01);
|
|
13
|
+
* 28% + s60 保证任意色相下白字 ≥4.86:1(判据与换算见 docs/design-language.md §2.1)。
|
|
14
|
+
* @param char
|
|
15
|
+
*/
|
|
16
|
+
export declare const getCharColor: (char: string) => string;
|
|
17
|
+
export declare function hexToRgb(hex: string): [number, number, number];
|
|
18
|
+
export declare function rgbToHex(r: number, g: number, b: number): string;
|
|
19
|
+
/** 解析 `#rgb`/`#rrggbb`/`hsl(h s% l%)`/`hsl(h, s%, l%)` 为 [r,g,b](0-255);无法识别返回 null */
|
|
20
|
+
export declare function parseColor(c: string): [number, number, number] | null;
|
|
21
|
+
/**
|
|
22
|
+
* 与 CSS `color-mix(in srgb, base pct%, other)` 同口径的 JS 版本。
|
|
23
|
+
* 存在的理由:antd 的 token 值(colorLink、Menu.itemSelectedColor 等)会被 antd 再做
|
|
24
|
+
* 一次色彩运算,不能填 `var(--gowind-*)`,所以「语义色作文字」的降档/升档要在 TS 里算一遍;
|
|
25
|
+
* 比例与 vue-element 端 `styles/vendors/_element-plus.scss` §3 完全一致,改动须同步两处。
|
|
26
|
+
*/
|
|
27
|
+
export declare function mixColor(base: string, other: string, pct: number): string;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function formatDate(dateString: string | undefined): string;
|
|
2
|
+
export declare const formatDateTime: (timestamp?: any) => string;
|
|
3
|
+
export declare const DATE_FORMAT = "YYYY-MM-DD";
|
|
4
|
+
export declare const TIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
|
|
5
|
+
export declare const TIME_PICKER_FORMAT = "HH:mm:ss";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare function arraysEqual<T>(a: T[], b: T[]): boolean;
|
|
2
|
+
type DiffResult<T> = Partial<{
|
|
3
|
+
[K in keyof T]: T[K] extends object ? DiffResult<T[K]> : T[K];
|
|
4
|
+
}>;
|
|
5
|
+
declare function diff<T extends Record<string, any>>(obj1: T, obj2: T): DiffResult<T>;
|
|
6
|
+
export { arraysEqual, diff };
|