little-wheels 1.2.14 → 1.3.1

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/README.md CHANGED
@@ -1,45 +1,312 @@
1
- [keyClock登录](/docs/Login.md)
2
-
3
- #### v1.2.12
4
- - 修复登出时缺少 `id_token` 导致的问题
5
-
6
- #### v1.2.11
7
- - 修复独立鉴权模式下的 401 响应处理
8
-
9
- #### v1.2.10
10
- - 新增 `setTokenStr` 方法用于仅设置 Access Token
11
- - 更新 `.npmrc` 配置文件
12
-
13
- #### v1.2.9
14
- - 修复 SSO 用户组类型判断逻辑
15
-
16
- #### v1.2.8
17
- - 修复 SSO 登录分组数据匹配失败时返回 `null`
18
- - 添加 `.npmrc` 配置文件
19
-
20
- #### v1.2.7
21
- - 添加根据 `groupId` 获取分公司信息的方法
22
-
23
- #### v1.2.6
24
- - 支持传入初始 `token` 参数
25
-
26
- #### v1.2.5
27
- - 支持自定义基础 URL 配置
28
-
29
- #### v1.2.4
30
- - 将请求参数从 body 移动到 URL 查询字符串
31
-
32
- #### v1.2.3
33
- - 更新用户组列表接口地址
34
-
35
- #### v1.2.2
36
- - 支持 TypeScript 类型导出声明
37
-
38
- #### v1.2.1
39
- - Login 模块移除所有静态方法,调用方式发生变化
40
-
41
- #### v1.2.0
42
- - 新增 react-hooks
43
-
44
- #### v1.1.0
45
- - 新增 Login 模块
1
+ # little-wheels
2
+
3
+ 一个面向 React + TypeScript 项目的轻量工具库,提供 SSO 登录、用户与组织查询接口,以及常用 React Hooks。
4
+
5
+ ## 功能
6
+
7
+ | 模块 | 说明 |
8
+ | --- | --- |
9
+ | `AuthLogin` | SSO 登录、登出、Token 存取、刷新与解析 |
10
+ | `useSSOApi` | 用户、角色、公司和分组查询接口 |
11
+ | `LocalStorageUtil` | 按应用 ID 隔离的本地存储工具 |
12
+ | `useAudio` | 音频播放状态与控制 |
13
+ | `usePage` | 列表分页、查询和重置状态管理 |
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ pnpm add little-wheels
19
+ ```
20
+
21
+ 也可以使用 `npm install little-wheels` `yarn add little-wheels`。
22
+
23
+ ## SSO 登录
24
+
25
+ ### 快速开始
26
+
27
+ ```typescript
28
+ import { AuthLogin } from "little-wheels";
29
+
30
+ const authLogin = new AuthLogin({
31
+ APPID: "your-app-id",
32
+ });
33
+
34
+ async function bootstrap() {
35
+ if (!authLogin.getTokenInfo()) {
36
+ // 首次访问会跳转至登录页;登录回调时会自动换取并保存 Token。
37
+ await authLogin.SSOLogin();
38
+ }
39
+
40
+ console.log(authLogin.getDecodeToken());
41
+ }
42
+
43
+ void bootstrap();
44
+
45
+ // 退出登录
46
+ // authLogin.logout();
47
+ ```
48
+
49
+ `AuthLogin` 从 `v1.2.1` 起使用实例方法,请勿再通过 `AuthLogin.getTokenInfo()` 等静态方式调用。
50
+
51
+ ### 配置项
52
+
53
+ ```typescript
54
+ interface AuthLoginType {
55
+ APPID: string;
56
+ dev?: boolean;
57
+ baseURL?: string;
58
+ token?: string;
59
+ }
60
+ ```
61
+
62
+ | 参数 | 必填 | 默认值 | 说明 |
63
+ | --- | --- | --- | --- |
64
+ | `APPID` | 是 | - | 应用唯一标识,同时用于隔离本地 Token |
65
+ | `dev` | 否 | `false` | 开发环境标记,影响 IP 地址访问时的 Keycloak 地址处理 |
66
+ | `baseURL` | 否 | `""` | API 请求基础地址;为空时使用当前域名 |
67
+ | `token` | 否 | `""` | 初始 Access Token,适用于独立鉴权场景 |
68
+
69
+ 前后端分离开发时,需要将 `/lxwork/api` 和 `/sso` 代理到认证服务。例如:
70
+
71
+ ```typescript
72
+ // vite.config.ts
73
+ export default {
74
+ server: {
75
+ proxy: {
76
+ "/lxwork/api": {
77
+ target: "https://your-sso-host.example.com",
78
+ changeOrigin: true,
79
+ },
80
+ "/sso": {
81
+ target: "https://your-sso-host.example.com",
82
+ changeOrigin: true,
83
+ },
84
+ },
85
+ },
86
+ };
87
+ ```
88
+
89
+ ### 常用方法
90
+
91
+ | 方法 | 说明 |
92
+ | --- | --- |
93
+ | `SSOLogin()` | 执行 SSO 登录或处理登录回调 |
94
+ | `login()` | 直接跳转至登录页 |
95
+ | `logout()` | 清除 Token 并跳转至登出页 |
96
+ | `getTokenInfo()` | 获取完整 Token 信息 |
97
+ | `getToken()` | 获取 Access Token |
98
+ | `getRefreshToken()` | 获取 Refresh Token |
99
+ | `getDecodeToken()` | 解析当前 Access Token |
100
+ | `setToken(data, type?)` | 保存完整 Token 信息 |
101
+ | `setTokenStr(token)` | 仅保存 Access Token 字符串 |
102
+ | `refreshToken(forceRefresh?)` | Token 临近过期时刷新;传入 `true` 可强制刷新 |
103
+ | `removeToken()` | 清除本地 Token |
104
+ | `getCompanyList()` | 获取公司列表 |
105
+ | `getUserBranchGroup()` | 获取当前用户所属分公司名称 |
106
+ | `getUserBranchGroupByGroupId({ groupId })` | 根据分组 ID 获取所属分公司信息 |
107
+
108
+ ### 独立 Token 鉴权
109
+
110
+ 适用于 App WebView 等由外部传入 Access Token、无需发起完整 SSO 登录的场景:
111
+
112
+ ```typescript
113
+ import { AuthLogin, useSSOApi } from "little-wheels";
114
+
115
+ const authLogin = new AuthLogin({ APPID: "your-app-id" });
116
+ const token = new URLSearchParams(window.location.search).get("token");
117
+
118
+ if (token) {
119
+ authLogin.setTokenStr(token);
120
+ }
121
+
122
+ const userInfo = await useSSOApi(authLogin).getUserInfo();
123
+ ```
124
+
125
+ ## 请求 API
126
+
127
+ `useSSOApi` 接收一个 `AuthLogin` 实例。请求会自动携带 Bearer Token,并在常规业务接口返回 `401` 时合并并发重登录,然后重试一次。
128
+
129
+ ```typescript
130
+ import { AuthLogin, useSSOApi } from "little-wheels";
131
+
132
+ const authLogin = new AuthLogin({ APPID: "your-app-id" });
133
+ const api = useSSOApi(authLogin);
134
+
135
+ const currentUser = await api.getUserDetail();
136
+ const users = await api.getUsers({
137
+ real_name: "张三",
138
+ exact: false,
139
+ first: 0,
140
+ max_size: 20,
141
+ });
142
+ ```
143
+
144
+ 所有路径都会自动拼接构造 `AuthLogin` 时传入的 `baseURL`。
145
+
146
+ | 方法 | 请求 |
147
+ | --- | --- |
148
+ | `getTokenInfo(params)` | `GET /lxwork/api/auth/token?{查询参数}` |
149
+ | `createPermissionTicket(data)` | `POST /lxwork/api/auth/create-permission-ticket` |
150
+ | `getAuthTokenInfo(data)` | `POST /sso/realms/myrealm/protocol/openid-connect/token` |
151
+ | `refreshAuthToken(refreshToken?)` | `GET /lxwork/api/auth/refresh` |
152
+ | `getCompanyList()` | `GET /lxwork/api/auth/groups/branch` |
153
+ | `getUserGroupList()` | `GET /lxwork/api/auth/users/groups` |
154
+ | `getUserInfo()` | `GET /lxwork/api/auth/userinfo` |
155
+ | `getUserDetail()` | `GET /lxwork/api/auth/users/detail` |
156
+ | `getUserDetailById({ id })` | `GET /lxwork/api/auth/users/{id}` |
157
+ | `getUsers(params)` | `GET /lxwork/api/auth/users/search?{查询参数}` |
158
+ | `getUsersByRole(params)` | `GET /lxwork/api/auth/users/search-by-role?{查询参数}` |
159
+ | `getCurUserGroupList()` | `GET /lxwork/api/auth/users/groups-parsed` |
160
+ | `getAllRoles()` | `GET /lxwork/api/auth/users/all-roles` |
161
+ | `getCurUserRoles()` | `GET /lxwork/api/auth/users/role-mappings` |
162
+ | `getGroupByParentId(params)` | `GET /lxwork/api/auth/groups?{查询参数}` |
163
+ | `getAllGroup()` | `GET /lxwork/api/auth/groups/all` |
164
+ | `getGroupsByName(params)` | `GET /lxwork/api/auth/groups/search?{查询参数}` |
165
+ | `getGroupDetail({ id })` | `GET /lxwork/api/auth/groups/{id}` |
166
+ | `getChildrenGroup({ group_id })` | `GET /lxwork/api/auth/groups/{group_id}/children-parse` |
167
+ | `getUsersByGroup(params)` | `GET /lxwork/api/auth/groups/{group_id}/members?{查询参数}` |
168
+
169
+ 参数和返回值均已提供 TypeScript 类型声明,可直接通过编辑器查看。
170
+
171
+ ## React Hooks
172
+
173
+ Hooks 会单独构建到 `dist/react-hooks/index.es.js`。
174
+
175
+ ### useAudio
176
+
177
+ ```typescript
178
+ import { useAudio } from "little-wheels/dist/react-hooks/index.es.js";
179
+
180
+ const {
181
+ currentTime,
182
+ duration,
183
+ isPlaying,
184
+ volume,
185
+ playRate,
186
+ audioPlay,
187
+ audioPause,
188
+ togglePlay,
189
+ setAudioCurrentTime,
190
+ setAudioVolume,
191
+ setAudioRate,
192
+ } = useAudio({
193
+ src: "/audio/example.mp3",
194
+ onError: (error) => console.error(error),
195
+ });
196
+ ```
197
+
198
+ - 音量范围为 `0` 到 `1`。
199
+ - 播放倍速范围为 `0.5` 到 `4`。
200
+ - `audioPlay(url?)` 和 `togglePlay(url?)` 可在调用时切换音频地址。
201
+
202
+ ### usePage
203
+
204
+ ```typescript
205
+ import { usePage } from "little-wheels/dist/react-hooks/index.es.js";
206
+
207
+ const {
208
+ state,
209
+ listLoading,
210
+ getTableData,
211
+ onPageInfoChange,
212
+ reset,
213
+ } = usePage<User>({
214
+ defaultPageInfo: { pageNum: 1, pageSize: 20 },
215
+ getListApi: (params) => fetchUserList(params),
216
+ customQueryParameters: () => ({ enabled: true }),
217
+ });
218
+
219
+ console.log(state.tableData, state.total, state.pageInfo);
220
+ ```
221
+
222
+ `getListApi` 可以返回数组,也可以返回包含 `dataList`、`list` 和 `total` 字段的对象。传入的 `form` 如包含 `getFieldsValue()` 和 `resetFields()`,会自动参与查询与重置。
223
+
224
+ ## 本地开发
225
+
226
+ ```bash
227
+ pnpm install
228
+ pnpm start
229
+ pnpm build
230
+ ```
231
+
232
+ - `pnpm start`:启动示例项目,默认端口为 `3000`。
233
+ - `pnpm build`:生成 ESM 构建产物和 TypeScript 声明文件。
234
+
235
+ ## 版本记录
236
+
237
+ ### v1.3.1
238
+
239
+ - 修正获取所有分组的接口地址为 `/lxwork/api/auth/groups/all`
240
+ - 补充 Login 请求方法的 URL 注释与项目使用文档
241
+
242
+ ### v1.3.0
243
+
244
+ - 优化 SSO 回调参数校验和 URL 参数清理逻辑
245
+ - 登录及登出重定向地址会移除 SSO 回调参数
246
+
247
+ ### v1.2.14
248
+
249
+ - 合并同一实例的并发重登录,避免多个 `401` 重复跳转
250
+ - 优化多实例场景下的 Token 清理逻辑
251
+
252
+ ### v1.2.13
253
+
254
+ - `refreshAuthToken` 支持传入自定义 Refresh Token
255
+
256
+ ### v1.2.12
257
+
258
+ - 修复登出时缺少 `id_token` 导致的问题
259
+
260
+ ### v1.2.11
261
+
262
+ - 修复独立鉴权模式下的 `401` 响应处理
263
+
264
+ ### v1.2.10
265
+
266
+ - 新增 `setTokenStr` 方法用于仅设置 Access Token
267
+ - 更新 `.npmrc` 配置文件
268
+
269
+ ### v1.2.9
270
+
271
+ - 修复 SSO 用户组类型判断逻辑
272
+
273
+ ### v1.2.8
274
+
275
+ - 修复 SSO 登录分组数据匹配失败时返回 `null`
276
+ - 添加 `.npmrc` 配置文件
277
+
278
+ ### v1.2.7
279
+
280
+ - 添加根据 `groupId` 获取分公司信息的方法
281
+
282
+ ### v1.2.6
283
+
284
+ - 支持传入初始 `token` 参数
285
+
286
+ ### v1.2.5
287
+
288
+ - 支持自定义基础 URL 配置
289
+
290
+ ### v1.2.4
291
+
292
+ - 将请求参数从 body 移动到 URL 查询字符串
293
+
294
+ ### v1.2.3
295
+
296
+ - 更新用户组列表接口地址
297
+
298
+ ### v1.2.2
299
+
300
+ - 支持 TypeScript 类型导出声明
301
+
302
+ ### v1.2.1
303
+
304
+ - Login 模块移除所有静态方法,调用方式发生变化
305
+
306
+ ### v1.2.0
307
+
308
+ - 新增 React Hooks
309
+
310
+ ### v1.1.0
311
+
312
+ - 新增 Login 模块
package/dist/index.d.ts CHANGED
@@ -281,6 +281,8 @@ export declare interface PermissionItem {
281
281
 
282
282
  export declare function removeUrlParam(paramsArr: string[]): void;
283
283
 
284
+ export declare function removeUrlParams(url: string, paramsArr: string[]): string;
285
+
284
286
  export declare interface RoleItem {
285
287
  id: number;
286
288
  position_type_id: number;
@@ -378,26 +380,56 @@ export declare interface UserRoleItem {
378
380
  }
379
381
 
380
382
  export declare const useSSOApi: (authLogin: AuthLogin) => {
383
+ /**
384
+ * 获取令牌信息
385
+ * 请求 URL:GET /lxwork/api/auth/token?{查询参数}
386
+ */
381
387
  getTokenInfo: (params: SearchTokenParams) => Promise<TokenInfoType<number>>;
388
+ /**
389
+ * 创建权限票据
390
+ * 请求 URL:POST /lxwork/api/auth/create-permission-ticket
391
+ */
382
392
  createPermissionTicket: (data: {
383
393
  client_id: string;
384
394
  }) => Promise<{
385
395
  ticket: string;
386
396
  }>;
397
+ /**
398
+ * 使用权限票据获取认证令牌
399
+ * 请求 URL:POST /sso/realms/myrealm/protocol/openid-connect/token
400
+ */
387
401
  getAuthTokenInfo: (data: {
388
402
  grant_type: string;
389
403
  ticket: string;
390
404
  }) => Promise<TokenInfoType<number>>;
405
+ /**
406
+ * 刷新认证令牌
407
+ * 请求 URL:GET /lxwork/api/auth/refresh
408
+ */
391
409
  refreshAuthToken: (refreshToken?: string) => Promise<TokenInfoType<number>>;
410
+ /**
411
+ * 获取所有分公司
412
+ * 请求 URL:GET /lxwork/api/auth/groups/branch
413
+ */
392
414
  getCompanyList: () => Promise<CompanyItem[]>;
415
+ /**
416
+ * 获取当前用户所属分组
417
+ * 请求 URL:GET /lxwork/api/auth/users/groups
418
+ */
393
419
  getUserGroupList: () => Promise<UserGroupItem[]>;
420
+ /**
421
+ * 获取当前登录用户信息
422
+ * 请求 URL:GET /lxwork/api/auth/userinfo
423
+ */
394
424
  getUserInfo: () => Promise<UserInfo>;
395
425
  /**
396
426
  * 获取当前登录用户详细信息
427
+ * 请求 URL:GET /lxwork/api/auth/users/detail
397
428
  */
398
429
  getUserDetail: () => Promise<UserDetail>;
399
430
  /**
400
431
  * 获取当前登录用户详细信息
432
+ * 请求 URL:GET /lxwork/api/auth/users/{id}
401
433
  * @param id 用户id
402
434
  */
403
435
  getUserDetailById: ({ id }: {
@@ -405,6 +437,7 @@ export declare const useSSOApi: (authLogin: AuthLogin) => {
405
437
  }) => Promise<OriginUserDetail>;
406
438
  /**
407
439
  * 根据工号姓名等搜索用户
440
+ * 请求 URL:GET /lxwork/api/auth/users/search?{查询参数}
408
441
  * @param params.username 工号 至少四个字符
409
442
  * @param params.real_name 姓名 至少两个字符
410
443
  * @param params.exact 是否精确查找, 如果为 true 只返回完全匹配的记录, 否则返回模糊匹配的记录
@@ -424,6 +457,7 @@ export declare const useSSOApi: (authLogin: AuthLogin) => {
424
457
  }) => Promise<SearchUserItem[]>;
425
458
  /**
426
459
  * 根据角色名称搜索用户列表(带分页)
460
+ * 请求 URL:GET /lxwork/api/auth/users/search-by-role?{查询参数}
427
461
  * @param params 查询参数对象
428
462
  * @param params.role_name 必填,角色名称(需完全匹配)
429
463
  * @param params.name 可选,用户姓名模糊搜索(支持部分匹配)
@@ -440,21 +474,25 @@ export declare const useSSOApi: (authLogin: AuthLogin) => {
440
474
  /**
441
475
  * 获取当前用户可用的分公司或业务组
442
476
  * 如果当前用户属于分公司,则返回分公司及下属分公司,如果属于分公司下的部门,则返回部门下的业务组, 如果属于业务组,则返回业务组
477
+ * 请求 URL:GET /lxwork/api/auth/users/groups-parsed
443
478
  * @returns Promise<CompanyItem[]>
444
479
  */
445
480
  getCurUserGroupList: () => Promise<CompanyItem[]>;
446
481
  /**
447
482
  * 获取所有岗位角色名称
483
+ * 请求 URL:GET /lxwork/api/auth/users/all-roles
448
484
  * @returns Promise<RoleItem[]>
449
485
  */
450
486
  getAllRoles: () => Promise<RoleItem[]>;
451
487
  /**
452
488
  * 获取当前用户Roles
489
+ * 请求 URL:GET /lxwork/api/auth/users/role-mappings
453
490
  * @returns Promise<UserRoleItem[]>
454
491
  */
455
492
  getCurUserRoles: () => Promise<UserRoleItem[]>;
456
493
  /**
457
494
  * 获取所属 parent_id 下分组
495
+ * 请求 URL:GET /lxwork/api/auth/groups?{查询参数}
458
496
  * @param params.parent_id 可选,分组的父级id
459
497
  * 接口文档 不统一 GroupItem UserGroupItem 字段有下划线 有驼峰
460
498
  * @returns Promise<GroupItem[]>
@@ -464,11 +502,13 @@ export declare const useSSOApi: (authLogin: AuthLogin) => {
464
502
  }) => Promise<GroupItem[]>;
465
503
  /**
466
504
  * 获取所有分组
505
+ * 请求 URL:GET /lxwork/api/auth/groups/all
467
506
  * @returns Promise<GroupItem[]>
468
507
  */
469
508
  getAllGroup: () => Promise<GroupItem[]>;
470
509
  /**
471
510
  * 按组名搜索组, 按树结构返回匹配的组,以及这个组的上级组, 直到根节点
511
+ * 请求 URL:GET /lxwork/api/auth/groups/search?{查询参数}
472
512
  * @param params.search 搜索组, 不少于2个字符
473
513
  * @param params.max 返回结果数, keycloak 默认返回 11 个, 如何希望返回所有,可以设一个较大值
474
514
  * @returns Promise<GroupItem[]> 会按照树形结构返回所有符合搜索条件的树形结果
@@ -479,6 +519,7 @@ export declare const useSSOApi: (authLogin: AuthLogin) => {
479
519
  }) => Promise<GroupItem[]>;
480
520
  /**
481
521
  * 获取组的详细信息
522
+ * 请求 URL:GET /lxwork/api/auth/groups/{id}
482
523
  * @returns Promise<UserGroupItem>
483
524
  */
484
525
  getGroupDetail: ({ id }: {
@@ -486,6 +527,7 @@ export declare const useSSOApi: (authLogin: AuthLogin) => {
486
527
  }) => Promise<UserGroupItem>;
487
528
  /**
488
529
  * 获取某个分公司或分公司部门下的所有下级业务组
530
+ * 请求 URL:GET /lxwork/api/auth/groups/{group_id}/children-parse
489
531
  * @param group_id 分组id
490
532
  * @returns Promise<CompanyItem[]>
491
533
  */
@@ -494,6 +536,7 @@ export declare const useSSOApi: (authLogin: AuthLogin) => {
494
536
  }) => Promise<CompanyItem[]>;
495
537
  /**
496
538
  * 获取某个分组下的所有用户
539
+ * 请求 URL:GET /lxwork/api/auth/groups/{group_id}/members?{查询参数}
497
540
  * @param group_id 分组id
498
541
  * @param params.first Pagination offset, 从 0 开始
499
542
  * @param params.max_size Maximum results size (defaults to 100)