@zxiaosi/sdk 0.5.2 → 1.0.0-beta.2
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/dist/index.d.ts +192 -393
- package/dist/index.js +1 -1
- package/package.json +10 -9
package/dist/index.d.ts
CHANGED
|
@@ -1,295 +1,191 @@
|
|
|
1
|
-
import * as zustand from "zustand";
|
|
2
1
|
import { ComponentType, ReactElement } from "react";
|
|
3
|
-
import {
|
|
4
|
-
import { AxiosInstance, AxiosRequestConfig, CreateAxiosDefaults } from "axios";
|
|
5
|
-
import { ConfigProviderProps } from "antd";
|
|
6
|
-
import * as react_intl_universal0 from "react-intl-universal";
|
|
7
|
-
import intl from "react-intl-universal";
|
|
8
|
-
import { MenuDataItem, ProLayoutProps } from "@ant-design/pro-layout";
|
|
2
|
+
import { NavigateFunction, UIMatch } from "react-router-dom";
|
|
9
3
|
import { MicroApp, ObjectType, RegistrableApp } from "qiankun";
|
|
4
|
+
import { StateCreator } from "zustand";
|
|
10
5
|
|
|
11
|
-
//#region src/plugins/api/http.d.ts
|
|
12
|
-
interface ApiRequestOption extends AxiosRequestConfig {
|
|
13
|
-
/** 请求唯一key(默认自动生成) */
|
|
14
|
-
requestId?: string;
|
|
15
|
-
/** 是否取消重复请求 */
|
|
16
|
-
isCancelRequest?: boolean;
|
|
17
|
-
/** 是否需要原始数据 */
|
|
18
|
-
isOriginalData?: boolean;
|
|
19
|
-
/** 是否显示错误信息 */
|
|
20
|
-
isShowFailMsg?: boolean;
|
|
21
|
-
}
|
|
22
|
-
//#endregion
|
|
23
6
|
//#region src/plugins/api/index.d.ts
|
|
24
|
-
interface ApiOptions {
|
|
25
|
-
/** Axios配置 */
|
|
26
|
-
config?: CreateAxiosDefaults;
|
|
27
|
-
/** 取消请求控制器 */
|
|
28
|
-
controllers?: Map<string, AbortController>;
|
|
29
|
-
/**
|
|
30
|
-
* 自定义请求实例
|
|
31
|
-
* - 替换 SDK 内置的请求实例
|
|
32
|
-
* @example instance = axios.create(options)
|
|
33
|
-
*/
|
|
34
|
-
instance?: AxiosInstance;
|
|
35
|
-
/**
|
|
36
|
-
* 获取用户信息
|
|
37
|
-
* {@link UserInfo}
|
|
38
|
-
* @example { code: 0, data: { user: {}, permissions: [], roles: [], settings: {} } }
|
|
39
|
-
*/
|
|
40
|
-
getUserInfoApi?(): Promise<any>;
|
|
41
|
-
/**
|
|
42
|
-
* 获取路由数据
|
|
43
|
-
* {@link RouteObject}
|
|
44
|
-
* @example { code: 0, data: [{path: '/', name: '首页', component: 'Home'}] }
|
|
45
|
-
*/
|
|
46
|
-
getRoutesApi?(): Promise<any>;
|
|
47
|
-
/**
|
|
48
|
-
* 登录接口
|
|
49
|
-
* @example { code: 0, data: { token: 'xxxx' } }
|
|
50
|
-
*/
|
|
51
|
-
loginApi?(params: any): Promise<any>;
|
|
52
|
-
}
|
|
53
|
-
interface ApiResults extends Required<ApiOptions> {
|
|
54
|
-
/**
|
|
55
|
-
* 请求
|
|
56
|
-
* @param url 请求地址
|
|
57
|
-
* @param options 自定义配置项
|
|
58
|
-
*/
|
|
59
|
-
request(url: string, options?: ApiRequestOption): Promise<any>;
|
|
60
|
-
}
|
|
7
|
+
interface ApiOptions {}
|
|
61
8
|
/**
|
|
62
9
|
* 请求插件
|
|
63
|
-
* - 详情参考 {@link ApiOptions} {@link ApiResults}
|
|
64
|
-
* - 内置了请求, 通过 sdk.api.request 发起请求
|
|
65
|
-
* - 可通过外部传入 instance 自定义请求实例
|
|
66
|
-
* - 预置了获取用户信息, 获取路由接口, 以便组件使用
|
|
67
|
-
* @example sdk.api.request('/getTemp', { method: 'POST', ... })
|
|
68
|
-
* @example sdk.api.request('/getTemp', { method: 'POST', isOriginalData: true }) // 返回原始数据
|
|
69
|
-
* @example sdk.api.request('/getTemp', { method: 'POST', isShowFailMsg: false }) // 不显示错误信息
|
|
70
|
-
* @example sdk.api.request('/getTemp', { method: 'POST', isCancelRequest: false }) // 不自动取消重复请求
|
|
71
10
|
*/
|
|
72
|
-
declare const
|
|
11
|
+
declare const SDKApiPlugin: SDKPlugin;
|
|
73
12
|
//#endregion
|
|
74
13
|
//#region src/plugins/app/index.d.ts
|
|
75
14
|
interface AppOptions {
|
|
76
15
|
/** 菜单数据 */
|
|
77
|
-
menuData
|
|
16
|
+
menuData: any[];
|
|
78
17
|
/** 所有路由信息 */
|
|
79
|
-
allRoutes
|
|
18
|
+
allRoutes: any[];
|
|
80
19
|
/** 微应用信息 */
|
|
81
|
-
microApps
|
|
20
|
+
microApps: RegistrableApp<ObjectType>[];
|
|
82
21
|
/** 微应用实例 */
|
|
83
|
-
microAppsInstance
|
|
22
|
+
microAppsInstance: Map<string, MicroApp>;
|
|
84
23
|
/** 用户信息 */
|
|
85
|
-
user
|
|
24
|
+
user: UserInfo['user'];
|
|
86
25
|
/** 用户权限 */
|
|
87
|
-
permissions
|
|
88
|
-
/** 用户角色 */
|
|
89
|
-
roles?: UserInfo['roles'];
|
|
26
|
+
permissions: UserInfo['permissions'];
|
|
90
27
|
/** 用户设置 */
|
|
91
|
-
settings
|
|
92
|
-
}
|
|
93
|
-
interface AppResults extends Required<AppOptions> {
|
|
28
|
+
settings: UserInfo['settings'];
|
|
94
29
|
/**
|
|
95
|
-
*
|
|
96
|
-
* - sdk.
|
|
30
|
+
* 获取国际化默认值
|
|
31
|
+
* - 1. 本地缓存 `sdk.storage.getItem(sdk.storage.localeKey)`
|
|
32
|
+
* - 2. sdk中国际化 `sdk.config.locale`
|
|
33
|
+
* - 3. 浏览器语言 `navigator.language`
|
|
34
|
+
* - 4. 默认 `zh-CN`
|
|
97
35
|
*/
|
|
98
|
-
|
|
36
|
+
getDefaultLocale(): LocaleProps;
|
|
99
37
|
/**
|
|
100
|
-
*
|
|
101
|
-
* - sdk.
|
|
38
|
+
* 获取主题默认值
|
|
39
|
+
* - 1. 本地缓存 `sdk.storage.getItem(sdk.storage.themeKey)`
|
|
40
|
+
* - 2. sdk中主题 `sdk.config.theme`
|
|
41
|
+
* - 3. 系统主题 `window.matchMedia('(prefers-color-scheme: dark)').matches`
|
|
42
|
+
* - 4. 默认 `light`
|
|
102
43
|
*/
|
|
103
|
-
|
|
44
|
+
getDefaultTheme(): ThemeProps;
|
|
45
|
+
/**
|
|
46
|
+
* 获取重定向路径
|
|
47
|
+
* - 1. 优先使用指定值 `sdk.config.defaultPath`
|
|
48
|
+
* - 2. 其次使用重定向的值 `sdk.config.redirectField`
|
|
49
|
+
* - 3. 最后使用菜单中第一项 `/`
|
|
50
|
+
*/
|
|
51
|
+
getRedirectPath(): string;
|
|
52
|
+
/**
|
|
53
|
+
* 初始化数据
|
|
54
|
+
*/
|
|
55
|
+
initData(): void | Promise<void>;
|
|
104
56
|
/**
|
|
105
57
|
* 跳转登录页
|
|
58
|
+
* - 1. 清除 Token
|
|
59
|
+
* - 2. 清除用户信息
|
|
60
|
+
* - 3. 获取当前页路由
|
|
61
|
+
* - 4. 清空微应用
|
|
106
62
|
*/
|
|
107
63
|
pageToLogin(): void;
|
|
108
64
|
/**
|
|
109
|
-
*
|
|
65
|
+
* 卸载微应用
|
|
66
|
+
* - 默认卸载所有微应用
|
|
67
|
+
* - 传入名称数组则卸载指定微应用
|
|
110
68
|
*/
|
|
111
|
-
|
|
69
|
+
unmountMicroApp(names?: string[]): void;
|
|
112
70
|
}
|
|
113
71
|
/**
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* - 用户信息 sdk.app.user
|
|
120
|
-
* - 用户权限 sdk.app.permissions
|
|
121
|
-
* - 用户角色 sdk.app.roles
|
|
122
|
-
* - 用户设置 sdk.app.settings
|
|
72
|
+
* 应用插件
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* sdk.use(SDKAppPlugin, { menuData: [...] }).mount('xxx');
|
|
76
|
+
* sdk.app.unmountMicroApp();
|
|
123
77
|
*/
|
|
124
|
-
declare const
|
|
78
|
+
declare const SDKAppPlugin: SDKPlugin;
|
|
125
79
|
//#endregion
|
|
126
|
-
//#region src/plugins/
|
|
127
|
-
interface
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
80
|
+
//#region src/plugins/components/index.d.ts
|
|
81
|
+
interface ComponentsOptions {
|
|
82
|
+
/** 组件 */
|
|
83
|
+
[key: string]: any;
|
|
84
|
+
/**
|
|
85
|
+
* 设置组件
|
|
86
|
+
* @param component 组件
|
|
87
|
+
* @param name 组件名称
|
|
88
|
+
*/
|
|
89
|
+
setComponent(component: ComponentType, name?: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* 获取组件
|
|
92
|
+
* @param name 组件名称
|
|
93
|
+
*/
|
|
94
|
+
getComponent(name: string): ComponentType | null;
|
|
95
|
+
/**
|
|
96
|
+
* 渲染组件
|
|
97
|
+
* @param name 组件名称
|
|
98
|
+
*/
|
|
99
|
+
renderComponent(name: string, props?: any): ReactElement | null;
|
|
135
100
|
}
|
|
136
101
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
102
|
+
* 组件插件
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* sdk.use(SDKComponentsPlugin).mount('xxx');
|
|
106
|
+
* sdk.components.setComponent(组件, '组件名称');
|
|
107
|
+
* sdk.components.renderComponent('组件名称', props);
|
|
142
108
|
*/
|
|
143
|
-
declare const
|
|
109
|
+
declare const SDKComponentsPlugin: SDKPlugin;
|
|
144
110
|
//#endregion
|
|
145
111
|
//#region src/plugins/config/index.d.ts
|
|
146
112
|
interface ConfigOptions {
|
|
147
113
|
/** 环境变量(主应用共享给微应用变量) */
|
|
148
|
-
env
|
|
114
|
+
env: Record<string, any>;
|
|
149
115
|
/** 主题 */
|
|
150
|
-
theme
|
|
116
|
+
theme: ThemeProps;
|
|
151
117
|
/** 语言 */
|
|
152
|
-
locale
|
|
153
|
-
/**
|
|
154
|
-
* Qiankun模式(切换模式后请重新打开页面)
|
|
155
|
-
* - 'router': 基于路由模式
|
|
156
|
-
* - 登录时,刷新页面,会自动调用 getUserInfoApi、getRoutesApi 获取数据
|
|
157
|
-
* - 拿到 routes 数据之后,需要 registerMicroApps 注册微应用 和 start 启动微应用
|
|
158
|
-
* - 系统退出时,刷新页面,自动销毁 qiankun 声明周期和缓存的数据
|
|
159
|
-
* - 系统登录和系统退出仅有一次刷新页面即可,为了销毁 qiankun 的声明周期,但数据需要手动加载或者清除
|
|
160
|
-
* - 'load': 手动加载模式
|
|
161
|
-
* - 登录时,不需刷新页面, 但需要手动调用 getUserInfoApi、getRoutesApi 获取数据
|
|
162
|
-
* - 拿到 routes 数据之后,在 Microapp 组件中使用 loadMicroApp 手动加载微应用
|
|
163
|
-
* - 系统退出时,不刷新页面,但需要手动销毁每个微应用,并清除缓存数据
|
|
164
|
-
*/
|
|
165
|
-
qiankunMode?: 'router' | 'load';
|
|
118
|
+
locale: LocaleProps;
|
|
166
119
|
/** 登录页路由 */
|
|
167
|
-
loginPath
|
|
168
|
-
/**
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
* - 最后使用菜单中第一项
|
|
173
|
-
*/
|
|
174
|
-
defaultPath?: string;
|
|
175
|
-
/**
|
|
176
|
-
* 自定义路由信息
|
|
177
|
-
* - 目前只支持最外层路由自定义
|
|
178
|
-
* - 会合并到 sdk.app.allRoutes 中
|
|
179
|
-
*/
|
|
180
|
-
customRoutes?: RouteObject[];
|
|
181
|
-
/** Antd 配置 */
|
|
182
|
-
antdConfig?: ConfigProviderProps;
|
|
183
|
-
/** ProLayout 配置 */
|
|
184
|
-
proLayoutConfig?: ProLayoutProps;
|
|
120
|
+
loginPath: string;
|
|
121
|
+
/** 登录后跳转的路由 */
|
|
122
|
+
defaultPath: string;
|
|
123
|
+
/** 重定向字段 */
|
|
124
|
+
redirectField?: string;
|
|
185
125
|
}
|
|
186
|
-
interface ConfigResults extends Required<ConfigOptions> {}
|
|
187
126
|
/**
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* - 配置 默认登录路径、跳转路径、自定义路由
|
|
194
|
-
* - 配置 Antd 配置、ProLayout 配置
|
|
127
|
+
* 配置插件
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* sdk.use(SDKConfigPlugin, { theme: 'light' }).mount('xxx');
|
|
131
|
+
* console.log(sdk.api.theme); // 'light'
|
|
195
132
|
*/
|
|
196
|
-
declare const
|
|
133
|
+
declare const SDKConfigPlugin: SDKPlugin;
|
|
197
134
|
//#endregion
|
|
198
135
|
//#region src/plugins/i18n/index.d.ts
|
|
199
|
-
interface I18nOptions {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
* }
|
|
217
|
-
* }
|
|
218
|
-
*/
|
|
219
|
-
intlConfig?: Record<string, any>;
|
|
220
|
-
/**
|
|
221
|
-
* 加载语言包
|
|
222
|
-
* @param locale 语言包名
|
|
223
|
-
* @example
|
|
224
|
-
* import enUS from 'antd/es/locale/en_US';
|
|
225
|
-
* import zhCN from 'antd/es/locale/zh_CN';
|
|
226
|
-
* import dayjs from 'dayjs';
|
|
227
|
-
* import 'dayjs/locale/en';
|
|
228
|
-
* import 'dayjs/locale/zh';
|
|
229
|
-
*
|
|
230
|
-
* const loadLocale = (locale: string) => {
|
|
231
|
-
* switch (locale) {
|
|
232
|
-
* case 'en-US':
|
|
233
|
-
* dayjs.locale('en');
|
|
234
|
-
* return enUS;
|
|
235
|
-
* case 'zh-CN':
|
|
236
|
-
* dayjs.locale('zh');
|
|
237
|
-
* return zhCN;
|
|
238
|
-
* default:
|
|
239
|
-
* return undefined;
|
|
240
|
-
* }
|
|
241
|
-
* }
|
|
242
|
-
*/
|
|
243
|
-
loadLocale?(locale: string): any;
|
|
136
|
+
interface I18nOptions {}
|
|
137
|
+
/**
|
|
138
|
+
* 国际化插件
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* sdk.use(SDKI18nPlugin).mount('xxx');
|
|
142
|
+
*/
|
|
143
|
+
declare const SDKI18nPlugin: SDKPlugin;
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/plugins/router/index.d.ts
|
|
146
|
+
interface RouterOptions {
|
|
147
|
+
/** 主应用 location */
|
|
148
|
+
location: Location;
|
|
149
|
+
/** 路由匹配(用于面包屑) */
|
|
150
|
+
matches: UIMatch[];
|
|
151
|
+
/** 主应用navigate(解决微应用跳转问题) */
|
|
152
|
+
navigate: NavigateFunction;
|
|
244
153
|
}
|
|
245
|
-
interface I18nResults extends Required<I18nOptions> {}
|
|
246
154
|
/**
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
155
|
+
* 路由插件
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* sdk.use(SDKI18nPlugin).mount('xxx');
|
|
159
|
+
* sdk.router.location; // 路由信息
|
|
160
|
+
* sdk.router.navigate; // 路由跳转
|
|
161
|
+
* sdk.router.matches; // 面包屑信息
|
|
251
162
|
*/
|
|
252
|
-
declare const
|
|
163
|
+
declare const SDKRouterPlugin: SDKPlugin;
|
|
253
164
|
//#endregion
|
|
254
165
|
//#region src/plugins/storage/index.d.ts
|
|
255
166
|
interface StorageOptions {
|
|
256
167
|
/** 语言存储名称 */
|
|
257
|
-
localeKey
|
|
168
|
+
localeKey: string;
|
|
258
169
|
/** 主题存储名称 */
|
|
259
|
-
themeKey
|
|
170
|
+
themeKey: string;
|
|
260
171
|
/** Token存储名称 */
|
|
261
|
-
tokenKey
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
|
|
270
|
-
/** 获取当前主题 */
|
|
271
|
-
getTheme(): ThemeProps;
|
|
272
|
-
/** 设置/切换主题 */
|
|
273
|
-
setTheme(theme: ThemeProps): void;
|
|
274
|
-
/** 清空主题 */
|
|
275
|
-
clearTheme(): void;
|
|
276
|
-
/** 获取当前 Token */
|
|
277
|
-
getToken(): string;
|
|
278
|
-
/** 设置 Token */
|
|
279
|
-
setToken(token: string): void;
|
|
280
|
-
/** 清空 Token */
|
|
281
|
-
clearToken(): void;
|
|
172
|
+
tokenKey: string;
|
|
173
|
+
/** 设置缓存 */
|
|
174
|
+
setItem(key: string, value: string): void;
|
|
175
|
+
/** 获取缓存 */
|
|
176
|
+
getItem(key: string): string | null;
|
|
177
|
+
/** 删除缓存 */
|
|
178
|
+
removeItem(key: string): void;
|
|
179
|
+
/** 清空缓存 */
|
|
180
|
+
clear(): void;
|
|
282
181
|
}
|
|
283
182
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
* @example sdk.storage.getToken() // 获取 Token
|
|
289
|
-
* @example sdk.storage.setTheme('dark') // 设置主题
|
|
290
|
-
* @example sdk.storage.clearLocale() // 清空语言
|
|
183
|
+
* 本地缓存插件
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* sdk.use(SDKStoragePlugin).mount('xxx');
|
|
291
187
|
*/
|
|
292
|
-
declare const
|
|
188
|
+
declare const SDKStoragePlugin: SDKPlugin;
|
|
293
189
|
//#endregion
|
|
294
190
|
//#region src/plugins/store/createLocale.d.ts
|
|
295
191
|
interface LocaleStoreProps {
|
|
@@ -330,65 +226,33 @@ interface UserInfoStoreProps {
|
|
|
330
226
|
/** 创建用户信息切片 */
|
|
331
227
|
//#endregion
|
|
332
228
|
//#region src/plugins/store/index.d.ts
|
|
333
|
-
|
|
334
|
-
type
|
|
229
|
+
interface StoreProps extends LocaleStoreProps, MicroAppLoadingStoreProps, ThemeStoreProps, UserInfoStoreProps {}
|
|
230
|
+
type StoreSlice<T = any> = StateCreator<T>;
|
|
231
|
+
/** 插件 options */
|
|
232
|
+
type StorePluginOptions = Record<string, StoreSlice>;
|
|
335
233
|
/**
|
|
336
234
|
* 创建 Store
|
|
337
|
-
* - 这里单独声明变量, 主要是为了使用返回类型
|
|
235
|
+
* - 这里单独声明变量, 主要是为了使用返回类型 StoreOptions 🤔
|
|
338
236
|
*/
|
|
339
|
-
declare const
|
|
237
|
+
declare const createGlobalStore: (options?: StorePluginOptions) => Omit<import("zustand").StoreApi<StoreProps>, "subscribe"> & {
|
|
340
238
|
subscribe: {
|
|
341
|
-
(listener: (selectedState:
|
|
342
|
-
<U>(selector: (state:
|
|
239
|
+
(listener: (selectedState: StoreProps, previousSelectedState: StoreProps) => void): () => void;
|
|
240
|
+
<U>(selector: (state: StoreProps) => U, listener: (selectedState: U, previousSelectedState: U) => void, options?: {
|
|
343
241
|
equalityFn?: (a: U, b: U) => boolean;
|
|
344
242
|
fireImmediately?: boolean;
|
|
345
243
|
}): () => void;
|
|
346
244
|
};
|
|
347
245
|
};
|
|
246
|
+
type StoreOptions = ReturnType<typeof createGlobalStore>;
|
|
348
247
|
/**
|
|
349
|
-
*
|
|
350
|
-
* - 详情参考 {@link StoreOptions} {@link StoreResults}
|
|
351
|
-
* - 此插件不会合并传入属性
|
|
248
|
+
* 状态管理插件
|
|
352
249
|
* @example const setTheme = useStore(sdk.store, (state) => state.setTheme)
|
|
353
250
|
* @example const { theme, setTheme } = useStore(sdk.store, useShallow((state) => { theme: state.theme, setTheme: state.setTheme }))
|
|
354
251
|
* @example const [theme, setTheme] = useStore(sdk.store, useShallow((state) => [state.theme, state.setTheme]))
|
|
355
252
|
* @example sdk.store?.getState()?.setTheme('light')
|
|
356
253
|
* @example sdk.store.subscribe((state) => state.theme, (theme) => { console.log('theme', theme) }, { fireImmediately: true }) // fireImmediately 立即变更
|
|
357
254
|
*/
|
|
358
|
-
declare const
|
|
359
|
-
//#endregion
|
|
360
|
-
//#region src/plugins/ui/index.d.ts
|
|
361
|
-
interface UIOptions {
|
|
362
|
-
/** 组件 */
|
|
363
|
-
[key: string]: ComponentType | ((name: string) => ComponentType) | ((component: ComponentType, name?: string) => void);
|
|
364
|
-
}
|
|
365
|
-
interface UIResults extends Required<UIOptions> {
|
|
366
|
-
/**
|
|
367
|
-
* 设置组件
|
|
368
|
-
* @param component 组件
|
|
369
|
-
* @param name 组件名称
|
|
370
|
-
*/
|
|
371
|
-
setComponent(component: ComponentType, name?: string): void;
|
|
372
|
-
/**
|
|
373
|
-
* 获取组件
|
|
374
|
-
* @param name 组件名称
|
|
375
|
-
*/
|
|
376
|
-
getComponent(name: string): ComponentType;
|
|
377
|
-
/**
|
|
378
|
-
* 渲染组件
|
|
379
|
-
* @param name 组件名称
|
|
380
|
-
*/
|
|
381
|
-
renderComponent(name: string, props?: any): ReactElement;
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* 可复用组件
|
|
385
|
-
* - 详情参考 {@link UIOptions} {@link UIResults}
|
|
386
|
-
* - 内置了 Layout、Loading、Login、Mainapp、Microapp、NotFound 等组件, 可传入覆盖
|
|
387
|
-
* - 组件共享
|
|
388
|
-
* - 在主应用中, 可通过 sdk.use(SdkUIPlugin, { MyComponent }) 传入组件
|
|
389
|
-
* - 在微应用中, 可通过 sdk.ui.renderComponent('MyComponent') 使用组件
|
|
390
|
-
*/
|
|
391
|
-
declare const SdkUIPlugin: Plugin<'ui'>;
|
|
255
|
+
declare const SDKStorePlugin: SDKPlugin;
|
|
392
256
|
//#endregion
|
|
393
257
|
//#region src/types.d.ts
|
|
394
258
|
type ThemeProps = 'light' | 'dark' | (string & {});
|
|
@@ -398,137 +262,72 @@ interface UserInfo {
|
|
|
398
262
|
user?: any;
|
|
399
263
|
/** 用户权限 */
|
|
400
264
|
permissions?: string[];
|
|
401
|
-
/** 用户角色 */
|
|
402
|
-
roles?: string[];
|
|
403
265
|
/** 用户设置 */
|
|
404
266
|
settings?: {
|
|
405
267
|
theme?: ThemeProps;
|
|
406
268
|
locale?: LocaleProps;
|
|
407
269
|
};
|
|
408
270
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
app?: AppOptions;
|
|
414
|
-
/** 全局路由信息 */
|
|
415
|
-
client?: ClientOptions;
|
|
416
|
-
/** Sdk 配置信息 */
|
|
417
|
-
config?: ConfigOptions;
|
|
418
|
-
/** 多语言 */
|
|
419
|
-
i18n?: I18nOptions;
|
|
420
|
-
/** 本地缓存 */
|
|
421
|
-
storage?: StorageOptions;
|
|
422
|
-
/** 全局状态管理 */
|
|
423
|
-
store?: StoreOptions;
|
|
424
|
-
/** 可复用组件 */
|
|
425
|
-
ui?: UIOptions;
|
|
271
|
+
declare global {
|
|
272
|
+
interface Window {
|
|
273
|
+
[key: string]: any;
|
|
274
|
+
}
|
|
426
275
|
}
|
|
427
|
-
interface
|
|
428
|
-
/**
|
|
429
|
-
api:
|
|
430
|
-
/**
|
|
431
|
-
app:
|
|
432
|
-
/**
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
config:
|
|
436
|
-
/**
|
|
437
|
-
i18n:
|
|
276
|
+
interface SDKPlugins {
|
|
277
|
+
/** 请求 */
|
|
278
|
+
api: ApiOptions;
|
|
279
|
+
/** 应用 */
|
|
280
|
+
app: AppOptions;
|
|
281
|
+
/** 组件 */
|
|
282
|
+
components: ComponentsOptions;
|
|
283
|
+
/** 配置 */
|
|
284
|
+
config: ConfigOptions;
|
|
285
|
+
/** 国际化 */
|
|
286
|
+
i18n: I18nOptions;
|
|
287
|
+
/** 路由 */
|
|
288
|
+
router: RouterOptions;
|
|
438
289
|
/** 本地缓存 */
|
|
439
|
-
storage:
|
|
440
|
-
/**
|
|
441
|
-
store:
|
|
442
|
-
/** 可复用组件 */
|
|
443
|
-
ui: UIResults;
|
|
290
|
+
storage: StorageOptions;
|
|
291
|
+
/** 状态管理 */
|
|
292
|
+
store: StoreOptions;
|
|
444
293
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
name: K;
|
|
294
|
+
interface SDKPlugin {
|
|
295
|
+
/** 插件名称 */
|
|
296
|
+
name: string;
|
|
449
297
|
/** 插件安装方法 */
|
|
450
|
-
install(sdk:
|
|
298
|
+
install(sdk: SDKInstance, options?: Record<string, any>): void;
|
|
451
299
|
/** 插件配置项 */
|
|
452
|
-
options?:
|
|
453
|
-
}
|
|
454
|
-
interface SdkBase {
|
|
455
|
-
/** SDK 名称 */
|
|
456
|
-
name: string;
|
|
457
|
-
/** 插件列表 */
|
|
458
|
-
_plugins: Map<string, any>;
|
|
459
|
-
/** 挂载sdk - 主应用挂载 SDK 到 Window */
|
|
460
|
-
mount(name: string): void;
|
|
461
|
-
/** 继承sdk - 微应用从 Window 上继承 SDK */
|
|
462
|
-
extend(name: string): void;
|
|
463
|
-
/** 使用插件 */
|
|
464
|
-
use<K extends PluginName>(plugin: Plugin<K>, options?: PluginOptions[K]): this;
|
|
300
|
+
options?: Record<string, any>;
|
|
465
301
|
}
|
|
466
|
-
type
|
|
302
|
+
type SDKPluginOptions = Record<string, any | ((...args: any[]) => any)>;
|
|
303
|
+
type SDKInstance = SDKCore & SDKPlugins;
|
|
467
304
|
//#endregion
|
|
468
305
|
//#region src/core/index.d.ts
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
ui: SdkResult['ui'];
|
|
480
|
-
constructor();
|
|
306
|
+
/** SDK 类 */
|
|
307
|
+
declare class SDKCore {
|
|
308
|
+
/** 名称 */
|
|
309
|
+
name?: string;
|
|
310
|
+
/** 插件列表 */
|
|
311
|
+
_plugins: Map<string, any>;
|
|
312
|
+
/**
|
|
313
|
+
* 将实例挂载到 Window 对象上
|
|
314
|
+
* @param name - 要挂载的属性名
|
|
315
|
+
*/
|
|
481
316
|
mount(name: string): void;
|
|
317
|
+
/**
|
|
318
|
+
* 继承实例, 从 Window 对象上获取指定名称的实例并合并属性
|
|
319
|
+
* @param name - 要从 Window 对象上获取的实例名称
|
|
320
|
+
* @throws 当指定的 SDK 实例不存在时抛出错误
|
|
321
|
+
*/
|
|
482
322
|
extend(name: string): void;
|
|
483
|
-
|
|
323
|
+
/**
|
|
324
|
+
* 使用插件
|
|
325
|
+
* @param plugin - 插件对象 {@link SDKPlugin}
|
|
326
|
+
* @param options - 插件选项
|
|
327
|
+
*/
|
|
328
|
+
use(plugin: SDKPlugin, options?: SDKPlugin['options']): this;
|
|
484
329
|
}
|
|
485
|
-
/**
|
|
486
|
-
|
|
487
|
-
*/
|
|
488
|
-
declare const sdk: Sdk;
|
|
489
|
-
//#endregion
|
|
490
|
-
//#region src/hooks/useUserInfo.d.ts
|
|
491
|
-
/** 用户信息 */
|
|
492
|
-
declare const useUserInfo: () => {
|
|
493
|
-
userInfo: UserInfo;
|
|
494
|
-
setUserInfo: (userInfo: UserInfo) => void;
|
|
495
|
-
resetUserInfo: () => void;
|
|
496
|
-
};
|
|
497
|
-
//#endregion
|
|
498
|
-
//#region src/hooks/useIntl.d.ts
|
|
499
|
-
/**
|
|
500
|
-
* React Intl Universal
|
|
501
|
-
* - 如果项目不使用 React Compiler, 可以直接使用 sdk.i18n.intl
|
|
502
|
-
* - 不要解构使用, const { get } = useIntl() 会报错
|
|
503
|
-
* @example const intl = useIntl(); intl.get(key).d(defaultValue)
|
|
504
|
-
*/
|
|
505
|
-
declare const useIntl: () => {
|
|
506
|
-
determineLocale: typeof react_intl_universal0.determineLocale;
|
|
507
|
-
formatHTMLMessage: typeof react_intl_universal0.formatHTMLMessage;
|
|
508
|
-
formatMessage: typeof react_intl_universal0.formatMessage;
|
|
509
|
-
get: typeof react_intl_universal0.get;
|
|
510
|
-
getHTML: typeof react_intl_universal0.getHTML;
|
|
511
|
-
getInitOptions: typeof react_intl_universal0.getInitOptions;
|
|
512
|
-
init: typeof react_intl_universal0.init;
|
|
513
|
-
load: typeof react_intl_universal0.load;
|
|
514
|
-
formatList: typeof react_intl_universal0.formatList;
|
|
515
|
-
formatParentheses: typeof react_intl_universal0.formatParentheses;
|
|
516
|
-
getColon: typeof react_intl_universal0.getColon;
|
|
517
|
-
formatNumber: typeof react_intl_universal0.formatNumber;
|
|
518
|
-
};
|
|
519
|
-
//#endregion
|
|
520
|
-
//#region src/hooks/useCrumb.d.ts
|
|
521
|
-
/**
|
|
522
|
-
* 获取面包屑
|
|
523
|
-
* @see https://reactrouter.com/6.30.3/hooks/use-matches
|
|
524
|
-
*/
|
|
525
|
-
declare const useCrumb: () => any[];
|
|
526
|
-
//#endregion
|
|
527
|
-
//#region src/hooks/usePermission.d.ts
|
|
528
|
-
/**
|
|
529
|
-
* 判断是否有权限
|
|
530
|
-
* @param code 权限code (默认为当前路由)
|
|
531
|
-
*/
|
|
532
|
-
declare const usePermission: (code?: string) => boolean;
|
|
330
|
+
/** 创建 SDK 实例 */
|
|
331
|
+
declare const sdk: SDKInstance;
|
|
533
332
|
//#endregion
|
|
534
|
-
export { type ApiOptions, type
|
|
333
|
+
export { type ApiOptions, type AppOptions, type ComponentsOptions, type ConfigOptions, type I18nOptions, LocaleProps, type RouterOptions, SDKApiPlugin, SDKAppPlugin, SDKComponentsPlugin, SDKConfigPlugin, SDKCore, SDKI18nPlugin, SDKInstance, SDKPlugin, SDKPluginOptions, SDKPlugins, SDKRouterPlugin, SDKStoragePlugin, SDKStorePlugin, type StorageOptions, type StoreOptions, type StoreProps, type StoreSlice, ThemeProps, UserInfo, sdk };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createStore as e,useStore as t}from"zustand";import{useShallow as n}from"zustand/shallow";import{Suspense as r,createElement as i,memo as a,useEffect as o,useMemo as s,useState as c}from"react";import{Navigate as ee,Outlet as l,RouterProvider as te,createBrowserRouter as ne,useLocation as u,useMatches as d,useNavigate as f}from"react-router-dom";import{Fragment as p,jsx as m,jsxs as h}from"react/jsx-runtime";import g from"axios";import{Button as _,ConfigProvider as re,Flex as v,Form as y,Input as b,message as x,theme as S}from"antd";import C from"react-intl-universal";import{subscribeWithSelector as w}from"zustand/middleware";import T from"@ant-design/pro-layout";import{loadMicroApp as E,registerMicroApps as ie,start as ae}from"qiankun";const D=new class{name;_plugins;api;app;client;config;i18n;storage;store;ui;constructor(){this.name=``,this._plugins=new Map}mount(e){if(window[e])throw Error(`The SDK already exists - ${e}`);console.log(`%c SDK mounted:`,`color: pink; font-weight: bold;`,e,D),this.name=e;let t=new Proxy(this,{get:(e,t,n)=>e?Reflect.get(e,t,n):null,set:()=>(console.error(`The SDK cannot be modified.`),!1),deleteProperty:()=>(console.error(`The SDK cannot be deleted.`),!1)});window[this.name]=t}extend(e){if(!window[e])throw Error(`The SDK not found - ${e}`);console.log(`%c SDK extended:`,`color: pink; font-weight: bold;`,e),Object.assign(this,window[e])}use(e,t){let{name:n,install:r}=e;if(!n)throw Error(`${n} plugin has no name`);if(typeof r!=`function`)throw Error(`${n} plugin is not a function`);return r(this,t),this._plugins.set(n,{...e,options:t}),this}},O=()=>{let[e,r,i]=t(D.store,n(e=>[e.userInfo,e.setUserInfo,e.resetUserInfo]));return{userInfo:e,setUserInfo:r,resetUserInfo:i}};function k(e){return e==null||typeof e!=`object`&&typeof e!=`function`}function A(e){return ArrayBuffer.isView(e)&&!(e instanceof DataView)}function oe(e){return Object.getOwnPropertySymbols(e).filter(t=>Object.prototype.propertyIsEnumerable.call(e,t))}function se(e){return e==null?e===void 0?`[object Undefined]`:`[object Null]`:Object.prototype.toString.call(e)}function j(e,t,n,r=new Map,i=void 0){let a=i?.(e,t,n,r);if(a!==void 0)return a;if(k(e))return e;if(r.has(e))return r.get(e);if(Array.isArray(e)){let t=Array(e.length);r.set(e,t);for(let a=0;a<e.length;a++)t[a]=j(e[a],a,n,r,i);return Object.hasOwn(e,`index`)&&(t.index=e.index),Object.hasOwn(e,`input`)&&(t.input=e.input),t}if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp){let t=new RegExp(e.source,e.flags);return t.lastIndex=e.lastIndex,t}if(e instanceof Map){let t=new Map;r.set(e,t);for(let[a,o]of e)t.set(a,j(o,a,n,r,i));return t}if(e instanceof Set){let t=new Set;r.set(e,t);for(let a of e)t.add(j(a,void 0,n,r,i));return t}if(typeof Buffer<`u`&&Buffer.isBuffer(e))return e.subarray();if(A(e)){let t=new(Object.getPrototypeOf(e)).constructor(e.length);r.set(e,t);for(let a=0;a<e.length;a++)t[a]=j(e[a],a,n,r,i);return t}if(e instanceof ArrayBuffer||typeof SharedArrayBuffer<`u`&&e instanceof SharedArrayBuffer)return e.slice(0);if(e instanceof DataView){let t=new DataView(e.buffer.slice(0),e.byteOffset,e.byteLength);return r.set(e,t),M(t,e,n,r,i),t}if(typeof File<`u`&&e instanceof File){let t=new File([e],e.name,{type:e.type});return r.set(e,t),M(t,e,n,r,i),t}if(typeof Blob<`u`&&e instanceof Blob){let t=new Blob([e],{type:e.type});return r.set(e,t),M(t,e,n,r,i),t}if(e instanceof Error){let t=structuredClone(e);return r.set(e,t),t.message=e.message,t.name=e.name,t.stack=e.stack,t.cause=e.cause,t.constructor=e.constructor,M(t,e,n,r,i),t}if(e instanceof Boolean){let t=new Boolean(e.valueOf());return r.set(e,t),M(t,e,n,r,i),t}if(e instanceof Number){let t=new Number(e.valueOf());return r.set(e,t),M(t,e,n,r,i),t}if(e instanceof String){let t=new String(e.valueOf());return r.set(e,t),M(t,e,n,r,i),t}if(typeof e==`object`&&ce(e)){let t=Object.create(Object.getPrototypeOf(e));return r.set(e,t),M(t,e,n,r,i),t}return e}function M(e,t,n=e,r,i){let a=[...Object.keys(t),...oe(t)];for(let o=0;o<a.length;o++){let s=a[o],c=Object.getOwnPropertyDescriptor(e,s);(c==null||c.writable)&&(e[s]=j(t[s],s,n,r,i))}}function ce(e){switch(se(e)){case`[object Arguments]`:case`[object Array]`:case`[object ArrayBuffer]`:case`[object DataView]`:case`[object Boolean]`:case`[object Date]`:case`[object Float32Array]`:case`[object Float64Array]`:case`[object Int8Array]`:case`[object Int16Array]`:case`[object Int32Array]`:case`[object Map]`:case`[object Number]`:case`[object Object]`:case`[object RegExp]`:case`[object Set]`:case`[object String]`:case`[object Symbol]`:case`[object Uint8Array]`:case`[object Uint8ClampedArray]`:case`[object Uint16Array]`:case`[object Uint32Array]`:return!0;default:return!1}}function N(e){return j(e,void 0,e,new Map,void 0)}function P(e){if(!e||typeof e!=`object`)return!1;let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype||Object.getPrototypeOf(t)===null?Object.prototype.toString.call(e)===`[object Object]`:!1}function le(e){return e===`__proto__`}function F(e,t){let n=Object.keys(t);for(let r=0;r<n.length;r++){let i=n[r];if(le(i))continue;let a=t[i],o=e[i];I(a)&&I(o)?e[i]=F(o,a):Array.isArray(a)?e[i]=F([],a):P(a)?e[i]=F({},a):(o===void 0||a!==void 0)&&(e[i]=a)}return e}function I(e){return P(e)||Array.isArray(e)}const ue=()=>s(()=>N(D.i18n.intl),[t(D.store,e=>e.locale)]),L=()=>s(()=>D.client.matches,[u()]).filter(e=>!!e.handle?.crumb).map(e=>e.handle.crumb(e.data)),R=e=>{let{requestId:t,url:n,method:r,params:i,data:a}=e;return t||`${r}:${n}?${JSON.stringify(i)}&${JSON.stringify(a)}`},z=e=>{let t=R(e),n=D.api.controllers.get(t);n&&(n.abort(),D.api.controllers.delete(t))},B={beforeLoad:[async e=>{console.log(`[LifeCycle] before load %c%s`,`color: green;`,e.name)}],beforeMount:[async e=>{console.log(`[LifeCycle] before mount %c%s`,`color: green;`,e.name)}],afterUnmount:[async e=>{console.log(`[LifeCycle] after unmount %c%s`,`color: green;`,e.name)}]},V=e=>{let t=e.storage.getTheme();if(t)return t;let n=e.config?.theme;if(n)return n;let r=window.matchMedia(`(prefers-color-scheme: dark)`);return r.matches&&r.matches?`dark`:`light`},H=e=>e.storage.getLocale()||e.config?.locale||navigator.language||`zh-CN`,U=e=>D.app.permissions?.includes?.(e),de=e=>{let t=new Map,n=W(e,t);return{microApps:[...t.values()],menuData:n}},W=(e,t)=>!e||e?.length===0?[]:e.map(e=>{let n=null,{locale:r,path:i,icon:a,component:o,routeAttr:s,children:c}=e;if(s){let e={};try{e=JSON.parse(s)}catch(e){console.error(`Sdk: initData - Subapp routeAttr error: `,e)}let{name:r,rootId:i,...a}=e,o={...a,name:r,container:`#${i}`,props:{sdk:D},loader:e=>D.store.getState().setMicroAppLoading(e)};t.set(r,o),n=D.ui.renderComponent(`Microapp`,{name:r,rootId:i})}else if(o===`Microapp`)n=D.ui.renderComponent(`Microapp`);else if(o===`Outlet`)n=m(l,{});else{let e=U(i);n=D.ui.renderComponent(e?o:`NoPermission`)}return{...e,key:`${i}_${a}_${r}`,element:n,children:W(c,t),handle:{crumb:(t={})=>({...e,...t})}}}),G=e=>{let t=`/`;return!e||e.length===0?t:(t=e?.[0]?.path,e?.[0]?.children&&e?.[0]?.children.length>0&&(t=G(e?.[0]?.children)),t)},fe=e=>s(()=>U(e||D.client.location.pathname),[u().pathname,e]);var pe=class{instance;constructor(e={}){this.instance=g.create(e),this.defaultRequestInterceptor(),this.defaultResponseInterceptor()}defaultRequestInterceptor(){this.instance.interceptors.request.use(function(e){if(e?.isCancelRequest){let t=R(e);z(e);let n=new AbortController;D.api.controllers.set(t,n),e.requestId=t,e.signal=n.signal}let t=D.storage.getToken();return e.headers.lang=D.config.locale,e.headers.Authorization=t,F(e.headers,D.api.config.headers||{}),e},function(e){return console.error(`Sdk: defaultRequestInterceptor - 请求错误`),Promise.reject(e)})}defaultResponseInterceptor(){this.instance.interceptors.response.use(function(e){let{data:t,config:n}=e,{isOriginalData:r,isShowFailMsg:i,isCancelRequest:a}=n,{code:o,msg:s}=t;return o!==0&&(i&&x.error(s),console.error(`Sdk: defaultResponseInterceptor - Response error: `,n.url,s),o==20041&&D.app.pageToLogin()),a&&D.api.controllers.delete(n.requestId),r?e:e.data},function(e){let{response:t,config:n}=e,{isShowFailMsg:r}=n;if(g.isCancel(e))return Promise.reject(e);if(t){let{status:e,data:n,statusText:i}=t;r&&x.error(n.msg||i),e==401&&D.app.pageToLogin()}else r&&x.error(`请求超时或服务器异常,请检查网络或联系管理员`),console.error(`Sdk: defaultResponseInterceptor - Request error:`,n.url,e);return Promise.reject(e)})}getInstance(){return this.instance}};const me={name:`api`,install(e,t={}){let n={baseURL:`/`,timeout:0,...t.config},r=t?.instance||new pe(n).getInstance();e.api=F({config:n,controllers:new Map,instance:null,request:(e,t={})=>r.request({url:e,isOriginalData:!1,isShowFailMsg:!0,isCancelRequest:!0,...t}),getUserInfoApi:()=>e.api.request(`/getUserInfo`,{method:`GET`}),getRoutesApi:()=>e.api.request(`/routes`,{method:`GET`}),loginApi:()=>e.api.request(`/login`,{method:`POST`})},t)}},he={name:`app`,install(e,t={}){e.app=F({menuData:[],allRoutes:[],microApps:[],microAppsInstance:new Map,user:null,permissions:[],roles:[],settings:{},initData:null,clearData:()=>{e.app.menuData=[],e.app.allRoutes=e.app.allRoutes.filter(e=>e.path!==`/`),e.app.microApps=[],e.app.microAppsInstance.forEach(e=>e.unmount()),e.app.microAppsInstance.clear(),e.store.getState().resetUserInfo()},pageToLogin:()=>{e.storage.clearToken();let t=window.location.pathname||`/`,n=e.config.loginPath,r=t===n?n:`${n}?redirect=${encodeURIComponent(t)}`;e.config.qiankunMode===`router`?window.location.replace(r):(e.app.clearData(),e.client.navigate(r,{replace:!0}))},getRedirectPath:()=>{let t=e.config.defaultPath;if(t)return t;let n=new URLSearchParams(window.location.search);return decodeURIComponent(n.get(`redirect`)||``)||`/`}},t)}},K=`client`,ge={name:K,install(e,t={}){e[K]=F({location:null,navigate:null,matches:null},t)}},q=`config`,_e={name:q,install(e,t={}){e[q]=F({env:{},qiankunMode:`router`,theme:null,locale:null,loginPath:`/login`,defaultPath:``,customRoutes:[],antdConfig:{},proLayoutConfig:{title:`Demo`}},t)}},J=`i18n`,ve={name:J,install(e,t={}){e[J]=F({intl:C,intlConfig:{},loadLocale:e=>void 0},t)}},Y=`storage`,ye={name:Y,install(e,t={}){e[Y]=F({localeKey:`locale`,themeKey:`theme`,tokenKey:`token`,getLocale:()=>localStorage.getItem(e.storage.localeKey),setLocale:t=>{localStorage.setItem(e.storage.localeKey,t)},clearLocale:()=>{localStorage.removeItem(e.storage.localeKey)},getTheme:()=>localStorage.getItem(e.storage.themeKey),setTheme:t=>{localStorage.setItem(e.storage.themeKey,t)},clearTheme:()=>{localStorage.removeItem(e.storage.themeKey)},getToken:()=>localStorage.getItem(e.storage.tokenKey),setToken:t=>{localStorage.setItem(e.storage.tokenKey,t)},clearToken:()=>{localStorage.removeItem(e.storage.tokenKey)}},t)}},be=(e,t)=>({locale:null,setLocale:t=>{e(()=>({locale:t})),D.config.locale=t,D.storage.setLocale(t),document.documentElement.setAttribute(`lang`,t);let n=D.i18n.intlConfig;C.init({currentLocale:t,locales:n});try{let e=D.i18n.loadLocale?.(t)||void 0;F(D.config.antdConfig,{locale:e})}catch(e){console.error(`Sdk: createLocaleSlice - sdk.i18n.loadLocale error:`,e)}}}),xe=(e,t)=>({microAppLoading:!1,setMicroAppLoading:t=>e(()=>({microAppLoading:t}))}),{defaultAlgorithm:Se,darkAlgorithm:Ce}=S,we=(e,t)=>({theme:null,setTheme:t=>{e(()=>({theme:t})),D.config.theme=t,D.storage.setTheme(t),document.documentElement.setAttribute(`theme`,t);let n=t===`light`?Se:Ce;F(D.config.antdConfig,{theme:{algorithm:n}})}}),X={user:{},permissions:[],roles:[],settings:{}},Te=(e,t)=>({userInfo:X,setUserInfo:t=>{e(()=>({userInfo:t})),D.app={...D.app,...t}},resetUserInfo:()=>{e(()=>({userInfo:X}))}}),Ee=e()(w((...e)=>({...be(...e),...xe(...e),...we(...e),...Te(...e)}))),Z=`store`,De={name:Z,install(e,t={}){e[Z]=Ee}},Oe=()=>{let e=f(),n=u(),i=d(),a=t(D.store,e=>e.locale),o=i[i.length-1]?.handle?.crumb()||{},s=JSON.parse(o?.routeAttr||`{}`)?.noLayout,c=t=>{e(t.path)};return m(T,{locale:a,formatMessage:({id:e,defaultMessage:t})=>D.i18n.intl.get(e).d(t),location:n,menuItemRender:(e,t)=>m(`div`,{onClick:()=>c(e),children:t}),onMenuHeaderClick:()=>{e(`/`)},onPageChange:e=>{if(!D.app.user||Object.keys(D.app.user).length===0)return D.app.pageToLogin()},...s&&{headerRender:!1,footerRender:!1,menuRender:!1},menu:{request:async()=>D.app.menuData||[],...D.config.proLayoutConfig.menu},...D.config.proLayoutConfig,children:m(r,{fallback:D.ui.renderComponent(`Loading`,{isSuspense:!0}),children:m(l,{})})})},{useToken:Q}=S,ke=({isInitData:e=!1,isSuspense:t=!1,isMicroApp:n=!1})=>{let{token:r}=Q();return m(`div`,{style:e?{width:`100%`,height:`100%`,display:`flex`,alignItems:`center`,justifyContent:`center`,background:r.colorBgContainer,color:r.colorText}:{},children:`Loading...`})},{useToken:Ae}=S,je=()=>{let{token:e}=Ae(),[t,n]=c(!1);return m(v,{style:{width:`100%`,height:`100%`,background:e.colorBgContainer},justify:`center`,align:`center`,children:h(y,{labelCol:{span:8},labelAlign:`left`,wrapperCol:{span:16},style:{maxWidth:600},initialValues:{username:`admin`,password:`admin`},onFinish:async e=>{try{n(()=>!0);let t=await D.api.loginApi(e);n(()=>!1);let r=t?.data?.token||``;if(!r)return;D.storage.setToken(r);let i=D.app.getRedirectPath();D.config.qiankunMode===`load`?(D.client.navigate(i,{replace:!0}),D.app.initData?.()):window.location.replace(i)}catch(e){console.log(`Sdk: Login - handleFinish: `,e),n(()=>!1)}},autoComplete:`off`,children:[m(y.Item,{label:`用户名`,name:`username`,rules:[{required:!0,message:`请输入用户名!`}],children:m(b,{})}),m(y.Item,{label:`密码`,name:`password`,rules:[{required:!0,message:`请输入密码!`}],children:m(b.Password,{})}),m(y.Item,{noStyle:!0,children:m(_,{block:!0,type:`primary`,htmlType:`submit`,loading:t,children:`登录`})})]})})},$=({children:e})=>{let t=u(),n=d(),r=f();return D.client.location=t,D.client.matches=n,D.client.navigate=r,e},Me=()=>{let e=D.config.loginPath,i=D.config.customRoutes,a=D.config.qiankunMode===`router`,l=e=>D.ui.renderComponent(`Loading`,e),u=D.ui.renderComponent(`Layout`),d=D.ui.renderComponent(`Login`),f=D.ui.renderComponent(`NotFound`),p=[{path:e,element:d},{path:`*`,element:f},...i].map(e=>({...e,element:m($,{children:e.element})})),[h,g]=c(!1),[_,v]=c(p),[y,b,x,S,C]=t(D.store,n(e=>[e.locale,e.setLocale,e.theme,e.setTheme,e.setUserInfo])),w=s(()=>N(D.config.antdConfig),[y,x]),T=(e,t)=>{S(e||V(D)),b(t||H(D))},E=async()=>{try{g(()=>!0);let[{data:e={}},{data:t=[]}]=await Promise.all([D.api.getUserInfoApi(),D.api.getRoutesApi()]);g(()=>!1),C(e);let{theme:n,locale:r}=e?.settings||{};T(n,r);let{microApps:i=[],menuData:o=[]}=de(t);a&&(ie(i,B),ae());let s=G(o),c=[...p,{path:`/`,element:m(ee,{to:s,replace:!0})},{path:`/`,element:m($,{children:u}),children:o,errorElement:f}];v(c),D.app={...D.app,allRoutes:c,microApps:i,menuData:o}}catch(e){console.error(e),g(()=>!1)}};return o(()=>{D.app.initData=E,D.app.allRoutes=p;let t=D.config.customRoutes?.map(e=>e.path),n=window.location.pathname;[e,...t]?.includes(n)?T():E()},[]),m(re,{...w,children:m(r,{fallback:l({isSuspense:!0}),children:h?l({isInitData:!0}):m(te,{router:ne(_,{basename:`/`}),future:{v7_startTransition:!1}})})})};var Ne=a(({name:e,rootId:r})=>{let[i,a]=t(D.store,n(e=>[e.microAppLoading,e.setMicroAppLoading]));return o(()=>{if(!e||D.config.qiankunMode!==`load`)return;let t=D.app.microAppsInstance.get(e);if(t)t?.mount();else{let n=D.app.microApps.find(t=>t.name===e);if(!n)return;a(!0),t=E(n,{},B),t?.mountPromise?.finally(()=>{a(!1)}),D.app.microAppsInstance.set(e,t)}return()=>{t?.unmount()}},[e]),h(p,{children:[i&&D.ui.renderComponent(`Loading`,{isMicroApp:!0}),m(`main`,{id:r})]})});const Pe=()=>m(`div`,{children:`无权限`}),{useToken:Fe}=S,Ie=()=>{let{token:e}=Fe();return m(`div`,{style:{width:`100%`,height:`100%`,display:`flex`,alignItems:`center`,justifyContent:`center`,background:e.colorBgContainer},children:`找不到页面`})},Le={name:`ui`,install(e,t={}){e.ui=F({Layout:Oe,Loading:ke,Login:je,Mainapp:Me,Microapp:Ne,NotFound:Ie,NoPermission:Pe,setComponent:(t,n)=>{if(!t){console.error(`Sdk: SdkUIPlugin - component cannot be empty`);return}let r=n||t.displayName||t.name;if(!r){console.error(`Sdk: SdkUIPlugin - Component name cannot be empty`);return}e.ui[r]=t},getComponent:t=>t?e.ui[t]:(console.error(`Sdk: SdkUIPlugin - Component name cannot be empty`),null),renderComponent:(t,n={})=>{let r=e.ui.getComponent(t);return r?i(r,n):(console.error(`Sdk: SdkUIPlugin - Component ${t} not found`),null)}},t)}};export{me as SdkApiPlugin,he as SdkAppPlugin,ge as SdkClientPlugin,_e as SdkConfigPlugin,ve as SdkI18nPlugin,ye as SdkStoragePlugin,De as SdkStorePlugin,Le as SdkUIPlugin,D as sdk,L as useCrumb,ue as useIntl,fe as usePermission,O as useUserInfo};
|
|
1
|
+
import{Suspense as e,createElement as t,memo as n,useEffect as r,useState as i}from"react";import{Outlet as a,useLocation as o,useNavigate as s}from"react-router-dom";import{Fragment as c,jsx as l,jsxs as u}from"react/jsx-runtime";import{loadMicroApp as d}from"qiankun";import{createStore as f,useStore as p}from"zustand";import{useShallow as m}from"zustand/shallow";import{subscribeWithSelector as h}from"zustand/middleware";var g=class{name;_plugins=new Map;mount(e){this.name=e,window[e]=this}extend(e){let t=window[e];if(!t)throw Error(`SDK "${e}" not found`);Object.assign(this,t)}use(e,t={}){let{name:n,install:r}=e;if(!n)throw Error(`SDK - The plugin requires a name`);if(typeof r!=`function`)throw Error(`SDK - The plugin "${n}" requires an install function`);return r(this,t),this._plugins.set(n,{...e,options:t}),this}};const _=new g,v={name:`api`,install(e,t={}){e.api=t}};function y(e){if(!e||typeof e!=`object`)return!1;let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype||Object.getPrototypeOf(t)===null?Object.prototype.toString.call(e)===`[object Object]`:!1}function b(e){return e===`__proto__`}function x(e,t){let n=Object.keys(t);for(let r=0;r<n.length;r++){let i=n[r];if(b(i))continue;let a=t[i],o=e[i];S(a)&&S(o)?e[i]=x(o,a):Array.isArray(a)?e[i]=x([],a):y(a)?e[i]=x({},a):(o===void 0||a!==void 0)&&(e[i]=a)}return e}function S(e){return y(e)||Array.isArray(e)}const C={name:`app`,install(e,t={}){e.app=x({menuData:[],allRoutes:[],microApps:[],microAppsInstance:new Map,user:null,permissions:[],settings:{},getDefaultLocale(){return e.storage.getItem(e.storage.localeKey)||e.config?.locale||navigator.language||`zh-CN`},getDefaultTheme(){let t=e.storage.getItem(e.storage.themeKey);if(t)return t;let n=e.config?.theme;if(n)return n;let r=window.matchMedia(`(prefers-color-scheme: dark)`);return r.matches&&r.matches?`dark`:`light`},getRedirectPath(){let t=e.config.defaultPath;if(t)return t;let n=new URLSearchParams(window.location.search),r=e.config.redirectField||`redirect`;return decodeURIComponent(n.get(r)||``)||`/`},initData:()=>{},pageToLogin(){e.storage.removeItem(e.storage.tokenKey),e.app.user=null,e.app.permissions=[],e.app.settings={};let t=location.pathname,n=e.config.loginPath,r=e.config.redirectField||`redirect`,i=t===n?n:`${n}?${r}=${encodeURIComponent(t||`/`)}`;e.router.navigate(i,{replace:!0}),e.app.unmountMicroApp()},unmountMicroApp(t){t?t.forEach(t=>{let n=e.app.microAppsInstance.get(t);n&&(n.unmount(),e.app.microAppsInstance.delete(t),e.app.microApps=e.app.microApps.filter(e=>e.name!==t))}):(e.app.microAppsInstance.forEach(e=>e.unmount()),e.app.microAppsInstance.clear(),e.app.microApps=[])}},t)}},w={layout:{height:`100vh`,display:`flex`,flexDirection:`column`,background:`#f5f7fb`},header:{height:64,padding:`0 24px`,background:`#fff`,borderBottom:`1px solid #e5e7eb`,display:`flex`,alignItems:`center`,justifyContent:`space-between`,boxShadow:`0 2px 8px rgba(0,0,0,0.04)`,zIndex:10},logo:{fontSize:20,fontWeight:700,color:`#1677ff`,cursor:`pointer`,userSelect:`none`},logoutBtn:{height:36,padding:`0 16px`,border:`none`,borderRadius:8,background:`#ff4d4f`,color:`#fff`,cursor:`pointer`,transition:`0.2s`},main:{flex:1,display:`flex`,overflow:`hidden`},sidebar:{width:240,padding:16,background:`#fff`,borderRight:`1px solid #e5e7eb`,overflowY:`auto`},content:{flex:1,padding:20,overflowY:`auto`},contentCard:{minHeight:`100%`,padding:24,background:`#fff`,borderRadius:16,boxShadow:`0 2px 12px rgba(0,0,0,0.04)`},menuItem:{marginBottom:4},menuTitle:{height:42,padding:`0 14px`,display:`flex`,alignItems:`center`,borderRadius:10,color:`#1f2937`,cursor:`pointer`,transition:`0.2s`},menuChildren:{marginLeft:12,paddingLeft:12,borderLeft:`1px solid #e5e7eb`}},T=({items:e=[]})=>{let t=o(),n=s();return e?.length?e.map(e=>{let{key:r,name:i,path:a,children:o,hideInMenu:s=!1}=e;if(s)return null;let c=o&&o.filter(e=>!e.hideInMenu).length>0,d=t.pathname===a,f=e=>{d||(e.currentTarget.style.background=`#f3f4f6`)},p=e=>{d||(e.currentTarget.style.background=`transparent`)},m=()=>{c||n(a)};return u(`div`,{style:w.menuItem,children:[l(`div`,{style:{...w.menuTitle,...d?{background:`#e8f3ff`,color:`#1677ff`}:{},...c?{cursor:`not-allowed`}:{}},onMouseEnter:f,onMouseLeave:p,onClick:m,children:i}),c&&l(`div`,{style:w.menuChildren,children:l(T,{items:o})})]},r)}):null},E=()=>{let t=s(),n=o(),i=()=>{t(`/`)},c=()=>{_.app.pageToLogin()};return r(()=>{if(!_.app.user||Object.keys(_.app.user).length===0)return c();t(n.pathname)},[n.pathname]),u(`div`,{style:w.layout,children:[u(`header`,{style:w.header,children:[l(`div`,{style:w.logo,onClick:i,children:`Logo`}),l(`button`,{style:w.logoutBtn,onClick:c,onMouseEnter:e=>{e.currentTarget.style.opacity=`0.75`},onMouseLeave:e=>{e.currentTarget.style.opacity=`1`},children:`退出登录`})]}),u(`div`,{style:w.main,children:[l(`aside`,{style:w.sidebar,children:l(T,{items:_.app.menuData||[]})}),l(`main`,{style:w.content,children:l(`div`,{style:w.contentCard,children:l(e,{fallback:_.components.renderComponent(`Loading`,{isSuspense:!0}),children:l(a,{})})})})]})]})},D=({isInitData:e=!1,isSuspense:t=!1,isMicroApp:n=!1})=>l(`div`,{style:e?{width:`100%`,height:`100%`,display:`flex`,alignItems:`center`,justifyContent:`center`}:{},children:`Loading...`}),O={page:{height:`100vh`,display:`flex`,flexDirection:`column`,justifyContent:`center`,alignItems:`center`,gap:16},btn:{height:36,padding:`0 60px`,border:`none`,borderRadius:8,background:`#1677ff`,color:`#fff`,cursor:`pointer`,transition:`0.2s`}},k=()=>{let[e,t]=i(!1);return u(`div`,{style:O.page,children:[l(`h2`,{children:`欢迎登录系统`}),l(`button`,{style:O.btn,onClick:async()=>{if(e)return;t(()=>!0),await new Promise(e=>setTimeout(()=>e(!0),500)),t(()=>!1),_.storage.setItem(_.storage.tokenKey,`123456`);let n=_.app.getRedirectPath();_.router.navigate(n,{replace:!0}),await _.app.initData?.()},onMouseEnter:e=>{e.currentTarget.style.opacity=`0.75`},onMouseLeave:e=>{e.currentTarget.style.opacity=`1`},children:e?`登录中...`:`登录`})]})},A={beforeLoad:[async e=>{console.log(`[LifeCycle] before load %c%s`,`color: green;`,e.name)}],beforeMount:[async e=>{console.log(`[LifeCycle] before mount %c%s`,`color: green;`,e.name)}],afterUnmount:[async e=>{console.log(`[LifeCycle] after unmount %c%s`,`color: green;`,e.name)}]};var j=n(({name:e,rootId:t})=>{let[n,i]=p(_.store,m(e=>[e.microAppLoading,e.setMicroAppLoading]));return r(()=>{if(!e)return;let t=_.app.microAppsInstance.get(e);if(t)t?.mount();else{let n=_.app.microApps.find(t=>t.name===e);if(!n)return;i(!0),t=d(n,{},A),t?.mountPromise?.finally(()=>{i(!1)}),_.app.microAppsInstance.set(e,t)}return()=>{t?.unmount()}},[e]),u(c,{children:[n&&_.components.renderComponent(`Loading`,{isMicroApp:!0}),l(`main`,{id:t})]})});const M=`components`,N={name:M,install(e,n={}){e[M]=x({Layout:E,Loading:D,Login:k,Microapp:j,setComponent:(t,n)=>{if(!t){console.error(`SDKComponentsPlugin - Component cannot be empty`);return}let r=n||t.displayName||t.name;if(!r){console.error(`SDKComponentsPlugin - Component name cannot be empty`);return}e.components[r]=t},getComponent:t=>t?e.components[t]:(console.error(`SDKComponentsPlugin - Component name cannot be empty`),null),renderComponent:(n,r={})=>{let i=e.components.getComponent(n);return i?t(i,r):(console.error(`SDKComponentsPlugin - Component ${n} not found`),null)}},n)}},P=`config`,F={name:P,install(e,t){e[P]=x({env:{},theme:``,locale:``,loginPath:`/login`,defaultPath:``,redirectField:`redirect`},t)}},I=`i18n`,L={name:I,install(e,t){e[I]=x({},t)}},R=`router`,z={name:R,install(e,t){e[R]=x({location:null,navigate:null,matches:null},t)}},B=`storage`,V={name:B,install(e,t){e[B]=x({localeKey:`locale`,themeKey:`theme`,tokenKey:`token`,setItem(e,t){localStorage.setItem(e,t)},getItem(e){return localStorage.getItem(e)},removeItem(e){localStorage.removeItem(e)},clear(){localStorage.clear()}},t)}},H=(e,t)=>({locale:``,setLocale:t=>{e(()=>({locale:t})),_.config.locale=t,_.storage.setItem(_.storage.localeKey,t),document.documentElement.setAttribute(`lang`,t)}}),U=(e,t)=>({microAppLoading:!1,setMicroAppLoading:t=>e(()=>({microAppLoading:t}))}),W=(e,t)=>({theme:``,setTheme:t=>{e(()=>({theme:t})),_.config.theme=t,_.storage.setItem(_.storage.themeKey,t),document.documentElement.setAttribute(`theme`,t)}}),G={user:{},permissions:[],settings:{}},K=(e,t)=>({userInfo:G,setUserInfo:t=>{e(()=>({userInfo:t})),_.app={..._.app,...t}},resetUserInfo:()=>{e(()=>({userInfo:G}))}}),q=e=>f()(h((...t)=>({...H(...t),...U(...t),...W(...t),...K(...t),...Object.values(e||{}).reduce((e,n)=>({...e,...n(...t)}),{})}))),J=`store`,Y={name:J,install(e,t={}){e[J]=q(t)}};export{v as SDKApiPlugin,C as SDKAppPlugin,N as SDKComponentsPlugin,F as SDKConfigPlugin,g as SDKCore,L as SDKI18nPlugin,z as SDKRouterPlugin,V as SDKStoragePlugin,Y as SDKStorePlugin,_ as sdk};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zxiaosi/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-beta.2",
|
|
4
4
|
"description": "A micro frontend kit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"micro frontend",
|
|
@@ -18,8 +18,11 @@
|
|
|
18
18
|
"dist"
|
|
19
19
|
],
|
|
20
20
|
"type": "module",
|
|
21
|
-
"main": "./dist/index.js",
|
|
22
21
|
"types": "dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": "./dist/index.js",
|
|
24
|
+
"./package.json": "./package.json"
|
|
25
|
+
},
|
|
23
26
|
"publishConfig": {
|
|
24
27
|
"access": "public",
|
|
25
28
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -29,20 +32,18 @@
|
|
|
29
32
|
"dev": "tsdown --watch"
|
|
30
33
|
},
|
|
31
34
|
"dependencies": {
|
|
32
|
-
"
|
|
33
|
-
"axios": "^1.13.6",
|
|
34
|
-
"qiankun": "^2.10.16",
|
|
35
|
-
"react-intl-universal": "^2.13.4"
|
|
35
|
+
"axios": "^1.13.6"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
+
"@tsdown/css": "^0.22.1",
|
|
38
39
|
"@types/react": "^18.3.12",
|
|
39
40
|
"@types/react-dom": "^18.3.1",
|
|
40
|
-
"es-toolkit": "^1.
|
|
41
|
-
"tsdown": "^0.
|
|
41
|
+
"es-toolkit": "^1.47.0",
|
|
42
|
+
"tsdown": "^0.22.1",
|
|
42
43
|
"typescript": "^5.9.3"
|
|
43
44
|
},
|
|
44
45
|
"peerDependencies": {
|
|
45
|
-
"
|
|
46
|
+
"qiankun": "^2.10.16",
|
|
46
47
|
"react": "^18.3.1 || >=19.0.0",
|
|
47
48
|
"react-dom": "^18.3.1 || >=19.0.0",
|
|
48
49
|
"react-router-dom": "^6.30.0",
|