@blueking/bk-user-selector 0.0.1-beta.2 → 0.0.2-beta.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.
@@ -3,8 +3,239 @@
3
3
  })(this, function(exports2, vue, bkuiVue) {
4
4
  "use strict";
5
5
  var __vite_style__ = document.createElement("style");
6
- __vite_style__.textContent = "\n.user-selector[data-v-5e8a952d] {\n width: 100%;\n}\n.form-item[data-v-5e8a952d] {\n display: flex;\n align-items: center;\n margin-bottom: 15px;\n}\n.form-label[data-v-5e8a952d] {\n width: 80px;\n text-align: right;\n padding-right: 10px;\n font-size: 14px;\n color: #63656e;\n}\n.form-required[data-v-5e8a952d] {\n color: #ea3636;\n margin-right: 4px;\n}\n.form-content[data-v-5e8a952d] {\n flex: 1;\n position: relative;\n}\n.tag-input-container[data-v-5e8a952d] {\n display: flex;\n flex-wrap: wrap;\n border: 1px solid #dcdee5;\n border-radius: 2px;\n min-height: 32px;\n align-items: center;\n padding: 2px 8px;\n gap: 4px;\n}\n.tag-inline-container[data-v-5e8a952d] {\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n gap: 4px;\n flex-grow: 1;\n min-height: 24px;\n}\n.is-focused[data-v-5e8a952d] {\n border-color: #3a84ff;\n}\n.tag-group[data-v-5e8a952d] {\n display: contents;\n /* 让draggable的内容直接成为父容器的子元素 */\n}\n.tag-item[data-v-5e8a952d] {\n flex-shrink: 0;\n height: 24px;\n line-height: 24px;\n margin: 0;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n}\n.tag-content[data-v-5e8a952d] {\n display: flex;\n align-items: center;\n height: 100%;\n}\n\n/* 输入框样式 */\n.tag-input[data-v-5e8a952d] {\n flex-grow: 0;\n width: 10px;\n min-width: 10px;\n max-width: 100%;\n border: none;\n outline: none;\n height: 32px;\n font-size: 14px;\n padding: 0 8px;\n background: transparent;\n cursor: text;\n transition: width 0.1s ease-in-out;\n}\n.tag-input[data-v-5e8a952d]::placeholder {\n color: #c4c6cc;\n font-size: 12px;\n}\n.full-width[data-v-5e8a952d] {\n flex-grow: 1;\n padding: 0 8px;\n /* 添加统一的内边距 */\n}\n.popover-content[data-v-5e8a952d] {\n min-height: 80px;\n max-height: 250px;\n overflow-y: auto;\n background-color: #fff;\n}\n.user-option[data-v-5e8a952d] {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n cursor: pointer;\n}\n.user-option[data-v-5e8a952d]:hover {\n background-color: #f5f7fa;\n}\n.user-avatar[data-v-5e8a952d] {\n width: 24px;\n height: 24px;\n border-radius: 50%;\n margin-right: 8px;\n}\n.user-avatar-text[data-v-5e8a952d] {\n width: 24px;\n height: 24px;\n line-height: 24px;\n text-align: center;\n border-radius: 50%;\n background-color: #3a84ff;\n color: white;\n font-size: 12px;\n margin-right: 8px;\n}\n.user-name[data-v-5e8a952d] {\n font-size: 12px;\n}\n\n/* 拖拽相关样式 */\n.draggable[data-v-5e8a952d] {\n cursor: move;\n padding-left: 4px;\n}\n.ghost-tag[data-v-5e8a952d] {\n opacity: 0.5;\n background: #c8ebfb;\n}\n.chosen-tag[data-v-5e8a952d] {\n box-shadow: 0 0 2px 2px #3a84ff;\n}\n.drag-tag[data-v-5e8a952d] {\n opacity: 0.8;\n}\n.drag-handle[data-v-5e8a952d] {\n display: inline-flex;\n align-items: center;\n margin-right: 4px;\n opacity: 0.6;\n cursor: move;\n}\n.drag-handle svg[data-v-5e8a952d] {\n fill: currentColor;\n}\n.tag-wrapper[data-v-5e8a952d] {\n display: flex;\n align-items: center;\n padding: 0;\n height: 24px;\n}\n.inline-input[data-v-5e8a952d] {\n margin-left: 4px;\n min-width: 10px;\n padding: 0 2px;\n}\n\n/* 测量元素样式 */\n.measure-text[data-v-5e8a952d] {\n position: absolute;\n visibility: hidden;\n height: 0;\n white-space: pre;\n font-size: 14px;\n font-family: inherit;\n padding: 0 2px;\n}\n\n/* 单选模式样式 */\n.is-single[data-v-5e8a952d] {\n cursor: pointer;\n}\n.single-select[data-v-5e8a952d] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n height: 100%;\n}\n.single-value[data-v-5e8a952d] {\n display: flex;\n align-items: center;\n padding: 0 8px;\n margin-right: 4px;\n height: 24px;\n}\n.single-input[data-v-5e8a952d] {\n flex: 1;\n width: auto;\n}\n.placeholder[data-v-5e8a952d] {\n color: #c4c6cc;\n}\n.dropdown-arrow[data-v-5e8a952d] {\n margin-left: 8px;\n font-size: 10px;\n color: #979ba5;\n}\n.clear-icon[data-v-5e8a952d] {\n margin-left: 8px;\n font-size: 14px;\n color: #979ba5;\n cursor: pointer;\n}\n.clear-icon[data-v-5e8a952d]:hover {\n color: #63656e;\n}\n.no-data[data-v-5e8a952d] {\n padding: 8px 12px;\n font-size: 12px;\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n/*$vite$:1*/";
6
+ __vite_style__.textContent = ".user-option[data-v-0ae61279] {\n display: flex;\n align-items: center;\n}\n.user-option .user-name[data-v-0ae61279] {\n font-size: 14px;\n}\n.user-option .tenant-name[data-v-0ae61279] {\n font-size: 12px;\n color: #f59500;\n margin-left: 4px;\n padding: 0 4px;\n background: rgba(245, 149, 0, 0.1);\n border-radius: 2px;\n}.user-tag[data-v-cf26d9e2] {\n margin-right: 4px;\n}\n.user-tag.draggable[data-v-cf26d9e2] {\n cursor: move;\n}\n.user-tag.active[data-v-cf26d9e2] {\n background-color: #e1ecff;\n border-color: #3a84ff;\n}\n.user-tag .tag-content .user-name[data-v-cf26d9e2] {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 12px;\n}\n.user-tag .tag-content .tenant-name[data-v-cf26d9e2] {\n color: #f59500;\n margin-left: 3px;\n white-space: nowrap;\n padding: 0 3px;\n border-radius: 2px;\n}.bk-user-selector-popover.bk-popover.bk-pop2-content {\n padding: 0;\n}.multiple-selector[data-v-6a1779a9] {\n position: relative;\n width: 100%;\n}\n.multiple-selector .tags-container[data-v-6a1779a9] {\n min-height: 32px;\n border: 1px solid #dcdee5;\n border-radius: 2px;\n padding: 1px 4px;\n transition: all 0.2s ease;\n background-color: #fff;\n}\n.multiple-selector .tags-container.focused[data-v-6a1779a9] {\n border-color: #3a84ff;\n box-shadow: 0 0 0 2px rgba(58, 132, 255, 0.1);\n}\n.multiple-selector .tags-container.collapsed[data-v-6a1779a9] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n}\n.multiple-selector .tag-list[data-v-6a1779a9] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n}\n.multiple-selector .tag-wrapper[data-v-6a1779a9] {\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n}\n.multiple-selector .search-input[data-v-6a1779a9] {\n outline: none;\n border: none;\n font-size: 14px;\n height: 28px;\n background: transparent;\n}\n.multiple-selector .search-input[data-v-6a1779a9]::placeholder {\n color: #C4C6CC;\n}\n.multiple-selector .search-input.inline[data-v-6a1779a9] {\n width: 4px;\n min-width: 4px;\n}\n.multiple-selector .search-input.last[data-v-6a1779a9], .multiple-selector .search-input.collapsed[data-v-6a1779a9] {\n flex: 1;\n min-width: 60px;\n}\n.multiple-selector .tag-more[data-v-6a1779a9] {\n background-color: #f0f1f5;\n color: #63656e;\n margin: 0 4px 4px 0;\n cursor: pointer;\n}\n.dropdown-content[data-v-6a1779a9] {\n min-height: 40px;\n max-height: 300px;\n overflow-y: auto;\n padding: 5px 0;\n}\n.dropdown-content .no-data[data-v-6a1779a9] {\n padding: 10px;\n text-align: center;\n color: #979ba5;\n}\n.dropdown-content .user-option[data-v-6a1779a9] {\n padding: 8px 12px;\n cursor: pointer;\n display: flex;\n align-items: center;\n height: 32px;\n}\n.dropdown-content .user-option[data-v-6a1779a9]:hover {\n background-color: #f5f7fa;\n}\n.dropdown-content .user-option .user-name[data-v-6a1779a9] {\n font-size: 14px;\n}\n.dropdown-content .user-option .tenant-name[data-v-6a1779a9] {\n font-size: 12px;\n color: #f59500;\n margin-left: 4px;\n padding: 0 4px;\n background: rgba(245, 149, 0, 0.1);\n border-radius: 2px;\n}.bk-user-selector[data-v-144c2518] {\n width: 100%;\n position: relative;\n}/*$vite$:1*/";
7
7
  document.head.appendChild(__vite_style__);
8
+ const getTenants = async (apiBaseUrl, tenantId) => {
9
+ if (!apiBaseUrl || !tenantId) {
10
+ console.warn("获取租户信息需要提供有效的API基础URL和租户ID");
11
+ return [];
12
+ }
13
+ try {
14
+ const url = `${apiBaseUrl}/api/v3/open-web/tenant/data-source-owner-tenants/`;
15
+ const response = await fetch(url, {
16
+ method: "GET",
17
+ headers: {
18
+ "x-bk-tenant-id": tenantId
19
+ },
20
+ credentials: "include"
21
+ });
22
+ if (!response.ok) {
23
+ throw new Error(`获取租户信息失败: ${response.status} ${response.statusText}`);
24
+ }
25
+ const data = await response.json();
26
+ return data.data || [];
27
+ } catch (error) {
28
+ console.error("获取租户信息失败:", error);
29
+ return [];
30
+ }
31
+ };
32
+ const searchUsers = async (apiBaseUrl, tenantId, keyword = "") => {
33
+ if (!keyword || !apiBaseUrl || !tenantId) {
34
+ console.warn("搜索用户需要提供有效的API基础URL、租户ID和关键词");
35
+ return [];
36
+ }
37
+ try {
38
+ const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/search/?keyword=${encodeURIComponent(keyword)}`;
39
+ const response = await fetch(url, {
40
+ method: "GET",
41
+ headers: {
42
+ "x-bk-tenant-id": tenantId
43
+ },
44
+ credentials: "include"
45
+ });
46
+ if (!response.ok) {
47
+ throw new Error(`搜索用户失败: ${response.status} ${response.statusText}`);
48
+ }
49
+ const data = await response.json();
50
+ return data.data || [];
51
+ } catch (error) {
52
+ console.error("搜索用户失败:", error);
53
+ return [];
54
+ }
55
+ };
56
+ const lookupUsers = async (apiBaseUrl, tenantId, users = []) => {
57
+ if (users.length === 0 || !apiBaseUrl || !tenantId) {
58
+ console.warn("批量查找用户需要提供有效的API基础URL、租户ID和至少一个用户名");
59
+ return [];
60
+ }
61
+ try {
62
+ const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/lookup/?lookups=${users.join(",")}&lookup_fields=bk_username`;
63
+ const response = await fetch(url, {
64
+ method: "GET",
65
+ headers: {
66
+ "x-bk-tenant-id": tenantId
67
+ },
68
+ credentials: "include"
69
+ });
70
+ if (!response.ok) {
71
+ throw new Error(`批量查找用户失败: ${response.status} ${response.statusText}`);
72
+ }
73
+ const data = await response.json();
74
+ return data.data || [];
75
+ } catch (error) {
76
+ console.error("批量查找用户失败:", error);
77
+ return [];
78
+ }
79
+ };
80
+ const formatUsers = (users) => {
81
+ if (!users || !Array.isArray(users)) return [];
82
+ return users.map((user) => ({
83
+ id: user.bk_username,
84
+ name: user.display_name,
85
+ tenantId: user.owner_tenant_id
86
+ }));
87
+ };
88
+ const useTenantData = (apiBaseUrl, tenantId) => {
89
+ const tenants = vue.ref({});
90
+ const loading = vue.ref(false);
91
+ const fetchTenants = async () => {
92
+ if (!apiBaseUrl || !tenantId) {
93
+ console.warn("获取租户需要提供有效的API基础URL和租户ID");
94
+ return;
95
+ }
96
+ loading.value = true;
97
+ try {
98
+ const result = await getTenants(apiBaseUrl, tenantId);
99
+ const tenantMap = {};
100
+ result.forEach((item) => {
101
+ if (item.id && item.name) {
102
+ tenantMap[item.id] = item.name;
103
+ }
104
+ });
105
+ tenants.value = tenantMap;
106
+ } catch (error) {
107
+ console.error("获取租户数据失败:", error);
108
+ } finally {
109
+ loading.value = false;
110
+ }
111
+ };
112
+ vue.onBeforeMount(() => {
113
+ fetchTenants();
114
+ });
115
+ return {
116
+ tenants,
117
+ loading,
118
+ fetchTenants
119
+ };
120
+ };
121
+ const _hoisted_1$3 = { class: "user-option" };
122
+ const _hoisted_2$2 = { class: "user-name" };
123
+ const _hoisted_3$2 = {
124
+ key: 0,
125
+ class: "tenant-name"
126
+ };
127
+ const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
128
+ ...{
129
+ name: "BkUserSelectorSingle"
130
+ },
131
+ __name: "single-selector",
132
+ props: {
133
+ modelValue: {},
134
+ placeholder: {},
135
+ apiBaseUrl: {},
136
+ tenantId: {},
137
+ tenants: {}
138
+ },
139
+ emits: ["update:modelValue", "change"],
140
+ setup(__props, { emit: __emit }) {
141
+ const props = __props;
142
+ const emit = __emit;
143
+ const { tenants } = useTenantData(props.apiBaseUrl || "", props.tenantId || "");
144
+ const options = vue.ref([]);
145
+ const loading = vue.ref(false);
146
+ const selectedUser = vue.ref(props.modelValue || "");
147
+ vue.onBeforeMount(async () => {
148
+ if (typeof props.modelValue === "string" && props.modelValue) {
149
+ try {
150
+ loading.value = true;
151
+ const result = await lookupUsers(props.apiBaseUrl || "", props.tenantId || "", [props.modelValue]);
152
+ options.value = formatUsers(result);
153
+ } catch (error) {
154
+ console.error("获取用户信息失败:", error);
155
+ } finally {
156
+ loading.value = false;
157
+ }
158
+ }
159
+ });
160
+ const fetchUsers = async (keyword = "") => {
161
+ if (!keyword || keyword.length < 2) return [];
162
+ loading.value = true;
163
+ try {
164
+ const result = await searchUsers(props.apiBaseUrl || "", props.tenantId || "", keyword);
165
+ const formattedResults = formatUsers(result);
166
+ options.value = formattedResults;
167
+ return formattedResults;
168
+ } catch (error) {
169
+ console.error("获取用户列表失败:", error);
170
+ return [];
171
+ } finally {
172
+ loading.value = false;
173
+ }
174
+ };
175
+ vue.watch(selectedUser, (newVal) => {
176
+ emit("update:modelValue", newVal);
177
+ const selectedUserInfo = options.value.find((user) => user.id === newVal);
178
+ emit("change", selectedUserInfo || null);
179
+ });
180
+ return (_ctx, _cache) => {
181
+ return vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Select), {
182
+ modelValue: selectedUser.value,
183
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedUser.value = $event),
184
+ placeholder: _ctx.placeholder,
185
+ "input-search": true,
186
+ "remote-method": fetchUsers,
187
+ filterable: ""
188
+ }, {
189
+ default: vue.withCtx(() => [
190
+ (vue.openBlock(true), vue.createElementBlock(
191
+ vue.Fragment,
192
+ null,
193
+ vue.renderList(options.value, (item) => {
194
+ return vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Select).Option, {
195
+ key: item.id,
196
+ label: item.name,
197
+ value: item.id
198
+ }, {
199
+ default: vue.withCtx(() => [
200
+ vue.createElementVNode("div", _hoisted_1$3, [
201
+ vue.createElementVNode(
202
+ "span",
203
+ _hoisted_2$2,
204
+ vue.toDisplayString(item.name),
205
+ 1
206
+ /* TEXT */
207
+ ),
208
+ item.tenantId !== props.tenantId && item.tenantId && vue.unref(tenants)[item.tenantId] ? (vue.openBlock(), vue.createElementBlock(
209
+ "span",
210
+ _hoisted_3$2,
211
+ "@" + vue.toDisplayString(vue.unref(tenants)[item.tenantId]),
212
+ 1
213
+ /* TEXT */
214
+ )) : vue.createCommentVNode("v-if", true)
215
+ ])
216
+ ]),
217
+ _: 2
218
+ /* DYNAMIC */
219
+ }, 1032, ["label", "value"]);
220
+ }),
221
+ 128
222
+ /* KEYED_FRAGMENT */
223
+ ))
224
+ ]),
225
+ _: 1
226
+ /* STABLE */
227
+ }, 8, ["modelValue", "placeholder"]);
228
+ };
229
+ }
230
+ });
231
+ const _export_sfc = (sfc, props) => {
232
+ const target = sfc.__vccOpts || sfc;
233
+ for (const [key, val] of props) {
234
+ target[key] = val;
235
+ }
236
+ return target;
237
+ };
238
+ const SingleSelector = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-0ae61279"]]);
8
239
  /**!
9
240
  * Sortable 1.15.6
10
241
  * @author RubaXa <trash@rubaxa.org>
@@ -2162,716 +2393,711 @@
2162
2393
  });
2163
2394
  Sortable.mount(new AutoScrollPlugin());
2164
2395
  Sortable.mount(Remove, Revert);
2165
- const _sfc_main$1 = {
2166
- __name: "single",
2167
- props: {
2168
- modelValue: {
2169
- type: String,
2170
- default: ""
2171
- },
2172
- apiBaseUrl: {
2173
- type: String,
2174
- default: ""
2175
- },
2176
- tenantId: {
2177
- type: String,
2178
- default: ""
2396
+ const debounce = (fn, delay) => {
2397
+ let timer = null;
2398
+ return function(...args) {
2399
+ if (timer) {
2400
+ clearTimeout(timer);
2401
+ }
2402
+ timer = window.setTimeout(() => {
2403
+ fn(...args);
2404
+ timer = null;
2405
+ }, delay);
2406
+ };
2407
+ };
2408
+ const calculateVisibleTags = (container, items, containerWidth) => {
2409
+ if (!container || !items.length) return 0;
2410
+ let totalWidth = 0;
2411
+ let visibleCount = 0;
2412
+ for (let i = 0; i < items.length; i++) {
2413
+ const item = items[i];
2414
+ if (!item) continue;
2415
+ const style = window.getComputedStyle(item);
2416
+ const width = item.offsetWidth;
2417
+ const marginLeft = parseInt(style.marginLeft, 10) || 0;
2418
+ const marginRight = parseInt(style.marginRight, 10) || 0;
2419
+ totalWidth += width + marginLeft + marginRight;
2420
+ if (totalWidth > containerWidth) {
2421
+ break;
2422
+ }
2423
+ visibleCount++;
2424
+ }
2425
+ return Math.max(1, visibleCount);
2426
+ };
2427
+ const useUserSearch = (apiBaseUrl, tenantId) => {
2428
+ const searchResults = vue.ref([]);
2429
+ const loading = vue.ref(false);
2430
+ const searchQuery = vue.ref("");
2431
+ const performSearch = async (keyword) => {
2432
+ if (!keyword || keyword.length < 2) {
2433
+ searchResults.value = [];
2434
+ return;
2435
+ }
2436
+ if (!apiBaseUrl || !tenantId) {
2437
+ console.warn("执行用户搜索需要提供有效的API基础URL和租户ID");
2438
+ return;
2439
+ }
2440
+ loading.value = true;
2441
+ try {
2442
+ const results = await searchUsers(apiBaseUrl, tenantId, keyword);
2443
+ searchResults.value = formatUsers(results);
2444
+ } catch (error) {
2445
+ console.error("用户搜索失败:", error);
2446
+ searchResults.value = [];
2447
+ } finally {
2448
+ loading.value = false;
2179
2449
  }
2450
+ };
2451
+ const debouncedSearch = debounce(performSearch, 300);
2452
+ const handleSearchInput = (value) => {
2453
+ searchQuery.value = value;
2454
+ debouncedSearch(value);
2455
+ };
2456
+ const clearSearch = () => {
2457
+ searchQuery.value = "";
2458
+ searchResults.value = [];
2459
+ };
2460
+ return {
2461
+ searchResults,
2462
+ loading,
2463
+ searchQuery,
2464
+ performSearch,
2465
+ handleSearchInput,
2466
+ clearSearch
2467
+ };
2468
+ };
2469
+ const _hoisted_1$2 = { class: "tag-content" };
2470
+ const _hoisted_2$1 = { class: "user-name" };
2471
+ const _hoisted_3$1 = {
2472
+ key: 0,
2473
+ class: "tenant-name"
2474
+ };
2475
+ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
2476
+ ...{
2477
+ name: "UserTag"
2180
2478
  },
2181
- emits: ["update:modelValue", "change"],
2479
+ __name: "user-tag",
2480
+ props: {
2481
+ user: {},
2482
+ tenants: {},
2483
+ currentTenantId: {},
2484
+ draggable: { type: Boolean },
2485
+ active: { type: Boolean },
2486
+ showTenant: { type: Boolean }
2487
+ },
2488
+ emits: ["click", "close"],
2182
2489
  setup(__props, { emit: __emit }) {
2183
- const props = __props;
2184
2490
  const emit = __emit;
2185
- const options = vue.ref([]);
2186
- const loading = vue.ref(false);
2187
- const selectedUser = vue.ref(props.modelValue);
2188
- vue.onBeforeMount(async () => {
2189
- if (props.modelValue) {
2190
- const url = `${props.apiBaseUrl}/api/v3/open-web/tenant/users/-/lookup/?lookups=${props.modelValue}&lookup_fields=bk_username`;
2191
- const response = await fetch(url, {
2192
- method: "GET",
2193
- headers: {
2194
- ...apiConfig.headers
2195
- },
2196
- credentials: "include"
2197
- // 包含cookie
2198
- });
2199
- const data = await response.json();
2200
- console.log("data", data);
2201
- options.value = data.data.map((item) => ({
2202
- id: item.bk_username,
2203
- name: item.display_name
2204
- }));
2205
- }
2206
- });
2207
- const apiConfig = {
2208
- baseUrl: `${props.apiBaseUrl}/api/v3/open-web/tenant/users/-/search/`,
2209
- headers: {
2210
- "x-bk-tenant-id": props.tenantId
2211
- }
2491
+ const handleClick = () => {
2492
+ emit("click");
2212
2493
  };
2213
- const fetchUsers = async (keyword = "") => {
2214
- var _a;
2215
- if (!keyword || keyword.length < 2) return [];
2216
- loading.value = true;
2217
- try {
2218
- const url = `${apiConfig.baseUrl}?keyword=${encodeURIComponent(keyword)}`;
2219
- const response = await fetch(url, {
2220
- method: "GET",
2221
- headers: {
2222
- ...apiConfig.headers
2223
- },
2224
- credentials: "include"
2225
- // 包含cookie
2226
- });
2227
- const data = await response.json();
2228
- console.log("data", data);
2229
- const result = ((_a = data.data) == null ? void 0 : _a.filter((item) => {
2230
- var _a2;
2231
- return !((_a2 = selectedUser.value) == null ? void 0 : _a2.includes(item.bk_username));
2232
- }).map((item) => ({
2233
- id: item.bk_username,
2234
- name: item.display_name
2235
- }))) || [];
2236
- options.value = result;
2237
- return result;
2238
- } catch (error) {
2239
- console.error("获取用户列表失败:", error);
2240
- return [];
2241
- } finally {
2242
- loading.value = false;
2243
- }
2494
+ const handleClose = () => {
2495
+ emit("close");
2244
2496
  };
2245
- vue.watch(selectedUser, (newVal) => {
2246
- console.log("newVal", newVal);
2247
- emit("update:modelValue", newVal);
2248
- });
2249
2497
  return (_ctx, _cache) => {
2250
- return vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Select), {
2251
- filterable: "",
2252
- "input-search": true,
2253
- "remote-method": fetchUsers,
2254
- modelValue: selectedUser.value,
2255
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedUser.value = $event)
2498
+ return vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Tag), {
2499
+ class: vue.normalizeClass(["user-tag", { draggable: _ctx.draggable, active: _ctx.active }]),
2500
+ closable: "",
2501
+ onClick: vue.withModifiers(handleClick, ["stop"]),
2502
+ onClose: handleClose
2256
2503
  }, {
2257
2504
  default: vue.withCtx(() => [
2258
- (vue.openBlock(true), vue.createElementBlock(
2259
- vue.Fragment,
2260
- null,
2261
- vue.renderList(options.value, (item) => {
2262
- return vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Select).Option, {
2263
- key: item.id,
2264
- value: item.id,
2265
- label: item.name
2266
- }, null, 8, ["value", "label"]);
2267
- }),
2268
- 128
2269
- /* KEYED_FRAGMENT */
2270
- ))
2505
+ vue.createElementVNode("div", _hoisted_1$2, [
2506
+ vue.createElementVNode(
2507
+ "span",
2508
+ _hoisted_2$1,
2509
+ vue.toDisplayString(_ctx.user.name),
2510
+ 1
2511
+ /* TEXT */
2512
+ ),
2513
+ _ctx.showTenant && _ctx.user.tenantId && _ctx.tenants[_ctx.user.tenantId] ? (vue.openBlock(), vue.createElementBlock(
2514
+ "span",
2515
+ _hoisted_3$1,
2516
+ " @" + vue.toDisplayString(_ctx.tenants[_ctx.user.tenantId]),
2517
+ 1
2518
+ /* TEXT */
2519
+ )) : vue.createCommentVNode("v-if", true)
2520
+ ])
2271
2521
  ]),
2272
2522
  _: 1
2273
2523
  /* STABLE */
2274
- }, 8, ["modelValue"]);
2524
+ }, 8, ["class"]);
2275
2525
  };
2276
2526
  }
2527
+ });
2528
+ const UserTag = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-cf26d9e2"]]);
2529
+ const _hoisted_1$1 = ["onClick"];
2530
+ const _hoisted_2 = ["placeholder"];
2531
+ const _hoisted_3 = ["placeholder"];
2532
+ const _hoisted_4 = {
2533
+ key: 0,
2534
+ class: "no-data"
2277
2535
  };
2278
- const _export_sfc = (sfc, props) => {
2279
- const target = sfc.__vccOpts || sfc;
2280
- for (const [key, val] of props) {
2281
- target[key] = val;
2282
- }
2283
- return target;
2284
- };
2285
- const _withScopeId = (n) => (vue.pushScopeId("data-v-5e8a952d"), n = n(), vue.popScopeId(), n);
2286
- const _hoisted_1 = { class: "popover-content" };
2287
- const _hoisted_2 = { key: 0 };
2288
- const _hoisted_3 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode(
2289
- "div",
2290
- { class: "no-data" },
2291
- [
2292
- /* @__PURE__ */ vue.createElementVNode("span", null, "暂无数据")
2293
- ],
2294
- -1
2295
- /* HOISTED */
2296
- ));
2297
- const _hoisted_4 = [
2298
- _hoisted_3
2299
- ];
2300
2536
  const _hoisted_5 = ["onMousedown"];
2301
- const _hoisted_6 = ["src"];
2537
+ const _hoisted_6 = { class: "user-name" };
2302
2538
  const _hoisted_7 = {
2303
- key: 1,
2304
- class: "user-avatar-text"
2539
+ key: 0,
2540
+ class: "tenant-name"
2305
2541
  };
2306
- const _hoisted_8 = { class: "user-name" };
2307
- const _hoisted_9 = {
2308
- ref: "sortableContainer",
2309
- class: "tag-group"
2310
- };
2311
- const _hoisted_10 = ["onClick"];
2312
- const _hoisted_11 = { class: "tag-content" };
2313
- const _hoisted_12 = { class: "user-name" };
2314
- const _hoisted_13 = ["placeholder"];
2315
- const _hoisted_14 = ["placeholder"];
2316
- const _hoisted_15 = { class: "tag-content" };
2317
- const _hoisted_16 = { class: "user-name" };
2318
- const _hoisted_17 = ["placeholder"];
2319
- const _sfc_main = {
2320
- __name: "index",
2542
+ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
2543
+ ...{
2544
+ name: "BkUserSelectorMultiple"
2545
+ },
2546
+ __name: "multiple-selector",
2321
2547
  props: {
2322
- // 文本标签
2323
- label: {
2324
- type: String,
2325
- default: "人员选择"
2326
- },
2327
- // 是否必填
2328
- required: {
2329
- type: Boolean,
2330
- default: false
2548
+ /**
2549
+ * 绑定值
2550
+ */
2551
+ modelValue: {
2552
+ type: Array,
2553
+ default: () => []
2331
2554
  },
2332
- // 占位文字
2555
+ /**
2556
+ * 占位文本
2557
+ */
2333
2558
  placeholder: {
2334
2559
  type: String,
2335
2560
  default: "请输入人员名称搜索"
2336
2561
  },
2337
- // 默认选中的用户(单选时为字符串,多选时为数组)
2338
- modelValue: {
2339
- type: [String, Array],
2340
- default: ""
2341
- },
2342
- // 是否支持拖拽排序
2562
+ /**
2563
+ * 是否可拖拽
2564
+ */
2343
2565
  draggable: {
2344
2566
  type: Boolean,
2345
2567
  default: false
2346
2568
  },
2347
- // 是否多选
2348
- multiple: {
2349
- type: Boolean,
2350
- default: false
2351
- },
2352
- // 接口基础URL
2569
+ /**
2570
+ * API 基础 URL
2571
+ */
2353
2572
  apiBaseUrl: {
2354
2573
  type: String,
2355
2574
  default: ""
2356
2575
  },
2357
- // 租户ID
2576
+ /**
2577
+ * 租户 ID
2578
+ */
2358
2579
  tenantId: {
2359
2580
  type: String,
2360
2581
  default: ""
2582
+ },
2583
+ /**
2584
+ * 已选用户
2585
+ */
2586
+ selectedUsers: {
2587
+ type: Array,
2588
+ default: () => []
2361
2589
  }
2362
2590
  },
2363
- emits: ["update:modelValue", "change"],
2591
+ emits: ["update:selectedUsers", "add-user", "remove-user"],
2364
2592
  setup(__props, { emit: __emit }) {
2365
- const vClickoutside = bkuiVue.clickoutside;
2366
- const vLoading = bkuiVue.Loading;
2367
2593
  const props = __props;
2368
2594
  const emit = __emit;
2369
- const selectedUsers = vue.ref(props.modelValue || []);
2370
- const searchQuery = vue.ref("");
2371
- const loading = vue.ref(false);
2372
- const showDropdown = vue.ref(false);
2373
- const searchInput = vue.ref(null);
2595
+ const { tenants } = useTenantData(props.apiBaseUrl, props.tenantId);
2596
+ const {
2597
+ searchResults,
2598
+ loading: searchLoading,
2599
+ searchQuery,
2600
+ handleSearchInput
2601
+ } = useUserSearch(props.apiBaseUrl, props.tenantId);
2374
2602
  const containerRef = vue.ref(null);
2375
- const tagInlineContainerRef = vue.ref(null);
2603
+ const tagsContainerRef = vue.ref(null);
2604
+ const sortableContainerRef = vue.ref(null);
2605
+ const collapsedContainerRef = vue.ref(null);
2606
+ const inlineInputRef = vue.ref(null);
2607
+ const lastInputRef = vue.ref(null);
2608
+ const collapsedInputRef = vue.ref(null);
2376
2609
  const isFocused = vue.ref(false);
2377
- const visibleUsers = vue.ref([]);
2378
- const hiddenCount = vue.ref(0);
2379
- const userList = vue.ref([]);
2380
- let searchTimer = null;
2610
+ const showDropdown = vue.ref(false);
2381
2611
  const activeTagIndex = vue.ref(-1);
2382
- const measureEl = vue.ref(null);
2383
2612
  const sortableInstance = vue.ref(null);
2384
- const apiConfig = {
2385
- baseUrl: `${props.apiBaseUrl}/api/v3/open-web/tenant/users/-/search/`,
2386
- headers: {
2387
- "x-bk-tenant-id": props.tenantId
2388
- }
2613
+ const visibleUsers = vue.ref([]);
2614
+ const hiddenCount = vue.ref(0);
2615
+ const initSortable = () => {
2616
+ if (!props.draggable || !sortableContainerRef.value) return;
2617
+ if (sortableInstance.value) {
2618
+ sortableInstance.value.destroy();
2619
+ }
2620
+ sortableInstance.value = new Sortable(sortableContainerRef.value, {
2621
+ animation: 150,
2622
+ draggable: ".tag-wrapper",
2623
+ onEnd: (evt) => {
2624
+ const { oldIndex: oldIndex2, newIndex: newIndex2 } = evt;
2625
+ if (oldIndex2 === newIndex2 || oldIndex2 === void 0 || newIndex2 === void 0) return;
2626
+ const updatedUsers = [...props.selectedUsers];
2627
+ const [movedUser] = updatedUsers.splice(oldIndex2, 1);
2628
+ updatedUsers.splice(newIndex2, 0, movedUser);
2629
+ emit("update:selectedUsers", updatedUsers);
2630
+ activeTagIndex.value = newIndex2;
2631
+ }
2632
+ });
2389
2633
  };
2390
- const fetchUsers = async (keyword = "") => {
2391
- var _a;
2392
- if (!keyword) return [];
2393
- loading.value = true;
2394
- try {
2395
- const url = `${apiConfig.baseUrl}?keyword=${encodeURIComponent(keyword)}`;
2396
- const response = await fetch(url, {
2397
- method: "GET",
2398
- headers: {
2399
- ...apiConfig.headers
2400
- },
2401
- credentials: "include"
2402
- // 包含cookie
2403
- });
2404
- const data = await response.json();
2405
- const selectedIds = selectedUsers.value.map((user) => user.id);
2406
- return ((_a = data.data) == null ? void 0 : _a.filter((item) => !selectedIds.includes(item.bk_username)).map((item) => ({
2407
- id: item.bk_username,
2408
- name: item.login_name,
2409
- avatar: item.avatar_url || ""
2410
- }))) || [];
2411
- } catch (error) {
2412
- console.error("获取用户列表失败:", error);
2413
- return [];
2414
- } finally {
2415
- loading.value = false;
2634
+ const calculateVisibleUsers = () => {
2635
+ if (!collapsedContainerRef.value || !props.selectedUsers.length) {
2636
+ visibleUsers.value = [];
2637
+ hiddenCount.value = 0;
2638
+ return;
2416
2639
  }
2640
+ const containerWidth = collapsedContainerRef.value.offsetWidth;
2641
+ const tagElements = collapsedContainerRef.value.querySelectorAll(".user-tag");
2642
+ const visibleCount = calculateVisibleTags(
2643
+ collapsedContainerRef.value,
2644
+ tagElements,
2645
+ containerWidth - 100
2646
+ // 为输入框和更多标签预留空间
2647
+ );
2648
+ visibleUsers.value = props.selectedUsers.slice(0, visibleCount);
2649
+ hiddenCount.value = Math.max(0, props.selectedUsers.length - visibleCount);
2417
2650
  };
2418
- vue.watch(() => props.modelValue, (val) => {
2419
- selectedUsers.value = val || [];
2420
- });
2421
- vue.watch(() => selectedUsers.value, (val) => {
2422
- emit("update:modelValue", val);
2423
- });
2424
- const getAvatarText = (name) => name ? name.charAt(0) : "";
2425
- const updateInputWidth = () => {
2426
- if (!searchInput.value || !measureEl.value) return;
2427
- measureEl.value.textContent = searchQuery.value || searchInput.value.placeholder || "";
2428
- const width = Math.max(20, measureEl.value.offsetWidth + 10);
2429
- searchInput.value.style.width = `${width}px`;
2651
+ const handleFocus = () => {
2652
+ isFocused.value = true;
2653
+ showDropdown.value = false;
2654
+ activeTagIndex.value = -1;
2655
+ vue.nextTick(() => {
2656
+ if (lastInputRef.value) {
2657
+ lastInputRef.value.focus();
2658
+ }
2659
+ });
2430
2660
  };
2431
- const handleInput = () => {
2432
- if (searchTimer) {
2433
- clearTimeout(searchTimer);
2434
- }
2435
- loading.value = true;
2436
- showDropdown.value = true;
2437
- searchTimer = setTimeout(async () => {
2438
- if (searchQuery.value.length >= 2) {
2439
- userList.value = await fetchUsers(searchQuery.value);
2440
- } else {
2441
- userList.value = [];
2661
+ const handleClickOutside = () => {
2662
+ isFocused.value = false;
2663
+ showDropdown.value = false;
2664
+ activeTagIndex.value = -1;
2665
+ searchQuery.value = "";
2666
+ vue.nextTick(() => {
2667
+ calculateVisibleUsers();
2668
+ });
2669
+ };
2670
+ const handleContainerClick = () => {
2671
+ activeTagIndex.value = -1;
2672
+ vue.nextTick(() => {
2673
+ if (lastInputRef.value) {
2674
+ lastInputRef.value.focus();
2442
2675
  }
2443
- loading.value = false;
2444
- }, 300);
2445
- updateInputWidth();
2676
+ });
2446
2677
  };
2447
2678
  const handleTagClick = (index2) => {
2448
2679
  activeTagIndex.value = index2;
2449
- setTimeout(() => {
2450
- var _a;
2451
- (_a = searchInput.value) == null ? void 0 : _a.focus();
2452
- }, 0);
2680
+ vue.nextTick(() => {
2681
+ if (activeTagIndex.value === props.selectedUsers.length - 1) {
2682
+ if (lastInputRef.value) {
2683
+ lastInputRef.value.focus();
2684
+ }
2685
+ } else if (inlineInputRef.value) {
2686
+ inlineInputRef.value.focus();
2687
+ }
2688
+ });
2453
2689
  };
2454
- const handleFocus = () => {
2690
+ const handleInputFocus = () => {
2455
2691
  if (!isFocused.value) {
2456
2692
  isFocused.value = true;
2457
- activeTagIndex.value = selectedUsers.value.length - 1;
2458
2693
  }
2459
- showDropdown.value = true;
2460
- setTimeout(() => {
2461
- var _a;
2462
- (_a = searchInput.value) == null ? void 0 : _a.focus();
2463
- }, 0);
2694
+ if (searchQuery.value.length >= 2) {
2695
+ showDropdown.value = true;
2696
+ }
2464
2697
  };
2465
- const addUser = (user) => {
2466
- if (!selectedUsers.value.some((item) => item.id === user.id)) {
2698
+ const handleInput = () => {
2699
+ handleSearchInput(searchQuery.value);
2700
+ showDropdown.value = searchQuery.value.length >= 2;
2701
+ };
2702
+ const handlePaste = (event) => {
2703
+ var _a;
2704
+ const pastedText = ((_a = event.clipboardData) == null ? void 0 : _a.getData("text")) || "";
2705
+ if (pastedText.trim()) {
2706
+ searchQuery.value = pastedText.trim();
2707
+ handleInput();
2708
+ }
2709
+ };
2710
+ const handleKeyDown = (event) => {
2711
+ if (event.key === "Backspace" && !searchQuery.value && props.selectedUsers.length > 0) {
2467
2712
  if (activeTagIndex.value >= 0) {
2468
- const updatedUsers = [...selectedUsers.value];
2469
- updatedUsers.splice(activeTagIndex.value + 1, 0, user);
2470
- selectedUsers.value = updatedUsers;
2471
- activeTagIndex.value += 1;
2713
+ const userToRemove = props.selectedUsers[activeTagIndex.value];
2714
+ removeUser(userToRemove);
2715
+ if (activeTagIndex.value > 0) {
2716
+ activeTagIndex.value = activeTagIndex.value - 1;
2717
+ } else {
2718
+ activeTagIndex.value = -1;
2719
+ }
2472
2720
  } else {
2473
- selectedUsers.value = [...selectedUsers.value, user];
2474
- activeTagIndex.value = selectedUsers.value.length - 1;
2721
+ const lastUser = props.selectedUsers[props.selectedUsers.length - 1];
2722
+ removeUser(lastUser);
2475
2723
  }
2476
- emit("change", selectedUsers.value);
2724
+ }
2725
+ };
2726
+ const addUser = (user) => {
2727
+ if (!user || !user.id) return;
2728
+ if (!props.selectedUsers.some((item) => item.id === user.id)) {
2729
+ const updatedUsers = [...props.selectedUsers, user];
2730
+ emit("update:selectedUsers", updatedUsers);
2731
+ emit("add-user", user);
2477
2732
  }
2478
2733
  searchQuery.value = "";
2479
- userList.value = [];
2480
- setTimeout(() => {
2481
- var _a;
2482
- (_a = searchInput.value) == null ? void 0 : _a.focus();
2483
- }, 0);
2734
+ showDropdown.value = false;
2484
2735
  };
2485
2736
  const removeUser = (user) => {
2486
- selectedUsers.value = selectedUsers.value.filter((item) => item.id !== user.id);
2487
- emit("change", selectedUsers.value);
2488
- };
2489
- const calculateVisibleTags = async () => {
2490
- if (!props.multiple) {
2491
- return;
2492
- }
2493
- await vue.nextTick();
2494
- if (selectedUsers.value.length === 0) {
2495
- visibleUsers.value = [];
2496
- hiddenCount.value = 0;
2497
- return;
2737
+ if (!user || !user.id) return;
2738
+ const updatedUsers = props.selectedUsers.filter((item) => item.id !== user.id);
2739
+ emit("update:selectedUsers", updatedUsers);
2740
+ emit("remove-user", user);
2741
+ if (activeTagIndex.value >= updatedUsers.length) {
2742
+ activeTagIndex.value = updatedUsers.length - 1;
2498
2743
  }
2499
- if (isFocused.value) {
2500
- visibleUsers.value = [...selectedUsers.value];
2501
- hiddenCount.value = 0;
2502
- return;
2744
+ if (!isFocused.value) {
2745
+ vue.nextTick(() => {
2746
+ calculateVisibleUsers();
2747
+ });
2503
2748
  }
2504
- const container = tagInlineContainerRef.value;
2505
- const originalStyle = {
2506
- flexWrap: container.style.flexWrap,
2507
- height: container.style.height,
2508
- whiteSpace: container.style.whiteSpace,
2509
- overflow: container.style.overflow
2510
- };
2511
- container.style.flexWrap = "wrap";
2512
- container.style.height = "auto";
2513
- container.style.whiteSpace = "normal";
2514
- container.style.overflow = "visible";
2515
- const tagElements = container.querySelectorAll(".tag-item");
2516
- if (tagElements.length === 0) {
2517
- Object.assign(container.style, originalStyle);
2518
- visibleUsers.value = [];
2519
- hiddenCount.value = 0;
2520
- return;
2749
+ };
2750
+ vue.watch(() => props.selectedUsers, () => {
2751
+ visibleUsers.value = [...props.selectedUsers];
2752
+ if (!isFocused.value) {
2753
+ vue.nextTick(() => {
2754
+ calculateVisibleUsers();
2755
+ });
2521
2756
  }
2522
- const firstRowTop = tagElements[0].offsetTop;
2523
- const visibleIndexes = [];
2524
- for (let i = 0; i < tagElements.length; i++) {
2525
- if (tagElements[i].offsetTop === firstRowTop) {
2526
- visibleIndexes.push(i);
2527
- } else {
2528
- break;
2529
- }
2757
+ }, { deep: true });
2758
+ vue.watch(isFocused, (newVal) => {
2759
+ if (newVal) {
2760
+ vue.nextTick(() => {
2761
+ initSortable();
2762
+ });
2530
2763
  }
2531
- let visibleCount = visibleIndexes.length;
2532
- if (visibleCount < selectedUsers.value.length) {
2533
- const moreTagElement = document.createElement("span");
2534
- moreTagElement.className = "tag-item tag-more";
2535
- moreTagElement.textContent = `+${selectedUsers.value.length - visibleCount}`;
2536
- container.appendChild(moreTagElement);
2537
- if (moreTagElement.offsetTop > firstRowTop) {
2538
- visibleCount = Math.max(0, visibleCount - 1);
2539
- }
2540
- container.removeChild(moreTagElement);
2764
+ });
2765
+ const handleResize = () => {
2766
+ if (!isFocused.value) {
2767
+ calculateVisibleUsers();
2541
2768
  }
2542
- Object.assign(container.style, originalStyle);
2543
- visibleUsers.value = selectedUsers.value.slice(0, visibleCount);
2544
- hiddenCount.value = selectedUsers.value.length - visibleCount;
2545
2769
  };
2546
- vue.watch(() => selectedUsers.value.length, () => {
2547
- calculateVisibleTags();
2548
- });
2549
2770
  vue.onMounted(() => {
2550
- window.addEventListener("resize", calculateVisibleTags);
2551
- calculateVisibleTags();
2552
- updateInputWidth();
2553
2771
  initSortable();
2772
+ calculateVisibleUsers();
2773
+ window.addEventListener("resize", handleResize);
2774
+ vue.nextTick(() => {
2775
+ calculateVisibleUsers();
2776
+ });
2554
2777
  });
2555
- const handleBlur = () => {
2556
- isFocused.value = false;
2557
- activeTagIndex.value = -1;
2558
- showDropdown.value = false;
2559
- searchQuery.value = "";
2560
- calculateVisibleTags();
2778
+ return (_ctx, _cache) => {
2779
+ return vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", {
2780
+ ref_key: "containerRef",
2781
+ ref: containerRef,
2782
+ class: "multiple-selector"
2783
+ }, [
2784
+ vue.createCommentVNode(" 聚焦状态 - 可编辑模式 "),
2785
+ isFocused.value ? (vue.openBlock(), vue.createElementBlock(
2786
+ "div",
2787
+ {
2788
+ key: 0,
2789
+ ref_key: "tagsContainerRef",
2790
+ ref: tagsContainerRef,
2791
+ class: "tags-container focused",
2792
+ onClick: vue.withModifiers(handleContainerClick, ["stop"])
2793
+ },
2794
+ [
2795
+ vue.createCommentVNode(" 用户标签列表 "),
2796
+ vue.createElementVNode(
2797
+ "div",
2798
+ {
2799
+ ref_key: "sortableContainerRef",
2800
+ ref: sortableContainerRef,
2801
+ class: "tag-list"
2802
+ },
2803
+ [
2804
+ (vue.openBlock(true), vue.createElementBlock(
2805
+ vue.Fragment,
2806
+ null,
2807
+ vue.renderList(__props.selectedUsers, (user, index2) => {
2808
+ return vue.openBlock(), vue.createElementBlock("div", {
2809
+ key: user.id,
2810
+ class: "tag-wrapper",
2811
+ onClick: vue.withModifiers(($event) => handleTagClick(index2), ["stop"])
2812
+ }, [
2813
+ vue.createVNode(UserTag, {
2814
+ user,
2815
+ tenants: vue.unref(tenants),
2816
+ "current-tenant-id": __props.tenantId,
2817
+ draggable: __props.draggable,
2818
+ active: index2 === activeTagIndex.value,
2819
+ "show-tenant": true,
2820
+ onClick: ($event) => handleTagClick(index2),
2821
+ onClose: ($event) => removeUser(user)
2822
+ }, null, 8, ["user", "tenants", "current-tenant-id", "draggable", "active", "onClick", "onClose"]),
2823
+ vue.createCommentVNode(" 在当前激活标签后插入输入框 "),
2824
+ index2 === activeTagIndex.value && activeTagIndex.value !== __props.selectedUsers.length - 1 ? vue.withDirectives((vue.openBlock(), vue.createElementBlock(
2825
+ "input",
2826
+ {
2827
+ key: 0,
2828
+ ref_for: true,
2829
+ ref_key: "inlineInputRef",
2830
+ ref: inlineInputRef,
2831
+ class: "search-input inline",
2832
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(searchQuery) ? searchQuery.value = $event : null),
2833
+ onFocus: handleInputFocus,
2834
+ onInput: handleInput,
2835
+ onKeydown: handleKeyDown,
2836
+ onPaste: handlePaste
2837
+ },
2838
+ null,
2839
+ 544
2840
+ /* NEED_HYDRATION, NEED_PATCH */
2841
+ )), [
2842
+ [vue.vModelText, vue.unref(searchQuery)]
2843
+ ]) : vue.createCommentVNode("v-if", true)
2844
+ ], 8, _hoisted_1$1);
2845
+ }),
2846
+ 128
2847
+ /* KEYED_FRAGMENT */
2848
+ )),
2849
+ vue.createCommentVNode(" 最后一个输入框 "),
2850
+ activeTagIndex.value === -1 || activeTagIndex.value === __props.selectedUsers.length - 1 ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
2851
+ key: 0,
2852
+ ref_key: "lastInputRef",
2853
+ ref: lastInputRef,
2854
+ class: "search-input last",
2855
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => vue.isRef(searchQuery) ? searchQuery.value = $event : null),
2856
+ placeholder: !__props.selectedUsers.length ? __props.placeholder : "",
2857
+ onFocus: handleInputFocus,
2858
+ onInput: handleInput,
2859
+ onKeydown: handleKeyDown,
2860
+ onPaste: handlePaste
2861
+ }, null, 40, _hoisted_2)), [
2862
+ [vue.vModelText, vue.unref(searchQuery)]
2863
+ ]) : vue.createCommentVNode("v-if", true)
2864
+ ],
2865
+ 512
2866
+ /* NEED_PATCH */
2867
+ )
2868
+ ],
2869
+ 512
2870
+ /* NEED_PATCH */
2871
+ )) : (vue.openBlock(), vue.createElementBlock(
2872
+ vue.Fragment,
2873
+ { key: 1 },
2874
+ [
2875
+ vue.createCommentVNode(" 未聚焦状态 - 只读展示模式 "),
2876
+ vue.createElementVNode(
2877
+ "div",
2878
+ {
2879
+ ref_key: "collapsedContainerRef",
2880
+ ref: collapsedContainerRef,
2881
+ class: "tags-container collapsed",
2882
+ onClick: vue.withModifiers(handleFocus, ["stop"])
2883
+ },
2884
+ [
2885
+ (vue.openBlock(true), vue.createElementBlock(
2886
+ vue.Fragment,
2887
+ null,
2888
+ vue.renderList(visibleUsers.value, (user) => {
2889
+ return vue.openBlock(), vue.createBlock(UserTag, {
2890
+ key: user.id,
2891
+ user,
2892
+ tenants: vue.unref(tenants),
2893
+ "current-tenant-id": __props.tenantId,
2894
+ "show-tenant": true,
2895
+ onClick: handleFocus,
2896
+ onClose: ($event) => removeUser(user)
2897
+ }, null, 8, ["user", "tenants", "current-tenant-id", "onClose"]);
2898
+ }),
2899
+ 128
2900
+ /* KEYED_FRAGMENT */
2901
+ )),
2902
+ vue.createCommentVNode(" 显示折叠标签数量 "),
2903
+ hiddenCount.value > 0 ? (vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Tag), {
2904
+ key: 0,
2905
+ class: "tag-more",
2906
+ onClick: vue.withModifiers(handleFocus, ["stop"])
2907
+ }, {
2908
+ default: vue.withCtx(() => [
2909
+ vue.createTextVNode(
2910
+ " +" + vue.toDisplayString(hiddenCount.value),
2911
+ 1
2912
+ /* TEXT */
2913
+ )
2914
+ ]),
2915
+ _: 1
2916
+ /* STABLE */
2917
+ })) : vue.createCommentVNode("v-if", true),
2918
+ vue.createCommentVNode(" 搜索输入框 "),
2919
+ vue.withDirectives(vue.createElementVNode("input", {
2920
+ ref_key: "collapsedInputRef",
2921
+ ref: collapsedInputRef,
2922
+ class: "search-input collapsed",
2923
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => vue.isRef(searchQuery) ? searchQuery.value = $event : null),
2924
+ placeholder: !__props.selectedUsers.length ? __props.placeholder : "",
2925
+ onFocus: handleFocus
2926
+ }, null, 40, _hoisted_3), [
2927
+ [vue.vModelText, vue.unref(searchQuery)]
2928
+ ])
2929
+ ],
2930
+ 512
2931
+ /* NEED_PATCH */
2932
+ )
2933
+ ],
2934
+ 2112
2935
+ /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
2936
+ )),
2937
+ vue.createCommentVNode(" 下拉选项列表 "),
2938
+ vue.createVNode(vue.unref(bkuiVue.Popover), {
2939
+ "ext-cls": "bk-user-selector-popover",
2940
+ arrow: false,
2941
+ disabled: !showDropdown.value,
2942
+ "is-show": showDropdown.value,
2943
+ width: containerRef.value ? containerRef.value.offsetWidth : "auto",
2944
+ boundary: "document.body",
2945
+ placement: "bottom-start",
2946
+ theme: "light",
2947
+ trigger: "manual"
2948
+ }, {
2949
+ content: vue.withCtx(() => [
2950
+ vue.createVNode(vue.unref(bkuiVue.Loading), {
2951
+ class: "dropdown-content",
2952
+ loading: vue.unref(searchLoading),
2953
+ size: "small",
2954
+ mode: "spin"
2955
+ }, {
2956
+ default: vue.withCtx(() => [
2957
+ vue.unref(searchResults).length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4, [
2958
+ vue.createElementVNode(
2959
+ "span",
2960
+ null,
2961
+ vue.toDisplayString(vue.unref(searchQuery).length > 1 ? "未找到匹配用户" : "请输入关键词搜索"),
2962
+ 1
2963
+ /* TEXT */
2964
+ )
2965
+ ])) : (vue.openBlock(true), vue.createElementBlock(
2966
+ vue.Fragment,
2967
+ { key: 1 },
2968
+ vue.renderList(vue.unref(searchResults), (user) => {
2969
+ return vue.openBlock(), vue.createElementBlock("div", {
2970
+ class: "user-option",
2971
+ key: user.id,
2972
+ onMousedown: vue.withModifiers(($event) => addUser(user), ["prevent"])
2973
+ }, [
2974
+ vue.createElementVNode(
2975
+ "span",
2976
+ _hoisted_6,
2977
+ vue.toDisplayString(user.name),
2978
+ 1
2979
+ /* TEXT */
2980
+ ),
2981
+ user.tenantId !== __props.tenantId && user.tenantId && vue.unref(tenants)[user.tenantId] ? (vue.openBlock(), vue.createElementBlock(
2982
+ "span",
2983
+ _hoisted_7,
2984
+ "@" + vue.toDisplayString(vue.unref(tenants)[user.tenantId]),
2985
+ 1
2986
+ /* TEXT */
2987
+ )) : vue.createCommentVNode("v-if", true)
2988
+ ], 40, _hoisted_5);
2989
+ }),
2990
+ 128
2991
+ /* KEYED_FRAGMENT */
2992
+ ))
2993
+ ]),
2994
+ _: 1
2995
+ /* STABLE */
2996
+ }, 8, ["loading"])
2997
+ ]),
2998
+ _: 1
2999
+ /* STABLE */
3000
+ }, 8, ["disabled", "is-show", "width"])
3001
+ ])), [
3002
+ [vue.unref(bkuiVue.clickoutside), handleClickOutside]
3003
+ ]);
2561
3004
  };
2562
- const dragOptions = vue.computed(() => ({
2563
- animation: 150,
2564
- ghostClass: "ghost-tag",
2565
- chosenClass: "chosen-tag",
2566
- dragClass: "drag-tag",
2567
- handle: ".tag-item",
2568
- // 根据draggable属性决定是否启用排序
2569
- sort: props.draggable
2570
- }));
2571
- const initSortable = () => {
2572
- vue.nextTick(() => {
2573
- const sortableContainerEl = document.querySelector(".tag-group");
2574
- console.log(sortableContainerEl, "sortableContainerEl");
2575
- if (sortableContainerEl && props.draggable) {
2576
- if (sortableInstance.value) {
2577
- sortableInstance.value.destroy();
3005
+ }
3006
+ });
3007
+ const MultipleSelector = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-6a1779a9"]]);
3008
+ const _hoisted_1 = { class: "bk-user-selector" };
3009
+ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
3010
+ ...{
3011
+ name: "BkUserSelector"
3012
+ },
3013
+ __name: "user-selector",
3014
+ props: {
3015
+ label: { default: "人员选择" },
3016
+ required: { type: Boolean, default: false },
3017
+ placeholder: { default: "请输入人员名称搜索" },
3018
+ modelValue: { default: "" },
3019
+ draggable: { type: Boolean, default: false },
3020
+ multiple: { type: Boolean, default: false },
3021
+ apiBaseUrl: { default: "" },
3022
+ tenantId: { default: "" }
3023
+ },
3024
+ emits: ["update:modelValue", "change"],
3025
+ setup(__props, { emit: __emit }) {
3026
+ const props = __props;
3027
+ const emit = __emit;
3028
+ const { tenants } = useTenantData(props.apiBaseUrl, props.tenantId);
3029
+ const selectedUsers = vue.ref([]);
3030
+ const selectedUser = vue.ref(props.multiple ? "" : props.modelValue);
3031
+ const selectedUserIds = vue.computed(() => {
3032
+ return props.multiple ? selectedUsers.value.map((user) => user.id) : [];
3033
+ });
3034
+ const initSelectedUsers = async () => {
3035
+ if (props.multiple) {
3036
+ const ids = Array.isArray(props.modelValue) ? props.modelValue : [];
3037
+ if (ids.length > 0) {
3038
+ try {
3039
+ const result = await lookupUsers(props.apiBaseUrl, props.tenantId, ids);
3040
+ selectedUsers.value = formatUsers(result);
3041
+ } catch (error) {
3042
+ console.error("获取选中用户信息失败:", error);
2578
3043
  }
2579
- sortableInstance.value = Sortable.create(sortableContainerEl, {
2580
- ...dragOptions.value,
2581
- onEnd: (evt) => {
2582
- const newOrder = [...selectedUsers.value];
2583
- const { oldIndex: oldIndex2, newIndex: newIndex2 } = evt;
2584
- if (oldIndex2 !== newIndex2) {
2585
- const movedItem = newOrder.splice(oldIndex2, 1)[0];
2586
- newOrder.splice(newIndex2, 0, movedItem);
2587
- selectedUsers.value = newOrder;
2588
- handleDragChange();
2589
- }
2590
- }
2591
- });
2592
3044
  }
2593
- });
3045
+ } else {
3046
+ selectedUser.value = props.modelValue;
3047
+ }
2594
3048
  };
2595
- vue.watch([
2596
- () => selectedUsers.value,
2597
- () => props.draggable,
2598
- () => isFocused.value
2599
- ], () => {
2600
- initSortable();
2601
- }, { deep: true });
2602
- const handleDragChange = () => {
2603
- emit("change", selectedUsers.value);
3049
+ const handleUpdateUser = (user) => {
3050
+ emit("change", user);
2604
3051
  };
2605
- vue.watch(searchQuery, () => {
2606
- updateInputWidth();
2607
- });
2608
- const handleUpdateSelected = (user) => {
2609
- selectedUsers.value = [user];
3052
+ const handleUpdateSelectedUsers = (users) => {
3053
+ selectedUsers.value = users;
3054
+ emit("update:modelValue", users.map((user) => user.id));
3055
+ emit("change", users);
2610
3056
  };
3057
+ vue.watch(selectedUser, (newVal) => {
3058
+ if (!props.multiple) {
3059
+ emit("update:modelValue", newVal);
3060
+ }
3061
+ });
3062
+ vue.onBeforeMount(() => {
3063
+ initSelectedUsers();
3064
+ });
2611
3065
  return (_ctx, _cache) => {
2612
- return vue.withDirectives((vue.openBlock(), vue.createElementBlock("section", null, [
3066
+ return vue.openBlock(), vue.createElementBlock("section", _hoisted_1, [
2613
3067
  vue.createCommentVNode(" 单选模式 "),
2614
- !__props.multiple ? (vue.openBlock(), vue.createBlock(_sfc_main$1, {
3068
+ !_ctx.multiple ? (vue.openBlock(), vue.createBlock(SingleSelector, {
2615
3069
  key: 0,
2616
- modelValue: selectedUsers.value,
2617
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedUsers.value = $event),
2618
- placeholder: __props.placeholder,
2619
- "api-base-url": __props.apiBaseUrl,
2620
- "tenant-id": __props.tenantId,
2621
- "onUpdate:selected": handleUpdateSelected
2622
- }, null, 8, ["modelValue", "placeholder", "api-base-url", "tenant-id"])) : (vue.openBlock(), vue.createElementBlock(
3070
+ modelValue: selectedUser.value,
3071
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedUser.value = $event),
3072
+ "api-base-url": _ctx.apiBaseUrl,
3073
+ placeholder: _ctx.placeholder,
3074
+ "tenant-id": _ctx.tenantId,
3075
+ tenants: vue.unref(tenants),
3076
+ onChange: handleUpdateUser
3077
+ }, null, 8, ["modelValue", "api-base-url", "placeholder", "tenant-id", "tenants"])) : (vue.openBlock(), vue.createElementBlock(
2623
3078
  vue.Fragment,
2624
3079
  { key: 1 },
2625
3080
  [
2626
- vue.createCommentVNode(" 使用 popover 包裹内容 "),
2627
- vue.createVNode(vue.unref(bkuiVue.Popover), {
2628
- placement: "bottom-start",
2629
- theme: "light",
2630
- trigger: "manual",
2631
- arrow: false,
2632
- "is-show": showDropdown.value,
2633
- width: containerRef.value ? containerRef.value.offsetWidth : "auto",
2634
- disabled: !showDropdown.value
2635
- }, {
2636
- content: vue.withCtx(() => [
2637
- vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
2638
- userList.value.length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2, _hoisted_4)) : (vue.openBlock(true), vue.createElementBlock(
2639
- vue.Fragment,
2640
- { key: 1 },
2641
- vue.renderList(userList.value, (item) => {
2642
- return vue.openBlock(), vue.createElementBlock("div", {
2643
- key: item.id,
2644
- class: "user-option",
2645
- onMousedown: vue.withModifiers(($event) => addUser(item), ["prevent"])
2646
- }, [
2647
- item.avatar ? (vue.openBlock(), vue.createElementBlock("img", {
2648
- key: 0,
2649
- class: "user-avatar",
2650
- src: item.avatar,
2651
- alt: "用户头像"
2652
- }, null, 8, _hoisted_6)) : (vue.openBlock(), vue.createElementBlock(
2653
- "span",
2654
- _hoisted_7,
2655
- vue.toDisplayString(getAvatarText(item.name)),
2656
- 1
2657
- /* TEXT */
2658
- )),
2659
- vue.createElementVNode(
2660
- "span",
2661
- _hoisted_8,
2662
- vue.toDisplayString(item.name),
2663
- 1
2664
- /* TEXT */
2665
- )
2666
- ], 40, _hoisted_5);
2667
- }),
2668
- 128
2669
- /* KEYED_FRAGMENT */
2670
- ))
2671
- ])), [
2672
- [vue.unref(vLoading), { mode: "spin", size: "small", loading: loading.value }]
2673
- ])
2674
- ]),
2675
- default: vue.withCtx(() => [
2676
- vue.createElementVNode(
2677
- "div",
2678
- {
2679
- ref_key: "containerRef",
2680
- ref: containerRef,
2681
- class: vue.normalizeClass(["tag-input-container", { "is-focused": isFocused.value, "is-single": !__props.multiple }])
2682
- },
2683
- [
2684
- vue.createCommentVNode(" 多选模式 "),
2685
- vue.createCommentVNode(" 聚焦状态 - 使用单一draggable "),
2686
- isFocused.value ? (vue.openBlock(), vue.createElementBlock(
2687
- vue.Fragment,
2688
- { key: 0 },
2689
- [
2690
- vue.createCommentVNode(" 多选模式 "),
2691
- vue.createElementVNode(
2692
- "div",
2693
- _hoisted_9,
2694
- [
2695
- (vue.openBlock(true), vue.createElementBlock(
2696
- vue.Fragment,
2697
- null,
2698
- vue.renderList(selectedUsers.value, (element, index2) => {
2699
- return vue.openBlock(), vue.createElementBlock("div", {
2700
- key: element.id,
2701
- class: "tag-wrapper",
2702
- onClick: vue.withModifiers(($event) => handleTagClick(index2), ["stop"])
2703
- }, [
2704
- vue.createVNode(vue.unref(bkuiVue.Tag), {
2705
- class: vue.normalizeClass(["tag-item", { "draggable": __props.draggable, "active": index2 === activeTagIndex.value }]),
2706
- size: "small",
2707
- closable: "",
2708
- onClose: ($event) => removeUser(element),
2709
- onClick: vue.withModifiers(($event) => handleTagClick(index2), ["stop"])
2710
- }, {
2711
- default: vue.withCtx(() => [
2712
- vue.createElementVNode("div", _hoisted_11, [
2713
- vue.createElementVNode(
2714
- "span",
2715
- _hoisted_12,
2716
- vue.toDisplayString(element.name),
2717
- 1
2718
- /* TEXT */
2719
- )
2720
- ])
2721
- ]),
2722
- _: 2
2723
- /* DYNAMIC */
2724
- }, 1032, ["class", "onClose", "onClick"]),
2725
- vue.createCommentVNode(" 在当前激活的标签后插入输入框 "),
2726
- vue.createElementVNode(
2727
- "span",
2728
- {
2729
- ref_for: true,
2730
- ref_key: "measureEl",
2731
- ref: measureEl,
2732
- class: "measure-text",
2733
- "aria-hidden": "true"
2734
- },
2735
- null,
2736
- 512
2737
- /* NEED_PATCH */
2738
- ),
2739
- index2 === activeTagIndex.value && activeTagIndex.value !== selectedUsers.value.length - 1 ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
2740
- key: 0,
2741
- ref_for: true,
2742
- ref_key: "searchInput",
2743
- ref: searchInput,
2744
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => searchQuery.value = $event),
2745
- placeholder: selectedUsers.value.length ? "" : __props.placeholder,
2746
- class: "tag-input inline-input",
2747
- onInput: handleInput,
2748
- onFocus: handleFocus
2749
- }, null, 40, _hoisted_13)), [
2750
- [vue.vModelText, searchQuery.value]
2751
- ]) : vue.createCommentVNode("v-if", true)
2752
- ], 8, _hoisted_10);
2753
- }),
2754
- 128
2755
- /* KEYED_FRAGMENT */
2756
- ))
2757
- ],
2758
- 512
2759
- /* NEED_PATCH */
2760
- ),
2761
- vue.createCommentVNode(" 如果激活索引是最后一个或没有激活的标签,将输入框放在最后 "),
2762
- activeTagIndex.value === -1 || activeTagIndex.value === selectedUsers.value.length - 1 ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
2763
- key: 0,
2764
- ref_key: "searchInput",
2765
- ref: searchInput,
2766
- "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => searchQuery.value = $event),
2767
- placeholder: selectedUsers.value.length ? "" : __props.placeholder,
2768
- class: "tag-input single-input",
2769
- onInput: handleInput,
2770
- onFocus: handleFocus
2771
- }, null, 40, _hoisted_14)), [
2772
- [vue.vModelText, searchQuery.value]
2773
- ]) : vue.createCommentVNode("v-if", true)
2774
- ],
2775
- 64
2776
- /* STABLE_FRAGMENT */
2777
- )) : (vue.openBlock(), vue.createElementBlock(
2778
- vue.Fragment,
2779
- { key: 1 },
2780
- [
2781
- vue.createCommentVNode(" 失焦状态 "),
2782
- vue.createCommentVNode(" 多选模式 "),
2783
- vue.createElementVNode(
2784
- "div",
2785
- {
2786
- ref_key: "tagInlineContainerRef",
2787
- ref: tagInlineContainerRef,
2788
- class: "tag-inline-container",
2789
- onClick: vue.withModifiers(handleFocus, ["stop"])
2790
- },
2791
- [
2792
- (vue.openBlock(true), vue.createElementBlock(
2793
- vue.Fragment,
2794
- null,
2795
- vue.renderList(visibleUsers.value, (user) => {
2796
- return vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Tag), {
2797
- key: user.id,
2798
- class: "tag-item",
2799
- closable: "",
2800
- onClose: ($event) => removeUser(user),
2801
- onClick: vue.withModifiers(handleFocus, ["stop"])
2802
- }, {
2803
- default: vue.withCtx(() => [
2804
- vue.createElementVNode("div", _hoisted_15, [
2805
- vue.createElementVNode(
2806
- "span",
2807
- _hoisted_16,
2808
- vue.toDisplayString(user.name),
2809
- 1
2810
- /* TEXT */
2811
- )
2812
- ])
2813
- ]),
2814
- _: 2
2815
- /* DYNAMIC */
2816
- }, 1032, ["onClose"]);
2817
- }),
2818
- 128
2819
- /* KEYED_FRAGMENT */
2820
- )),
2821
- vue.createCommentVNode(" 显示折叠标签数量 "),
2822
- hiddenCount.value > 0 ? (vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Tag), {
2823
- key: 0,
2824
- class: "tag-item tag-more",
2825
- onClick: vue.withModifiers(handleFocus, ["stop"])
2826
- }, {
2827
- default: vue.withCtx(() => [
2828
- vue.createTextVNode(
2829
- " +" + vue.toDisplayString(hiddenCount.value),
2830
- 1
2831
- /* TEXT */
2832
- )
2833
- ]),
2834
- _: 1
2835
- /* STABLE */
2836
- })) : vue.createCommentVNode("v-if", true),
2837
- vue.createCommentVNode(" 修改这里的输入框样式 "),
2838
- vue.withDirectives(vue.createElementVNode("input", {
2839
- ref_key: "searchInput",
2840
- ref: searchInput,
2841
- "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => searchQuery.value = $event),
2842
- placeholder: selectedUsers.value.length ? "" : __props.placeholder,
2843
- class: vue.normalizeClass(["tag-input full-width", { "placeholder-style": !selectedUsers.value.length }]),
2844
- onFocus: handleFocus
2845
- }, null, 42, _hoisted_17), [
2846
- [vue.vModelText, searchQuery.value]
2847
- ])
2848
- ],
2849
- 512
2850
- /* NEED_PATCH */
2851
- )
2852
- ],
2853
- 64
2854
- /* STABLE_FRAGMENT */
2855
- ))
2856
- ],
2857
- 2
2858
- /* CLASS */
2859
- )
2860
- ]),
2861
- _: 1
2862
- /* STABLE */
2863
- }, 8, ["is-show", "width", "disabled"])
3081
+ vue.createCommentVNode(" 多选模式 "),
3082
+ vue.createVNode(MultipleSelector, {
3083
+ modelValue: selectedUserIds.value,
3084
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => selectedUserIds.value = $event),
3085
+ "api-base-url": _ctx.apiBaseUrl,
3086
+ placeholder: _ctx.placeholder,
3087
+ "tenant-id": _ctx.tenantId,
3088
+ draggable: _ctx.draggable,
3089
+ "selected-users": selectedUsers.value,
3090
+ "onUpdate:selectedUsers": handleUpdateSelectedUsers
3091
+ }, null, 8, ["modelValue", "api-base-url", "placeholder", "tenant-id", "draggable", "selected-users"])
2864
3092
  ],
2865
3093
  2112
2866
3094
  /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
2867
3095
  ))
2868
- ])), [
2869
- [vue.unref(vClickoutside), handleBlur]
2870
3096
  ]);
2871
3097
  };
2872
3098
  }
2873
- };
2874
- const BkUserSelector = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-5e8a952d"]]);
3099
+ });
3100
+ const BkUserSelector = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-144c2518"]]);
2875
3101
  exports2.BkUserSelector = BkUserSelector;
2876
3102
  exports2.default = BkUserSelector;
2877
3103
  Object.defineProperties(exports2, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });