@blueking/bk-user-selector 0.1.5 → 0.1.7
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 +144 -34
- package/package.json +6 -3
- package/typings/components/selection-popover.vue.d.ts +8 -2
- package/typings/components/user-selector.vue.d.ts +14 -2
- package/typings/hooks/use-api-config.d.ts +33 -0
- package/typings/locale/en-us.d.ts +1 -0
- package/typings/locale/zh-cn.d.ts +1 -0
- package/typings/types/index.d.ts +50 -0
- package/typings/utils/logger.d.ts +9 -1
- package/vue2/index.es.min.js +5514 -2529
- package/vue2/index.iife.min.js +6260 -3177
- package/vue2/index.umd.min.js +5690 -2704
- package/vue2/vue2.css +53 -8
- package/vue3/index.es.min.js +1232 -285
- package/vue3/index.iife.min.js +5499 -2521
- package/vue3/index.umd.min.js +1232 -285
- package/vue3/vue3.css +53 -8
package/README.md
CHANGED
|
@@ -18,10 +18,12 @@
|
|
|
18
18
|
| 🎨 **可拖拽** | 多选模式下支持拖拽排序 |
|
|
19
19
|
| ⚡ **快捷操作** | 支持快速选择当前用户("我") |
|
|
20
20
|
| 👥 **用户组** | 支持用户组/角色分组显示 |
|
|
21
|
+
| 🕘 **最近选择** | 支持在下拉右侧展示最近选择人员 |
|
|
21
22
|
| ✏️ **自定义输入** | 支持创建自定义用户和自由粘贴 |
|
|
22
23
|
| 🎭 **自定义渲染** | 支持自定义标签和列表项渲染 |
|
|
23
24
|
| 📝 **多行输入** | 支持 textarea 模式,完整展示所有标签 |
|
|
24
25
|
| ⌨️ **键盘导航** | 支持上下键切换选项、Enter 快速选中 |
|
|
26
|
+
| 🎯 **焦点控制** | 支持自动聚焦和手动 focus/blur 方法 |
|
|
25
27
|
|
|
26
28
|
## 📦 安装
|
|
27
29
|
|
|
@@ -157,6 +159,29 @@ export default {
|
|
|
157
159
|
</script>
|
|
158
160
|
```
|
|
159
161
|
|
|
162
|
+
### 最近选择
|
|
163
|
+
|
|
164
|
+
业务只需传入最近选择用户 ID,组件会自动补全并展示在下拉右侧:
|
|
165
|
+
|
|
166
|
+
```vue
|
|
167
|
+
<template>
|
|
168
|
+
<BkUserSelector
|
|
169
|
+
v-model="selectedUsers"
|
|
170
|
+
:api-base-url="apiBaseUrl"
|
|
171
|
+
:multiple="true"
|
|
172
|
+
:recent-user-ids="recentUserIds"
|
|
173
|
+
/>
|
|
174
|
+
</template>
|
|
175
|
+
|
|
176
|
+
<script setup>
|
|
177
|
+
import { ref } from 'vue';
|
|
178
|
+
|
|
179
|
+
const apiBaseUrl = ref('https://api.example.com');
|
|
180
|
+
const selectedUsers = ref([]);
|
|
181
|
+
const recentUserIds = ref(['admin', 'operator']);
|
|
182
|
+
</script>
|
|
183
|
+
```
|
|
184
|
+
|
|
160
185
|
### 自定义渲染
|
|
161
186
|
|
|
162
187
|
支持自定义标签和列表项的渲染:
|
|
@@ -294,33 +319,35 @@ export default {
|
|
|
294
319
|
|
|
295
320
|
### Props 属性
|
|
296
321
|
|
|
297
|
-
| 参数 | 说明
|
|
298
|
-
| --------------------- |
|
|
299
|
-
| modelValue / v-model | 绑定值,单选为字符串,多选为数组
|
|
300
|
-
| apiBaseUrl | API 基础 URL
|
|
301
|
-
| tenantId | 租户 ID
|
|
302
|
-
| hasAvatar | 是否显示头像
|
|
303
|
-
| avatarBaseUrl | 头像基础 URL
|
|
304
|
-
| label | 文本标签
|
|
305
|
-
| placeholder | 占位文本
|
|
306
|
-
| multiple | 是否多选
|
|
307
|
-
| draggable | 是否可拖拽排序(仅多选模式有效)
|
|
308
|
-
| exactSearchKey | 精确查找 key
|
|
309
|
-
| currentUserId | 当前用户 ID(用于快速选择"我")
|
|
310
|
-
| userGroup | 用户组列表
|
|
311
|
-
| userGroupName | 用户组分类名称
|
|
312
|
-
| emptyText | 无匹配人员时的提示文本
|
|
313
|
-
| disabled | 是否禁用
|
|
314
|
-
| renderTag | 自定义标签渲染函数
|
|
315
|
-
| renderListItem | 自定义列表项渲染函数
|
|
316
|
-
| excludeUserIds | 排除的用户 ID 列表
|
|
317
|
-
|
|
|
318
|
-
|
|
|
319
|
-
|
|
|
320
|
-
|
|
|
321
|
-
|
|
|
322
|
-
|
|
|
323
|
-
|
|
|
322
|
+
| 参数 | 说明 | 类型 | 默认值 | 必填 |
|
|
323
|
+
| --------------------- | -------------------------------------------------- | ------------------------------------------------ | ---------------------- | ---- |
|
|
324
|
+
| modelValue / v-model | 绑定值,单选为字符串,多选为数组 | `string` / `string[]` | `''` / `[]` | 是 |
|
|
325
|
+
| apiBaseUrl | API 基础 URL | `string` | `''` | 是 |
|
|
326
|
+
| tenantId | 租户 ID | `string` | `'default'` | 否 |
|
|
327
|
+
| hasAvatar | 是否显示头像 | `boolean` | `false` | 否 |
|
|
328
|
+
| avatarBaseUrl | 头像基础 URL | `string` | `` | 否 |
|
|
329
|
+
| label | 文本标签 | `string` | `'人员选择'` | 否 |
|
|
330
|
+
| placeholder | 占位文本 | `string` | `'请输入人员名称搜索'` | 否 |
|
|
331
|
+
| multiple | 是否多选 | `boolean` | `false` | 否 |
|
|
332
|
+
| draggable | 是否可拖拽排序(仅多选模式有效) | `boolean` | `false` | 否 |
|
|
333
|
+
| exactSearchKey | 精确查找 key | `'bk_username'` / `'login_name'` / `'full_name'` | `'bk_username'` | 否 |
|
|
334
|
+
| currentUserId | 当前用户 ID(用于快速选择"我") | `string` | `''` | 否 |
|
|
335
|
+
| userGroup | 用户组列表 | `UserGroupItem[]` | `[]` | 否 |
|
|
336
|
+
| userGroupName | 用户组分类名称 | `string` | `'用户群组'` | 否 |
|
|
337
|
+
| emptyText | 无匹配人员时的提示文本 | `string` | `'无匹配人员'` | 否 |
|
|
338
|
+
| disabled | 是否禁用 | `boolean` | `false` | 否 |
|
|
339
|
+
| renderTag | 自定义标签渲染函数 | `(h, userInfo) => VNode` | - | 否 |
|
|
340
|
+
| renderListItem | 自定义列表项渲染函数 | `(h, userInfo) => VNode` | - | 否 |
|
|
341
|
+
| excludeUserIds | 排除的用户 ID 列表 | `string[]` | `[]` | 否 |
|
|
342
|
+
| recentUserIds | 最近选择用户 ID 列表,传入后在下拉右侧展示最近选择 | `string[]` | `[]` | 否 |
|
|
343
|
+
| enableMultiTenantMode | 是否启用多租户模式 | `boolean` | `true` | 否 |
|
|
344
|
+
| allowCreate | 是否允许自定义输入,按 Enter 确认 | `boolean` | `false` | 否 |
|
|
345
|
+
| freePaste | 是否允许粘贴任意文本 | `boolean` | `false` | 否 |
|
|
346
|
+
| maxCount | 最大可选数量(0 表示不限制) | `number` | `0` | 否 |
|
|
347
|
+
| type | 输入框类型 | `'input'` / `'textarea'` | `'input'` | 否 |
|
|
348
|
+
| rows | 默认行数(仅 textarea 模式生效) | `number` | `4` | 否 |
|
|
349
|
+
| resize | 是否允许拖拽调整高度(仅 textarea 模式生效) | `boolean` | `true` | 否 |
|
|
350
|
+
| autoFocus | 是否自动聚焦 | `boolean` | `false` | 否 |
|
|
324
351
|
|
|
325
352
|
#### exactSearchKey 说明
|
|
326
353
|
|
|
@@ -335,12 +362,42 @@ export default {
|
|
|
335
362
|
|
|
336
363
|
### Events 事件
|
|
337
364
|
|
|
338
|
-
| 事件名称 | 说明
|
|
339
|
-
| ----------------- |
|
|
340
|
-
| update:modelValue | 绑定值变化时触发
|
|
341
|
-
| change | 选中值变化时触发
|
|
342
|
-
| focus | 输入框获得焦点时触发
|
|
343
|
-
| blur | 输入框失去焦点时触发
|
|
365
|
+
| 事件名称 | 说明 | 回调参数 |
|
|
366
|
+
| ----------------- | ---------------------------------------------------------------------------------- | ------------------------------------ |
|
|
367
|
+
| update:modelValue | 绑定值变化时触发 | `(value: string \| string[])` |
|
|
368
|
+
| change | 选中值变化时触发 | `(userInfo: UserInfo \| UserInfo[])` |
|
|
369
|
+
| focus | 输入框获得焦点时触发 | - |
|
|
370
|
+
| blur | 输入框失去焦点时触发 | - |
|
|
371
|
+
| error | 任意接口请求失败时触发(包含 401、网络错误等),业务可在此弹 Message、上报 Sentry | `(error: ApiError)` |
|
|
372
|
+
| unauthorized | 登录态失效(HTTP 401)时触发,同时也会触发 `error`,业务可在此跳转登录或刷新 token | `(error: ApiError)` |
|
|
373
|
+
|
|
374
|
+
### Methods 方法
|
|
375
|
+
|
|
376
|
+
通过模板 ref 调用组件方法:
|
|
377
|
+
|
|
378
|
+
| 方法名 | 说明 | 参数 |
|
|
379
|
+
| ------ | ---------- | ---- |
|
|
380
|
+
| focus | 使组件聚焦 | - |
|
|
381
|
+
| blur | 使组件失焦 | - |
|
|
382
|
+
|
|
383
|
+
```vue
|
|
384
|
+
<template>
|
|
385
|
+
<BkUserSelector
|
|
386
|
+
ref="selectorRef"
|
|
387
|
+
v-model="value"
|
|
388
|
+
:api-base-url="apiBaseUrl"
|
|
389
|
+
/>
|
|
390
|
+
<button @click="selectorRef?.focus()">聚焦</button>
|
|
391
|
+
<button @click="selectorRef?.blur()">失焦</button>
|
|
392
|
+
</template>
|
|
393
|
+
|
|
394
|
+
<script setup>
|
|
395
|
+
import { ref } from 'vue';
|
|
396
|
+
const selectorRef = ref(null);
|
|
397
|
+
const value = ref('');
|
|
398
|
+
const apiBaseUrl = 'https://api.example.com';
|
|
399
|
+
</script>
|
|
400
|
+
```
|
|
344
401
|
|
|
345
402
|
### 类型定义
|
|
346
403
|
|
|
@@ -367,8 +424,56 @@ type RenderFunction = (
|
|
|
367
424
|
h: CreateElement, // Vue createElement 函数
|
|
368
425
|
userInfo: UserInfo, // 用户信息
|
|
369
426
|
) => VNode;
|
|
427
|
+
|
|
428
|
+
// 接口错误
|
|
429
|
+
interface ApiError {
|
|
430
|
+
scene: string; // 业务场景,如 '搜索用户'、'批量查找用户'
|
|
431
|
+
cause: unknown; // 原始错误对象
|
|
432
|
+
status?: number; // HTTP 状态码(网络错误时为 undefined)
|
|
433
|
+
isUnauthorized: boolean; // 是否为登录态失效(HTTP 401)
|
|
434
|
+
}
|
|
370
435
|
```
|
|
371
436
|
|
|
437
|
+
## 🛡️ 错误处理
|
|
438
|
+
|
|
439
|
+
组件遵循「不强依赖 UI 反馈」的设计原则,接口失败时**不会自动弹 Message**,而是通过事件向业务侧暴露错误,由业务自行决定弹消息、上报监控或静默处理。
|
|
440
|
+
|
|
441
|
+
```vue
|
|
442
|
+
<template>
|
|
443
|
+
<BkUserSelector
|
|
444
|
+
v-model="selectedUser"
|
|
445
|
+
:api-base-url="apiBaseUrl"
|
|
446
|
+
:tenant-id="tenantId"
|
|
447
|
+
@error="handleApiError"
|
|
448
|
+
@unauthorized="handleUnauthorized"
|
|
449
|
+
/>
|
|
450
|
+
</template>
|
|
451
|
+
|
|
452
|
+
<script setup lang="ts">
|
|
453
|
+
import { Message } from 'bkui-vue';
|
|
454
|
+
|
|
455
|
+
import type { ApiError } from '@blueking/bk-user-selector';
|
|
456
|
+
|
|
457
|
+
const handleApiError = (err: ApiError) => {
|
|
458
|
+
// 401 不需要重复弹 Message,由 unauthorized 单独处理
|
|
459
|
+
if (err.isUnauthorized) return;
|
|
460
|
+
Message({ theme: 'error', message: `${err.scene}失败,请稍后重试` });
|
|
461
|
+
// 也可以上报 Sentry / 蓝鲸监控
|
|
462
|
+
// sentry.captureException(err.cause, { extra: { scene: err.scene, status: err.status } });
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
const handleUnauthorized = (err: ApiError) => {
|
|
466
|
+
location.href = `/login?next=${encodeURIComponent(location.href)}`;
|
|
467
|
+
};
|
|
468
|
+
</script>
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
行为说明:
|
|
472
|
+
|
|
473
|
+
- 失败统一构造 `ApiError`,已通过 `console.error` 打印兜底日志
|
|
474
|
+
- 401 会同时触发 `unauthorized` 和 `error` 事件,便于业务统一收口或独立处理
|
|
475
|
+
- 业务回调如果抛错不会影响组件正常流程
|
|
476
|
+
|
|
372
477
|
## 💡 功能说明
|
|
373
478
|
|
|
374
479
|
### 快速选择"我"
|
|
@@ -437,6 +542,7 @@ type RenderFunction = (
|
|
|
437
542
|
- 多选模式:`v-model` 应为 `string[]` 类型
|
|
438
543
|
4. **跨租户显示**:跨租户用户会在名称旁显示租户标识
|
|
439
544
|
5. **自定义输入**:启用 `allowCreate` 后,用户输入的内容会作为 `id` 值
|
|
545
|
+
6. **批量粘贴限制**:单次粘贴最多处理 `100` 个用户标识,超出部分会被截断;批量精准查询按后端限制分批执行(每批最多 `100` 个)
|
|
440
546
|
|
|
441
547
|
## ❓ FAQ
|
|
442
548
|
|
|
@@ -462,7 +568,11 @@ A: 通过 `change` 事件获取,它会返回完整的用户信息对象,而
|
|
|
462
568
|
|
|
463
569
|
### Q: 多选模式下如何限制选择数量?
|
|
464
570
|
|
|
465
|
-
A:
|
|
571
|
+
A: 使用 `maxCount` 属性设置最大可选数量,`0` 表示不限制。
|
|
572
|
+
|
|
573
|
+
### Q: 一次粘贴很多用户,为什么没有全部添加?
|
|
574
|
+
|
|
575
|
+
A: 出于性能与安全保护,批量粘贴单次最多处理 `100` 个用户标识,超出部分会被截断;组件会按后端限制分批查询(每批最多 `100` 个)。如需导入更多用户,请分批粘贴。
|
|
466
576
|
|
|
467
577
|
### Q: 搜索没有结果怎么办?
|
|
468
578
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blueking/bk-user-selector",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "蓝鲸用户选择器",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Tencent BlueKing",
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
"build": "vite-node ./scripts/vite.build.ts",
|
|
11
11
|
"dts": "vue-tsc --project tsconfig.dts.json",
|
|
12
12
|
"prettier": "prettier ./src ./scripts ./playground --write",
|
|
13
|
-
"visualize": "vite-bundle-visualizer -c scripts/vite.visualizer.ts"
|
|
13
|
+
"visualize": "vite-bundle-visualizer -c scripts/vite.visualizer.ts",
|
|
14
|
+
"docs:dev": "vitepress dev docs",
|
|
15
|
+
"docs:build": "vitepress build docs",
|
|
16
|
+
"docs:preview": "vitepress preview docs"
|
|
14
17
|
},
|
|
15
18
|
"exports": {
|
|
16
19
|
".": {
|
|
@@ -61,4 +64,4 @@
|
|
|
61
64
|
"lodash": "^4.17.23",
|
|
62
65
|
"sortablejs": "^1.15.6"
|
|
63
66
|
}
|
|
64
|
-
}
|
|
67
|
+
}
|
|
@@ -21,6 +21,10 @@ interface SelectionPopoverProps {
|
|
|
21
21
|
loading?: boolean;
|
|
22
22
|
/** 搜索结果选项 */
|
|
23
23
|
options?: FormattedUser[];
|
|
24
|
+
/** 最近选择用户 */
|
|
25
|
+
recentUsers?: FormattedUser[];
|
|
26
|
+
/** 最近选择标题 */
|
|
27
|
+
recentUsersName?: string;
|
|
24
28
|
/** 渲染列表项 */
|
|
25
29
|
renderListItem?: RenderFunction;
|
|
26
30
|
/** 搜索关键词 */
|
|
@@ -34,9 +38,9 @@ interface SelectionPopoverProps {
|
|
|
34
38
|
/** 用户组名称 */
|
|
35
39
|
userGroupName?: string;
|
|
36
40
|
}
|
|
37
|
-
declare var
|
|
41
|
+
declare var __VLS_27: {};
|
|
38
42
|
type __VLS_Slots = {} & {
|
|
39
|
-
default?: (props: typeof
|
|
43
|
+
default?: (props: typeof __VLS_27) => any;
|
|
40
44
|
};
|
|
41
45
|
declare const __VLS_base: import("vue").DefineComponent<SelectionPopoverProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
42
46
|
"click-outside": (event: MouseEvent) => any;
|
|
@@ -58,6 +62,8 @@ declare const __VLS_base: import("vue").DefineComponent<SelectionPopoverProps, {
|
|
|
58
62
|
isShow: boolean;
|
|
59
63
|
loading: boolean;
|
|
60
64
|
options: FormattedUser[];
|
|
65
|
+
recentUsers: FormattedUser[];
|
|
66
|
+
recentUsersName: string;
|
|
61
67
|
userGroupName: string;
|
|
62
68
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
63
69
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
import { FormattedUser, UserSelectorProps } from '../types';
|
|
2
|
-
declare const __VLS_export: import("vue").DefineComponent<UserSelectorProps, {
|
|
1
|
+
import { ApiError, FormattedUser, UserSelectorProps } from '../types';
|
|
2
|
+
declare const __VLS_export: import("vue").DefineComponent<UserSelectorProps, {
|
|
3
|
+
focus: () => void;
|
|
4
|
+
blur: () => void;
|
|
5
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
error: (error: ApiError) => any;
|
|
3
7
|
blur: () => any;
|
|
4
8
|
change: (user: FormattedUser | FormattedUser[] | null) => any;
|
|
5
9
|
focus: () => any;
|
|
6
10
|
dragEnd: (event: Sortable.SortableEvent) => any;
|
|
7
11
|
dragStart: (event: Sortable.SortableEvent) => any;
|
|
12
|
+
unauthorized: (error: ApiError) => any;
|
|
8
13
|
"update:modelValue": (value: string | string[]) => any;
|
|
9
14
|
}, string, import("vue").PublicProps, Readonly<UserSelectorProps> & Readonly<{
|
|
15
|
+
onError?: ((error: ApiError) => any) | undefined;
|
|
10
16
|
onBlur?: (() => any) | undefined;
|
|
11
17
|
onChange?: ((user: FormattedUser | FormattedUser[] | null) => any) | undefined;
|
|
12
18
|
onFocus?: (() => any) | undefined;
|
|
13
19
|
onDragEnd?: ((event: Sortable.SortableEvent) => any) | undefined;
|
|
14
20
|
onDragStart?: ((event: Sortable.SortableEvent) => any) | undefined;
|
|
21
|
+
onUnauthorized?: ((error: ApiError) => any) | undefined;
|
|
15
22
|
"onUpdate:modelValue"?: ((value: string | string[]) => any) | undefined;
|
|
16
23
|
}>, {
|
|
17
24
|
userGroup: import("../types").UserGroupConfig[];
|
|
@@ -32,10 +39,15 @@ declare const __VLS_export: import("vue").DefineComponent<UserSelectorProps, {},
|
|
|
32
39
|
userGroupName: string;
|
|
33
40
|
disabled: boolean;
|
|
34
41
|
draggable: boolean;
|
|
42
|
+
autoFocus: boolean;
|
|
35
43
|
modelValue: string | string[];
|
|
36
44
|
multiple: boolean;
|
|
37
45
|
rows: number;
|
|
46
|
+
allowCrossOriginCredentials: boolean;
|
|
47
|
+
allowedApiOrigins: string[];
|
|
48
|
+
allowPrivateApiHost: boolean;
|
|
38
49
|
placeholder: string;
|
|
50
|
+
recentUserIds: string[];
|
|
39
51
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
40
52
|
declare const _default: typeof __VLS_export;
|
|
41
53
|
export default _default;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type InjectionKey } from 'vue';
|
|
2
|
+
import type { ApiErrorHandler } from '../types';
|
|
3
|
+
export interface ApiConfig {
|
|
4
|
+
allowCrossOriginCredentials: boolean;
|
|
5
|
+
allowedApiOrigins: string[];
|
|
6
|
+
allowPrivateApiHost: boolean;
|
|
7
|
+
apiBaseUrl: string;
|
|
8
|
+
/**
|
|
9
|
+
* 接口失败回调
|
|
10
|
+
* 由组件透传或调用方在直接调用 API 函数时传入
|
|
11
|
+
*/
|
|
12
|
+
onError?: ApiErrorHandler;
|
|
13
|
+
/**
|
|
14
|
+
* 登录态失效回调(HTTP 401)
|
|
15
|
+
* 由组件透传或调用方在直接调用 API 函数时传入
|
|
16
|
+
*/
|
|
17
|
+
onUnauthorized?: ApiErrorHandler;
|
|
18
|
+
tenantId: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 可选回调集合,用于向 provideApiConfig 注入回调
|
|
22
|
+
*/
|
|
23
|
+
export interface ApiConfigCallbacks {
|
|
24
|
+
onError?: ApiErrorHandler;
|
|
25
|
+
onUnauthorized?: ApiErrorHandler;
|
|
26
|
+
}
|
|
27
|
+
export declare const API_CONFIG_KEY: InjectionKey<ApiConfig>;
|
|
28
|
+
export declare const normalizeAllowedOrigins: (allowedApiOrigins?: string[]) => string[];
|
|
29
|
+
export declare const sanitizeApiBaseUrl: (apiBaseUrl: string, allowedApiOrigins?: string[], allowPrivateApiHost?: boolean) => string;
|
|
30
|
+
export declare const sanitizeTenantId: (tenantId: string) => string;
|
|
31
|
+
export declare const getApiConfig: () => ApiConfig;
|
|
32
|
+
export declare const provideApiConfig: (apiBaseUrl: string, tenantId: string, allowedApiOrigins?: string[], allowPrivateApiHost?: boolean, allowCrossOriginCredentials?: boolean, callbacks?: ApiConfigCallbacks) => void;
|
|
33
|
+
export declare const useApiConfig: (fallbackApiBaseUrl?: string, fallbackTenantId?: string, fallbackAllowedApiOrigins?: string[], fallbackAllowPrivateApiHost?: boolean, fallbackAllowCrossOriginCredentials?: boolean) => ApiConfig;
|
package/typings/types/index.d.ts
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
import type { createVNode } from 'vue';
|
|
2
2
|
import type { VNode } from 'vue';
|
|
3
3
|
import type { USER_TYPE } from '../constants';
|
|
4
|
+
/**
|
|
5
|
+
* API 请求错误对象
|
|
6
|
+
* 组件内部所有接口请求失败时统一构造此对象,向外暴露给业务侧
|
|
7
|
+
*/
|
|
8
|
+
export interface ApiError {
|
|
9
|
+
/**
|
|
10
|
+
* 原始错误对象
|
|
11
|
+
*/
|
|
12
|
+
cause: unknown;
|
|
13
|
+
/**
|
|
14
|
+
* 是否为登录态失效(HTTP 401)
|
|
15
|
+
* 同时会触发 onUnauthorized 回调
|
|
16
|
+
*/
|
|
17
|
+
isUnauthorized: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* 业务场景描述
|
|
20
|
+
* 例如:'获取租户信息'、'搜索用户'、'批量查找用户'
|
|
21
|
+
*/
|
|
22
|
+
scene: string;
|
|
23
|
+
/**
|
|
24
|
+
* HTTP 状态码(仅在响应已到达时存在;网络错误等情况下为 undefined)
|
|
25
|
+
*/
|
|
26
|
+
status?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* API 错误回调
|
|
30
|
+
* 所有接口失败(含 401、网络错误等)都会触发此回调
|
|
31
|
+
*/
|
|
32
|
+
export type ApiErrorHandler = (error: ApiError) => void;
|
|
4
33
|
/**
|
|
5
34
|
* 基础选择器属性
|
|
6
35
|
*/
|
|
@@ -9,6 +38,18 @@ export interface BaseSelectorProps {
|
|
|
9
38
|
* 是否允许创建用户
|
|
10
39
|
*/
|
|
11
40
|
allowCreate?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* 是否允许跨域请求携带 Cookie
|
|
43
|
+
*/
|
|
44
|
+
allowCrossOriginCredentials?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* 允许访问的跨域 API 源白名单
|
|
47
|
+
*/
|
|
48
|
+
allowedApiOrigins?: string[];
|
|
49
|
+
/**
|
|
50
|
+
* 是否允许 apiBaseUrl 指向私网或 localhost
|
|
51
|
+
*/
|
|
52
|
+
allowPrivateApiHost?: boolean;
|
|
12
53
|
/**
|
|
13
54
|
* 接口基础URL
|
|
14
55
|
*/
|
|
@@ -55,6 +96,10 @@ export interface BaseSelectorProps {
|
|
|
55
96
|
* 占位文字
|
|
56
97
|
*/
|
|
57
98
|
placeholder?: string;
|
|
99
|
+
/**
|
|
100
|
+
* 最近选择用户 ID 列表
|
|
101
|
+
*/
|
|
102
|
+
recentUserIds?: string[];
|
|
58
103
|
/**
|
|
59
104
|
* 渲染列表项
|
|
60
105
|
*/
|
|
@@ -204,6 +249,11 @@ export interface UserGroupConfig {
|
|
|
204
249
|
* 用户选择器属性
|
|
205
250
|
*/
|
|
206
251
|
export interface UserSelectorProps extends BaseSelectorProps {
|
|
252
|
+
/**
|
|
253
|
+
* 是否自动聚焦
|
|
254
|
+
* @default false
|
|
255
|
+
*/
|
|
256
|
+
autoFocus?: boolean;
|
|
207
257
|
/**
|
|
208
258
|
* 是否支持拖拽排序
|
|
209
259
|
*/
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 日志工具
|
|
3
|
+
* @module utils/logger
|
|
4
|
+
*/
|
|
5
|
+
import type { ApiConfig } from '../hooks/use-api-config';
|
|
1
6
|
/**
|
|
2
7
|
* 日志级别
|
|
3
8
|
*/
|
|
@@ -38,8 +43,11 @@ export declare const logger: {
|
|
|
38
43
|
};
|
|
39
44
|
/**
|
|
40
45
|
* API 错误处理
|
|
46
|
+
* - 打印错误日志(兜底)
|
|
47
|
+
* - 触发 apiConfig.onError 回调
|
|
48
|
+
* - 如果是 401,额外触发 apiConfig.onUnauthorized 回调
|
|
41
49
|
*/
|
|
42
|
-
export declare const handleApiError: (operation: string, error: unknown) => void;
|
|
50
|
+
export declare const handleApiError: (operation: string, error: unknown, apiConfig?: ApiConfig, status?: number, isUnauthorized?: boolean) => void;
|
|
43
51
|
/**
|
|
44
52
|
* 参数校验警告
|
|
45
53
|
*/
|