@blueking/bk-user-selector 0.0.39-beta.3 → 0.1.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,589 +3,228 @@
3
3
  })(this, function(exports2, vue, bkuiVue) {
4
4
  "use strict";
5
5
  var __vite_style__ = document.createElement("style");
6
- __vite_style__.textContent = ".me-tag[data-v-ef4a05c4] {\n position: absolute;\n top: 50%;\n right: 8px;\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 0 8px;\n font-size: 12px;\n color: #4d4f56;\n white-space: nowrap;\n cursor: pointer;\n background-color: #e1ecff;\n border-radius: 50%;\n transform: translateY(-50%);\n}\n.me-tag[data-v-ef4a05c4]:hover {\n color: #3a84ff;\n background-color: #cddffe;\n}\n.me-tag.disabled[data-v-ef4a05c4] {\n color: #c4c6cc;\n cursor: not-allowed;\n background-color: #f0f1f5;\n}.dropdown-content[data-v-78875ea6] {\n min-height: 40px;\n max-height: 300px;\n padding: 5px 0;\n overflow-y: auto;\n}\n.dropdown-content .no-data[data-v-78875ea6] {\n padding: 10px;\n color: #979ba5;\n text-align: center;\n}\n.dropdown-content .user-group .group-header[data-v-78875ea6] {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n color: #979ba5;\n}\n.dropdown-content .user-group .group-header .group-count[data-v-78875ea6] {\n margin-left: 4px;\n}\n.dropdown-content .user-option[data-v-78875ea6] {\n display: flex;\n align-items: center;\n height: 32px;\n padding: 8px 12px;\n cursor: pointer;\n}\n.dropdown-content .user-option[data-v-78875ea6]:hover {\n background-color: #f5f7fa;\n}.user-tag[data-v-48ac8fc1] {\n margin-right: 4px;\n margin-left: 0;\n}\n.user-tag.draggable[data-v-48ac8fc1] {\n cursor: move;\n}\n.user-tag.active[data-v-48ac8fc1] {\n background-color: #e1ecff;\n border-color: #3a84ff;\n}\n.user-tag.is-custom[data-v-48ac8fc1] {\n color: #ea3636;\n background-color: #feebea;\n border-color: rgba(234, 53, 54, 0.3019607843);\n}\n.user-tag.is-custom[data-v-48ac8fc1]:hover {\n background-color: #fedddc;\n}\n.user-tag .tag-content .user-name[data-v-48ac8fc1] {\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 12px;\n white-space: nowrap;\n}.multiple-selector[data-v-2a532f24] {\n position: relative;\n width: 100%;\n}\n.multiple-selector.is-disabled[data-v-2a532f24] {\n pointer-events: none;\n}\n.multiple-selector .tags-container[data-v-2a532f24] {\n min-height: 32px;\n padding: 1px 10px 1px 8px;\n background-color: #fff;\n border: 1px solid #c4c6cc;\n border-radius: 2px;\n transition: all 0.2s ease;\n}\n.multiple-selector .tags-container.focused[data-v-2a532f24] {\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-2a532f24] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n}\n.multiple-selector .tag-list[data-v-2a532f24] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n}\n.multiple-selector .tag-wrapper[data-v-2a532f24] {\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n}\n.multiple-selector .search-input[data-v-2a532f24] {\n min-width: 10px;\n height: 28px;\n outline: none;\n background: transparent;\n border: none;\n}\n.multiple-selector .search-input[data-v-2a532f24]::placeholder {\n color: #c4c6cc;\n}\n.multiple-selector .search-input.inline[data-v-2a532f24] {\n min-width: 10px;\n}\n.multiple-selector .search-input.last[data-v-2a532f24], .multiple-selector .search-input.collapsed[data-v-2a532f24] {\n flex: 1;\n}\n.hidden-users[data-v-2a532f24] {\n padding: 6px 10px;\n}.single-selector[data-v-cbe352a6] {\n position: relative;\n width: 100%;\n}\n.single-selector.is-disabled[data-v-cbe352a6] {\n pointer-events: none;\n}\n.input-container[data-v-cbe352a6] {\n position: relative;\n display: flex;\n align-items: center;\n min-height: 32px;\n padding: 0 8px;\n background-color: #fff;\n border: 1px solid #c4c6cc;\n border-radius: 2px;\n}\n.input-container[data-v-cbe352a6]:focus-within {\n border-color: #3a84ff;\n box-shadow: 0 0 0 2px rgba(58, 132, 255, 0.1);\n}\n.search-input[data-v-cbe352a6] {\n flex: 1;\n height: 30px;\n outline: none;\n background: transparent;\n border: none;\n}\n.search-input[data-v-cbe352a6]::placeholder {\n color: #c4c6cc;\n}.bk-user-selector[data-v-9c628c83] {\n position: relative;\n width: 100%;\n font-size: 12px;\n}\n.bk-user-selector.is-disabled[data-v-9c628c83] {\n cursor: not-allowed;\n background-color: #dcdee5;\n}.bk-user-selector-popover {\n padding: 0 !important;\n}";
6
+ __vite_style__.textContent = ".me-tag[data-v-4f251ce1] {\n position: absolute;\n top: 50%;\n right: 8px;\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 0 8px;\n font-size: 12px;\n color: #4d4f56;\n white-space: nowrap;\n cursor: pointer;\n background-color: #e1ecff;\n border-radius: 50%;\n transform: translateY(-50%);\n}\n.me-tag[data-v-4f251ce1]:hover {\n color: #3a84ff;\n background-color: #cddffe;\n}\n.me-tag.disabled[data-v-4f251ce1] {\n color: #c4c6cc;\n cursor: not-allowed;\n background-color: #f0f1f5;\n}.dropdown-content[data-v-d5a338f0] {\n min-height: 40px;\n max-height: 300px;\n padding: 5px 0;\n overflow-y: auto;\n}\n.dropdown-content .no-data[data-v-d5a338f0] {\n padding: 10px;\n color: #979ba5;\n text-align: center;\n}\n.dropdown-content .user-group .group-header[data-v-d5a338f0] {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n color: #979ba5;\n}\n.dropdown-content .user-group .group-header .group-count[data-v-d5a338f0] {\n margin-left: 4px;\n}\n.dropdown-content .user-option[data-v-d5a338f0] {\n display: flex;\n align-items: center;\n height: 32px;\n padding: 8px 12px;\n cursor: pointer;\n}\n.dropdown-content .user-option[data-v-d5a338f0]:hover {\n background-color: #f5f7fa;\n}.user-tag[data-v-1f2e0737] {\n margin-right: 4px;\n margin-left: 0;\n}\n.user-tag.draggable[data-v-1f2e0737] {\n cursor: move;\n}\n.user-tag.active[data-v-1f2e0737] {\n background-color: #e1ecff;\n border-color: #3a84ff;\n}\n.user-tag.is-custom[data-v-1f2e0737] {\n color: #ea3636;\n background-color: #feebea;\n border-color: rgba(234, 53, 54, 0.3019607843);\n}\n.user-tag.is-custom[data-v-1f2e0737]:hover {\n background-color: #fedddc;\n}\n.user-tag .tag-content .user-name[data-v-1f2e0737] {\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 12px;\n white-space: nowrap;\n}.bk-user-selector[data-v-9975c7e1] {\n position: relative;\n width: 100%;\n height: 32px;\n font-size: 12px;\n}\n.bk-user-selector.is-disabled[data-v-9975c7e1] {\n pointer-events: none;\n cursor: not-allowed;\n background-color: #dcdee5;\n}\n.bk-user-selector .tags-container[data-v-9975c7e1] {\n position: relative;\n min-height: 32px;\n padding: 1px 10px 1px 8px;\n background-color: #fff;\n border: 1px solid #c4c6cc;\n border-radius: 2px;\n transition: all 0.2s ease;\n}\n.bk-user-selector .tags-container.focused[data-v-9975c7e1] {\n border-color: #3a84ff;\n box-shadow: 0 0 0 2px rgba(58, 132, 255, 0.1);\n}\n.bk-user-selector .tags-container.tags-container-collapsed[data-v-9975c7e1] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n}\n.bk-user-selector .tag-list[data-v-9975c7e1] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n}\n.bk-user-selector .tag-wrapper[data-v-9975c7e1] {\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n}\n.bk-user-selector .search-input[data-v-9975c7e1] {\n min-width: 20px;\n height: 28px;\n outline: none;\n background: transparent;\n border: none;\n}\n.bk-user-selector .search-input[data-v-9975c7e1]::placeholder {\n color: #c4c6cc;\n}\n.bk-user-selector .search-input.input-inline[data-v-9975c7e1] {\n min-width: 20px;\n}\n.bk-user-selector .search-input.input-last[data-v-9975c7e1], .bk-user-selector .search-input.search-input-collapsed[data-v-9975c7e1] {\n flex: 1;\n}\n.hidden-users[data-v-9975c7e1] {\n padding: 6px 10px;\n}.bk-user-selector-popover {\n padding: 0 !important;\n}";
7
7
  document.head.appendChild(__vite_style__);
8
- const generateCallbackName = () => {
9
- const timestamp = Date.now();
10
- const random = Math.random().toString(36).slice(2, 9);
11
- return `__jsonp_callback_${timestamp}_${random}`;
12
- };
13
- const jsonpRequest = (requestUrl, options = {}) => {
14
- return new Promise((resolve, reject) => {
15
- const url = vue.unref(requestUrl);
16
- const { timeout = 1e3 * 60 * 2, params } = options;
17
- const callbackName = generateCallbackName();
18
- const script = document.createElement("script");
19
- let timeoutId = null;
20
- script.setAttribute("type", "text/javascript");
21
- const cleanup = () => {
22
- if (timeoutId) {
23
- clearTimeout(timeoutId);
8
+ var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
9
+ function getDefaultExportFromCjs(x) {
10
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
11
+ }
12
+ var Sortable$1 = { exports: {} };
13
+ /**!
14
+ * Sortable 1.15.6
15
+ * @author RubaXa <trash@rubaxa.org>
16
+ * @author owenm <owen23355@gmail.com>
17
+ * @license MIT
18
+ */
19
+ (function(module2, exports3) {
20
+ (function(global2, factory) {
21
+ module2.exports = factory();
22
+ })(commonjsGlobal, function() {
23
+ function ownKeys(object, enumerableOnly) {
24
+ var keys = Object.keys(object);
25
+ if (Object.getOwnPropertySymbols) {
26
+ var symbols = Object.getOwnPropertySymbols(object);
27
+ if (enumerableOnly) {
28
+ symbols = symbols.filter(function(sym) {
29
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
30
+ });
31
+ }
32
+ keys.push.apply(keys, symbols);
24
33
  }
25
- if (script.parentNode) {
26
- script.parentNode.removeChild(script);
34
+ return keys;
35
+ }
36
+ function _objectSpread2(target) {
37
+ for (var i = 1; i < arguments.length; i++) {
38
+ var source = arguments[i] != null ? arguments[i] : {};
39
+ if (i % 2) {
40
+ ownKeys(Object(source), true).forEach(function(key) {
41
+ _defineProperty(target, key, source[key]);
42
+ });
43
+ } else if (Object.getOwnPropertyDescriptors) {
44
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
45
+ } else {
46
+ ownKeys(Object(source)).forEach(function(key) {
47
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
48
+ });
49
+ }
27
50
  }
28
- if (window[callbackName]) {
29
- delete window[callbackName];
51
+ return target;
52
+ }
53
+ function _typeof(obj) {
54
+ "@babel/helpers - typeof";
55
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
56
+ _typeof = function(obj2) {
57
+ return typeof obj2;
58
+ };
59
+ } else {
60
+ _typeof = function(obj2) {
61
+ return obj2 && typeof Symbol === "function" && obj2.constructor === Symbol && obj2 !== Symbol.prototype ? "symbol" : typeof obj2;
62
+ };
30
63
  }
31
- };
32
- window[callbackName] = (data) => {
33
- cleanup();
34
- resolve(data.data || data);
35
- };
36
- timeoutId = setTimeout(() => {
37
- cleanup();
38
- reject(new Error(`JSONP request timeout: ${url}`));
39
- }, timeout);
40
- script.onerror = () => {
41
- cleanup();
42
- reject(new Error(`JSONP request failed: ${url}`));
43
- };
44
- const separator = url.includes("?") ? "&" : "?";
45
- const paramsStr = params ? `&${Object.entries(params).map(([key, value]) => value ? `${key}=${value}` : "").filter(Boolean).join("&")}` : "";
46
- script.src = `${url}${separator}callback=${callbackName}${paramsStr}`;
47
- document.head.appendChild(script);
48
- });
49
- };
50
- const getTenants = async (apiBaseUrl, tenantId) => {
51
- if (!apiBaseUrl || !tenantId) {
52
- console.warn("获取租户信息需要提供有效的apiBaseUrl和租户ID");
53
- return [];
54
- }
55
- try {
56
- const url = `${apiBaseUrl}/api/v3/open-web/tenant/data-source-owner-tenants/`;
57
- const response = await fetch(url, {
58
- method: "GET",
59
- headers: {
60
- "x-bk-tenant-id": tenantId
61
- },
62
- credentials: "include"
63
- });
64
- if (!response.ok) {
65
- throw new Error(`获取租户信息失败: ${response.status} ${response.statusText}`);
64
+ return _typeof(obj);
66
65
  }
67
- const data = await response.json();
68
- return data.data || [];
69
- } catch (error) {
70
- console.error("获取租户信息失败:", error);
71
- return [];
72
- }
73
- };
74
- const searchUsers = async (params) => {
75
- const { apiBaseUrl, tenantId, keyword, enableMultiTenantMode = true } = params;
76
- if (!enableMultiTenantMode) {
77
- const userList = await getUserList(apiBaseUrl, {
78
- keyword,
79
- pageSize: 100,
80
- page: 1
81
- }).catch(() => {
82
- return [];
83
- });
84
- return userList;
85
- }
86
- if (!keyword || !apiBaseUrl || !tenantId) {
87
- console.warn("搜索用户需要提供有效的apiBaseUrl、租户ID和关键词");
88
- return [];
89
- }
90
- try {
91
- const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/search/?keyword=${encodeURIComponent(keyword)}`;
92
- const response = await fetch(url, {
93
- method: "GET",
94
- headers: {
95
- "x-bk-tenant-id": tenantId
96
- },
97
- credentials: "include"
98
- });
99
- if (!response.ok) {
100
- throw new Error(`搜索用户失败: ${response.status} ${response.statusText}`);
66
+ function _defineProperty(obj, key, value) {
67
+ if (key in obj) {
68
+ Object.defineProperty(obj, key, {
69
+ value,
70
+ enumerable: true,
71
+ configurable: true,
72
+ writable: true
73
+ });
74
+ } else {
75
+ obj[key] = value;
76
+ }
77
+ return obj;
101
78
  }
102
- const data = await response.json();
103
- return data.data || [];
104
- } catch (error) {
105
- console.error("搜索用户失败:", error);
106
- return [];
107
- }
108
- };
109
- const lookupUsers = async (params) => {
110
- const { apiBaseUrl, tenantId, exactSearchKey = "bk_username", usersList = [], enableMultiTenantMode = true } = params;
111
- const users = usersList.filter((user) => user).map((user) => user.trim());
112
- if (!enableMultiTenantMode) {
113
- const userList = await getUserList(apiBaseUrl, {
114
- userIds: users
115
- }).catch(() => {
116
- return [];
117
- });
118
- return users.map((user) => userList.find((u) => u.username === user)).filter(Boolean);
119
- }
120
- if (users.length === 0 || !apiBaseUrl || !tenantId) {
121
- console.warn("批量查找用户需要提供有效的apiBaseUrl、租户ID和至少一个用户名");
122
- return [];
123
- }
124
- try {
125
- const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/lookup/?lookups=${users.join(",")}&lookup_fields=${exactSearchKey}`;
126
- const response = await fetch(url, {
127
- method: "GET",
128
- headers: {
129
- "x-bk-tenant-id": tenantId
130
- },
131
- credentials: "include"
132
- });
133
- if (!response.ok) {
134
- throw new Error(`批量查找用户失败: ${response.status} ${response.statusText}`);
79
+ function _extends() {
80
+ _extends = Object.assign || function(target) {
81
+ for (var i = 1; i < arguments.length; i++) {
82
+ var source = arguments[i];
83
+ for (var key in source) {
84
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
85
+ target[key] = source[key];
86
+ }
87
+ }
88
+ }
89
+ return target;
90
+ };
91
+ return _extends.apply(this, arguments);
135
92
  }
136
- const data = await response.json();
137
- return data.data || [];
138
- } catch (error) {
139
- console.error("批量查找用户失败:", error);
140
- return [];
141
- }
142
- };
143
- const formatUsers = (users, enableMultiTenantMode = true) => {
144
- if (!users || !Array.isArray(users)) return [];
145
- if (!enableMultiTenantMode) {
146
- return users.map((user) => ({
147
- ...user,
148
- id: user.username,
149
- name: `${user.display_name}(${user.username})`,
150
- tenantId: user.owner_tenant_id
151
- }));
152
- }
153
- return users.map((user) => ({
154
- id: user.bk_username,
155
- name: user.display_name,
156
- tenantId: user.owner_tenant_id,
157
- ...user
158
- }));
159
- };
160
- const getUserList = async (url, params) => {
161
- const { userIds, keyword, pageSize = 20, page, appCode } = params;
162
- const data = await jsonpRequest(url, {
163
- params: {
164
- exact_lookups: (userIds == null ? void 0 : userIds.join(",")) || void 0,
165
- fuzzy_lookups: keyword || void 0,
166
- page_size: Math.max((userIds == null ? void 0 : userIds.length) || 0, 20, Number(pageSize)).toString(),
167
- page: (page == null ? void 0 : page.toString()) || "1",
168
- app_code: appCode || "bk-magicbox"
93
+ function _objectWithoutPropertiesLoose(source, excluded) {
94
+ if (source == null) return {};
95
+ var target = {};
96
+ var sourceKeys = Object.keys(source);
97
+ var key, i;
98
+ for (i = 0; i < sourceKeys.length; i++) {
99
+ key = sourceKeys[i];
100
+ if (excluded.indexOf(key) >= 0) continue;
101
+ target[key] = source[key];
102
+ }
103
+ return target;
169
104
  }
170
- });
171
- return (data == null ? void 0 : data.results) || [];
172
- };
173
- /*! js-cookie v3.0.5 | MIT */
174
- function assign(target) {
175
- for (var i = 1; i < arguments.length; i++) {
176
- var source = arguments[i];
177
- for (var key in source) {
178
- target[key] = source[key];
105
+ function _objectWithoutProperties(source, excluded) {
106
+ if (source == null) return {};
107
+ var target = _objectWithoutPropertiesLoose(source, excluded);
108
+ var key, i;
109
+ if (Object.getOwnPropertySymbols) {
110
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
111
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
112
+ key = sourceSymbolKeys[i];
113
+ if (excluded.indexOf(key) >= 0) continue;
114
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
115
+ target[key] = source[key];
116
+ }
117
+ }
118
+ return target;
179
119
  }
180
- }
181
- return target;
182
- }
183
- var defaultConverter = {
184
- read: function(value) {
185
- if (value[0] === '"') {
186
- value = value.slice(1, -1);
120
+ function _toConsumableArray(arr) {
121
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
187
122
  }
188
- return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
189
- },
190
- write: function(value) {
191
- return encodeURIComponent(value).replace(
192
- /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,
193
- decodeURIComponent
194
- );
195
- }
196
- };
197
- function init(converter, defaultAttributes) {
198
- function set(name, value, attributes) {
199
- if (typeof document === "undefined") {
200
- return;
201
- }
202
- attributes = assign({}, defaultAttributes, attributes);
203
- if (typeof attributes.expires === "number") {
204
- attributes.expires = new Date(Date.now() + attributes.expires * 864e5);
123
+ function _arrayWithoutHoles(arr) {
124
+ if (Array.isArray(arr)) return _arrayLikeToArray(arr);
205
125
  }
206
- if (attributes.expires) {
207
- attributes.expires = attributes.expires.toUTCString();
126
+ function _iterableToArray(iter) {
127
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
208
128
  }
209
- name = encodeURIComponent(name).replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent).replace(/[()]/g, escape);
210
- var stringifiedAttributes = "";
211
- for (var attributeName in attributes) {
212
- if (!attributes[attributeName]) {
213
- continue;
214
- }
215
- stringifiedAttributes += "; " + attributeName;
216
- if (attributes[attributeName] === true) {
217
- continue;
218
- }
219
- stringifiedAttributes += "=" + attributes[attributeName].split(";")[0];
129
+ function _unsupportedIterableToArray(o, minLen) {
130
+ if (!o) return;
131
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
132
+ var n = Object.prototype.toString.call(o).slice(8, -1);
133
+ if (n === "Object" && o.constructor) n = o.constructor.name;
134
+ if (n === "Map" || n === "Set") return Array.from(o);
135
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
220
136
  }
221
- return document.cookie = name + "=" + converter.write(value, name) + stringifiedAttributes;
222
- }
223
- function get(name) {
224
- if (typeof document === "undefined" || arguments.length && !name) {
225
- return;
137
+ function _arrayLikeToArray(arr, len) {
138
+ if (len == null || len > arr.length) len = arr.length;
139
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
140
+ return arr2;
226
141
  }
227
- var cookies = document.cookie ? document.cookie.split("; ") : [];
228
- var jar = {};
229
- for (var i = 0; i < cookies.length; i++) {
230
- var parts = cookies[i].split("=");
231
- var value = parts.slice(1).join("=");
232
- try {
233
- var found = decodeURIComponent(parts[0]);
234
- jar[found] = converter.read(value, found);
235
- if (name === found) {
236
- break;
237
- }
238
- } catch (e) {
239
- }
142
+ function _nonIterableSpread() {
143
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
240
144
  }
241
- return name ? jar[name] : jar;
242
- }
243
- return Object.create(
244
- {
245
- set,
246
- get,
247
- remove: function(name, attributes) {
248
- set(
249
- name,
250
- "",
251
- assign({}, attributes, {
252
- expires: -1
253
- })
254
- );
255
- },
256
- withAttributes: function(attributes) {
257
- return init(this.converter, assign({}, this.attributes, attributes));
258
- },
259
- withConverter: function(converter2) {
260
- return init(assign({}, this.converter, converter2), this.attributes);
145
+ var version = "1.15.6";
146
+ function userAgent(pattern) {
147
+ if (typeof window !== "undefined" && window.navigator) {
148
+ return !!/* @__PURE__ */ navigator.userAgent.match(pattern);
261
149
  }
262
- },
263
- {
264
- attributes: { value: Object.freeze(defaultAttributes) },
265
- converter: { value: Object.freeze(converter) }
266
150
  }
267
- );
268
- }
269
- var api = init(defaultConverter, { path: "/" });
270
- const enUS = {
271
- 我: "Me",
272
- 请输入人员名称搜索: "Please enter the name of the user to search",
273
- 用户群组: "User Group",
274
- 无匹配人员: "No matching users",
275
- 虚拟账号: "Virtual Account",
276
- 用户: "User"
277
- };
278
- const zhCN = {
279
- 我: "我",
280
- 请输入人员名称搜索: "请输入人员名称搜索",
281
- 用户群组: "用户群组",
282
- 无匹配人员: "无匹配人员",
283
- 虚拟账号: "虚拟账号",
284
- 用户: "用户"
285
- };
286
- const BLUEKINNG_LANGUAGE = "blueking_language";
287
- const languageMap = {
288
- "en-US": enUS,
289
- "zh-CN": zhCN
290
- };
291
- const getPath = (obj, path, variables) => {
292
- const pathStack = /^\w/.test(path) ? path.split(".") : [path];
293
- const { length } = pathStack;
294
- let target = obj;
295
- let i = 0;
296
- while (i <= length && target) {
297
- if (typeof target === "string") {
298
- return target;
151
+ var IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i);
152
+ var Edge = userAgent(/Edge/i);
153
+ var FireFox = userAgent(/firefox/i);
154
+ var Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i);
155
+ var IOS = userAgent(/iP(ad|od|hone)/i);
156
+ var ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i);
157
+ var captureMode = {
158
+ capture: false,
159
+ passive: false
160
+ };
161
+ function on(el, event, fn) {
162
+ el.addEventListener(event, fn, !IE11OrLess && captureMode);
299
163
  }
300
- if (variables) {
301
- target = target[pathStack[i]];
302
- Object.keys(variables).forEach((key) => {
303
- target = target.replace(`{${key}}`, variables[key]);
304
- });
305
- } else {
306
- target = target[pathStack[i]];
164
+ function off(el, event, fn) {
165
+ el.removeEventListener(event, fn, !IE11OrLess && captureMode);
307
166
  }
308
- i = i + 1;
309
- if (!target) {
310
- return target;
167
+ function matches(el, selector) {
168
+ if (!selector) return;
169
+ selector[0] === ">" && (selector = selector.substring(1));
170
+ if (el) {
171
+ try {
172
+ if (el.matches) {
173
+ return el.matches(selector);
174
+ } else if (el.msMatchesSelector) {
175
+ return el.msMatchesSelector(selector);
176
+ } else if (el.webkitMatchesSelector) {
177
+ return el.webkitMatchesSelector(selector);
178
+ }
179
+ } catch (_) {
180
+ return false;
181
+ }
182
+ }
183
+ return false;
311
184
  }
312
- }
313
- return target;
314
- };
315
- const useI18n = () => {
316
- let localeLanguage = "zh-CN";
317
- const bluekingLanguage = api.get(BLUEKINNG_LANGUAGE);
318
- if (bluekingLanguage && bluekingLanguage.toLowerCase() === "en") {
319
- localeLanguage = "en-US";
320
- }
321
- const languagePackage = languageMap[localeLanguage];
322
- const t = (path, variable) => {
323
- const value = getPath(languagePackage, path, variable);
324
- if (value === void 0) {
325
- console.warn(`缺少索引 * ${path} *`);
185
+ function getParentOrHost(el) {
186
+ return el.host && el !== document && el.host.nodeType ? el.host : el.parentNode;
326
187
  }
327
- return value;
328
- };
329
- return {
330
- local: localeLanguage,
331
- t
332
- };
333
- };
334
- const useTenantData = (apiBaseUrl, tenantId, enableMultiTenantMode = true) => {
335
- const tenants = vue.ref({});
336
- const loading = vue.ref(false);
337
- const fetchTenants = async () => {
338
- if (!apiBaseUrl || !tenantId) {
339
- console.warn("获取租户需要提供有效的API基础URL和租户ID");
340
- return;
188
+ function closest(el, selector, ctx, includeCTX) {
189
+ if (el) {
190
+ ctx = ctx || document;
191
+ do {
192
+ if (selector != null && (selector[0] === ">" ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) {
193
+ return el;
194
+ }
195
+ if (el === ctx) break;
196
+ } while (el = getParentOrHost(el));
197
+ }
198
+ return null;
341
199
  }
342
- loading.value = true;
343
- try {
344
- const result = await getTenants(apiBaseUrl, tenantId);
345
- const tenantMap = {};
346
- result.forEach((item) => {
347
- if (item.id && item.name) {
348
- tenantMap[item.id] = item.name;
200
+ var R_SPACE = /\s+/g;
201
+ function toggleClass(el, name, state) {
202
+ if (el && name) {
203
+ if (el.classList) {
204
+ el.classList[state ? "add" : "remove"](name);
205
+ } else {
206
+ var className = (" " + el.className + " ").replace(R_SPACE, " ").replace(" " + name + " ", " ");
207
+ el.className = (className + (state ? " " + name : "")).replace(R_SPACE, " ");
349
208
  }
350
- });
351
- tenants.value = tenantMap;
352
- } catch (error) {
353
- console.error("获取租户数据失败:", error);
354
- } finally {
355
- loading.value = false;
209
+ }
356
210
  }
357
- };
358
- vue.onBeforeMount(() => {
359
- if (enableMultiTenantMode) {
360
- fetchTenants();
361
- }
362
- });
363
- return {
364
- tenants,
365
- loading,
366
- fetchTenants
367
- };
368
- };
369
- var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
370
- function getDefaultExportFromCjs(x) {
371
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
372
- }
373
- var Sortable$1 = { exports: {} };
374
- /**!
375
- * Sortable 1.15.6
376
- * @author RubaXa <trash@rubaxa.org>
377
- * @author owenm <owen23355@gmail.com>
378
- * @license MIT
379
- */
380
- (function(module2, exports3) {
381
- (function(global2, factory) {
382
- module2.exports = factory();
383
- })(commonjsGlobal, function() {
384
- function ownKeys(object, enumerableOnly) {
385
- var keys = Object.keys(object);
386
- if (Object.getOwnPropertySymbols) {
387
- var symbols = Object.getOwnPropertySymbols(object);
388
- if (enumerableOnly) {
389
- symbols = symbols.filter(function(sym) {
390
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
391
- });
392
- }
393
- keys.push.apply(keys, symbols);
394
- }
395
- return keys;
396
- }
397
- function _objectSpread2(target) {
398
- for (var i = 1; i < arguments.length; i++) {
399
- var source = arguments[i] != null ? arguments[i] : {};
400
- if (i % 2) {
401
- ownKeys(Object(source), true).forEach(function(key) {
402
- _defineProperty(target, key, source[key]);
403
- });
404
- } else if (Object.getOwnPropertyDescriptors) {
405
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
406
- } else {
407
- ownKeys(Object(source)).forEach(function(key) {
408
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
409
- });
410
- }
411
- }
412
- return target;
413
- }
414
- function _typeof(obj) {
415
- "@babel/helpers - typeof";
416
- if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
417
- _typeof = function(obj2) {
418
- return typeof obj2;
419
- };
420
- } else {
421
- _typeof = function(obj2) {
422
- return obj2 && typeof Symbol === "function" && obj2.constructor === Symbol && obj2 !== Symbol.prototype ? "symbol" : typeof obj2;
423
- };
424
- }
425
- return _typeof(obj);
426
- }
427
- function _defineProperty(obj, key, value) {
428
- if (key in obj) {
429
- Object.defineProperty(obj, key, {
430
- value,
431
- enumerable: true,
432
- configurable: true,
433
- writable: true
434
- });
435
- } else {
436
- obj[key] = value;
437
- }
438
- return obj;
439
- }
440
- function _extends() {
441
- _extends = Object.assign || function(target) {
442
- for (var i = 1; i < arguments.length; i++) {
443
- var source = arguments[i];
444
- for (var key in source) {
445
- if (Object.prototype.hasOwnProperty.call(source, key)) {
446
- target[key] = source[key];
447
- }
448
- }
449
- }
450
- return target;
451
- };
452
- return _extends.apply(this, arguments);
453
- }
454
- function _objectWithoutPropertiesLoose(source, excluded) {
455
- if (source == null) return {};
456
- var target = {};
457
- var sourceKeys = Object.keys(source);
458
- var key, i;
459
- for (i = 0; i < sourceKeys.length; i++) {
460
- key = sourceKeys[i];
461
- if (excluded.indexOf(key) >= 0) continue;
462
- target[key] = source[key];
463
- }
464
- return target;
465
- }
466
- function _objectWithoutProperties(source, excluded) {
467
- if (source == null) return {};
468
- var target = _objectWithoutPropertiesLoose(source, excluded);
469
- var key, i;
470
- if (Object.getOwnPropertySymbols) {
471
- var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
472
- for (i = 0; i < sourceSymbolKeys.length; i++) {
473
- key = sourceSymbolKeys[i];
474
- if (excluded.indexOf(key) >= 0) continue;
475
- if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
476
- target[key] = source[key];
477
- }
478
- }
479
- return target;
480
- }
481
- function _toConsumableArray(arr) {
482
- return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
483
- }
484
- function _arrayWithoutHoles(arr) {
485
- if (Array.isArray(arr)) return _arrayLikeToArray(arr);
486
- }
487
- function _iterableToArray(iter) {
488
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
489
- }
490
- function _unsupportedIterableToArray(o, minLen) {
491
- if (!o) return;
492
- if (typeof o === "string") return _arrayLikeToArray(o, minLen);
493
- var n = Object.prototype.toString.call(o).slice(8, -1);
494
- if (n === "Object" && o.constructor) n = o.constructor.name;
495
- if (n === "Map" || n === "Set") return Array.from(o);
496
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
497
- }
498
- function _arrayLikeToArray(arr, len) {
499
- if (len == null || len > arr.length) len = arr.length;
500
- for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
501
- return arr2;
502
- }
503
- function _nonIterableSpread() {
504
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
505
- }
506
- var version = "1.15.6";
507
- function userAgent(pattern) {
508
- if (typeof window !== "undefined" && window.navigator) {
509
- return !!/* @__PURE__ */ navigator.userAgent.match(pattern);
510
- }
511
- }
512
- var IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i);
513
- var Edge = userAgent(/Edge/i);
514
- var FireFox = userAgent(/firefox/i);
515
- var Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i);
516
- var IOS = userAgent(/iP(ad|od|hone)/i);
517
- var ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i);
518
- var captureMode = {
519
- capture: false,
520
- passive: false
521
- };
522
- function on(el, event, fn) {
523
- el.addEventListener(event, fn, !IE11OrLess && captureMode);
524
- }
525
- function off(el, event, fn) {
526
- el.removeEventListener(event, fn, !IE11OrLess && captureMode);
527
- }
528
- function matches(el, selector) {
529
- if (!selector) return;
530
- selector[0] === ">" && (selector = selector.substring(1));
531
- if (el) {
532
- try {
533
- if (el.matches) {
534
- return el.matches(selector);
535
- } else if (el.msMatchesSelector) {
536
- return el.msMatchesSelector(selector);
537
- } else if (el.webkitMatchesSelector) {
538
- return el.webkitMatchesSelector(selector);
539
- }
540
- } catch (_) {
541
- return false;
542
- }
543
- }
544
- return false;
545
- }
546
- function getParentOrHost(el) {
547
- return el.host && el !== document && el.host.nodeType ? el.host : el.parentNode;
548
- }
549
- function closest(el, selector, ctx, includeCTX) {
550
- if (el) {
551
- ctx = ctx || document;
552
- do {
553
- if (selector != null && (selector[0] === ">" ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) {
554
- return el;
555
- }
556
- if (el === ctx) break;
557
- } while (el = getParentOrHost(el));
558
- }
559
- return null;
560
- }
561
- var R_SPACE = /\s+/g;
562
- function toggleClass(el, name, state) {
563
- if (el && name) {
564
- if (el.classList) {
565
- el.classList[state ? "add" : "remove"](name);
566
- } else {
567
- var className = (" " + el.className + " ").replace(R_SPACE, " ").replace(" " + name + " ", " ");
568
- el.className = (className + (state ? " " + name : "")).replace(R_SPACE, " ");
569
- }
570
- }
571
- }
572
- function css(el, prop, val) {
573
- var style = el && el.style;
574
- if (style) {
575
- if (val === void 0) {
576
- if (document.defaultView && document.defaultView.getComputedStyle) {
577
- val = document.defaultView.getComputedStyle(el, "");
578
- } else if (el.currentStyle) {
579
- val = el.currentStyle;
580
- }
581
- return prop === void 0 ? val : val[prop];
582
- } else {
583
- if (!(prop in style) && prop.indexOf("webkit") === -1) {
584
- prop = "-webkit-" + prop;
585
- }
586
- style[prop] = val + (typeof val === "string" ? "" : "px");
587
- }
588
- }
211
+ function css(el, prop, val) {
212
+ var style = el && el.style;
213
+ if (style) {
214
+ if (val === void 0) {
215
+ if (document.defaultView && document.defaultView.getComputedStyle) {
216
+ val = document.defaultView.getComputedStyle(el, "");
217
+ } else if (el.currentStyle) {
218
+ val = el.currentStyle;
219
+ }
220
+ return prop === void 0 ? val : val[prop];
221
+ } else {
222
+ if (!(prop in style) && prop.indexOf("webkit") === -1) {
223
+ prop = "-webkit-" + prop;
224
+ }
225
+ style[prop] = val + (typeof val === "string" ? "" : "px");
226
+ }
227
+ }
589
228
  }
590
229
  function matrix(el, selfOnly) {
591
230
  var appliedTransforms = "";
@@ -3124,15 +2763,580 @@
3124
2763
  multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement);
3125
2764
  });
3126
2765
  }
3127
- Sortable2.mount(new AutoScrollPlugin());
3128
- Sortable2.mount(Remove, Revert);
3129
- Sortable2.mount(new SwapPlugin());
3130
- Sortable2.mount(new MultiDragPlugin());
3131
- return Sortable2;
2766
+ Sortable2.mount(new AutoScrollPlugin());
2767
+ Sortable2.mount(Remove, Revert);
2768
+ Sortable2.mount(new SwapPlugin());
2769
+ Sortable2.mount(new MultiDragPlugin());
2770
+ return Sortable2;
2771
+ });
2772
+ })(Sortable$1);
2773
+ var SortableExports = Sortable$1.exports;
2774
+ const Sortable = /* @__PURE__ */ getDefaultExportFromCjs(SortableExports);
2775
+ const RESERVED_SPACE_FOR_INPUT = 100;
2776
+ const SEARCH_DEBOUNCE_DELAY = 300;
2777
+ const DEFAULT_EXACT_SEARCH_KEY = "bk_username";
2778
+ const USER_TYPE = {
2779
+ /** 普通用户 */
2780
+ USER: "user",
2781
+ /** 虚拟账号 */
2782
+ VIRTUAL: "virtual",
2783
+ /** 自定义用户 */
2784
+ CUSTOM: "custom",
2785
+ /** 用户群组 */
2786
+ USER_GROUP: "userGroup"
2787
+ };
2788
+ const DEFAULT_PAGE_SIZE = 100;
2789
+ const generateCallbackName = () => {
2790
+ const timestamp = Date.now();
2791
+ const random = Math.random().toString(36).slice(2, 9);
2792
+ return `__jsonp_callback_${timestamp}_${random}`;
2793
+ };
2794
+ const jsonpRequest = (requestUrl, options = {}) => {
2795
+ return new Promise((resolve, reject) => {
2796
+ const url = vue.unref(requestUrl);
2797
+ const { timeout = 1e3 * 60 * 2, params } = options;
2798
+ const callbackName = generateCallbackName();
2799
+ const script = document.createElement("script");
2800
+ let timeoutId = null;
2801
+ script.setAttribute("type", "text/javascript");
2802
+ const cleanup = () => {
2803
+ if (timeoutId) {
2804
+ clearTimeout(timeoutId);
2805
+ }
2806
+ if (script.parentNode) {
2807
+ script.parentNode.removeChild(script);
2808
+ }
2809
+ if (window[callbackName]) {
2810
+ delete window[callbackName];
2811
+ }
2812
+ };
2813
+ window[callbackName] = (data) => {
2814
+ cleanup();
2815
+ resolve(data.data || data);
2816
+ };
2817
+ timeoutId = setTimeout(() => {
2818
+ cleanup();
2819
+ reject(new Error(`JSONP request timeout: ${url}`));
2820
+ }, timeout);
2821
+ script.onerror = () => {
2822
+ cleanup();
2823
+ reject(new Error(`JSONP request failed: ${url}`));
2824
+ };
2825
+ const separator = url.includes("?") ? "&" : "?";
2826
+ const paramsStr = params ? `&${Object.entries(params).map(([key, value]) => value ? `${key}=${value}` : "").filter(Boolean).join("&")}` : "";
2827
+ script.src = `${url}${separator}callback=${callbackName}${paramsStr}`;
2828
+ document.head.appendChild(script);
2829
+ });
2830
+ };
2831
+ const logger = {
2832
+ /**
2833
+ * 调试日志
2834
+ */
2835
+ debug: (message, ...args) => {
2836
+ },
2837
+ /**
2838
+ * 信息日志
2839
+ */
2840
+ info: (message, ...args) => {
2841
+ },
2842
+ /**
2843
+ * 警告日志
2844
+ */
2845
+ warn: (message, ...args) => {
2846
+ },
2847
+ /**
2848
+ * 错误日志
2849
+ */
2850
+ error: (message, error) => {
2851
+ }
2852
+ };
2853
+ const warnMissingParams = (operation, params) => {
2854
+ logger.warn(`${operation}需要提供有效的参数: ${params.join(", ")}`);
2855
+ };
2856
+ const getTenants = async (apiBaseUrl, tenantId) => {
2857
+ if (!apiBaseUrl || !tenantId) {
2858
+ warnMissingParams("获取租户信息", ["apiBaseUrl", "tenantId"]);
2859
+ return [];
2860
+ }
2861
+ try {
2862
+ const url = `${apiBaseUrl}/api/v3/open-web/tenant/data-source-owner-tenants/`;
2863
+ const response = await fetch(url, {
2864
+ method: "GET",
2865
+ headers: {
2866
+ "x-bk-tenant-id": tenantId
2867
+ },
2868
+ credentials: "include"
2869
+ });
2870
+ if (!response.ok) {
2871
+ throw new Error(`${response.status} ${response.statusText}`);
2872
+ }
2873
+ const data = await response.json();
2874
+ return data.data || [];
2875
+ } catch (error) {
2876
+ return [];
2877
+ }
2878
+ };
2879
+ const searchUsers = async (params) => {
2880
+ const { apiBaseUrl, tenantId, keyword, enableMultiTenantMode = true } = params;
2881
+ if (!enableMultiTenantMode) {
2882
+ try {
2883
+ return await getUserList(apiBaseUrl, {
2884
+ keyword,
2885
+ pageSize: DEFAULT_PAGE_SIZE,
2886
+ page: 1
2887
+ });
2888
+ } catch {
2889
+ return [];
2890
+ }
2891
+ }
2892
+ if (!keyword || !apiBaseUrl || !tenantId) {
2893
+ warnMissingParams("搜索用户", ["apiBaseUrl", "tenantId", "keyword"]);
2894
+ return [];
2895
+ }
2896
+ try {
2897
+ const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/search/?keyword=${encodeURIComponent(keyword)}`;
2898
+ const response = await fetch(url, {
2899
+ method: "GET",
2900
+ headers: {
2901
+ "x-bk-tenant-id": tenantId
2902
+ },
2903
+ credentials: "include"
2904
+ });
2905
+ if (!response.ok) {
2906
+ throw new Error(`${response.status} ${response.statusText}`);
2907
+ }
2908
+ const data = await response.json();
2909
+ return data.data || [];
2910
+ } catch (error) {
2911
+ return [];
2912
+ }
2913
+ };
2914
+ const lookupUsers = async (params) => {
2915
+ const { apiBaseUrl, tenantId, exactSearchKey = "bk_username", usersList = [], enableMultiTenantMode = true } = params;
2916
+ const users = usersList.filter(Boolean).map((user) => user.trim());
2917
+ if (!enableMultiTenantMode) {
2918
+ try {
2919
+ const userList = await getUserList(apiBaseUrl, { userIds: users });
2920
+ return users.map((user) => userList.find((u) => u.username === user)).filter(Boolean);
2921
+ } catch {
2922
+ return [];
2923
+ }
2924
+ }
2925
+ if (users.length === 0 || !apiBaseUrl || !tenantId) {
2926
+ warnMissingParams("批量查找用户", ["apiBaseUrl", "tenantId", "usersList"]);
2927
+ return [];
2928
+ }
2929
+ try {
2930
+ const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/lookup/?lookups=${users.join(",")}&lookup_fields=${exactSearchKey}`;
2931
+ const response = await fetch(url, {
2932
+ method: "GET",
2933
+ headers: {
2934
+ "x-bk-tenant-id": tenantId
2935
+ },
2936
+ credentials: "include"
2937
+ });
2938
+ if (!response.ok) {
2939
+ throw new Error(`${response.status} ${response.statusText}`);
2940
+ }
2941
+ const data = await response.json();
2942
+ return data.data || [];
2943
+ } catch (error) {
2944
+ return [];
2945
+ }
2946
+ };
2947
+ const formatUsers = (users, enableMultiTenantMode = true) => {
2948
+ if (!users || !Array.isArray(users)) return [];
2949
+ if (!enableMultiTenantMode) {
2950
+ return users.map((user) => ({
2951
+ ...user,
2952
+ id: user.username,
2953
+ name: `${user.display_name}(${user.username})`,
2954
+ type: user.data_source_type,
2955
+ tenantId: user.owner_tenant_id
2956
+ }));
2957
+ }
2958
+ return users.map((user) => ({
2959
+ id: user.bk_username,
2960
+ name: user.display_name,
2961
+ type: user.data_source_type,
2962
+ tenantId: user.owner_tenant_id,
2963
+ ...user
2964
+ }));
2965
+ };
2966
+ const getUserList = async (url, params) => {
2967
+ const { userIds, keyword, pageSize = 20, page = 1, appCode = "bk-magicbox" } = params;
2968
+ const data = await jsonpRequest(url, {
2969
+ params: {
2970
+ exact_lookups: (userIds == null ? void 0 : userIds.join(",")) || void 0,
2971
+ fuzzy_lookups: keyword || void 0,
2972
+ page_size: Math.max((userIds == null ? void 0 : userIds.length) || 0, 20, Number(pageSize)).toString(),
2973
+ page: page.toString(),
2974
+ app_code: appCode
2975
+ }
2976
+ });
2977
+ return (data == null ? void 0 : data.results) || [];
2978
+ };
2979
+ const useCurrentUser = (options) => {
2980
+ const {
2981
+ apiBaseUrl,
2982
+ tenantId,
2983
+ currentUserId,
2984
+ exactSearchKey = DEFAULT_EXACT_SEARCH_KEY,
2985
+ enableMultiTenantMode = true
2986
+ } = options;
2987
+ const loading = vue.ref(false);
2988
+ const fetchCurrentUser = async () => {
2989
+ if (!currentUserId) {
2990
+ return null;
2991
+ }
2992
+ loading.value = true;
2993
+ try {
2994
+ const result = await lookupUsers({
2995
+ apiBaseUrl,
2996
+ tenantId,
2997
+ exactSearchKey,
2998
+ usersList: [currentUserId],
2999
+ enableMultiTenantMode
3000
+ });
3001
+ const formattedUsers = formatUsers(result, enableMultiTenantMode);
3002
+ return formattedUsers.length > 0 ? formattedUsers[0] : null;
3003
+ } catch (error) {
3004
+ console.error("获取当前用户信息失败:", error);
3005
+ return null;
3006
+ } finally {
3007
+ loading.value = false;
3008
+ }
3009
+ };
3010
+ return {
3011
+ loading,
3012
+ fetchCurrentUser
3013
+ };
3014
+ };
3015
+ /*! js-cookie v3.0.5 | MIT */
3016
+ function assign(target) {
3017
+ for (var i = 1; i < arguments.length; i++) {
3018
+ var source = arguments[i];
3019
+ for (var key in source) {
3020
+ target[key] = source[key];
3021
+ }
3022
+ }
3023
+ return target;
3024
+ }
3025
+ var defaultConverter = {
3026
+ read: function(value) {
3027
+ if (value[0] === '"') {
3028
+ value = value.slice(1, -1);
3029
+ }
3030
+ return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
3031
+ },
3032
+ write: function(value) {
3033
+ return encodeURIComponent(value).replace(
3034
+ /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,
3035
+ decodeURIComponent
3036
+ );
3037
+ }
3038
+ };
3039
+ function init(converter, defaultAttributes) {
3040
+ function set(name, value, attributes) {
3041
+ if (typeof document === "undefined") {
3042
+ return;
3043
+ }
3044
+ attributes = assign({}, defaultAttributes, attributes);
3045
+ if (typeof attributes.expires === "number") {
3046
+ attributes.expires = new Date(Date.now() + attributes.expires * 864e5);
3047
+ }
3048
+ if (attributes.expires) {
3049
+ attributes.expires = attributes.expires.toUTCString();
3050
+ }
3051
+ name = encodeURIComponent(name).replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent).replace(/[()]/g, escape);
3052
+ var stringifiedAttributes = "";
3053
+ for (var attributeName in attributes) {
3054
+ if (!attributes[attributeName]) {
3055
+ continue;
3056
+ }
3057
+ stringifiedAttributes += "; " + attributeName;
3058
+ if (attributes[attributeName] === true) {
3059
+ continue;
3060
+ }
3061
+ stringifiedAttributes += "=" + attributes[attributeName].split(";")[0];
3062
+ }
3063
+ return document.cookie = name + "=" + converter.write(value, name) + stringifiedAttributes;
3064
+ }
3065
+ function get(name) {
3066
+ if (typeof document === "undefined" || arguments.length && !name) {
3067
+ return;
3068
+ }
3069
+ var cookies = document.cookie ? document.cookie.split("; ") : [];
3070
+ var jar = {};
3071
+ for (var i = 0; i < cookies.length; i++) {
3072
+ var parts = cookies[i].split("=");
3073
+ var value = parts.slice(1).join("=");
3074
+ try {
3075
+ var found = decodeURIComponent(parts[0]);
3076
+ jar[found] = converter.read(value, found);
3077
+ if (name === found) {
3078
+ break;
3079
+ }
3080
+ } catch (e) {
3081
+ }
3082
+ }
3083
+ return name ? jar[name] : jar;
3084
+ }
3085
+ return Object.create(
3086
+ {
3087
+ set,
3088
+ get,
3089
+ remove: function(name, attributes) {
3090
+ set(
3091
+ name,
3092
+ "",
3093
+ assign({}, attributes, {
3094
+ expires: -1
3095
+ })
3096
+ );
3097
+ },
3098
+ withAttributes: function(attributes) {
3099
+ return init(this.converter, assign({}, this.attributes, attributes));
3100
+ },
3101
+ withConverter: function(converter2) {
3102
+ return init(assign({}, this.converter, converter2), this.attributes);
3103
+ }
3104
+ },
3105
+ {
3106
+ attributes: { value: Object.freeze(defaultAttributes) },
3107
+ converter: { value: Object.freeze(converter) }
3108
+ }
3109
+ );
3110
+ }
3111
+ var api = init(defaultConverter, { path: "/" });
3112
+ const enUS = {
3113
+ 我: "Me",
3114
+ 请输入人员名称搜索: "Please enter the name of the user to search",
3115
+ 用户群组: "User Group",
3116
+ 无匹配人员: "No matching users",
3117
+ 虚拟账号: "Virtual Account",
3118
+ 用户: "User"
3119
+ };
3120
+ const zhCN = {
3121
+ 我: "我",
3122
+ 请输入人员名称搜索: "请输入人员名称搜索",
3123
+ 用户群组: "用户群组",
3124
+ 无匹配人员: "无匹配人员",
3125
+ 虚拟账号: "虚拟账号",
3126
+ 用户: "用户"
3127
+ };
3128
+ const BLUEKINNG_LANGUAGE = "blueking_language";
3129
+ const languageMap = {
3130
+ "en-US": enUS,
3131
+ "zh-CN": zhCN
3132
+ };
3133
+ const getPath = (obj, path, variables) => {
3134
+ const pathStack = /^\w/.test(path) ? path.split(".") : [path];
3135
+ const { length } = pathStack;
3136
+ let target = obj;
3137
+ let i = 0;
3138
+ while (i <= length && target) {
3139
+ if (typeof target === "string") {
3140
+ return target;
3141
+ }
3142
+ if (variables) {
3143
+ target = target[pathStack[i]];
3144
+ Object.keys(variables).forEach((key) => {
3145
+ target = target.replace(`{${key}}`, variables[key]);
3146
+ });
3147
+ } else {
3148
+ target = target[pathStack[i]];
3149
+ }
3150
+ i = i + 1;
3151
+ if (!target) {
3152
+ return target;
3153
+ }
3154
+ }
3155
+ return target;
3156
+ };
3157
+ const useI18n = () => {
3158
+ let localeLanguage = "zh-CN";
3159
+ const bluekingLanguage = api.get(BLUEKINNG_LANGUAGE);
3160
+ if (bluekingLanguage && bluekingLanguage.toLowerCase() === "en") {
3161
+ localeLanguage = "en-US";
3162
+ }
3163
+ const languagePackage = languageMap[localeLanguage];
3164
+ const t = (path, variable) => {
3165
+ const value = getPath(languagePackage, path, variable);
3166
+ if (value === void 0) {
3167
+ console.warn(`缺少索引 * ${path} *`);
3168
+ }
3169
+ return value;
3170
+ };
3171
+ return {
3172
+ local: localeLanguage,
3173
+ t
3174
+ };
3175
+ };
3176
+ const useInputHandler = (options) => {
3177
+ const {
3178
+ apiBaseUrl,
3179
+ tenantId,
3180
+ searchQuery,
3181
+ selectedUsers,
3182
+ allowCreate = false,
3183
+ freePaste = false,
3184
+ enableMultiTenantMode = true,
3185
+ maxCount = 0,
3186
+ onAddUser,
3187
+ onBatchAddUsers
3188
+ } = options;
3189
+ const isPasting = vue.ref(false);
3190
+ const createCustomUser = (loginName) => ({
3191
+ id: loginName,
3192
+ name: loginName,
3193
+ type: USER_TYPE.CUSTOM,
3194
+ tenantId: "",
3195
+ login_name: loginName
3196
+ });
3197
+ const parsePastedText = (text) => {
3198
+ const usersList = text.split(/[,,;\n\s]+/).filter(Boolean);
3199
+ return usersList.map((user) => user.trim().replace(/\s*\(.*?\)\s*/, "")).filter(Boolean);
3200
+ };
3201
+ const mergeUsers = (existingUsers, newUsers) => {
3202
+ const userMap = /* @__PURE__ */ new Map();
3203
+ for (const user of [...existingUsers, ...newUsers]) {
3204
+ if (!userMap.has(user.id)) {
3205
+ userMap.set(user.id, user);
3206
+ }
3207
+ }
3208
+ return Array.from(userMap.values());
3209
+ };
3210
+ const handleEnterCreate = (event) => {
3211
+ if (event.key !== "Enter" || !allowCreate || !searchQuery.value.trim()) {
3212
+ return;
3213
+ }
3214
+ const customUser = createCustomUser(searchQuery.value.trim());
3215
+ const isDuplicate = selectedUsers.value.some((user) => user.id === customUser.id);
3216
+ if (!isDuplicate) {
3217
+ onAddUser(customUser);
3218
+ }
3219
+ };
3220
+ const handlePaste = async (event) => {
3221
+ var _a, _b;
3222
+ event.preventDefault();
3223
+ const pastedText = (_b = (_a = event.clipboardData) == null ? void 0 : _a.getData("text")) == null ? void 0 : _b.trim();
3224
+ if (!pastedText) return;
3225
+ isPasting.value = true;
3226
+ try {
3227
+ const usersList = parsePastedText(pastedText);
3228
+ if (usersList.length === 0) return;
3229
+ const result = await lookupUsers({
3230
+ apiBaseUrl,
3231
+ tenantId,
3232
+ exactSearchKey: "login_name",
3233
+ usersList,
3234
+ enableMultiTenantMode
3235
+ });
3236
+ const formattedUsers = formatUsers(result, enableMultiTenantMode);
3237
+ if (onBatchAddUsers) {
3238
+ let mergedUsers = mergeUsers(selectedUsers.value, formattedUsers);
3239
+ if (freePaste) {
3240
+ for (const loginName of usersList) {
3241
+ const isDuplicate = mergedUsers.some((item) => item.login_name === loginName || item.id === loginName);
3242
+ if (!isDuplicate) {
3243
+ mergedUsers.push(createCustomUser(loginName));
3244
+ }
3245
+ }
3246
+ }
3247
+ if (maxCount > 0 && mergedUsers.length > maxCount) {
3248
+ mergedUsers = mergedUsers.slice(0, maxCount);
3249
+ }
3250
+ onBatchAddUsers(mergedUsers);
3251
+ } else {
3252
+ if (formattedUsers.length > 0) {
3253
+ onAddUser(formattedUsers[0]);
3254
+ } else if (freePaste && usersList.length > 0) {
3255
+ onAddUser(createCustomUser(usersList[0]));
3256
+ }
3257
+ }
3258
+ } catch (error) {
3259
+ console.error("精准查找用户失败:", error);
3260
+ } finally {
3261
+ isPasting.value = false;
3262
+ }
3263
+ };
3264
+ return {
3265
+ isPasting,
3266
+ parsePastedText,
3267
+ handleEnterCreate,
3268
+ handlePaste
3269
+ };
3270
+ };
3271
+ const useResizeObserver = (target, callback, options = {}) => {
3272
+ const { immediate = true } = options;
3273
+ let observer = null;
3274
+ const cleanup = () => {
3275
+ if (observer) {
3276
+ observer.disconnect();
3277
+ observer = null;
3278
+ }
3279
+ };
3280
+ const observe = () => {
3281
+ cleanup();
3282
+ if (!target.value) return;
3283
+ observer = new ResizeObserver((entries) => {
3284
+ for (const entry of entries) {
3285
+ callback(entry);
3286
+ }
3287
+ });
3288
+ observer.observe(target.value);
3289
+ if (immediate && target.value) {
3290
+ const rect = target.value.getBoundingClientRect();
3291
+ const entry = {
3292
+ target: target.value,
3293
+ contentRect: rect,
3294
+ borderBoxSize: [{ blockSize: rect.height, inlineSize: rect.width }],
3295
+ contentBoxSize: [{ blockSize: rect.height, inlineSize: rect.width }],
3296
+ devicePixelContentBoxSize: [{ blockSize: rect.height, inlineSize: rect.width }]
3297
+ };
3298
+ callback(entry);
3299
+ }
3300
+ };
3301
+ vue.watch(target, observe, { immediate: true });
3302
+ vue.onUnmounted(cleanup);
3303
+ return cleanup;
3304
+ };
3305
+ const useTenantData = (apiBaseUrl, tenantId, enableMultiTenantMode = true) => {
3306
+ const tenants = vue.ref({});
3307
+ const loading = vue.ref(false);
3308
+ const fetchTenants = async () => {
3309
+ if (!apiBaseUrl || !tenantId) {
3310
+ console.warn("获取租户需要提供有效的API基础URL和租户ID");
3311
+ return;
3312
+ }
3313
+ loading.value = true;
3314
+ try {
3315
+ const result = await getTenants(apiBaseUrl, tenantId);
3316
+ const tenantMap = {};
3317
+ result.forEach((item) => {
3318
+ if (item.id && item.name) {
3319
+ tenantMap[item.id] = item.name;
3320
+ }
3321
+ });
3322
+ tenants.value = tenantMap;
3323
+ } catch (error) {
3324
+ console.error("获取租户数据失败:", error);
3325
+ } finally {
3326
+ loading.value = false;
3327
+ }
3328
+ };
3329
+ vue.onBeforeMount(() => {
3330
+ if (enableMultiTenantMode) {
3331
+ fetchTenants();
3332
+ }
3132
3333
  });
3133
- })(Sortable$1);
3134
- var SortableExports = Sortable$1.exports;
3135
- const Sortable = /* @__PURE__ */ getDefaultExportFromCjs(SortableExports);
3334
+ return {
3335
+ tenants,
3336
+ loading,
3337
+ fetchTenants
3338
+ };
3339
+ };
3136
3340
  const debounce = (fn, delay) => {
3137
3341
  let timer = null;
3138
3342
  return function(...args) {
@@ -3171,10 +3375,12 @@
3171
3375
  const performSearch = async (keyword) => {
3172
3376
  if (!(keyword == null ? void 0 : keyword.length)) {
3173
3377
  searchResults.value = [];
3378
+ loading.value = false;
3174
3379
  return;
3175
3380
  }
3176
3381
  if (enableMultiTenantMode && (!apiBaseUrl || !tenantId)) {
3177
3382
  console.warn("执行用户搜索需要提供有效的API基础URL和租户ID");
3383
+ loading.value = false;
3178
3384
  return;
3179
3385
  }
3180
3386
  loading.value = true;
@@ -3193,14 +3399,16 @@
3193
3399
  loading.value = false;
3194
3400
  }
3195
3401
  };
3196
- const debouncedSearch = debounce(performSearch, 300);
3402
+ const debouncedSearch = debounce(performSearch, SEARCH_DEBOUNCE_DELAY);
3197
3403
  const handleSearchInput = (value) => {
3198
- searchQuery.value = value;
3199
- debouncedSearch(value);
3404
+ loading.value = true;
3405
+ searchQuery.value = value.trim();
3406
+ debouncedSearch(searchQuery.value);
3200
3407
  };
3201
3408
  const clearSearch = () => {
3202
3409
  searchQuery.value = "";
3203
3410
  searchResults.value = [];
3411
+ loading.value = false;
3204
3412
  };
3205
3413
  return {
3206
3414
  searchResults,
@@ -3211,26 +3419,57 @@
3211
3419
  clearSearch
3212
3420
  };
3213
3421
  };
3214
- const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
3422
+ const useUserSelection = (options) => {
3423
+ const { selectedUserIds, excludeUserIds, userGroup, searchQuery } = options;
3424
+ const createCustomUser = (loginName) => ({
3425
+ id: loginName,
3426
+ name: loginName,
3427
+ type: USER_TYPE.CUSTOM,
3428
+ tenantId: "",
3429
+ login_name: loginName
3430
+ });
3431
+ const isUserSelected = (userId) => {
3432
+ return selectedUserIds.value.includes(userId);
3433
+ };
3434
+ const filterOptions = (options2) => {
3435
+ return options2.filter((user) => !isUserSelected(user.id)).filter((user) => {
3436
+ var _a;
3437
+ return !((_a = excludeUserIds == null ? void 0 : excludeUserIds.value) == null ? void 0 : _a.includes(user.id));
3438
+ });
3439
+ };
3440
+ const filteredUserGroup = vue.computed(() => {
3441
+ var _a;
3442
+ if (!((_a = userGroup == null ? void 0 : userGroup.value) == null ? void 0 : _a.length)) {
3443
+ return [];
3444
+ }
3445
+ return userGroup.value.filter((group) => {
3446
+ var _a2, _b;
3447
+ const isNotSelectedAndVisible = !isUserSelected(group.id) && !group.hidden;
3448
+ if (!isNotSelectedAndVisible) {
3449
+ return false;
3450
+ }
3451
+ const query = searchQuery.value.trim();
3452
+ if (!query) {
3453
+ return true;
3454
+ }
3455
+ return ((_a2 = group.id) == null ? void 0 : _a2.includes(query)) || ((_b = group.name) == null ? void 0 : _b.includes(query));
3456
+ });
3457
+ });
3458
+ return {
3459
+ createCustomUser,
3460
+ isUserSelected,
3461
+ filterOptions,
3462
+ filteredUserGroup
3463
+ };
3464
+ };
3465
+ const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
3215
3466
  ...{
3216
3467
  name: "MeTag"
3217
3468
  },
3218
3469
  __name: "me-tag",
3219
3470
  props: {
3220
- /**
3221
- * 当前用户ID
3222
- */
3223
- currentUserId: {
3224
- type: String,
3225
- default: ""
3226
- },
3227
- /**
3228
- * 是否禁用
3229
- */
3230
- isDisabled: {
3231
- type: Boolean,
3232
- default: false
3233
- }
3471
+ currentUserId: { default: "" },
3472
+ isDisabled: { type: Boolean, default: false }
3234
3473
  },
3235
3474
  emits: ["click"],
3236
3475
  setup(__props, { emit: __emit }) {
@@ -3242,11 +3481,11 @@
3242
3481
  emit("click");
3243
3482
  };
3244
3483
  return (_ctx, _cache) => {
3245
- return __props.currentUserId ? (vue.openBlock(), vue.createElementBlock(
3484
+ return _ctx.currentUserId ? (vue.openBlock(), vue.createElementBlock(
3246
3485
  "div",
3247
3486
  {
3248
3487
  key: 0,
3249
- class: vue.normalizeClass(["me-tag", { disabled: __props.isDisabled }]),
3488
+ class: vue.normalizeClass(["me-tag", { disabled: _ctx.isDisabled }]),
3250
3489
  onClick: vue.withModifiers(handleClick, ["stop"])
3251
3490
  },
3252
3491
  vue.toDisplayString(vue.unref(t)("我")),
@@ -3263,7 +3502,10 @@
3263
3502
  }
3264
3503
  return target;
3265
3504
  };
3266
- const MeTag = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-ef4a05c4"]]);
3505
+ const MeTag = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-4f251ce1"]]);
3506
+ const VirtualAvatar = "data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'?%3e%3csvg%20width='32px'%20height='32px'%20viewBox='0%200%2032%2032'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3eIcon/虚拟icon%3c/title%3e%3cg%20id='Icon/虚拟icon'%20stroke='none'%20stroke-width='1'%20fill='none'%20fill-rule='evenodd'%3e%3cpath%20d='M27.4705882,3%20C28.315259,3%2029,3.68474098%2029,4.52941178%20L29,22.4623054%20C29,23.3069762%2028.315259,23.9917172%2027.4705882,23.9917172%20L20.5882353,23.9917172%20L20.5882353,27.0244081%20L24.0294118,27.0244081%20C24.2405794,27.0244081%2024.4117647,27.1955933%2024.4117647,27.406761%20L24.4117647,28.617647%20C24.4117647,28.8288148%2024.2405795,29%2024.0294118,29%20L7.97058824,29%20C7.75942054,29%207.58823529,28.8288148%207.58823529,28.617647%20L7.58823529,27.406761%20C7.58823531,27.1955933%207.75942055,27.0244081%207.97058824,27.0244081%20L11.4117647,27.0244081%20L11.4117647,23.9917172%20L4.52941178,23.9917172%20C3.68474098,23.9917172%203,23.3069762%203,22.4623054%20L3,4.52941178%20C3,3.68474098%203.68474098,3%204.52941178,3%20L27.4705882,3%20Z%20M19,24%20L13,24%20L13,27%20L19,27%20L19,24%20Z%20M23.4117647,7%20L8.58823529,7%20C8.03595054,7%207.58823529,7.44771525%207.58823529,8%20L7.58823529,19%20C7.58823529,19.5522847%208.03595054,20%208.58823529,20%20L23.4117647,20%20C23.9640495,20%2024.4117647,19.5522847%2024.4117647,19%20L24.4117647,8%20C24.4117647,7.44771525%2023.9640495,7%2023.4117647,7%20Z%20M12,10%20C12.5522847,10%2013,10.4477153%2013,11%20L13,13%20C13,13.5522847%2012.5522847,14%2012,14%20C11.4477153,14%2011,13.5522847%2011,13%20L11,11%20C11,10.4477153%2011.4477153,10%2012,10%20Z%20M20,10%20C20.5522847,10%2021,10.4477153%2021,11%20L21,13%20C21,13.5522847%2020.5522847,14%2020,14%20C19.4477153,14%2019,13.5522847%2019,13%20L19,11%20C19,10.4477153%2019.4477153,10%2020,10%20Z%20M26,5%20C25.4477153,5%2025,5.44771525%2025,6%20C25,6.55228475%2025.4477153,7%2026,7%20C26.5522847,7%2027,6.55228475%2027,6%20C27,5.44771525%2026.5522847,5%2026,5%20Z'%20id='蒙版'%20fill='%23A3C5FD'%20fill-rule='nonzero'%3e%3c/path%3e%3c/g%3e%3c/svg%3e";
3507
+ const UserGroupAvatar = "data:image/svg+xml,%3csvg%20viewBox='0%200%201024%201024'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20style='fill:%20%23A3C5FD;'%3e%3cpath%20fill-rule='evenodd'%20d='M405.7858816%20162.66256256C416.4461344%20160.6535248%20439.8986944%20159.44810208%20457.3815104%20160.25171712%20484.2453504%20161.05533248%20494.052784%20163.4661776%20516.226112%20174.7167888%20567.8217376%20200.43247136%20597.670448%20242.22045568%20606.6250624%20301.28616416%20617.711728%20374.415136%20593.4063488%20443.5260352%20535.8409792%20500.180896%20509.8299584%20525.8965792%20505.565856%20537.5489984%20514.0940608%20557.237568%20521.3430336%20572.9080608%20546.0748224%20586.5695168%20629.2248%20620.3213504%20691.054272%20645.2334208%20760.985536%20687.4232096%20767.8080992%20703.8973216%20774.6306624%20720.3714304%20784.8645056%20752.114224%20791.6870688%20777.4280992%20799.7888608%20807.1618592%20793.3927072%20818.8142784%20761.8383584%20832.4757344%20720.4765728%20850.155264%20669.3073536%20857.3878016%20546.9276416%20862.2094912%20392.9935776%20868.2366048%20227.12002944%20858.5932224%20162.30568672%20840.1100768%20134.5890272%20832.4757344%20108.15159776%20815.1980096%20100.47621504%20799.5275136%2093.6536528%20786.2678656%2094.08006304%20784.2588288%20105.59313696%20746.4889184%20116.67980096%20709.924432%20119.23826176%20705.5045504%20141.41158944%20685.4141728%20143.84821888%20683.2001312%20146.05397248%20681.2036448%20148.2232096%20679.3252416L152.13038144%20676.0501632C159.5946992%20670.0236288%20167.98497088%20664.6722176%20184.94031712%20656.0863296L191.29263904%20652.915344C215.97973152%20640.7492736%20256.51622304%20622.3959904%20329.458464%20589.3821696%20359.7335872%20575.3189056%20371.2466592%20563.6664896%20375.084352%20542.772496%20377.2164032%20530.316464%20374.6579424%20526.7001952%20345.2356416%20496.9664352%20295.34565344%20446.338688%20274.02514592%20396.9163584%20273.59873568%20331.0199232%20273.59873568%20291.24097568%20282.12693888%20265.52529312%20307.71154784%20228.15719168%20332.8697472%20191.19089792%20365.703328%20169.49329056%20405.7858816%20162.66256256ZM668.7713728%20226.60405184C756.683056%20211.50282816%20820.4190272%20263.09867616%20827.0124032%20354.9644544%20831.8475456%20416.6277856%20815.1443264%20461.931456%20770.3093664%20510.1714752%20752.287472%20529.4674848%20747.891888%20536.5986176%20748.3314464%20548.344016%20748.7710048%20555.8946272%20751.4083552%20565.123152%20754.485264%20568.8984576%20757.5621728%20572.2542848%20788.331264%20588.1944672%20823.0563776%20604.1346464%20944.3745024%20659.92528%20966.791984%20682.996592%20958.4403712%20744.6599232%20954.923904%20771.9260224%20956.6821376%20771.0870656%20890.308816%20787.0272448%20867.4517792%20792.8999456%20845.0343008%20798.3531648%20841.0782752%20799.6116%20835.3640128%20801.2895136%20833.1662208%20797.9336864%20830.5288704%20781.5740256%20824.3750528%20739.6261824%20812.0674176%20710.6821696%20790.0894976%20687.6108576%20752.287472%20647.3409248%20703.9360448%20619.6553504%20624.3759712%20593.6476864%20597.5629088%20584.4191616%20560.64%20550.8608864%20560.64%20534.920704%20560.64%20527.7895712%20569.8707264%20514.7857408%20589.6508544%20494.6507744%20620.859504%20461.931456%20639.7605152%20429.631616%20648.5516832%20394.8149056%20655.5846208%20366.7098496%20652.0681504%20283.23364096%20642.837424%20254.7091072%20635.3649312%20231.63779328%20634.4858144%20232.47675008%20668.7713728%20226.60405184Z'%3e%3c/path%3e%3c/svg%3e";
3508
+ const UserAvatar = "data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'?%3e%3csvg%20width='32px'%20height='32px'%20viewBox='0%200%2032%2032'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3eIcon/用户%3c/title%3e%3cg%20id='Icon/用户'%20stroke='none'%20stroke-width='1'%20fill='none'%20fill-rule='evenodd'%3e%3cg%20id='user-(1)'%20transform='translate(3,%202)'%20fill='%23A3C5FD'%20fill-rule='nonzero'%3e%3cpath%20d='M13.0077612,27.9989067%20C10.3002732,27.9989067%207.59285518,28.0018792%204.88515705,27.997455%20C3.95018807,27.9959342%203.05044678,27.8282323%202.22816433,27.3628696%20C0.998627601,26.6672451%200.29953695,25.6114692%200.0864200465,24.2387462%20C-0.0656962495,23.259079%200.0147040645,22.4675755%200.0874005263,21.4879775%20C0.187970957,20.13461%200.423078914,19.3321844%200.863249688,18.0430358%20C1.22365046,16.9873982%201.73014453,16.0067633%202.49702917,15.175719%20C3.42254341,14.1726178%204.6014447,13.7297906%205.9255989,13.6440041%20C6.33292322,13.6073668%206.66741099,13.712025%206.9979768,13.9263185%20C7.58886318,14.3094892%208.17393665,14.7060014%208.79220674,15.0421658%20C10.1097776,15.758321%2011.5447274,16.1099698%2013.0616182,16.0930337%20C14.6806203,16.0750607%2016.2142496,15.63963%2017.592821,14.8169502%20C18.0555431,14.5407189%2018.5150436,14.256538%2018.9569652,13.9491996%20C19.3610679,13.6681294%2019.7808585,13.5749462%2020.274326,13.6337733%20C21.462472,13.7340074%2022.3872158,14.1103345%2023.2340106,14.8851094%20C23.902636,15.496952%2024.3685096,16.2520257%2024.7518119,17.0611566%20C25.272453,18.1598604%2025.5462904,18.7976948%2025.7441396,19.9861253%20C25.9499728,21.2233595%2026.0256808,22.2792045%2025.9924842,23.5308171%20C25.9627193,24.6543374%2025.6405577,25.6840525%2024.8535729,26.5307194%20C24.1686994,27.2671979%2023.3129402,27.7090574%2022.3211027,27.8808379%20C21.9232331,27.9495501%2021.5154185,27.9922014%2021.1120162,27.9935148%20C18.4104811,28.0036073%2015.7090862,27.9989067%2013.0077612,27.9989067%20L13.0077612,27.9989067%20Z%20M5.91775495,6.98479749%20C5.84814002,3.25685016%209.08684454,-0.00255470186%2013.0162355,1.5025268e-06%20C16.9117994,0.00256071584%2020.1304739,3.23452217%2020.1095656,7.04113598%20C20.0884528,10.8082092%2016.8998935,14.015354%2013.0058002,14.0149393%20C9.10134181,14.0145245%205.83322254,10.7695672%205.91775495,6.98479749%20Z'%20id='形状'%3e%3c/path%3e%3c/g%3e%3c/g%3e%3c/svg%3e";
3267
3509
  const UserRender = vue.defineComponent({
3268
3510
  name: "UserRender",
3269
3511
  props: {
@@ -3282,23 +3524,63 @@
3282
3524
  render: {
3283
3525
  type: Function,
3284
3526
  required: false
3527
+ },
3528
+ hasAvatar: {
3529
+ type: Boolean,
3530
+ default: false
3531
+ },
3532
+ avatarBaseUrl: {
3533
+ type: String,
3534
+ default: ""
3285
3535
  }
3286
3536
  },
3287
3537
  setup(props) {
3538
+ const getAvatarUrl = (user) => {
3539
+ if (user.type === "virtual") {
3540
+ return VirtualAvatar;
3541
+ }
3542
+ if (user.type === "userGroup") {
3543
+ return UserGroupAvatar;
3544
+ }
3545
+ if (!props.avatarBaseUrl) {
3546
+ return UserAvatar;
3547
+ }
3548
+ const loginName = user.login_name || user.bk_username || user.id;
3549
+ return `${props.avatarBaseUrl}${loginName}.png?default_when_absent=true`;
3550
+ };
3288
3551
  const defaultRender = (h2, props2) => {
3289
- return h2("div", [
3290
- h2("span", props2.user.name),
3291
- props2.user.tenantId !== props2.tenantId && props2.user.tenantId ? h2(
3292
- "span",
3293
- {
3552
+ return h2(
3553
+ "div",
3554
+ {
3555
+ style: {
3556
+ display: "flex",
3557
+ alignItems: "center"
3558
+ }
3559
+ },
3560
+ [
3561
+ props2.hasAvatar ? h2("img", {
3562
+ src: getAvatarUrl(props2.user),
3294
3563
  style: {
3295
- color: "#f59500",
3296
- marginLeft: "4px"
3564
+ width: "20px",
3565
+ height: "20px",
3566
+ borderRadius: "50%",
3567
+ marginRight: "6px",
3568
+ flexShrink: 0
3297
3569
  }
3298
- },
3299
- `@${props2.tenants[props2.user.tenantId] || props2.user.tenantId}`
3300
- ) : null
3301
- ]);
3570
+ }) : null,
3571
+ h2("span", props2.user.name),
3572
+ props2.user.tenantId !== props2.tenantId && props2.user.tenantId ? h2(
3573
+ "span",
3574
+ {
3575
+ style: {
3576
+ color: "#f59500",
3577
+ marginLeft: "4px"
3578
+ }
3579
+ },
3580
+ `@${props2.tenants[props2.user.tenantId] || props2.user.tenantId}`
3581
+ ) : null
3582
+ ]
3583
+ );
3302
3584
  };
3303
3585
  return () => {
3304
3586
  try {
@@ -3310,106 +3592,38 @@
3310
3592
  };
3311
3593
  }
3312
3594
  });
3313
- const _hoisted_1$2 = {
3595
+ const _hoisted_1$1 = {
3314
3596
  key: 0,
3315
3597
  class: "no-data"
3316
3598
  };
3317
- const _hoisted_2$2 = { class: "group-name" };
3599
+ const _hoisted_2$1 = { class: "group-name" };
3318
3600
  const _hoisted_3$1 = { class: "group-count" };
3319
- const _hoisted_4$1 = ["onClick"];
3320
- const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
3601
+ const _hoisted_4 = ["onClick"];
3602
+ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
3321
3603
  ...{
3322
3604
  name: "SelectionPopover"
3323
3605
  },
3324
3606
  __name: "selection-popover",
3325
3607
  props: {
3326
- /**
3327
- * 是否显示下拉菜单
3328
- */
3329
- isShow: {
3330
- type: Boolean,
3331
- default: false
3332
- },
3333
- /**
3334
- * 容器宽度
3335
- */
3336
- containerWidth: {
3337
- type: [Number, String],
3338
- default: "auto"
3339
- },
3340
- /**
3341
- * popover crossAxis 偏移量
3342
- */
3343
- crossAxisOffset: {
3344
- type: Number,
3345
- default: 0
3346
- },
3347
- /**
3348
- * 是否加载中
3349
- */
3350
- loading: {
3351
- type: Boolean,
3352
- default: false
3353
- },
3354
- /**
3355
- * 搜索结果选项
3356
- */
3357
- options: {
3358
- type: Array,
3359
- default: () => []
3360
- },
3361
- /**
3362
- * 搜索关键词
3363
- */
3364
- searchQuery: {
3365
- type: String,
3366
- default: ""
3367
- },
3368
- /**
3369
- * 当前租户ID
3370
- */
3371
- tenantId: {
3372
- type: String,
3373
- default: ""
3374
- },
3375
- /**
3376
- * 租户信息映射
3377
- */
3378
- tenants: {
3379
- type: Object,
3380
- default: () => ({})
3381
- },
3382
- /**
3383
- * 用户组
3384
- */
3385
- userGroup: {
3386
- type: Array,
3387
- default: () => []
3388
- },
3389
- /**
3390
- * 用户组名称
3391
- */
3392
- userGroupName: {
3393
- type: String,
3394
- default: ""
3395
- },
3396
- /**
3397
- * 无匹配人员时的提示文本
3398
- */
3399
- emptyText: {
3400
- type: String,
3401
- default: ""
3402
- },
3403
- /**
3404
- * 渲染列表项
3405
- */
3406
- renderListItem: {
3407
- type: Function
3408
- }
3608
+ avatarBaseUrl: { default: "" },
3609
+ containerWidth: { default: "auto" },
3610
+ emptyText: { default: "" },
3611
+ hasAvatar: { type: Boolean, default: false },
3612
+ isShow: { type: Boolean, default: false },
3613
+ loading: { type: Boolean, default: false },
3614
+ options: { default: () => [] },
3615
+ renderListItem: {},
3616
+ searchQuery: { default: "" },
3617
+ tenantId: { default: "" },
3618
+ tenants: { default: () => ({}) },
3619
+ userGroup: { default: () => [] },
3620
+ userGroupName: { default: "" }
3409
3621
  },
3410
- emits: ["select-user", "click-outside"],
3622
+ emits: ["click-outside", "select-user"],
3411
3623
  setup(__props, { emit: __emit }) {
3412
3624
  const { t } = useI18n();
3625
+ const slotContainerRef = vue.ref(null);
3626
+ const contentContainerRef = vue.ref(null);
3413
3627
  const props = __props;
3414
3628
  const emit = __emit;
3415
3629
  const groupedUsers = vue.computed(() => {
@@ -3418,11 +3632,11 @@
3418
3632
  groups[props.userGroupName] = props.userGroup.map((group) => ({
3419
3633
  ...group,
3420
3634
  tenantId: "",
3421
- type: "userGroup"
3635
+ type: USER_TYPE.USER_GROUP
3422
3636
  }));
3423
3637
  }
3424
3638
  props.options.forEach((user) => {
3425
- const groupName = user.data_source_type === "virtual" ? t("虚拟账号") : t("用户");
3639
+ const groupName = user.data_source_type === USER_TYPE.VIRTUAL ? t("虚拟账号") : t("用户");
3426
3640
  if (!groups[groupName]) {
3427
3641
  groups[groupName] = [];
3428
3642
  }
@@ -3434,114 +3648,150 @@
3434
3648
  emit("select-user", user);
3435
3649
  };
3436
3650
  const handleClickOutside = ({ event }) => {
3651
+ var _a, _b;
3652
+ const target = event.target;
3653
+ if ((_a = slotContainerRef.value) == null ? void 0 : _a.contains(target)) {
3654
+ return;
3655
+ }
3656
+ if ((_b = contentContainerRef.value) == null ? void 0 : _b.contains(target)) {
3657
+ return;
3658
+ }
3437
3659
  emit("click-outside", event);
3438
3660
  };
3439
3661
  return (_ctx, _cache) => {
3440
3662
  return vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Popover), {
3441
3663
  arrow: false,
3442
3664
  "ext-cls": "bk-user-selector-popover",
3443
- "is-show": __props.isShow,
3444
- offset: { mainAxis: 4, crossAxis: __props.crossAxisOffset },
3665
+ "is-show": _ctx.isShow,
3666
+ offset: { mainAxis: 4 },
3445
3667
  placement: "bottom-start",
3446
3668
  theme: "light",
3447
3669
  trigger: "manual",
3448
- width: __props.containerWidth,
3670
+ width: _ctx.containerWidth,
3449
3671
  onClickoutside: handleClickOutside
3450
3672
  }, {
3451
3673
  content: vue.withCtx(() => [
3452
- vue.createVNode(vue.unref(bkuiVue.Loading), {
3453
- class: "dropdown-content",
3454
- loading: __props.loading,
3455
- mode: "spin",
3456
- size: "mini"
3457
- }, {
3458
- default: vue.withCtx(() => [
3459
- __props.options.length === 0 && __props.userGroup.length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [
3460
- vue.createElementVNode(
3461
- "span",
3462
- null,
3463
- vue.toDisplayString(__props.emptyText),
3464
- 1
3465
- /* TEXT */
3466
- )
3467
- ])) : (vue.openBlock(true), vue.createElementBlock(
3468
- vue.Fragment,
3469
- { key: 1 },
3470
- vue.renderList(groupedUsers.value, (group, groupName) => {
3471
- return vue.openBlock(), vue.createElementBlock("div", {
3472
- key: groupName,
3473
- class: "user-group"
3474
- }, [
3475
- Object.keys(groupedUsers.value).length > 1 || group.some((user) => user.type === "userGroup") ? (vue.openBlock(), vue.createElementBlock("div", {
3476
- key: 0,
3477
- class: "group-header",
3478
- onClick: _cache[0] || (_cache[0] = vue.withModifiers(() => {
3479
- }, ["prevent"]))
3480
- }, [
3481
- vue.createElementVNode(
3482
- "span",
3483
- _hoisted_2$2,
3484
- vue.toDisplayString(groupName),
3485
- 1
3486
- /* TEXT */
3487
- ),
3488
- vue.createElementVNode(
3489
- "span",
3490
- _hoisted_3$1,
3491
- "(" + vue.toDisplayString(group.length) + ")",
3492
- 1
3493
- /* TEXT */
3494
- )
3495
- ])) : vue.createCommentVNode("v-if", true),
3496
- (vue.openBlock(true), vue.createElementBlock(
3497
- vue.Fragment,
3674
+ vue.createElementVNode(
3675
+ "div",
3676
+ {
3677
+ ref_key: "contentContainerRef",
3678
+ ref: contentContainerRef
3679
+ },
3680
+ [
3681
+ vue.createVNode(vue.unref(bkuiVue.Loading), {
3682
+ class: "dropdown-content",
3683
+ loading: _ctx.loading,
3684
+ mode: "spin",
3685
+ size: "mini"
3686
+ }, {
3687
+ default: vue.withCtx(() => [
3688
+ _ctx.options.length === 0 && _ctx.userGroup.length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
3689
+ vue.createElementVNode(
3690
+ "span",
3498
3691
  null,
3499
- vue.renderList(group, (user) => {
3500
- return vue.openBlock(), vue.createElementBlock("div", {
3501
- key: user.id,
3502
- class: "user-option",
3503
- onClick: vue.withModifiers(($event) => selectUser(user), ["prevent"])
3692
+ vue.toDisplayString(_ctx.emptyText),
3693
+ 1
3694
+ /* TEXT */
3695
+ )
3696
+ ])) : (vue.openBlock(true), vue.createElementBlock(
3697
+ vue.Fragment,
3698
+ { key: 1 },
3699
+ vue.renderList(groupedUsers.value, (group, groupName) => {
3700
+ return vue.openBlock(), vue.createElementBlock("div", {
3701
+ key: groupName,
3702
+ class: "user-group"
3703
+ }, [
3704
+ Object.keys(groupedUsers.value).length > 1 || group.some((user) => user.type === "userGroup") ? (vue.openBlock(), vue.createElementBlock("div", {
3705
+ key: 0,
3706
+ class: "group-header",
3707
+ onClick: _cache[0] || (_cache[0] = vue.withModifiers(() => {
3708
+ }, ["prevent"]))
3504
3709
  }, [
3505
- vue.createVNode(vue.unref(UserRender), {
3506
- render: __props.renderListItem,
3507
- "tenant-id": __props.tenantId,
3508
- tenants: __props.tenants,
3509
- user
3510
- }, null, 8, ["render", "tenant-id", "tenants", "user"])
3511
- ], 8, _hoisted_4$1);
3512
- }),
3513
- 128
3514
- /* KEYED_FRAGMENT */
3515
- ))
3516
- ]);
3517
- }),
3518
- 128
3519
- /* KEYED_FRAGMENT */
3520
- ))
3521
- ]),
3522
- _: 1
3523
- /* STABLE */
3524
- }, 8, ["loading"])
3710
+ vue.createElementVNode(
3711
+ "span",
3712
+ _hoisted_2$1,
3713
+ vue.toDisplayString(groupName),
3714
+ 1
3715
+ /* TEXT */
3716
+ ),
3717
+ vue.createElementVNode(
3718
+ "span",
3719
+ _hoisted_3$1,
3720
+ "(" + vue.toDisplayString(group.length) + ")",
3721
+ 1
3722
+ /* TEXT */
3723
+ )
3724
+ ])) : vue.createCommentVNode("v-if", true),
3725
+ (vue.openBlock(true), vue.createElementBlock(
3726
+ vue.Fragment,
3727
+ null,
3728
+ vue.renderList(group, (user) => {
3729
+ return vue.openBlock(), vue.createElementBlock("div", {
3730
+ key: user.id,
3731
+ class: "user-option",
3732
+ onClick: vue.withModifiers(($event) => selectUser(user), ["prevent"]),
3733
+ onMousedown: _cache[1] || (_cache[1] = vue.withModifiers(() => {
3734
+ }, ["prevent"]))
3735
+ }, [
3736
+ vue.createVNode(vue.unref(UserRender), {
3737
+ "avatar-base-url": _ctx.avatarBaseUrl,
3738
+ "has-avatar": _ctx.hasAvatar,
3739
+ render: _ctx.renderListItem,
3740
+ "tenant-id": _ctx.tenantId,
3741
+ tenants: _ctx.tenants,
3742
+ user
3743
+ }, null, 8, ["avatar-base-url", "has-avatar", "render", "tenant-id", "tenants", "user"])
3744
+ ], 40, _hoisted_4);
3745
+ }),
3746
+ 128
3747
+ /* KEYED_FRAGMENT */
3748
+ ))
3749
+ ]);
3750
+ }),
3751
+ 128
3752
+ /* KEYED_FRAGMENT */
3753
+ ))
3754
+ ]),
3755
+ _: 1
3756
+ /* STABLE */
3757
+ }, 8, ["loading"])
3758
+ ],
3759
+ 512
3760
+ /* NEED_PATCH */
3761
+ )
3525
3762
  ]),
3526
3763
  default: vue.withCtx(() => [
3527
- vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
3764
+ vue.createElementVNode(
3765
+ "div",
3766
+ {
3767
+ ref_key: "slotContainerRef",
3768
+ ref: slotContainerRef
3769
+ },
3770
+ [
3771
+ vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
3772
+ ],
3773
+ 512
3774
+ /* NEED_PATCH */
3775
+ )
3528
3776
  ]),
3529
3777
  _: 3
3530
3778
  /* FORWARDED */
3531
- }, 8, ["is-show", "offset", "width"]);
3779
+ }, 8, ["is-show", "width"]);
3532
3780
  };
3533
3781
  }
3534
3782
  });
3535
- const SelectionPopover = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-78875ea6"]]);
3536
- const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
3783
+ const SelectionPopover = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-d5a338f0"]]);
3784
+ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
3537
3785
  ...{
3538
3786
  name: "UserTag"
3539
3787
  },
3540
3788
  __name: "user-tag",
3541
3789
  props: {
3542
3790
  active: { type: Boolean },
3791
+ avatarBaseUrl: {},
3543
3792
  currentTenantId: {},
3544
3793
  draggable: { type: Boolean },
3794
+ hasAvatar: { type: Boolean },
3545
3795
  renderTag: { type: Function },
3546
3796
  showTenant: { type: Boolean },
3547
3797
  tenants: {},
@@ -3566,11 +3816,13 @@
3566
3816
  }, {
3567
3817
  default: vue.withCtx(() => [
3568
3818
  vue.createVNode(vue.unref(UserRender), {
3819
+ "avatar-base-url": _ctx.avatarBaseUrl,
3820
+ "has-avatar": _ctx.hasAvatar,
3569
3821
  render: _ctx.renderTag,
3570
3822
  "tenant-id": _ctx.currentTenantId,
3571
3823
  tenants: _ctx.tenants,
3572
3824
  user: _ctx.user
3573
- }, null, 8, ["render", "tenant-id", "tenants", "user"])
3825
+ }, null, 8, ["avatar-base-url", "has-avatar", "render", "tenant-id", "tenants", "user"])
3574
3826
  ]),
3575
3827
  _: 1
3576
3828
  /* STABLE */
@@ -3578,84 +3830,176 @@
3578
3830
  };
3579
3831
  }
3580
3832
  });
3581
- const UserTag = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-48ac8fc1"]]);
3582
- const _hoisted_1$1 = ["onClick"];
3583
- const _hoisted_2$1 = ["placeholder"];
3584
- const _hoisted_3 = { class: "hidden-users" };
3585
- const _hoisted_4 = ["placeholder"];
3586
- const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
3833
+ const UserTag = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-1f2e0737"]]);
3834
+ const _hoisted_1 = ["placeholder"];
3835
+ const _hoisted_2 = { class: "hidden-users" };
3836
+ const _hoisted_3 = ["placeholder"];
3837
+ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
3587
3838
  ...{
3588
- name: "BkUserSelectorMultiple"
3839
+ name: "BkUserSelector"
3589
3840
  },
3590
- __name: "multiple-selector",
3841
+ __name: "user-selector",
3591
3842
  props: {
3592
3843
  draggable: { type: Boolean, default: false },
3593
- freePaste: { type: Boolean, default: false },
3594
- modelValue: { default: () => [] },
3595
- selectedUsers: { default: () => [] },
3596
- tenants: { default: () => ({}) },
3844
+ maxCount: { default: 0 },
3845
+ modelValue: { default: "" },
3846
+ multiple: { type: Boolean, default: false },
3597
3847
  allowCreate: { type: Boolean, default: false },
3598
3848
  apiBaseUrl: { default: "" },
3849
+ avatarBaseUrl: { default: "" },
3850
+ hasAvatar: { type: Boolean, default: false },
3599
3851
  currentUserId: { default: "" },
3600
- disabled: { type: Boolean },
3852
+ disabled: { type: Boolean, default: false },
3601
3853
  emptyText: { default: "" },
3602
- enableMultiTenantMode: { type: Boolean },
3603
- exactSearchKey: { default: "bk_username" },
3854
+ enableMultiTenantMode: { type: Boolean, default: true },
3855
+ exactSearchKey: { default: DEFAULT_EXACT_SEARCH_KEY },
3604
3856
  excludeUserIds: { default: () => [] },
3857
+ freePaste: { type: Boolean, default: false },
3605
3858
  placeholder: { default: "" },
3606
- tenantId: { default: "" },
3607
- userGroupName: { default: "" },
3608
3859
  renderListItem: {},
3609
3860
  renderTag: {},
3610
- userGroup: { default: () => [] }
3861
+ tenantId: { default: "" },
3862
+ userGroup: { default: () => [] },
3863
+ userGroupName: { default: "" }
3611
3864
  },
3612
- emits: [
3613
- "update:selectedUsers",
3614
- "add-user",
3615
- "remove-user",
3616
- "dragStart",
3617
- "dragEnd",
3618
- "focus",
3619
- "blur"
3620
- ],
3865
+ emits: ["blur", "change", "dragEnd", "dragStart", "focus", "update:modelValue"],
3621
3866
  setup(__props, { emit: __emit }) {
3867
+ const { t } = useI18n();
3868
+ bkuiVue.provideGlobalConfig({
3869
+ prefix: "bk"
3870
+ });
3622
3871
  const props = __props;
3623
3872
  const emit = __emit;
3873
+ const { tenants = {} } = useTenantData(props.apiBaseUrl, props.tenantId, props.enableMultiTenantMode);
3624
3874
  const {
3625
3875
  searchResults,
3626
3876
  loading: searchLoading,
3627
3877
  searchQuery,
3628
- // clearSearch,
3878
+ clearSearch,
3629
3879
  handleSearchInput
3630
3880
  } = useUserSearch(props.apiBaseUrl, props.tenantId, props.enableMultiTenantMode);
3881
+ const { fetchCurrentUser } = useCurrentUser({
3882
+ apiBaseUrl: props.apiBaseUrl,
3883
+ tenantId: props.tenantId,
3884
+ currentUserId: props.currentUserId || "",
3885
+ exactSearchKey: props.exactSearchKey,
3886
+ enableMultiTenantMode: props.enableMultiTenantMode
3887
+ });
3631
3888
  const containerRef = vue.ref(null);
3632
- const tagsContainerRef = vue.ref(null);
3633
3889
  const sortableContainerRef = vue.ref(null);
3634
3890
  const collapsedContainerRef = vue.ref(null);
3635
3891
  const inlineInputRef = vue.ref(null);
3636
3892
  const lastInputRef = vue.ref(null);
3637
- const collapsedInputRef = vue.ref(null);
3638
3893
  const isFocused = vue.ref(false);
3639
- const showDropdown = vue.ref(false);
3640
3894
  const activeTagIndex = vue.ref(-1);
3641
3895
  const sortableInstance = vue.ref(null);
3642
3896
  const visibleUsers = vue.ref([]);
3643
3897
  const hiddenCount = vue.ref(0);
3644
- const options = vue.computed(() => {
3645
- return searchResults.value.filter((user) => !props.selectedUsers.some((selectedUser) => selectedUser.id === user.id)).filter((user) => !props.excludeUserIds.includes(user.id));
3898
+ const selectedUsers = vue.ref([]);
3899
+ const showDropdown = vue.computed(() => {
3900
+ return isFocused.value && (props.userGroup.length > 0 || searchQuery.value.trim() !== "");
3646
3901
  });
3647
- const userGroupFilter = vue.computed(() => {
3648
- return props.userGroup.filter((group) => {
3649
- var _a, _b;
3650
- const filtered = !props.selectedUsers.some((user) => user.id === group.id) && !group.hidden;
3651
- if (filtered) {
3652
- return ((_a = group.id) == null ? void 0 : _a.includes(searchQuery.value)) || ((_b = group.name) == null ? void 0 : _b.includes(searchQuery.value));
3653
- }
3654
- return false;
3655
- });
3902
+ const modelValueIds = vue.computed(() => {
3903
+ if (props.multiple) {
3904
+ return Array.isArray(props.modelValue) ? props.modelValue : [];
3905
+ }
3906
+ return props.modelValue ? [props.modelValue] : [];
3907
+ });
3908
+ const computedPlaceholder = vue.computed(() => props.placeholder || t("请输入人员名称搜索"));
3909
+ const computedUserGroupName = vue.computed(() => props.userGroupName || t("用户群组"));
3910
+ const computedEmptyText = vue.computed(() => props.emptyText || t("无匹配人员"));
3911
+ const selectedUserIds = vue.computed(() => selectedUsers.value.map((user) => user.id));
3912
+ const isMaxCountReached = vue.computed(() => {
3913
+ if (!props.maxCount || props.maxCount <= 0) return false;
3914
+ return selectedUsers.value.length >= props.maxCount;
3915
+ });
3916
+ const isMeTagDisabled = vue.computed(
3917
+ () => isMaxCountReached.value || !!props.currentUserId && selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId)
3918
+ );
3919
+ const userTagCommonProps = vue.computed(() => ({
3920
+ avatarBaseUrl: props.avatarBaseUrl,
3921
+ currentTenantId: props.tenantId,
3922
+ hasAvatar: props.hasAvatar,
3923
+ renderTag: props.renderTag,
3924
+ tenants
3925
+ }));
3926
+ const { filteredUserGroup, filterOptions, createCustomUser } = useUserSelection({
3927
+ selectedUserIds,
3928
+ excludeUserIds: vue.toRef(props, "excludeUserIds"),
3929
+ userGroup: vue.toRef(props, "userGroup"),
3930
+ searchQuery
3931
+ });
3932
+ const { handlePaste } = useInputHandler({
3933
+ apiBaseUrl: props.apiBaseUrl,
3934
+ tenantId: props.tenantId,
3935
+ searchQuery,
3936
+ selectedUsers,
3937
+ allowCreate: props.allowCreate,
3938
+ freePaste: props.freePaste,
3939
+ enableMultiTenantMode: props.enableMultiTenantMode,
3940
+ maxCount: props.maxCount,
3941
+ onAddUser: addUser,
3942
+ onBatchAddUsers: props.multiple ? updateSelectedUsers : void 0
3943
+ });
3944
+ const displayOptions = vue.computed(() => filterOptions(searchResults.value));
3945
+ const inputWidth = vue.computed(() => {
3946
+ const query = searchQuery.value;
3947
+ if (!query) return "20px";
3948
+ const charWidth = query.split("").reduce((acc, char) => {
3949
+ return acc + (/[\u4e00-\u9fa5]/.test(char) ? 12 : 8);
3950
+ }, 0);
3951
+ return `${Math.max(20, charWidth + 4)}px`;
3656
3952
  });
3953
+ const initSelectedUsers = async () => {
3954
+ const ids = modelValueIds.value;
3955
+ if (ids.length === 0) {
3956
+ selectedUsers.value = [];
3957
+ return;
3958
+ }
3959
+ let userGroupSelected = [];
3960
+ if (props.userGroup.length > 0) {
3961
+ const result = props.userGroup.filter((group) => ids.includes(group.id));
3962
+ userGroupSelected = result.map((group) => ({
3963
+ ...group,
3964
+ tenantId: "",
3965
+ type: USER_TYPE.USER_GROUP
3966
+ }));
3967
+ }
3968
+ try {
3969
+ const result = await lookupUsers({
3970
+ apiBaseUrl: props.apiBaseUrl,
3971
+ tenantId: props.tenantId,
3972
+ exactSearchKey: "bk_username",
3973
+ usersList: ids,
3974
+ enableMultiTenantMode: props.enableMultiTenantMode
3975
+ });
3976
+ const selectedList = [...userGroupSelected, ...formatUsers(result, props.enableMultiTenantMode)];
3977
+ if (props.allowCreate) {
3978
+ selectedList.push(
3979
+ ...ids.filter((id) => !selectedList.some((user) => user.id === id)).map((id) => ({ id, name: id, type: USER_TYPE.CUSTOM, tenantId: "" }))
3980
+ );
3981
+ }
3982
+ selectedUsers.value = ids.map((id) => selectedList.find((user) => user.id === id)).filter(Boolean);
3983
+ } catch (error) {
3984
+ console.error("获取选中用户信息失败:", error);
3985
+ selectedUsers.value = [];
3986
+ }
3987
+ };
3988
+ function updateSelectedUsers(users) {
3989
+ selectedUsers.value = users;
3990
+ if (props.multiple) {
3991
+ const ids = users.map((user) => user.id);
3992
+ emit("update:modelValue", ids);
3993
+ emit("change", users);
3994
+ } else {
3995
+ const user = users.length > 0 ? users[0] : null;
3996
+ const id = user ? user.id : "";
3997
+ emit("update:modelValue", id);
3998
+ emit("change", user);
3999
+ }
4000
+ }
3657
4001
  const initSortable = () => {
3658
- if (!props.draggable || !sortableContainerRef.value) return;
4002
+ if (!props.draggable || !props.multiple || !sortableContainerRef.value) return;
3659
4003
  if (sortableInstance.value) {
3660
4004
  sortableInstance.value.destroy();
3661
4005
  }
@@ -3668,276 +4012,206 @@
3668
4012
  onEnd: (evt) => {
3669
4013
  const { oldIndex, newIndex } = evt;
3670
4014
  if (oldIndex === newIndex || oldIndex === void 0 || newIndex === void 0) return;
3671
- const updatedUsers = [...props.selectedUsers];
4015
+ const updatedUsers = [...selectedUsers.value];
3672
4016
  const [movedUser] = updatedUsers.splice(oldIndex, 1);
3673
4017
  updatedUsers.splice(newIndex, 0, movedUser);
3674
- emit("update:selectedUsers", updatedUsers);
4018
+ updateSelectedUsers(updatedUsers);
3675
4019
  emit("dragEnd", evt);
3676
4020
  }
3677
4021
  });
3678
4022
  };
3679
4023
  const calculateVisibleUsers = () => {
3680
- if (!collapsedContainerRef.value || !props.selectedUsers.length) {
4024
+ if (!selectedUsers.value.length) {
3681
4025
  visibleUsers.value = [];
3682
4026
  hiddenCount.value = 0;
3683
4027
  return;
3684
4028
  }
4029
+ if (!collapsedContainerRef.value) {
4030
+ visibleUsers.value = [...selectedUsers.value];
4031
+ hiddenCount.value = 0;
4032
+ return;
4033
+ }
3685
4034
  const containerWidth = collapsedContainerRef.value.offsetWidth;
3686
4035
  const tagElements = collapsedContainerRef.value.querySelectorAll(".user-tag");
4036
+ if (tagElements.length !== selectedUsers.value.length) {
4037
+ visibleUsers.value = [...selectedUsers.value];
4038
+ hiddenCount.value = 0;
4039
+ vue.nextTick(calculateVisibleUsers);
4040
+ return;
4041
+ }
3687
4042
  const visibleCount = calculateVisibleTags(
3688
4043
  collapsedContainerRef.value,
3689
4044
  tagElements,
3690
- containerWidth - 100
3691
- // 为输入框和更多标签预留空间
4045
+ containerWidth - RESERVED_SPACE_FOR_INPUT
3692
4046
  );
3693
- visibleUsers.value = props.selectedUsers.slice(0, visibleCount);
3694
- hiddenCount.value = Math.max(0, props.selectedUsers.length - visibleCount);
4047
+ visibleUsers.value = selectedUsers.value.slice(0, visibleCount);
4048
+ hiddenCount.value = Math.max(0, selectedUsers.value.length - visibleCount);
3695
4049
  };
3696
4050
  const handleFocus = () => {
3697
4051
  isFocused.value = true;
3698
- if (props.userGroup.length > 0) {
3699
- showDropdown.value = true;
3700
- } else {
3701
- showDropdown.value = false;
3702
- }
3703
4052
  activeTagIndex.value = -1;
3704
4053
  vue.nextTick(() => {
3705
- if (lastInputRef.value) {
3706
- lastInputRef.value.focus();
3707
- }
4054
+ var _a;
4055
+ return (_a = lastInputRef.value) == null ? void 0 : _a.focus();
3708
4056
  });
3709
4057
  };
4058
+ const scheduleVisibleUsersCalculation = () => {
4059
+ if (!isFocused.value) {
4060
+ vue.nextTick(calculateVisibleUsers);
4061
+ }
4062
+ };
3710
4063
  const handleClickOutside = (event) => {
3711
4064
  const target = event.target;
3712
4065
  const container = containerRef.value;
3713
- if ((container == null ? void 0 : container.contains(target)) || container === target) {
3714
- return;
3715
- }
3716
- if (isFocused.value) {
3717
- emit("blur");
3718
- }
4066
+ if ((container == null ? void 0 : container.contains(target)) || container === target) return;
4067
+ if (isFocused.value) emit("blur");
3719
4068
  isFocused.value = false;
3720
- showDropdown.value = false;
3721
4069
  activeTagIndex.value = -1;
3722
- searchQuery.value = "";
3723
- vue.nextTick(() => {
3724
- calculateVisibleUsers();
3725
- });
4070
+ clearSearch();
4071
+ scheduleVisibleUsersCalculation();
3726
4072
  };
3727
4073
  const handleContainerClick = () => {
3728
4074
  activeTagIndex.value = -1;
3729
4075
  vue.nextTick(() => {
3730
- if (lastInputRef.value) {
3731
- lastInputRef.value.focus();
3732
- }
4076
+ var _a;
4077
+ return (_a = lastInputRef.value) == null ? void 0 : _a.focus();
3733
4078
  });
3734
4079
  };
3735
4080
  const handleTagClick = (index) => {
3736
4081
  activeTagIndex.value = index;
3737
4082
  vue.nextTick(() => {
3738
4083
  var _a;
3739
- if (activeTagIndex.value === props.selectedUsers.length - 1) {
3740
- if (lastInputRef.value) {
3741
- lastInputRef.value.focus();
3742
- }
3743
- } else if ((_a = inlineInputRef.value) == null ? void 0 : _a[0]) {
3744
- inlineInputRef.value[0].focus();
3745
- }
4084
+ const isLastTag = index === selectedUsers.value.length - 1;
4085
+ const targetInput = isLastTag ? lastInputRef.value : (_a = inlineInputRef.value) == null ? void 0 : _a[0];
4086
+ targetInput == null ? void 0 : targetInput.focus();
3746
4087
  });
3747
4088
  };
3748
4089
  const handleInputFocus = () => {
3749
4090
  emit("focus");
3750
- if (!isFocused.value) {
3751
- isFocused.value = true;
3752
- }
3753
- if (searchQuery.value.length >= 1) {
3754
- showDropdown.value = true;
3755
- }
4091
+ isFocused.value = true;
3756
4092
  };
3757
4093
  const handleInput = () => {
3758
4094
  handleSearchInput(searchQuery.value);
3759
- if (searchQuery.value.length >= 1) {
3760
- showDropdown.value = true;
3761
- } else {
3762
- showDropdown.value = false;
3763
- }
3764
4095
  };
3765
4096
  const addCurrentUser = async () => {
3766
- if (!props.currentUserId || props.selectedUsers.some((user) => user.id === props.currentUserId)) return;
3767
- try {
3768
- const result = await lookupUsers({
3769
- apiBaseUrl: props.apiBaseUrl,
3770
- tenantId: props.tenantId,
3771
- exactSearchKey: props.exactSearchKey,
3772
- usersList: [props.currentUserId],
3773
- enableMultiTenantMode: props.enableMultiTenantMode
3774
- });
3775
- const formattedUsers = formatUsers(result, props.enableMultiTenantMode);
3776
- if (formattedUsers.length > 0) {
3777
- if (!props.selectedUsers.some((item) => item.id === formattedUsers[0].id)) {
3778
- emit("update:selectedUsers", [...props.selectedUsers, formattedUsers[0]]);
3779
- emit("add-user", formattedUsers[0]);
3780
- }
3781
- searchQuery.value = "";
3782
- showDropdown.value = false;
3783
- }
3784
- } catch (error) {
3785
- console.error("获取当前用户信息失败:", error);
4097
+ if (!props.currentUserId || selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId))
4098
+ return;
4099
+ if (props.multiple && isMaxCountReached.value) {
4100
+ return;
3786
4101
  }
3787
- };
3788
- const handlePaste = async (event) => {
3789
- var _a;
3790
- event.preventDefault();
3791
- const pastedText = ((_a = event.clipboardData) == null ? void 0 : _a.getData("text")) || "";
3792
- if (pastedText.trim()) {
3793
- try {
3794
- const usersList = pastedText.trim().split(/[,,;\n\s]+/).filter(Boolean);
3795
- const users = usersList.map((user) => user.trim().replace(/\s*\(.*?\)\s*/, "")).filter((user) => user);
3796
- const result = await lookupUsers({
3797
- apiBaseUrl: props.apiBaseUrl,
3798
- tenantId: props.tenantId,
3799
- exactSearchKey: "login_name",
3800
- usersList: users,
3801
- enableMultiTenantMode: props.enableMultiTenantMode
3802
- });
3803
- const formattedUsers = formatUsers(result, props.enableMultiTenantMode);
3804
- if (formattedUsers.length > 0) {
3805
- const userMap = /* @__PURE__ */ new Map();
3806
- [...props.selectedUsers, ...formattedUsers].forEach((user) => {
3807
- if (!userMap.has(user.id)) {
3808
- userMap.set(user.id, user);
3809
- }
3810
- });
3811
- const updatedUsers = Array.from(userMap.values());
3812
- if (props.freePaste) {
3813
- const pastedUsers = usersList.map((user) => ({
3814
- id: user,
3815
- name: user,
3816
- type: "custom",
3817
- tenantId: "",
3818
- login_name: user
3819
- }));
3820
- pastedUsers.forEach((user) => {
3821
- if (!updatedUsers.some((item) => item.login_name === user.login_name)) {
3822
- addUser(user);
3823
- }
3824
- });
3825
- } else {
3826
- emit("update:selectedUsers", updatedUsers);
3827
- }
3828
- } else {
3829
- if (props.freePaste) {
3830
- const pastedUsers = usersList.map((user) => ({
3831
- id: user,
3832
- name: user,
3833
- type: "custom",
3834
- tenantId: "",
3835
- login_name: user
3836
- }));
3837
- pastedUsers.forEach((user) => {
3838
- if (!props.selectedUsers.some((item) => item.login_name === user.login_name)) {
3839
- addUser(user);
3840
- }
3841
- });
3842
- }
3843
- }
3844
- } catch (error) {
3845
- console.error("精准查找用户失败:", error);
4102
+ const currentUser = await fetchCurrentUser();
4103
+ if (currentUser) {
4104
+ if (!props.multiple) {
4105
+ updateSelectedUsers([currentUser]);
4106
+ } else if (!selectedUsers.value.some((item) => item.id === currentUser.id)) {
4107
+ updateSelectedUsers([...selectedUsers.value, currentUser]);
3846
4108
  }
4109
+ clearSearch();
4110
+ isFocused.value = true;
4111
+ vue.nextTick(() => {
4112
+ var _a;
4113
+ return (_a = lastInputRef.value) == null ? void 0 : _a.focus();
4114
+ });
3847
4115
  }
3848
4116
  };
4117
+ const onPaste = (event) => {
4118
+ handlePaste(event);
4119
+ };
3849
4120
  const handleKeyDown = (event) => {
3850
- if (event.key === "Backspace" && !searchQuery.value && props.selectedUsers.length > 0) {
4121
+ if (event.key === "Backspace" && !searchQuery.value && selectedUsers.value.length > 0) {
3851
4122
  if (activeTagIndex.value >= 0) {
3852
- const userToRemove = props.selectedUsers[activeTagIndex.value];
4123
+ const userToRemove = selectedUsers.value[activeTagIndex.value];
3853
4124
  removeUser(userToRemove);
3854
- if (activeTagIndex.value > 0) {
3855
- activeTagIndex.value = activeTagIndex.value - 1;
3856
- } else {
3857
- activeTagIndex.value = -1;
3858
- }
4125
+ activeTagIndex.value = activeTagIndex.value > 0 ? activeTagIndex.value - 1 : -1;
3859
4126
  } else {
3860
- const lastUser = props.selectedUsers[props.selectedUsers.length - 1];
4127
+ const lastUser = selectedUsers.value[selectedUsers.value.length - 1];
3861
4128
  removeUser(lastUser);
3862
4129
  }
3863
- } else if (event.key === "Enter" && props.allowCreate) {
3864
- addUser({
3865
- id: searchQuery.value,
3866
- name: searchQuery.value,
3867
- type: "custom",
3868
- tenantId: "",
3869
- login_name: searchQuery.value
3870
- });
4130
+ } else if (event.key === "Enter" && props.allowCreate && searchQuery.value) {
4131
+ addUser(createCustomUser(searchQuery.value));
3871
4132
  }
3872
4133
  };
3873
- const addUser = (user) => {
4134
+ function addUser(user) {
3874
4135
  if (!(user == null ? void 0 : user.id)) return;
3875
- if (!props.selectedUsers.some((item) => item.id === user.id)) {
4136
+ if (props.multiple && isMaxCountReached.value) {
4137
+ clearSearch();
4138
+ return;
4139
+ }
4140
+ if (!props.multiple) {
4141
+ updateSelectedUsers([user]);
4142
+ } else if (!selectedUsers.value.some((item) => item.id === user.id)) {
4143
+ const updatedUsers = activeTagIndex.value !== -1 ? [
4144
+ ...selectedUsers.value.slice(0, activeTagIndex.value + 1),
4145
+ user,
4146
+ ...selectedUsers.value.slice(activeTagIndex.value + 1)
4147
+ ] : [...selectedUsers.value, user];
4148
+ updateSelectedUsers(updatedUsers);
4149
+ }
4150
+ if (activeTagIndex.value !== -1) {
4151
+ activeTagIndex.value = activeTagIndex.value + 1;
4152
+ }
4153
+ clearSearch();
4154
+ isFocused.value = true;
4155
+ vue.nextTick(() => {
4156
+ var _a, _b, _c;
3876
4157
  if (activeTagIndex.value !== -1) {
3877
- const updatedUsers = [
3878
- ...props.selectedUsers.slice(0, activeTagIndex.value + 1),
3879
- user,
3880
- ...props.selectedUsers.slice(activeTagIndex.value + 1)
3881
- ];
3882
- emit("update:selectedUsers", updatedUsers);
4158
+ (_b = (_a = inlineInputRef.value) == null ? void 0 : _a[0]) == null ? void 0 : _b.focus();
3883
4159
  } else {
3884
- emit("update:selectedUsers", [...props.selectedUsers, user]);
4160
+ (_c = lastInputRef.value) == null ? void 0 : _c.focus();
3885
4161
  }
3886
- emit("add-user", user);
3887
- }
3888
- searchQuery.value = "";
3889
- showDropdown.value = false;
3890
- vue.nextTick(() => {
3891
- var _a;
3892
- (_a = lastInputRef.value) == null ? void 0 : _a.focus();
3893
4162
  });
3894
- };
4163
+ }
3895
4164
  const removeUser = (user) => {
3896
4165
  if (!(user == null ? void 0 : user.id)) return;
3897
- const updatedUsers = props.selectedUsers.filter((item) => item.id !== user.id);
3898
- emit("update:selectedUsers", updatedUsers);
3899
- emit("remove-user", user);
4166
+ const updatedUsers = selectedUsers.value.filter((item) => item.id !== user.id);
4167
+ updateSelectedUsers(updatedUsers);
3900
4168
  if (activeTagIndex.value >= updatedUsers.length) {
3901
- activeTagIndex.value = updatedUsers.length - 1;
3902
- }
3903
- if (!isFocused.value) {
3904
- vue.nextTick(() => {
3905
- calculateVisibleUsers();
3906
- });
4169
+ activeTagIndex.value = updatedUsers.length - 1;
3907
4170
  }
4171
+ scheduleVisibleUsersCalculation();
3908
4172
  };
3909
- const crossAxisOffset = vue.ref(0);
3910
4173
  vue.watch(
3911
- () => props.selectedUsers,
4174
+ selectedUsers,
3912
4175
  () => {
3913
- visibleUsers.value = [...props.selectedUsers];
3914
- if (!isFocused.value) {
3915
- vue.nextTick(() => {
3916
- calculateVisibleUsers();
3917
- });
3918
- }
4176
+ scheduleVisibleUsersCalculation();
3919
4177
  },
3920
4178
  { deep: true }
3921
4179
  );
3922
4180
  vue.watch(isFocused, (newVal) => {
3923
4181
  if (newVal) {
3924
- vue.nextTick(() => {
3925
- initSortable();
3926
- });
4182
+ vue.nextTick(() => initSortable());
3927
4183
  }
3928
4184
  });
3929
- const handleResize = () => {
3930
- if (!isFocused.value) {
3931
- calculateVisibleUsers();
4185
+ vue.watch(
4186
+ () => props.userGroup,
4187
+ () => {
4188
+ initSelectedUsers();
3932
4189
  }
3933
- };
4190
+ );
4191
+ vue.watch(
4192
+ () => props.modelValue,
4193
+ () => {
4194
+ const currentIds = selectedUsers.value.map((u) => u.id);
4195
+ const newIds = modelValueIds.value;
4196
+ if (currentIds.length !== newIds.length || !currentIds.every((id, index) => id === newIds[index])) {
4197
+ initSelectedUsers();
4198
+ }
4199
+ },
4200
+ { deep: true }
4201
+ );
4202
+ useResizeObserver(containerRef, () => {
4203
+ scheduleVisibleUsersCalculation();
4204
+ });
4205
+ vue.onBeforeMount(() => {
4206
+ initSelectedUsers();
4207
+ });
3934
4208
  vue.onMounted(() => {
3935
4209
  initSortable();
3936
- calculateVisibleUsers();
3937
- window.addEventListener("resize", handleResize);
3938
- vue.nextTick(() => {
3939
- calculateVisibleUsers();
3940
- });
4210
+ vue.nextTick(calculateVisibleUsers);
4211
+ });
4212
+ vue.onUnmounted(() => {
4213
+ var _a;
4214
+ (_a = sortableInstance.value) == null ? void 0 : _a.destroy();
3941
4215
  });
3942
4216
  return (_ctx, _cache) => {
3943
4217
  return vue.openBlock(), vue.createElementBlock(
@@ -3945,34 +4219,32 @@
3945
4219
  {
3946
4220
  ref_key: "containerRef",
3947
4221
  ref: containerRef,
3948
- class: vue.normalizeClass(["multiple-selector", { "is-disabled": _ctx.disabled }])
4222
+ class: vue.normalizeClass(["bk-user-selector", { "is-disabled": _ctx.disabled }])
3949
4223
  },
3950
4224
  [
3951
4225
  vue.createCommentVNode(" 下拉选项列表 "),
3952
4226
  vue.createVNode(SelectionPopover, {
4227
+ "avatar-base-url": _ctx.avatarBaseUrl,
3953
4228
  "container-width": containerRef.value ? containerRef.value.offsetWidth : "auto",
3954
- "cross-axis-offset": crossAxisOffset.value,
3955
- "empty-text": _ctx.emptyText,
4229
+ "empty-text": computedEmptyText.value,
4230
+ "has-avatar": _ctx.hasAvatar,
3956
4231
  "is-show": showDropdown.value,
3957
4232
  loading: vue.unref(searchLoading),
3958
- options: options.value,
4233
+ options: displayOptions.value,
3959
4234
  "render-list-item": _ctx.renderListItem,
3960
4235
  "search-query": vue.unref(searchQuery),
3961
4236
  "tenant-id": _ctx.tenantId,
3962
- tenants: _ctx.tenants,
3963
- "user-group": userGroupFilter.value,
3964
- "user-group-name": _ctx.userGroupName,
4237
+ tenants: vue.unref(tenants),
4238
+ "user-group": vue.unref(filteredUserGroup),
4239
+ "user-group-name": computedUserGroupName.value,
3965
4240
  onClickOutside: handleClickOutside,
3966
4241
  onSelectUser: addUser
3967
4242
  }, {
3968
4243
  default: vue.withCtx(() => [
3969
4244
  vue.createCommentVNode(" 聚焦状态 - 可编辑模式 "),
3970
- isFocused.value ? (vue.openBlock(), vue.createElementBlock(
4245
+ vue.withDirectives(vue.createElementVNode(
3971
4246
  "div",
3972
4247
  {
3973
- key: 0,
3974
- ref_key: "tagsContainerRef",
3975
- ref: tagsContainerRef,
3976
4248
  class: "tags-container focused",
3977
4249
  onClick: vue.withModifiers(handleContainerClick, ["stop"])
3978
4250
  },
@@ -3989,24 +4261,20 @@
3989
4261
  (vue.openBlock(true), vue.createElementBlock(
3990
4262
  vue.Fragment,
3991
4263
  null,
3992
- vue.renderList(_ctx.selectedUsers, (user, index) => {
4264
+ vue.renderList(selectedUsers.value, (user, index) => {
3993
4265
  return vue.openBlock(), vue.createElementBlock("div", {
3994
4266
  key: user.id,
3995
- class: "tag-wrapper",
3996
- onClick: vue.withModifiers(($event) => handleTagClick(index), ["stop"])
4267
+ class: "tag-wrapper"
3997
4268
  }, [
3998
- vue.createVNode(UserTag, {
4269
+ vue.createVNode(UserTag, vue.mergeProps({ ref_for: true }, userTagCommonProps.value, {
3999
4270
  active: index === activeTagIndex.value,
4000
- "current-tenant-id": _ctx.tenantId,
4001
- draggable: _ctx.draggable,
4002
- "render-tag": _ctx.renderTag,
4003
- tenants: _ctx.tenants,
4271
+ draggable: _ctx.draggable && _ctx.multiple,
4004
4272
  user,
4005
4273
  onClick: ($event) => handleTagClick(index),
4006
4274
  onClose: ($event) => removeUser(user)
4007
- }, null, 8, ["active", "current-tenant-id", "draggable", "render-tag", "tenants", "user", "onClick", "onClose"]),
4275
+ }), null, 16, ["active", "draggable", "user", "onClick", "onClose"]),
4008
4276
  vue.createCommentVNode(" 在当前激活标签后插入输入框 "),
4009
- index === activeTagIndex.value && activeTagIndex.value !== _ctx.selectedUsers.length - 1 ? vue.withDirectives((vue.openBlock(), vue.createElementBlock(
4277
+ index === activeTagIndex.value && activeTagIndex.value !== selectedUsers.value.length - 1 ? vue.withDirectives((vue.openBlock(), vue.createElementBlock(
4010
4278
  "input",
4011
4279
  {
4012
4280
  key: 0,
@@ -4014,42 +4282,45 @@
4014
4282
  ref_key: "inlineInputRef",
4015
4283
  ref: inlineInputRef,
4016
4284
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(searchQuery) ? searchQuery.value = $event : null),
4017
- class: "search-input inline",
4285
+ autofocus: "",
4286
+ class: "search-input input-inline",
4287
+ style: vue.normalizeStyle({ width: inputWidth.value }),
4018
4288
  onFocus: handleInputFocus,
4019
4289
  onInput: handleInput,
4020
4290
  onKeydown: handleKeyDown,
4021
- onPaste: handlePaste
4291
+ onPaste
4022
4292
  },
4023
4293
  null,
4024
- 544
4025
- /* NEED_HYDRATION, NEED_PATCH */
4294
+ 36
4295
+ /* STYLE, NEED_HYDRATION */
4026
4296
  )), [
4027
4297
  [vue.vModelText, vue.unref(searchQuery)]
4028
4298
  ]) : vue.createCommentVNode("v-if", true)
4029
- ], 8, _hoisted_1$1);
4299
+ ]);
4030
4300
  }),
4031
4301
  128
4032
4302
  /* KEYED_FRAGMENT */
4033
4303
  )),
4034
4304
  vue.createCommentVNode(" 最后一个输入框 "),
4035
- activeTagIndex.value === -1 || activeTagIndex.value === _ctx.selectedUsers.length - 1 ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
4305
+ activeTagIndex.value === -1 || activeTagIndex.value === selectedUsers.value.length - 1 ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
4036
4306
  key: 0,
4037
4307
  ref_key: "lastInputRef",
4038
4308
  ref: lastInputRef,
4039
4309
  "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => vue.isRef(searchQuery) ? searchQuery.value = $event : null),
4040
- class: "search-input last",
4041
- placeholder: !_ctx.selectedUsers.length ? _ctx.placeholder : "",
4310
+ autofocus: "",
4311
+ class: "search-input input-last",
4312
+ placeholder: !selectedUsers.value.length ? computedPlaceholder.value : "",
4042
4313
  onFocus: handleInputFocus,
4043
4314
  onInput: handleInput,
4044
4315
  onKeydown: handleKeyDown,
4045
- onPaste: handlePaste
4046
- }, null, 40, _hoisted_2$1)), [
4316
+ onPaste
4317
+ }, null, 40, _hoisted_1)), [
4047
4318
  [vue.vModelText, vue.unref(searchQuery)]
4048
4319
  ]) : vue.createCommentVNode("v-if", true),
4049
4320
  vue.createCommentVNode(' "我"标签 '),
4050
4321
  vue.createVNode(MeTag, {
4051
4322
  "current-user-id": _ctx.currentUserId,
4052
- "is-disabled": !!_ctx.currentUserId && _ctx.selectedUsers.some((user) => user.id === _ctx.currentUserId),
4323
+ "is-disabled": isMeTagDisabled.value,
4053
4324
  onClick: addCurrentUser
4054
4325
  }, null, 8, ["current-user-id", "is-disabled"])
4055
4326
  ],
@@ -4059,580 +4330,102 @@
4059
4330
  ],
4060
4331
  512
4061
4332
  /* NEED_PATCH */
4062
- )) : (vue.openBlock(), vue.createElementBlock(
4063
- vue.Fragment,
4064
- { key: 1 },
4333
+ ), [
4334
+ [vue.vShow, isFocused.value]
4335
+ ]),
4336
+ vue.createCommentVNode(" 未聚焦状态 - 只读展示模式 "),
4337
+ vue.withDirectives(vue.createElementVNode(
4338
+ "div",
4339
+ {
4340
+ ref_key: "collapsedContainerRef",
4341
+ ref: collapsedContainerRef,
4342
+ class: "tags-container tags-container-collapsed",
4343
+ onClick: vue.withModifiers(handleFocus, ["stop"])
4344
+ },
4065
4345
  [
4066
- vue.createCommentVNode(" 未聚焦状态 - 只读展示模式 "),
4067
- vue.createElementVNode(
4068
- "div",
4069
- {
4070
- ref_key: "collapsedContainerRef",
4071
- ref: collapsedContainerRef,
4072
- class: "tags-container collapsed",
4073
- onClick: vue.withModifiers(handleFocus, ["stop"])
4074
- },
4075
- [
4076
- (vue.openBlock(true), vue.createElementBlock(
4077
- vue.Fragment,
4078
- null,
4079
- vue.renderList(visibleUsers.value, (user) => {
4080
- return vue.openBlock(), vue.createBlock(UserTag, {
4081
- key: user.id,
4082
- "current-tenant-id": _ctx.tenantId,
4083
- "render-tag": _ctx.renderTag,
4084
- "show-tenant": true,
4085
- tenants: _ctx.tenants,
4086
- user,
4087
- onClick: handleFocus,
4088
- onClose: ($event) => removeUser(user)
4089
- }, null, 8, ["current-tenant-id", "render-tag", "tenants", "user", "onClose"]);
4090
- }),
4091
- 128
4092
- /* KEYED_FRAGMENT */
4093
- )),
4094
- vue.createCommentVNode(" 显示折叠标签数量 "),
4095
- hiddenCount.value > 0 ? (vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Popover), {
4096
- key: 0,
4097
- placement: "top"
4098
- }, {
4099
- content: vue.withCtx(() => [
4100
- vue.createElementVNode("div", _hoisted_3, [
4101
- (vue.openBlock(true), vue.createElementBlock(
4102
- vue.Fragment,
4103
- null,
4104
- vue.renderList(_ctx.selectedUsers.slice(visibleUsers.value.length), (user) => {
4105
- return vue.openBlock(), vue.createBlock(vue.unref(UserRender), {
4106
- key: user.id,
4107
- "tenant-id": _ctx.tenantId,
4108
- tenants: _ctx.tenants,
4109
- user
4110
- }, null, 8, ["tenant-id", "tenants", "user"]);
4111
- }),
4112
- 128
4113
- /* KEYED_FRAGMENT */
4114
- ))
4115
- ])
4116
- ]),
4346
+ (vue.openBlock(true), vue.createElementBlock(
4347
+ vue.Fragment,
4348
+ null,
4349
+ vue.renderList(visibleUsers.value, (user) => {
4350
+ return vue.openBlock(), vue.createBlock(UserTag, vue.mergeProps({
4351
+ key: user.id,
4352
+ ref_for: true
4353
+ }, userTagCommonProps.value, {
4354
+ "show-tenant": true,
4355
+ user,
4356
+ onClick: handleFocus,
4357
+ onClose: ($event) => removeUser(user)
4358
+ }), null, 16, ["user", "onClose"]);
4359
+ }),
4360
+ 128
4361
+ /* KEYED_FRAGMENT */
4362
+ )),
4363
+ vue.createCommentVNode(" 显示折叠标签数量 "),
4364
+ hiddenCount.value > 0 ? (vue.openBlock(), vue.createBlock(vue.unref(bkuiVue.Popover), {
4365
+ key: 0,
4366
+ placement: "top"
4367
+ }, {
4368
+ content: vue.withCtx(() => [
4369
+ vue.createElementVNode("div", _hoisted_2, [
4370
+ (vue.openBlock(true), vue.createElementBlock(
4371
+ vue.Fragment,
4372
+ null,
4373
+ vue.renderList(selectedUsers.value.slice(visibleUsers.value.length), (user) => {
4374
+ return vue.openBlock(), vue.createBlock(vue.unref(UserRender), {
4375
+ key: user.id,
4376
+ "avatar-base-url": _ctx.avatarBaseUrl,
4377
+ "has-avatar": _ctx.hasAvatar,
4378
+ "tenant-id": _ctx.tenantId,
4379
+ tenants: vue.unref(tenants),
4380
+ user
4381
+ }, null, 8, ["avatar-base-url", "has-avatar", "tenant-id", "tenants", "user"]);
4382
+ }),
4383
+ 128
4384
+ /* KEYED_FRAGMENT */
4385
+ ))
4386
+ ])
4387
+ ]),
4388
+ default: vue.withCtx(() => [
4389
+ vue.createVNode(vue.unref(bkuiVue.Tag), null, {
4117
4390
  default: vue.withCtx(() => [
4118
- vue.createVNode(vue.unref(bkuiVue.Tag), null, {
4119
- default: vue.withCtx(() => [
4120
- vue.createTextVNode(
4121
- " +" + vue.toDisplayString(hiddenCount.value),
4122
- 1
4123
- /* TEXT */
4124
- )
4125
- ]),
4126
- _: 1
4127
- /* STABLE */
4128
- })
4391
+ vue.createTextVNode(
4392
+ " +" + vue.toDisplayString(hiddenCount.value),
4393
+ 1
4394
+ /* TEXT */
4395
+ )
4129
4396
  ]),
4130
4397
  _: 1
4131
4398
  /* STABLE */
4132
- })) : vue.createCommentVNode("v-if", true),
4133
- vue.createCommentVNode(" 搜索输入框 "),
4134
- vue.withDirectives(vue.createElementVNode("input", {
4135
- ref_key: "collapsedInputRef",
4136
- ref: collapsedInputRef,
4137
- "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => vue.isRef(searchQuery) ? searchQuery.value = $event : null),
4138
- class: "search-input collapsed",
4139
- placeholder: !_ctx.selectedUsers.length ? _ctx.placeholder : "",
4140
- onFocus: handleFocus
4141
- }, null, 40, _hoisted_4), [
4142
- [vue.vModelText, vue.unref(searchQuery)]
4143
- ]),
4144
- vue.createCommentVNode(' 未聚焦状态下的"我"标签 '),
4145
- vue.createVNode(MeTag, {
4146
- "current-user-id": _ctx.currentUserId,
4147
- "is-disabled": !!_ctx.currentUserId && _ctx.selectedUsers.some((user) => user[props.exactSearchKey] === _ctx.currentUserId),
4148
- onClick: addCurrentUser
4149
- }, null, 8, ["current-user-id", "is-disabled"])
4150
- ],
4151
- 512
4152
- /* NEED_PATCH */
4153
- )
4399
+ })
4400
+ ]),
4401
+ _: 1
4402
+ /* STABLE */
4403
+ })) : vue.createCommentVNode("v-if", true),
4404
+ vue.createCommentVNode(" 搜索输入框 "),
4405
+ vue.withDirectives(vue.createElementVNode("input", {
4406
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => vue.isRef(searchQuery) ? searchQuery.value = $event : null),
4407
+ class: "search-input search-input-collapsed",
4408
+ placeholder: !selectedUsers.value.length ? computedPlaceholder.value : "",
4409
+ onFocus: handleFocus
4410
+ }, null, 40, _hoisted_3), [
4411
+ [vue.vModelText, vue.unref(searchQuery)]
4412
+ ]),
4413
+ vue.createCommentVNode(' 未聚焦状态下的""标签 '),
4414
+ vue.createVNode(MeTag, {
4415
+ "current-user-id": _ctx.currentUserId,
4416
+ "is-disabled": isMeTagDisabled.value,
4417
+ onClick: addCurrentUser
4418
+ }, null, 8, ["current-user-id", "is-disabled"])
4154
4419
  ],
4155
- 2112
4156
- /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
4157
- ))
4158
- ]),
4159
- _: 1
4160
- /* STABLE */
4161
- }, 8, ["container-width", "cross-axis-offset", "empty-text", "is-show", "loading", "options", "render-list-item", "search-query", "tenant-id", "tenants", "user-group", "user-group-name"])
4162
- ],
4163
- 2
4164
- /* CLASS */
4165
- );
4166
- };
4167
- }
4168
- });
4169
- const MultipleSelector = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-2a532f24"]]);
4170
- const _hoisted_1 = { class: "input-container" };
4171
- const _hoisted_2 = ["placeholder"];
4172
- const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
4173
- ...{
4174
- name: "BkUserSelectorSingle"
4175
- },
4176
- __name: "single-selector",
4177
- props: {
4178
- modelValue: { default: "" },
4179
- tenants: {},
4180
- allowCreate: { type: Boolean },
4181
- apiBaseUrl: { default: "" },
4182
- currentUserId: { default: "" },
4183
- disabled: { type: Boolean },
4184
- emptyText: { default: "" },
4185
- enableMultiTenantMode: { type: Boolean },
4186
- exactSearchKey: { default: "bk_username" },
4187
- excludeUserIds: { default: () => [] },
4188
- freePaste: { type: Boolean },
4189
- placeholder: { default: "" },
4190
- tenantId: { default: "" },
4191
- userGroupName: { default: "" },
4192
- renderListItem: {},
4193
- renderTag: {},
4194
- userGroup: { default: () => [] }
4195
- },
4196
- emits: ["update:modelValue", "change", "focus", "blur"],
4197
- setup(__props, { emit: __emit }) {
4198
- const props = __props;
4199
- const emit = __emit;
4200
- const containerRef = vue.ref(null);
4201
- const inputRef = vue.ref(null);
4202
- const options = vue.ref([]);
4203
- const isLoading = vue.ref(false);
4204
- const selectedUser = vue.ref(props.modelValue || "");
4205
- const searchQuery = vue.ref("");
4206
- const showDropdown = vue.ref(false);
4207
- const userGroupFilter = vue.computed(() => {
4208
- return props.userGroup.filter((group) => {
4209
- var _a, _b;
4210
- const filtered = group.id !== selectedUser.value && !group.hidden;
4211
- if (filtered) {
4212
- return ((_a = group.id) == null ? void 0 : _a.includes(searchQuery.value)) || ((_b = group.name) == null ? void 0 : _b.includes(searchQuery.value));
4213
- }
4214
- return false;
4215
- });
4216
- });
4217
- const selectedUserInfo = vue.computed(() => {
4218
- const userGroup = (props.userGroup || []).map((group) => ({
4219
- ...group,
4220
- tenantId: "",
4221
- type: "userGroup"
4222
- }));
4223
- const list = [...options.value, ...userGroup];
4224
- const selectedUserInfo2 = list.find((user) => user.id === selectedUser.value);
4225
- emit("change", selectedUserInfo2 || null);
4226
- return selectedUserInfo2;
4227
- });
4228
- const initSelectedUser = async () => {
4229
- if (typeof props.modelValue === "string" && props.modelValue) {
4230
- try {
4231
- isLoading.value = true;
4232
- const result = await lookupUsers({
4233
- apiBaseUrl: props.apiBaseUrl,
4234
- tenantId: props.tenantId,
4235
- exactSearchKey: props.exactSearchKey,
4236
- usersList: [props.modelValue],
4237
- enableMultiTenantMode: props.enableMultiTenantMode
4238
- });
4239
- options.value = formatUsers(result, props.enableMultiTenantMode).filter(
4240
- (user) => !props.excludeUserIds.includes(user.id)
4241
- );
4242
- if (props.userGroup.length > 0) {
4243
- const groupResult = props.userGroup.filter((group) => group.id == props.modelValue);
4244
- options.value = groupResult.map((group) => ({
4245
- ...group,
4246
- tenantId: "",
4247
- type: "userGroup"
4248
- }));
4249
- }
4250
- if (props.allowCreate && options.value.length === 0) {
4251
- options.value.push({
4252
- id: props.modelValue,
4253
- name: props.modelValue,
4254
- type: "custom",
4255
- tenantId: ""
4256
- });
4257
- }
4258
- } catch (error) {
4259
- console.error("获取用户信息失败:", error);
4260
- } finally {
4261
- isLoading.value = false;
4262
- }
4263
- } else {
4264
- options.value = [];
4265
- }
4266
- };
4267
- vue.onBeforeMount(async () => {
4268
- initSelectedUser();
4269
- });
4270
- const addCurrentUser = async () => {
4271
- if (!props.currentUserId || selectedUser.value === props.currentUserId) return;
4272
- try {
4273
- const result = await lookupUsers({
4274
- apiBaseUrl: props.apiBaseUrl,
4275
- tenantId: props.tenantId,
4276
- exactSearchKey: props.exactSearchKey,
4277
- usersList: [props.currentUserId],
4278
- enableMultiTenantMode: props.enableMultiTenantMode
4279
- });
4280
- const formattedResults = formatUsers(result, props.enableMultiTenantMode);
4281
- if (formattedResults.length > 0) {
4282
- options.value = formattedResults.filter((user) => !props.excludeUserIds.includes(user.id));
4283
- addUser(formattedResults[0]);
4284
- }
4285
- } catch (error) {
4286
- console.error("获取当前用户信息失败:", error);
4287
- }
4288
- };
4289
- const fetchUsers = async (keyword = "") => {
4290
- if (!(keyword == null ? void 0 : keyword.length)) {
4291
- options.value = [];
4292
- isLoading.value = false;
4293
- return;
4294
- }
4295
- isLoading.value = true;
4296
- try {
4297
- const result = await searchUsers({
4298
- apiBaseUrl: props.apiBaseUrl,
4299
- tenantId: props.tenantId,
4300
- keyword,
4301
- enableMultiTenantMode: props.enableMultiTenantMode
4302
- });
4303
- options.value = formatUsers(result, props.enableMultiTenantMode).filter((user) => !selectedUser.value || user.id !== selectedUser.value).filter((user) => !props.excludeUserIds.includes(user.id));
4304
- } catch (error) {
4305
- console.error("获取用户列表失败:", error);
4306
- options.value = [];
4307
- } finally {
4308
- isLoading.value = false;
4309
- }
4310
- };
4311
- const handleKeyDown = (event) => {
4312
- if (event.key === "Enter") {
4313
- if (props.allowCreate) {
4314
- const customUser = {
4315
- id: searchQuery.value,
4316
- name: searchQuery.value,
4317
- tenantId: "",
4318
- type: "custom"
4319
- };
4320
- options.value.push(customUser);
4321
- addUser(customUser);
4322
- }
4323
- }
4324
- };
4325
- const handlePaste = (event) => {
4326
- var _a;
4327
- event.preventDefault();
4328
- const pastedText = ((_a = event.clipboardData) == null ? void 0 : _a.getData("text").trim()) || "";
4329
- if (props.freePaste) {
4330
- const customUser = { id: pastedText, name: pastedText, type: "custom", tenantId: "", login_name: pastedText };
4331
- if (!options.value.some((item) => item.login_name === customUser.login_name)) {
4332
- options.value.push(customUser);
4333
- }
4334
- addUser(customUser);
4335
- }
4336
- };
4337
- const addUser = (user) => {
4338
- selectedUser.value = user.id;
4339
- searchQuery.value = "";
4340
- showDropdown.value = false;
4341
- };
4342
- const removeSelectedUser = () => {
4343
- selectedUser.value = "";
4344
- searchQuery.value = "";
4345
- };
4346
- const handleInputFocus = () => {
4347
- if (searchQuery.value.length >= 1 || Array.isArray(props.userGroup) && props.userGroup.length > 0) {
4348
- showDropdown.value = true;
4349
- }
4350
- emit("focus");
4351
- };
4352
- let timer = null;
4353
- const handleInput = () => {
4354
- showDropdown.value = searchQuery.value.length >= 1;
4355
- isLoading.value = true;
4356
- clearTimeout(timer);
4357
- timer = setTimeout(() => {
4358
- fetchUsers(searchQuery.value);
4359
- }, 300);
4360
- };
4361
- const handleClickOutside = () => {
4362
- setTimeout(() => {
4363
- showDropdown.value = false;
4364
- }, 0);
4365
- };
4366
- vue.watch(
4367
- () => props.modelValue,
4368
- (newVal) => {
4369
- selectedUser.value = newVal;
4370
- }
4371
- );
4372
- vue.watch(selectedUser, (newVal) => {
4373
- emit("update:modelValue", newVal);
4374
- });
4375
- return (_ctx, _cache) => {
4376
- return vue.withDirectives((vue.openBlock(), vue.createElementBlock(
4377
- "div",
4378
- {
4379
- ref_key: "containerRef",
4380
- ref: containerRef,
4381
- class: vue.normalizeClass(["single-selector", { "is-disabled": _ctx.disabled }])
4382
- },
4383
- [
4384
- vue.createCommentVNode(" 使用新的公共下拉选项组件 "),
4385
- vue.createVNode(SelectionPopover, {
4386
- "container-width": containerRef.value ? containerRef.value.offsetWidth : "auto",
4387
- "empty-text": _ctx.emptyText,
4388
- "is-show": showDropdown.value,
4389
- loading: isLoading.value,
4390
- options: options.value,
4391
- "render-list-item": _ctx.renderListItem,
4392
- "search-query": searchQuery.value,
4393
- "tenant-id": _ctx.tenantId,
4394
- tenants: _ctx.tenants,
4395
- "user-group": userGroupFilter.value,
4396
- "user-group-name": _ctx.userGroupName,
4397
- onSelectUser: addUser
4398
- }, {
4399
- default: vue.withCtx(() => [
4400
- vue.createCommentVNode(" 输入框 "),
4401
- vue.createElementVNode("div", _hoisted_1, [
4402
- vue.createCommentVNode(" 用户标签显示 "),
4403
- selectedUserInfo.value ? (vue.openBlock(), vue.createElementBlock("div", {
4404
- key: 0,
4405
- onClick: vue.withModifiers(removeSelectedUser, ["stop"])
4406
- }, [
4407
- vue.createVNode(UserTag, {
4408
- "current-tenant-id": _ctx.tenantId,
4409
- "render-tag": _ctx.renderTag,
4410
- tenants: _ctx.tenants,
4411
- user: selectedUserInfo.value,
4412
- onClose: removeSelectedUser
4413
- }, null, 8, ["current-tenant-id", "render-tag", "tenants", "user"])
4414
- ])) : vue.createCommentVNode("v-if", true),
4415
- vue.withDirectives(vue.createElementVNode("input", {
4416
- ref_key: "inputRef",
4417
- ref: inputRef,
4418
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchQuery.value = $event),
4419
- class: "search-input",
4420
- placeholder: selectedUserInfo.value ? "" : _ctx.placeholder,
4421
- onBlur: _cache[1] || (_cache[1] = ($event) => emit("blur")),
4422
- onFocus: handleInputFocus,
4423
- onInput: handleInput,
4424
- onKeydown: handleKeyDown,
4425
- onPaste: handlePaste
4426
- }, null, 40, _hoisted_2), [
4427
- [vue.vModelText, searchQuery.value]
4428
- ]),
4429
- vue.createCommentVNode(' "我"标签 '),
4430
- vue.createVNode(MeTag, {
4431
- "current-user-id": _ctx.currentUserId,
4432
- "is-disabled": !!_ctx.currentUserId && !!selectedUserInfo.value && selectedUserInfo.value[_ctx.exactSearchKey] === _ctx.currentUserId,
4433
- onClick: addCurrentUser
4434
- }, null, 8, ["current-user-id", "is-disabled"])
4420
+ 512
4421
+ /* NEED_PATCH */
4422
+ ), [
4423
+ [vue.vShow, !isFocused.value]
4435
4424
  ])
4436
4425
  ]),
4437
4426
  _: 1
4438
4427
  /* STABLE */
4439
- }, 8, ["container-width", "empty-text", "is-show", "loading", "options", "render-list-item", "search-query", "tenant-id", "tenants", "user-group", "user-group-name"])
4440
- ],
4441
- 2
4442
- /* CLASS */
4443
- )), [
4444
- [vue.unref(bkuiVue.clickoutside), handleClickOutside]
4445
- ]);
4446
- };
4447
- }
4448
- });
4449
- const SingleSelector = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-cbe352a6"]]);
4450
- const _sfc_main = /* @__PURE__ */ vue.defineComponent({
4451
- ...{
4452
- name: "BkUserSelector"
4453
- },
4454
- __name: "user-selector",
4455
- props: {
4456
- draggable: { type: Boolean, default: false },
4457
- modelValue: { default: "" },
4458
- multiple: { type: Boolean, default: false },
4459
- allowCreate: { type: Boolean, default: false },
4460
- apiBaseUrl: { default: "" },
4461
- currentUserId: { default: "" },
4462
- disabled: { type: Boolean, default: false },
4463
- emptyText: { default: "" },
4464
- enableMultiTenantMode: { type: Boolean, default: true },
4465
- exactSearchKey: { default: "bk_username" },
4466
- excludeUserIds: { default: () => [] },
4467
- freePaste: { type: Boolean, default: false },
4468
- placeholder: { default: "" },
4469
- tenantId: { default: "" },
4470
- userGroupName: { default: "" },
4471
- renderListItem: {},
4472
- renderTag: {},
4473
- userGroup: { default: () => [] }
4474
- },
4475
- emits: ["update:modelValue", "change", "dragStart", "dragEnd", "focus", "blur"],
4476
- setup(__props, { emit: __emit }) {
4477
- const { t } = useI18n();
4478
- bkuiVue.provideGlobalConfig({
4479
- prefix: "bk"
4480
- });
4481
- const props = __props;
4482
- const emit = __emit;
4483
- const { tenants = {} } = useTenantData(props.apiBaseUrl, props.tenantId, props.enableMultiTenantMode);
4484
- const selectedUsers = vue.ref([]);
4485
- const selectedUser = vue.ref(props.multiple ? "" : props.modelValue);
4486
- const selectedUserIds = vue.computed(() => {
4487
- return props.multiple ? selectedUsers.value.map((user) => user.id) : [];
4488
- });
4489
- const placeholder = vue.computed(() => props.placeholder || t("请输入人员名称搜索"));
4490
- const userGroupName = vue.computed(() => props.userGroupName || t("用户群组"));
4491
- const emptyText = vue.computed(() => props.emptyText || t("无匹配人员"));
4492
- const initSelectedUsers = async () => {
4493
- if (props.multiple) {
4494
- const ids = Array.isArray(props.modelValue) ? props.modelValue : [];
4495
- let userGroupSelected = [];
4496
- if (props.userGroup.length > 0) {
4497
- const result = props.userGroup.filter((group) => ids.includes(group.id));
4498
- userGroupSelected = result.map((group) => ({
4499
- ...group,
4500
- tenantId: "",
4501
- type: "userGroup"
4502
- }));
4503
- }
4504
- if (ids.length > 0) {
4505
- try {
4506
- const result = await lookupUsers({
4507
- apiBaseUrl: props.apiBaseUrl,
4508
- tenantId: props.tenantId,
4509
- exactSearchKey: "bk_username",
4510
- usersList: ids,
4511
- enableMultiTenantMode: props.enableMultiTenantMode
4512
- });
4513
- const selectedList = [...userGroupSelected, ...formatUsers(result, props.enableMultiTenantMode)];
4514
- if (props.allowCreate) {
4515
- selectedList.push(
4516
- ...ids.filter((id) => !selectedList.some((user) => user.id === id)).map((id) => ({ id, name: id, type: "custom", tenantId: "" }))
4517
- );
4518
- }
4519
- selectedUsers.value = ids.map((id) => selectedList.find((user) => user.id === id)).filter(Boolean);
4520
- } catch (error) {
4521
- console.error("获取选中用户信息失败:", error);
4522
- }
4523
- } else {
4524
- selectedUsers.value = [];
4525
- }
4526
- } else {
4527
- selectedUser.value = props.modelValue;
4528
- }
4529
- };
4530
- const handleUpdateUser = (user) => {
4531
- emit("change", user);
4532
- };
4533
- const handleUpdateSelectedUsers = (users) => {
4534
- selectedUsers.value = users;
4535
- emit(
4536
- "update:modelValue",
4537
- users.map((user) => user.id)
4538
- );
4539
- emit("change", users);
4540
- };
4541
- const handleFocus = () => {
4542
- emit("focus");
4543
- };
4544
- const handleBlur = () => {
4545
- emit("blur");
4546
- };
4547
- vue.watch(selectedUser, (newVal) => {
4548
- if (!props.multiple) {
4549
- emit("update:modelValue", newVal);
4550
- }
4551
- });
4552
- vue.watch(
4553
- () => props.userGroup,
4554
- () => {
4555
- initSelectedUsers();
4556
- }
4557
- );
4558
- vue.watch(
4559
- () => props.modelValue,
4560
- () => {
4561
- initSelectedUsers();
4562
- },
4563
- { deep: true }
4564
- );
4565
- vue.onBeforeMount(() => {
4566
- initSelectedUsers();
4567
- });
4568
- return (_ctx, _cache) => {
4569
- return vue.openBlock(), vue.createElementBlock(
4570
- "section",
4571
- {
4572
- ref: "containerRef",
4573
- class: vue.normalizeClass(["bk-user-selector", { "is-disabled": _ctx.disabled }])
4574
- },
4575
- [
4576
- vue.createCommentVNode(" 单选模式 "),
4577
- !_ctx.multiple ? (vue.openBlock(), vue.createBlock(SingleSelector, {
4578
- key: 0,
4579
- modelValue: selectedUser.value,
4580
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedUser.value = $event),
4581
- "allow-create": _ctx.allowCreate,
4582
- "api-base-url": _ctx.apiBaseUrl,
4583
- "current-user-id": _ctx.currentUserId,
4584
- disabled: _ctx.disabled,
4585
- "empty-text": emptyText.value,
4586
- "enable-multi-tenant-mode": _ctx.enableMultiTenantMode,
4587
- "exact-search-key": _ctx.exactSearchKey,
4588
- "exclude-user-ids": _ctx.excludeUserIds,
4589
- placeholder: placeholder.value,
4590
- "render-list-item": _ctx.renderListItem,
4591
- "render-tag": _ctx.renderTag,
4592
- "tenant-id": _ctx.tenantId,
4593
- tenants: vue.unref(tenants),
4594
- "user-group": _ctx.userGroup,
4595
- "user-group-name": userGroupName.value,
4596
- "free-paste": _ctx.freePaste,
4597
- onBlur: handleBlur,
4598
- onChange: handleUpdateUser,
4599
- onFocus: handleFocus
4600
- }, null, 8, ["modelValue", "allow-create", "api-base-url", "current-user-id", "disabled", "empty-text", "enable-multi-tenant-mode", "exact-search-key", "exclude-user-ids", "placeholder", "render-list-item", "render-tag", "tenant-id", "tenants", "user-group", "user-group-name", "free-paste"])) : (vue.openBlock(), vue.createElementBlock(
4601
- vue.Fragment,
4602
- { key: 1 },
4603
- [
4604
- vue.createCommentVNode(" 多选模式 "),
4605
- vue.createVNode(MultipleSelector, {
4606
- modelValue: selectedUserIds.value,
4607
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => selectedUserIds.value = $event),
4608
- "allow-create": _ctx.allowCreate,
4609
- "api-base-url": _ctx.apiBaseUrl,
4610
- "current-user-id": _ctx.currentUserId,
4611
- disabled: _ctx.disabled,
4612
- draggable: _ctx.draggable,
4613
- "empty-text": emptyText.value,
4614
- "enable-multi-tenant-mode": _ctx.enableMultiTenantMode,
4615
- "exact-search-key": _ctx.exactSearchKey,
4616
- "exclude-user-ids": _ctx.excludeUserIds,
4617
- placeholder: placeholder.value,
4618
- "render-list-item": _ctx.renderListItem,
4619
- "render-tag": _ctx.renderTag,
4620
- "selected-users": selectedUsers.value,
4621
- "tenant-id": _ctx.tenantId,
4622
- tenants: vue.unref(tenants),
4623
- "user-group": _ctx.userGroup,
4624
- "user-group-name": userGroupName.value,
4625
- "free-paste": _ctx.freePaste,
4626
- onBlur: handleBlur,
4627
- onDragEnd: _cache[2] || (_cache[2] = ($event) => _ctx.$emit("dragEnd", $event)),
4628
- onDragStart: _cache[3] || (_cache[3] = ($event) => _ctx.$emit("dragStart", $event)),
4629
- onFocus: handleFocus,
4630
- "onUpdate:selectedUsers": handleUpdateSelectedUsers
4631
- }, null, 8, ["modelValue", "allow-create", "api-base-url", "current-user-id", "disabled", "draggable", "empty-text", "enable-multi-tenant-mode", "exact-search-key", "exclude-user-ids", "placeholder", "render-list-item", "render-tag", "selected-users", "tenant-id", "tenants", "user-group", "user-group-name", "free-paste"])
4632
- ],
4633
- 2112
4634
- /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
4635
- ))
4428
+ }, 8, ["avatar-base-url", "container-width", "empty-text", "has-avatar", "is-show", "loading", "options", "render-list-item", "search-query", "tenant-id", "tenants", "user-group", "user-group-name"])
4636
4429
  ],
4637
4430
  2
4638
4431
  /* CLASS */
@@ -4640,7 +4433,7 @@
4640
4433
  };
4641
4434
  }
4642
4435
  });
4643
- const BkUserSelector = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-9c628c83"]]);
4436
+ const BkUserSelector = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-9975c7e1"]]);
4644
4437
  exports2.BkUserSelector = BkUserSelector;
4645
4438
  exports2.default = BkUserSelector;
4646
4439
  Object.defineProperties(exports2, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });