@blueking/bk-user-selector 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -34
- package/package.json +6 -3
- package/typings/components/selection-popover.vue.d.ts +8 -2
- package/typings/components/user-selector.vue.d.ts +14 -2
- package/typings/hooks/use-api-config.d.ts +33 -0
- package/typings/locale/en-us.d.ts +1 -0
- package/typings/locale/zh-cn.d.ts +1 -0
- package/typings/types/index.d.ts +50 -0
- package/typings/utils/logger.d.ts +9 -1
- package/vue2/index.es.min.js +5514 -2529
- package/vue2/index.iife.min.js +6260 -3177
- package/vue2/index.umd.min.js +5690 -2704
- package/vue2/vue2.css +53 -8
- package/vue3/index.es.min.js +1232 -285
- package/vue3/index.iife.min.js +5499 -2521
- package/vue3/index.umd.min.js +1232 -285
- package/vue3/vue3.css +53 -8
package/vue3/index.umd.min.js
CHANGED
|
@@ -6,12 +6,13 @@
|
|
|
6
6
|
], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.lesscodeCustomComponentLibrary = {}, global.Vue, global.bkui_vue));
|
|
7
7
|
})(this, function(exports, vue, bkui_vue) {
|
|
8
8
|
var __vite_style__ = document.createElement("style");
|
|
9
|
-
__vite_style__.textContent = "@charset \"UTF-8\";.me-tag[data-v-a1054364] {\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-a1054364]:hover {\n color: #3a84ff;\n background-color: #cddffe;\n}\n.me-tag.disabled[data-v-a1054364] {\n color: #c4c6cc;\n cursor: not-allowed;\n background-color: #f0f1f5;\n}.dropdown-content[data-v-9173accf] {\n min-height: 40px;\n max-height: 300px;\n padding: 5px 0;\n
|
|
9
|
+
__vite_style__.textContent = "@charset \"UTF-8\";.me-tag[data-v-a1054364] {\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-a1054364]:hover {\n color: #3a84ff;\n background-color: #cddffe;\n}\n.me-tag.disabled[data-v-a1054364] {\n color: #c4c6cc;\n cursor: not-allowed;\n background-color: #f0f1f5;\n}.dropdown-content[data-v-9173accf] {\n min-height: 40px;\n max-height: 300px;\n padding: 5px 0;\n}\n.dropdown-content .no-data[data-v-9173accf] {\n padding: 10px;\n color: #979ba5;\n text-align: center;\n}\n.dropdown-panels[data-v-9173accf] {\n display: block;\n}\n.dropdown-panel[data-v-9173accf] {\n min-width: 0;\n max-height: 290px;\n overflow-y: auto;\n}\n.dropdown-panels.is-two-column[data-v-9173accf] {\n display: flex;\n}\n.dropdown-panels.is-two-column .dropdown-panel[data-v-9173accf] {\n width: 50%;\n}\n.dropdown-panels.is-two-column .dropdown-panel + .dropdown-panel[data-v-9173accf] {\n border-left: 1px solid #eaebf0;\n}\n.group-header[data-v-9173accf] {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px 12px;\n color: #979ba5;\n}\n.group-header .group-name[data-v-9173accf],\n.group-header .group-count[data-v-9173accf] {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.user-group[data-v-9173accf],\n.dropdown-panel-main[data-v-9173accf],\n.dropdown-panel-recent[data-v-9173accf] {\n min-width: 0;\n}\n.user-option[data-v-9173accf] {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 32px;\n padding: 8px 12px;\n cursor: pointer;\n}\n.user-option[data-v-9173accf]:hover, .user-option.is-highlighted[data-v-9173accf] {\n background-color: #f5f7fa;\n}\n.dropdown-panel[data-v-9173accf] .user-render,\n.dropdown-panel[data-v-9173accf] .user-main,\n.dropdown-panel[data-v-9173accf] .user-name,\n.dropdown-panel[data-v-9173accf] .tenant-name,\n.user-option[data-v-9173accf] .user-render,\n.user-option[data-v-9173accf] .user-main,\n.user-option[data-v-9173accf] .user-name,\n.user-option[data-v-9173accf] .tenant-name {\n min-width: 0;\n}\n.dropdown-panel[data-v-9173accf] .user-name,\n.dropdown-panel[data-v-9173accf] .tenant-name,\n.user-option[data-v-9173accf] .user-name,\n.user-option[data-v-9173accf] .tenant-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}.user-tag[data-v-d1173d20] {\n height: 24px;\n margin-right: 4px;\n margin-left: 0;\n}\n.user-tag.draggable[data-v-d1173d20] {\n cursor: move;\n}\n.user-tag.active[data-v-d1173d20] {\n background-color: #e1ecff;\n border-color: #3a84ff;\n}\n.user-tag.is-custom[data-v-d1173d20] {\n color: #ea3636;\n background-color: #feebea;\n border-color: rgba(234, 53, 54, 0.3019607843);\n}\n.user-tag.is-custom[data-v-d1173d20]:hover {\n background-color: #fedddc;\n}\n.user-tag .tag-content .user-name[data-v-d1173d20] {\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 12px;\n white-space: nowrap;\n}\n.bk-user-selector[data-v-089550be] {\n position: relative;\n width: 100%;\n height: 32px;\n font-size: 12px;\n}\n.bk-user-selector.is-disabled[data-v-089550be] {\n pointer-events: none;\n cursor: not-allowed;\n background-color: #dcdee5;\n}\n.bk-user-selector.is-textarea[data-v-089550be] {\n height: auto;\n min-height: 32px;\n}\n.bk-user-selector .tags-container[data-v-089550be] {\n position: relative;\n min-height: 32px;\n padding: 3px 10px 3px 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-089550be] {\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-089550be] {\n display: flex;\n flex-wrap: wrap;\n row-gap: 4px;\n /* 与 .tag-list 一致:避免默认 stretch 拉高行高后 align-items:center 把首行顶离上边框 */\n align-content: flex-start;\n align-items: center;\n}\n.bk-user-selector .tag-list[data-v-089550be] {\n display: flex;\n flex-wrap: wrap;\n row-gap: 4px;\n align-content: flex-start;\n align-items: center;\n}\n.bk-user-selector .tag-wrapper[data-v-089550be] {\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n}\n.bk-user-selector .search-input[data-v-089550be] {\n min-width: 20px;\n height: 24px;\n outline: none;\n background: transparent;\n border: none;\n}\n.bk-user-selector .search-input[data-v-089550be]::placeholder {\n color: #c4c6cc;\n}\n.bk-user-selector .search-input.input-inline[data-v-089550be] {\n min-width: 20px;\n}\n.bk-user-selector .search-input.input-last[data-v-089550be], .bk-user-selector .search-input.search-input-collapsed[data-v-089550be] {\n flex: 1;\n}\n.hidden-users[data-v-089550be] {\n padding: 6px 10px;\n}.bk-user-selector-popover {\n padding: 0 !important;\n}\n.bk-user-selector.is-textarea .me-tag {\n top: 4px;\n transform: none;\n}/*$vite$:1*/";
|
|
10
10
|
document.head.appendChild(__vite_style__);
|
|
11
11
|
Object.defineProperties(exports, {
|
|
12
12
|
__esModule: { value: true },
|
|
13
13
|
[Symbol.toStringTag]: { value: "Module" }
|
|
14
14
|
});
|
|
15
|
+
//#region \0rolldown/runtime.js
|
|
15
16
|
var __create = Object.create;
|
|
16
17
|
var __defProp = Object.defineProperty;
|
|
17
18
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -33,6 +34,8 @@
|
|
|
33
34
|
value: mod,
|
|
34
35
|
enumerable: true
|
|
35
36
|
}) : target, mod));
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/constants/index.ts
|
|
36
39
|
var import_Sortable = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
37
40
|
/**!
|
|
38
41
|
* Sortable 1.15.6
|
|
@@ -70,11 +73,11 @@
|
|
|
70
73
|
}
|
|
71
74
|
function _typeof(obj) {
|
|
72
75
|
"@babel/helpers - typeof";
|
|
73
|
-
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") _typeof = function(obj
|
|
74
|
-
return typeof obj
|
|
76
|
+
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") _typeof = function(obj) {
|
|
77
|
+
return typeof obj;
|
|
75
78
|
};
|
|
76
|
-
else _typeof = function(obj
|
|
77
|
-
return obj
|
|
79
|
+
else _typeof = function(obj) {
|
|
80
|
+
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
78
81
|
};
|
|
79
82
|
return _typeof(obj);
|
|
80
83
|
}
|
|
@@ -234,6 +237,15 @@
|
|
|
234
237
|
if (scrollingElement) return scrollingElement;
|
|
235
238
|
else return document.documentElement;
|
|
236
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Returns the "bounding client rect" of given element
|
|
242
|
+
* @param {HTMLElement} el The element whose boundingClientRect is wanted
|
|
243
|
+
* @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container
|
|
244
|
+
* @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr
|
|
245
|
+
* @param {[Boolean]} undoScale Whether the container's scale() should be undone
|
|
246
|
+
* @param {[HTMLElement]} container The parent the element will be placed in
|
|
247
|
+
* @return {Object} The boundingClientRect of el, with specified adjustments
|
|
248
|
+
*/
|
|
237
249
|
function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) {
|
|
238
250
|
if (!el.getBoundingClientRect && el !== window) return;
|
|
239
251
|
var elRect, top, left, bottom, right, height, width;
|
|
@@ -286,6 +298,13 @@
|
|
|
286
298
|
height
|
|
287
299
|
};
|
|
288
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Checks if a side of an element is scrolled past a side of its parents
|
|
303
|
+
* @param {HTMLElement} el The element who's side being scrolled out of view is in question
|
|
304
|
+
* @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom')
|
|
305
|
+
* @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom')
|
|
306
|
+
* @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element
|
|
307
|
+
*/
|
|
289
308
|
function isScrolledPast(el, elSide, parentSide) {
|
|
290
309
|
var parent = getParentAutoScrollElement(el, true), elSideVal = getRect(el)[elSide];
|
|
291
310
|
while (parent) {
|
|
@@ -298,10 +317,18 @@
|
|
|
298
317
|
}
|
|
299
318
|
return false;
|
|
300
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible)
|
|
322
|
+
* and non-draggable elements
|
|
323
|
+
* @param {HTMLElement} el The parent element
|
|
324
|
+
* @param {Number} childNum The index of the child
|
|
325
|
+
* @param {Object} options Parent Sortable's options
|
|
326
|
+
* @return {HTMLElement} The child at index childNum, or null if not found
|
|
327
|
+
*/
|
|
301
328
|
function getChild(el, childNum, options, includeDragEl) {
|
|
302
329
|
var currentChild = 0, i = 0, children = el.children;
|
|
303
330
|
while (i < children.length) {
|
|
304
|
-
if (children[i].style.display !== "none" && children[i] !== Sortable
|
|
331
|
+
if (children[i].style.display !== "none" && children[i] !== Sortable.ghost && (includeDragEl || children[i] !== Sortable.dragged) && closest(children[i], options.draggable, el, false)) {
|
|
305
332
|
if (currentChild === childNum) return children[i];
|
|
306
333
|
currentChild++;
|
|
307
334
|
}
|
|
@@ -309,17 +336,36 @@
|
|
|
309
336
|
}
|
|
310
337
|
return null;
|
|
311
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
|
|
341
|
+
* @param {HTMLElement} el Parent element
|
|
342
|
+
* @param {selector} selector Any other elements that should be ignored
|
|
343
|
+
* @return {HTMLElement} The last child, ignoring ghostEl
|
|
344
|
+
*/
|
|
312
345
|
function lastChild(el, selector) {
|
|
313
346
|
var last = el.lastElementChild;
|
|
314
|
-
while (last && (last === Sortable
|
|
347
|
+
while (last && (last === Sortable.ghost || css(last, "display") === "none" || selector && !matches(last, selector))) last = last.previousElementSibling;
|
|
315
348
|
return last || null;
|
|
316
349
|
}
|
|
350
|
+
/**
|
|
351
|
+
* Returns the index of an element within its parent for a selected set of
|
|
352
|
+
* elements
|
|
353
|
+
* @param {HTMLElement} el
|
|
354
|
+
* @param {selector} selector
|
|
355
|
+
* @return {number}
|
|
356
|
+
*/
|
|
317
357
|
function index(el, selector) {
|
|
318
|
-
var index
|
|
358
|
+
var index = 0;
|
|
319
359
|
if (!el || !el.parentNode) return -1;
|
|
320
|
-
while (el = el.previousElementSibling) if (el.nodeName.toUpperCase() !== "TEMPLATE" && el !== Sortable
|
|
321
|
-
return index
|
|
360
|
+
while (el = el.previousElementSibling) if (el.nodeName.toUpperCase() !== "TEMPLATE" && el !== Sortable.clone && (!selector || matches(el, selector))) index++;
|
|
361
|
+
return index;
|
|
322
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.
|
|
365
|
+
* The value is returned in real pixels.
|
|
366
|
+
* @param {HTMLElement} el
|
|
367
|
+
* @return {Array} Offsets in the format of [left, top]
|
|
368
|
+
*/
|
|
323
369
|
function getRelativeScrollOffset(el) {
|
|
324
370
|
var offsetLeft = 0, offsetTop = 0, winScroller = getWindowScrollingElement();
|
|
325
371
|
if (el) do {
|
|
@@ -329,6 +375,12 @@
|
|
|
329
375
|
} while (el !== winScroller && (el = el.parentNode));
|
|
330
376
|
return [offsetLeft, offsetTop];
|
|
331
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Returns the index of the object within the given array
|
|
380
|
+
* @param {Array} arr Array that may or may not hold the object
|
|
381
|
+
* @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find
|
|
382
|
+
* @return {Number} The index of the object in the array, or -1
|
|
383
|
+
*/
|
|
332
384
|
function indexOfObject(arr, obj) {
|
|
333
385
|
for (var i in arr) {
|
|
334
386
|
if (!arr.hasOwnProperty(i)) continue;
|
|
@@ -403,11 +455,11 @@
|
|
|
403
455
|
css(el, "width", "");
|
|
404
456
|
css(el, "height", "");
|
|
405
457
|
}
|
|
406
|
-
function getChildContainingRectFromElement(container, options, ghostEl
|
|
458
|
+
function getChildContainingRectFromElement(container, options, ghostEl) {
|
|
407
459
|
var rect = {};
|
|
408
460
|
Array.from(container.children).forEach(function(child) {
|
|
409
461
|
var _rect$left, _rect$top, _rect$right, _rect$bottom;
|
|
410
|
-
if (!closest(child, options.draggable, container, false) || child.animated || child === ghostEl
|
|
462
|
+
if (!closest(child, options.draggable, container, false) || child.animated || child === ghostEl) return;
|
|
411
463
|
var childRect = getRect(child);
|
|
412
464
|
rect.left = Math.min((_rect$left = rect.left) !== null && _rect$left !== void 0 ? _rect$left : Infinity, childRect.left);
|
|
413
465
|
rect.top = Math.min((_rect$top = rect.top) !== null && _rect$top !== void 0 ? _rect$top : Infinity, childRect.top);
|
|
@@ -428,7 +480,7 @@
|
|
|
428
480
|
animationStates = [];
|
|
429
481
|
if (!this.options.animation) return;
|
|
430
482
|
[].slice.call(this.el.children).forEach(function(child) {
|
|
431
|
-
if (css(child, "display") === "none" || child === Sortable
|
|
483
|
+
if (css(child, "display") === "none" || child === Sortable.ghost) return;
|
|
432
484
|
animationStates.push({
|
|
433
485
|
target: child,
|
|
434
486
|
rect: getRect(child)
|
|
@@ -535,7 +587,7 @@
|
|
|
535
587
|
});
|
|
536
588
|
plugins.push(plugin);
|
|
537
589
|
},
|
|
538
|
-
pluginEvent: function pluginEvent
|
|
590
|
+
pluginEvent: function pluginEvent(eventName, sortable, evt) {
|
|
539
591
|
var _this = this;
|
|
540
592
|
this.eventCanceled = false;
|
|
541
593
|
evt.cancel = function() {
|
|
@@ -548,7 +600,7 @@
|
|
|
548
600
|
if (sortable.options[plugin.pluginName] && sortable[plugin.pluginName][eventName]) sortable[plugin.pluginName][eventName](_objectSpread2({ sortable }, evt));
|
|
549
601
|
});
|
|
550
602
|
},
|
|
551
|
-
initializePlugins: function initializePlugins(sortable, el, defaults
|
|
603
|
+
initializePlugins: function initializePlugins(sortable, el, defaults, options) {
|
|
552
604
|
plugins.forEach(function(plugin) {
|
|
553
605
|
var pluginName = plugin.pluginName;
|
|
554
606
|
if (!sortable.options[pluginName] && !plugin.initializeByDefault) return;
|
|
@@ -556,7 +608,7 @@
|
|
|
556
608
|
initialized.sortable = sortable;
|
|
557
609
|
initialized.options = sortable.options;
|
|
558
610
|
sortable[pluginName] = initialized;
|
|
559
|
-
_extends(defaults
|
|
611
|
+
_extends(defaults, initialized.defaults);
|
|
560
612
|
});
|
|
561
613
|
for (var option in sortable.options) {
|
|
562
614
|
if (!sortable.options.hasOwnProperty(option)) continue;
|
|
@@ -582,8 +634,8 @@
|
|
|
582
634
|
}
|
|
583
635
|
};
|
|
584
636
|
function dispatchEvent(_ref) {
|
|
585
|
-
var sortable = _ref.sortable, rootEl
|
|
586
|
-
sortable = sortable || rootEl
|
|
637
|
+
var sortable = _ref.sortable, rootEl = _ref.rootEl, name = _ref.name, targetEl = _ref.targetEl, cloneEl = _ref.cloneEl, toEl = _ref.toEl, fromEl = _ref.fromEl, oldIndex = _ref.oldIndex, newIndex = _ref.newIndex, oldDraggableIndex = _ref.oldDraggableIndex, newDraggableIndex = _ref.newDraggableIndex, originalEvent = _ref.originalEvent, putSortable = _ref.putSortable, extraEventProperties = _ref.extraEventProperties;
|
|
638
|
+
sortable = sortable || rootEl && rootEl[expando];
|
|
587
639
|
if (!sortable) return;
|
|
588
640
|
var evt, options = sortable.options, onName = "on" + name.charAt(0).toUpperCase() + name.substr(1);
|
|
589
641
|
if (window.CustomEvent && !IE11OrLess && !Edge) evt = new CustomEvent(name, {
|
|
@@ -594,25 +646,25 @@
|
|
|
594
646
|
evt = document.createEvent("Event");
|
|
595
647
|
evt.initEvent(name, true, true);
|
|
596
648
|
}
|
|
597
|
-
evt.to = toEl || rootEl
|
|
598
|
-
evt.from = fromEl || rootEl
|
|
599
|
-
evt.item = targetEl || rootEl
|
|
600
|
-
evt.clone = cloneEl
|
|
601
|
-
evt.oldIndex = oldIndex
|
|
602
|
-
evt.newIndex = newIndex
|
|
603
|
-
evt.oldDraggableIndex = oldDraggableIndex
|
|
604
|
-
evt.newDraggableIndex = newDraggableIndex
|
|
649
|
+
evt.to = toEl || rootEl;
|
|
650
|
+
evt.from = fromEl || rootEl;
|
|
651
|
+
evt.item = targetEl || rootEl;
|
|
652
|
+
evt.clone = cloneEl;
|
|
653
|
+
evt.oldIndex = oldIndex;
|
|
654
|
+
evt.newIndex = newIndex;
|
|
655
|
+
evt.oldDraggableIndex = oldDraggableIndex;
|
|
656
|
+
evt.newDraggableIndex = newDraggableIndex;
|
|
605
657
|
evt.originalEvent = originalEvent;
|
|
606
|
-
evt.pullMode = putSortable
|
|
658
|
+
evt.pullMode = putSortable ? putSortable.lastPutMode : void 0;
|
|
607
659
|
var allEventProperties = _objectSpread2(_objectSpread2({}, extraEventProperties), PluginManager.getEventProperties(name, sortable));
|
|
608
660
|
for (var option in allEventProperties) evt[option] = allEventProperties[option];
|
|
609
|
-
if (rootEl
|
|
661
|
+
if (rootEl) rootEl.dispatchEvent(evt);
|
|
610
662
|
if (options[onName]) options[onName].call(sortable, evt);
|
|
611
663
|
}
|
|
612
664
|
var _excluded = ["evt"];
|
|
613
|
-
var pluginEvent = function pluginEvent
|
|
665
|
+
var pluginEvent = function pluginEvent(eventName, sortable) {
|
|
614
666
|
var _ref = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, originalEvent = _ref.evt, data = _objectWithoutProperties(_ref, _excluded);
|
|
615
|
-
PluginManager.pluginEvent.bind(Sortable
|
|
667
|
+
PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, _objectSpread2({
|
|
616
668
|
dragEl,
|
|
617
669
|
parentEl,
|
|
618
670
|
ghostEl,
|
|
@@ -623,7 +675,7 @@
|
|
|
623
675
|
cloneHidden,
|
|
624
676
|
dragStarted: moved,
|
|
625
677
|
putSortable,
|
|
626
|
-
activeSortable: Sortable
|
|
678
|
+
activeSortable: Sortable.active,
|
|
627
679
|
originalEvent,
|
|
628
680
|
oldIndex,
|
|
629
681
|
oldDraggableIndex,
|
|
@@ -659,13 +711,14 @@
|
|
|
659
711
|
}, info));
|
|
660
712
|
}
|
|
661
713
|
var dragEl, parentEl, ghostEl, rootEl, nextEl, lastDownEl, cloneEl, cloneHidden, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, activeGroup, putSortable, awaitingDragStarted = false, ignoreNextClick = false, sortables = [], tapEvt, touchEvt, lastDx, lastDy, tapDistanceLeft, tapDistanceTop, moved, lastTarget, lastDirection, pastFirstInvertThresh = false, isCircumstantialInvert = false, targetMoveDistance, ghostRelativeParent, ghostRelativeParentInitialScroll = [], _silent = false, savedInputChecked = [];
|
|
714
|
+
/** @const */
|
|
662
715
|
var documentExists = typeof document !== "undefined", PositionGhostAbsolutely = IOS, CSSFloatProperty = Edge || IE11OrLess ? "cssFloat" : "float", supportDraggable = documentExists && !ChromeForAndroid && !IOS && "draggable" in document.createElement("div"), supportCssPointerEvents = function() {
|
|
663
716
|
if (!documentExists) return;
|
|
664
717
|
if (IE11OrLess) return false;
|
|
665
718
|
var el = document.createElement("x");
|
|
666
719
|
el.style.cssText = "pointer-events:auto";
|
|
667
720
|
return el.style.pointerEvents === "auto";
|
|
668
|
-
}(), _detectDirection = function _detectDirection
|
|
721
|
+
}(), _detectDirection = function _detectDirection(el, options) {
|
|
669
722
|
var elCSS = css(el), elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth), child1 = getChild(el, 0, options), child2 = getChild(el, 1, options), firstChildCSS = child1 && css(child1), secondChildCSS = child2 && css(child2), firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width, secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width;
|
|
670
723
|
if (elCSS.display === "flex") return elCSS.flexDirection === "column" || elCSS.flexDirection === "column-reverse" ? "vertical" : "horizontal";
|
|
671
724
|
if (elCSS.display === "grid") return elCSS.gridTemplateColumns.split(" ").length <= 1 ? "vertical" : "horizontal";
|
|
@@ -674,10 +727,10 @@
|
|
|
674
727
|
return child2 && (secondChildCSS.clear === "both" || secondChildCSS.clear === touchingSideChild2) ? "vertical" : "horizontal";
|
|
675
728
|
}
|
|
676
729
|
return child1 && (firstChildCSS.display === "block" || firstChildCSS.display === "flex" || firstChildCSS.display === "table" || firstChildCSS.display === "grid" || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === "none" || child2 && elCSS[CSSFloatProperty] === "none" && firstChildWidth + secondChildWidth > elWidth) ? "vertical" : "horizontal";
|
|
677
|
-
}, _dragElInRowColumn = function _dragElInRowColumn
|
|
730
|
+
}, _dragElInRowColumn = function _dragElInRowColumn(dragRect, targetRect, vertical) {
|
|
678
731
|
var dragElS1Opp = vertical ? dragRect.left : dragRect.top, dragElS2Opp = vertical ? dragRect.right : dragRect.bottom, dragElOppLength = vertical ? dragRect.width : dragRect.height, targetS1Opp = vertical ? targetRect.left : targetRect.top, targetS2Opp = vertical ? targetRect.right : targetRect.bottom, targetOppLength = vertical ? targetRect.width : targetRect.height;
|
|
679
732
|
return dragElS1Opp === targetS1Opp || dragElS2Opp === targetS2Opp || dragElS1Opp + dragElOppLength / 2 === targetS1Opp + targetOppLength / 2;
|
|
680
|
-
}, _detectNearestEmptySortable = function _detectNearestEmptySortable
|
|
733
|
+
}, _detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) {
|
|
681
734
|
var ret;
|
|
682
735
|
sortables.some(function(sortable) {
|
|
683
736
|
var threshold = sortable[expando].options.emptyInsertThreshold;
|
|
@@ -686,14 +739,14 @@
|
|
|
686
739
|
if (insideHorizontally && insideVertically) return ret = sortable;
|
|
687
740
|
});
|
|
688
741
|
return ret;
|
|
689
|
-
}, _prepareGroup = function _prepareGroup
|
|
742
|
+
}, _prepareGroup = function _prepareGroup(options) {
|
|
690
743
|
function toFn(value, pull) {
|
|
691
|
-
return function(to, from, dragEl
|
|
744
|
+
return function(to, from, dragEl, evt) {
|
|
692
745
|
var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name;
|
|
693
746
|
if (value == null && (pull || sameGroup)) return true;
|
|
694
747
|
else if (value == null || value === false) return false;
|
|
695
748
|
else if (pull && value === "clone") return value;
|
|
696
|
-
else if (typeof value === "function") return toFn(value(to, from, dragEl
|
|
749
|
+
else if (typeof value === "function") return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt);
|
|
697
750
|
else {
|
|
698
751
|
var otherGroup = (pull ? to : from).options.group.name;
|
|
699
752
|
return value === true || typeof value === "string" && value === otherGroup || value.join && value.indexOf(otherGroup) > -1;
|
|
@@ -708,9 +761,9 @@
|
|
|
708
761
|
group.checkPut = toFn(originalGroup.put);
|
|
709
762
|
group.revertClone = originalGroup.revertClone;
|
|
710
763
|
options.group = group;
|
|
711
|
-
}, _hideGhostForTarget = function _hideGhostForTarget
|
|
764
|
+
}, _hideGhostForTarget = function _hideGhostForTarget() {
|
|
712
765
|
if (!supportCssPointerEvents && ghostEl) css(ghostEl, "display", "none");
|
|
713
|
-
}, _unhideGhostForTarget = function _unhideGhostForTarget
|
|
766
|
+
}, _unhideGhostForTarget = function _unhideGhostForTarget() {
|
|
714
767
|
if (!supportCssPointerEvents && ghostEl) css(ghostEl, "display", "");
|
|
715
768
|
};
|
|
716
769
|
if (documentExists && !ChromeForAndroid) document.addEventListener("click", function(evt) {
|
|
@@ -722,7 +775,7 @@
|
|
|
722
775
|
return false;
|
|
723
776
|
}
|
|
724
777
|
}, true);
|
|
725
|
-
var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent
|
|
778
|
+
var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) {
|
|
726
779
|
if (dragEl) {
|
|
727
780
|
evt = evt.touches ? evt.touches[0] : evt;
|
|
728
781
|
var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY);
|
|
@@ -736,15 +789,20 @@
|
|
|
736
789
|
}
|
|
737
790
|
}
|
|
738
791
|
};
|
|
739
|
-
var _checkOutsideTargetEl = function _checkOutsideTargetEl
|
|
792
|
+
var _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) {
|
|
740
793
|
if (dragEl) dragEl.parentNode[expando]._isOutsideThisEl(evt.target);
|
|
741
794
|
};
|
|
742
|
-
|
|
795
|
+
/**
|
|
796
|
+
* @class Sortable
|
|
797
|
+
* @param {HTMLElement} el
|
|
798
|
+
* @param {Object} [options]
|
|
799
|
+
*/
|
|
800
|
+
function Sortable(el, options) {
|
|
743
801
|
if (!(el && el.nodeType && el.nodeType === 1)) throw "Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(el));
|
|
744
802
|
this.el = el;
|
|
745
803
|
this.options = options = _extends({}, options);
|
|
746
804
|
el[expando] = this;
|
|
747
|
-
var defaults
|
|
805
|
+
var defaults = {
|
|
748
806
|
group: null,
|
|
749
807
|
sort: true,
|
|
750
808
|
disabled: false,
|
|
@@ -766,8 +824,8 @@
|
|
|
766
824
|
preventOnFilter: true,
|
|
767
825
|
animation: 0,
|
|
768
826
|
easing: null,
|
|
769
|
-
setData: function setData(dataTransfer, dragEl
|
|
770
|
-
dataTransfer.setData("Text", dragEl
|
|
827
|
+
setData: function setData(dataTransfer, dragEl) {
|
|
828
|
+
dataTransfer.setData("Text", dragEl.textContent);
|
|
771
829
|
},
|
|
772
830
|
dropBubble: false,
|
|
773
831
|
dragoverBubble: false,
|
|
@@ -783,11 +841,11 @@
|
|
|
783
841
|
x: 0,
|
|
784
842
|
y: 0
|
|
785
843
|
},
|
|
786
|
-
supportPointer: Sortable
|
|
844
|
+
supportPointer: Sortable.supportPointer !== false && "PointerEvent" in window && (!Safari || IOS),
|
|
787
845
|
emptyInsertThreshold: 5
|
|
788
846
|
};
|
|
789
|
-
PluginManager.initializePlugins(this, el, defaults
|
|
790
|
-
for (var name in defaults
|
|
847
|
+
PluginManager.initializePlugins(this, el, defaults);
|
|
848
|
+
for (var name in defaults) !(name in options) && (options[name] = defaults[name]);
|
|
791
849
|
_prepareGroup(options);
|
|
792
850
|
for (var fn in this) if (fn.charAt(0) === "_" && typeof this[fn] === "function") this[fn] = this[fn].bind(this);
|
|
793
851
|
this.nativeDraggable = options.forceFallback ? false : supportDraggable;
|
|
@@ -805,8 +863,8 @@
|
|
|
805
863
|
options.store && options.store.get && this.sort(options.store.get(this) || []);
|
|
806
864
|
_extends(this, AnimationStateManager());
|
|
807
865
|
}
|
|
808
|
-
Sortable
|
|
809
|
-
constructor: Sortable
|
|
866
|
+
Sortable.prototype = ( /** @lends Sortable.prototype */ {
|
|
867
|
+
constructor: Sortable,
|
|
810
868
|
_isOutsideThisEl: function _isOutsideThisEl(target) {
|
|
811
869
|
if (!this.el.contains(target) && target !== this.el) lastTarget = null;
|
|
812
870
|
},
|
|
@@ -874,7 +932,7 @@
|
|
|
874
932
|
nextEl = dragEl.nextSibling;
|
|
875
933
|
lastDownEl = target;
|
|
876
934
|
activeGroup = options.group;
|
|
877
|
-
Sortable
|
|
935
|
+
Sortable.dragged = dragEl;
|
|
878
936
|
tapEvt = {
|
|
879
937
|
target: dragEl,
|
|
880
938
|
clientX: (touch || evt).clientX,
|
|
@@ -885,9 +943,9 @@
|
|
|
885
943
|
this._lastX = (touch || evt).clientX;
|
|
886
944
|
this._lastY = (touch || evt).clientY;
|
|
887
945
|
dragEl.style["will-change"] = "all";
|
|
888
|
-
dragStartFn = function dragStartFn
|
|
946
|
+
dragStartFn = function dragStartFn() {
|
|
889
947
|
pluginEvent("delayEnded", _this, { evt });
|
|
890
|
-
if (Sortable
|
|
948
|
+
if (Sortable.eventCanceled) {
|
|
891
949
|
_this._onDrop();
|
|
892
950
|
return;
|
|
893
951
|
}
|
|
@@ -921,7 +979,7 @@
|
|
|
921
979
|
}
|
|
922
980
|
pluginEvent("delayStart", this, { evt });
|
|
923
981
|
if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) {
|
|
924
|
-
if (Sortable
|
|
982
|
+
if (Sortable.eventCanceled) {
|
|
925
983
|
this._onDrop();
|
|
926
984
|
return;
|
|
927
985
|
}
|
|
@@ -984,7 +1042,7 @@
|
|
|
984
1042
|
var options = this.options;
|
|
985
1043
|
!fallback && toggleClass(dragEl, options.dragClass, false);
|
|
986
1044
|
toggleClass(dragEl, options.ghostClass, true);
|
|
987
|
-
Sortable
|
|
1045
|
+
Sortable.active = this;
|
|
988
1046
|
fallback && this._appendGhost();
|
|
989
1047
|
_dispatchEvent({
|
|
990
1048
|
sortable: this,
|
|
@@ -1025,7 +1083,7 @@
|
|
|
1025
1083
|
_onTouchMove: function _onTouchMove(evt) {
|
|
1026
1084
|
if (tapEvt) {
|
|
1027
1085
|
var options = this.options, fallbackTolerance = options.fallbackTolerance, fallbackOffset = options.fallbackOffset, touch = evt.touches ? evt.touches[0] : evt, ghostMatrix = ghostEl && matrix(ghostEl, true), scaleX = ghostEl && ghostMatrix && ghostMatrix.a, scaleY = ghostEl && ghostMatrix && ghostMatrix.d, relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent), dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1), dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1);
|
|
1028
|
-
if (!Sortable
|
|
1086
|
+
if (!Sortable.active && !awaitingDragStarted) {
|
|
1029
1087
|
if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) return;
|
|
1030
1088
|
this._onDragStart(evt, true);
|
|
1031
1089
|
}
|
|
@@ -1082,7 +1140,7 @@
|
|
|
1082
1140
|
css(ghostEl, "position", PositionGhostAbsolutely ? "absolute" : "fixed");
|
|
1083
1141
|
css(ghostEl, "zIndex", "100000");
|
|
1084
1142
|
css(ghostEl, "pointerEvents", "none");
|
|
1085
|
-
Sortable
|
|
1143
|
+
Sortable.ghost = ghostEl;
|
|
1086
1144
|
container.appendChild(ghostEl);
|
|
1087
1145
|
css(ghostEl, "transform-origin", tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + "% " + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + "%");
|
|
1088
1146
|
}
|
|
@@ -1092,23 +1150,23 @@
|
|
|
1092
1150
|
var dataTransfer = evt.dataTransfer;
|
|
1093
1151
|
var options = _this.options;
|
|
1094
1152
|
pluginEvent("dragStart", this, { evt });
|
|
1095
|
-
if (Sortable
|
|
1153
|
+
if (Sortable.eventCanceled) {
|
|
1096
1154
|
this._onDrop();
|
|
1097
1155
|
return;
|
|
1098
1156
|
}
|
|
1099
1157
|
pluginEvent("setupClone", this);
|
|
1100
|
-
if (!Sortable
|
|
1158
|
+
if (!Sortable.eventCanceled) {
|
|
1101
1159
|
cloneEl = clone(dragEl);
|
|
1102
1160
|
cloneEl.removeAttribute("id");
|
|
1103
1161
|
cloneEl.draggable = false;
|
|
1104
1162
|
cloneEl.style["will-change"] = "";
|
|
1105
1163
|
this._hideClone();
|
|
1106
1164
|
toggleClass(cloneEl, this.options.chosenClass, false);
|
|
1107
|
-
Sortable
|
|
1165
|
+
Sortable.clone = cloneEl;
|
|
1108
1166
|
}
|
|
1109
1167
|
_this.cloneId = _nextTick(function() {
|
|
1110
1168
|
pluginEvent("clone", _this);
|
|
1111
|
-
if (Sortable
|
|
1169
|
+
if (Sortable.eventCanceled) return;
|
|
1112
1170
|
if (!_this.options.removeCloneOnHide) rootEl.insertBefore(cloneEl, dragEl);
|
|
1113
1171
|
_this._hideClone();
|
|
1114
1172
|
_dispatchEvent({
|
|
@@ -1139,7 +1197,7 @@
|
|
|
1139
1197
|
if (Safari) css(document.body, "user-select", "none");
|
|
1140
1198
|
},
|
|
1141
1199
|
_onDragOver: function _onDragOver(evt) {
|
|
1142
|
-
var el = this.el, target = evt.target, dragRect, targetRect, revert, options = this.options, group = options.group, activeSortable = Sortable
|
|
1200
|
+
var el = this.el, target = evt.target, dragRect, targetRect, revert, options = this.options, group = options.group, activeSortable = Sortable.active, isOwner = activeGroup === group, canSort = options.sort, fromSortable = putSortable || activeSortable, vertical, _this = this, completedFired = false;
|
|
1143
1201
|
if (_silent) return;
|
|
1144
1202
|
function dragOverEvent(name, extra) {
|
|
1145
1203
|
pluginEvent(name, _this, _objectSpread2({
|
|
@@ -1153,8 +1211,8 @@
|
|
|
1153
1211
|
fromSortable,
|
|
1154
1212
|
target,
|
|
1155
1213
|
completed,
|
|
1156
|
-
onMove: function onMove(target
|
|
1157
|
-
return _onMove(rootEl, el, dragEl, dragRect, target
|
|
1214
|
+
onMove: function onMove(target, after) {
|
|
1215
|
+
return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after);
|
|
1158
1216
|
},
|
|
1159
1217
|
changed
|
|
1160
1218
|
}, extra));
|
|
@@ -1173,8 +1231,8 @@
|
|
|
1173
1231
|
toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false);
|
|
1174
1232
|
toggleClass(dragEl, options.ghostClass, true);
|
|
1175
1233
|
}
|
|
1176
|
-
if (putSortable !== _this && _this !== Sortable
|
|
1177
|
-
else if (_this === Sortable
|
|
1234
|
+
if (putSortable !== _this && _this !== Sortable.active) putSortable = _this;
|
|
1235
|
+
else if (_this === Sortable.active && putSortable) putSortable = null;
|
|
1178
1236
|
if (fromSortable === _this) _this._ignoreWhileAnimating = target;
|
|
1179
1237
|
_this.animateAll(function() {
|
|
1180
1238
|
dragOverEvent("dragOverAnimationComplete");
|
|
@@ -1208,20 +1266,20 @@
|
|
|
1208
1266
|
if (evt.preventDefault !== void 0) evt.cancelable && evt.preventDefault();
|
|
1209
1267
|
target = closest(target, options.draggable, el, true);
|
|
1210
1268
|
dragOverEvent("dragOver");
|
|
1211
|
-
if (Sortable
|
|
1269
|
+
if (Sortable.eventCanceled) return completedFired;
|
|
1212
1270
|
if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) return completed(false);
|
|
1213
1271
|
ignoreNextClick = false;
|
|
1214
1272
|
if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = parentEl !== rootEl) : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) {
|
|
1215
1273
|
vertical = this._getDirection(evt, target) === "vertical";
|
|
1216
1274
|
dragRect = getRect(dragEl);
|
|
1217
1275
|
dragOverEvent("dragOverValid");
|
|
1218
|
-
if (Sortable
|
|
1276
|
+
if (Sortable.eventCanceled) return completedFired;
|
|
1219
1277
|
if (revert) {
|
|
1220
1278
|
parentEl = rootEl;
|
|
1221
1279
|
capture();
|
|
1222
1280
|
this._hideClone();
|
|
1223
1281
|
dragOverEvent("revert");
|
|
1224
|
-
if (!Sortable
|
|
1282
|
+
if (!Sortable.eventCanceled) if (nextEl) rootEl.insertBefore(dragEl, nextEl);
|
|
1225
1283
|
else rootEl.appendChild(dragEl);
|
|
1226
1284
|
return completed(true);
|
|
1227
1285
|
}
|
|
@@ -1317,7 +1375,7 @@
|
|
|
1317
1375
|
parentEl = dragEl && dragEl.parentNode;
|
|
1318
1376
|
newIndex = index(dragEl);
|
|
1319
1377
|
newDraggableIndex = index(dragEl, options.draggable);
|
|
1320
|
-
if (Sortable
|
|
1378
|
+
if (Sortable.eventCanceled) {
|
|
1321
1379
|
this._nulling();
|
|
1322
1380
|
return;
|
|
1323
1381
|
}
|
|
@@ -1403,7 +1461,7 @@
|
|
|
1403
1461
|
});
|
|
1404
1462
|
}
|
|
1405
1463
|
}
|
|
1406
|
-
if (Sortable
|
|
1464
|
+
if (Sortable.active) {
|
|
1407
1465
|
if (newIndex == null || newIndex === -1) {
|
|
1408
1466
|
newIndex = oldIndex;
|
|
1409
1467
|
newDraggableIndex = oldDraggableIndex;
|
|
@@ -1422,7 +1480,7 @@
|
|
|
1422
1480
|
},
|
|
1423
1481
|
_nulling: function _nulling() {
|
|
1424
1482
|
pluginEvent("nulling", this);
|
|
1425
|
-
rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable
|
|
1483
|
+
rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable.dragged = Sortable.ghost = Sortable.clone = Sortable.active = null;
|
|
1426
1484
|
savedInputChecked.forEach(function(el) {
|
|
1427
1485
|
el.checked = true;
|
|
1428
1486
|
});
|
|
@@ -1455,16 +1513,16 @@
|
|
|
1455
1513
|
return order;
|
|
1456
1514
|
},
|
|
1457
1515
|
sort: function sort(order, useAnimation) {
|
|
1458
|
-
var items = {}, rootEl
|
|
1516
|
+
var items = {}, rootEl = this.el;
|
|
1459
1517
|
this.toArray().forEach(function(id, i) {
|
|
1460
|
-
var el = rootEl
|
|
1461
|
-
if (closest(el, this.options.draggable, rootEl
|
|
1518
|
+
var el = rootEl.children[i];
|
|
1519
|
+
if (closest(el, this.options.draggable, rootEl, false)) items[id] = el;
|
|
1462
1520
|
}, this);
|
|
1463
1521
|
useAnimation && this.captureAnimationState();
|
|
1464
1522
|
order.forEach(function(id) {
|
|
1465
1523
|
if (items[id]) {
|
|
1466
|
-
rootEl
|
|
1467
|
-
rootEl
|
|
1524
|
+
rootEl.removeChild(items[id]);
|
|
1525
|
+
rootEl.appendChild(items[id]);
|
|
1468
1526
|
}
|
|
1469
1527
|
});
|
|
1470
1528
|
useAnimation && this.animateAll();
|
|
@@ -1497,8 +1555,8 @@
|
|
|
1497
1555
|
off(el, "dragover", this);
|
|
1498
1556
|
off(el, "dragenter", this);
|
|
1499
1557
|
}
|
|
1500
|
-
Array.prototype.forEach.call(el.querySelectorAll("[draggable]"), function(el
|
|
1501
|
-
el
|
|
1558
|
+
Array.prototype.forEach.call(el.querySelectorAll("[draggable]"), function(el) {
|
|
1559
|
+
el.removeAttribute("draggable");
|
|
1502
1560
|
});
|
|
1503
1561
|
this._onDrop();
|
|
1504
1562
|
this._disableDelayedDragEvents();
|
|
@@ -1508,20 +1566,20 @@
|
|
|
1508
1566
|
_hideClone: function _hideClone() {
|
|
1509
1567
|
if (!cloneHidden) {
|
|
1510
1568
|
pluginEvent("hideClone", this);
|
|
1511
|
-
if (Sortable
|
|
1569
|
+
if (Sortable.eventCanceled) return;
|
|
1512
1570
|
css(cloneEl, "display", "none");
|
|
1513
1571
|
if (this.options.removeCloneOnHide && cloneEl.parentNode) cloneEl.parentNode.removeChild(cloneEl);
|
|
1514
1572
|
cloneHidden = true;
|
|
1515
1573
|
}
|
|
1516
1574
|
},
|
|
1517
|
-
_showClone: function _showClone(putSortable
|
|
1518
|
-
if (putSortable
|
|
1575
|
+
_showClone: function _showClone(putSortable) {
|
|
1576
|
+
if (putSortable.lastPutMode !== "clone") {
|
|
1519
1577
|
this._hideClone();
|
|
1520
1578
|
return;
|
|
1521
1579
|
}
|
|
1522
1580
|
if (cloneHidden) {
|
|
1523
1581
|
pluginEvent("showClone", this);
|
|
1524
|
-
if (Sortable
|
|
1582
|
+
if (Sortable.eventCanceled) return;
|
|
1525
1583
|
if (dragEl.parentNode == rootEl && !this.options.group.revertClone) rootEl.insertBefore(cloneEl, dragEl);
|
|
1526
1584
|
else if (nextEl) rootEl.insertBefore(cloneEl, nextEl);
|
|
1527
1585
|
else rootEl.appendChild(cloneEl);
|
|
@@ -1530,12 +1588,12 @@
|
|
|
1530
1588
|
cloneHidden = false;
|
|
1531
1589
|
}
|
|
1532
1590
|
}
|
|
1533
|
-
};
|
|
1591
|
+
});
|
|
1534
1592
|
function _globalDragOver(evt) {
|
|
1535
1593
|
if (evt.dataTransfer) evt.dataTransfer.dropEffect = "move";
|
|
1536
1594
|
evt.cancelable && evt.preventDefault();
|
|
1537
1595
|
}
|
|
1538
|
-
function _onMove(fromEl, toEl, dragEl
|
|
1596
|
+
function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) {
|
|
1539
1597
|
var evt, sortable = fromEl[expando], onMoveFn = sortable.options.onMove, retVal;
|
|
1540
1598
|
if (window.CustomEvent && !IE11OrLess && !Edge) evt = new CustomEvent("move", {
|
|
1541
1599
|
bubbles: true,
|
|
@@ -1547,7 +1605,7 @@
|
|
|
1547
1605
|
}
|
|
1548
1606
|
evt.to = toEl;
|
|
1549
1607
|
evt.from = fromEl;
|
|
1550
|
-
evt.dragged = dragEl
|
|
1608
|
+
evt.dragged = dragEl;
|
|
1551
1609
|
evt.draggedRect = dragRect;
|
|
1552
1610
|
evt.related = targetEl || toEl;
|
|
1553
1611
|
evt.relatedRect = targetRect || getRect(toEl);
|
|
@@ -1591,10 +1649,22 @@
|
|
|
1591
1649
|
}
|
|
1592
1650
|
return 0;
|
|
1593
1651
|
}
|
|
1652
|
+
/**
|
|
1653
|
+
* Gets the direction dragEl must be swapped relative to target in order to make it
|
|
1654
|
+
* seem that dragEl has been "inserted" into that element's position
|
|
1655
|
+
* @param {HTMLElement} target The target whose position dragEl is being inserted at
|
|
1656
|
+
* @return {Number} Direction dragEl must be swapped
|
|
1657
|
+
*/
|
|
1594
1658
|
function _getInsertDirection(target) {
|
|
1595
1659
|
if (index(dragEl) < index(target)) return 1;
|
|
1596
1660
|
else return -1;
|
|
1597
1661
|
}
|
|
1662
|
+
/**
|
|
1663
|
+
* Generate id
|
|
1664
|
+
* @param {HTMLElement} el
|
|
1665
|
+
* @returns {String}
|
|
1666
|
+
* @private
|
|
1667
|
+
*/
|
|
1598
1668
|
function _generateId(el) {
|
|
1599
1669
|
var str = el.tagName + el.className + el.src + el.href + el.textContent, i = str.length, sum = 0;
|
|
1600
1670
|
while (i--) sum += str.charCodeAt(i);
|
|
@@ -1616,9 +1686,9 @@
|
|
|
1616
1686
|
return clearTimeout(id);
|
|
1617
1687
|
}
|
|
1618
1688
|
if (documentExists) on(document, "touchmove", function(evt) {
|
|
1619
|
-
if ((Sortable
|
|
1689
|
+
if ((Sortable.active || awaitingDragStarted) && evt.cancelable) evt.preventDefault();
|
|
1620
1690
|
});
|
|
1621
|
-
Sortable
|
|
1691
|
+
Sortable.utils = {
|
|
1622
1692
|
on,
|
|
1623
1693
|
off,
|
|
1624
1694
|
css,
|
|
@@ -1638,22 +1708,36 @@
|
|
|
1638
1708
|
getChild,
|
|
1639
1709
|
expando
|
|
1640
1710
|
};
|
|
1641
|
-
|
|
1711
|
+
/**
|
|
1712
|
+
* Get the Sortable instance of an element
|
|
1713
|
+
* @param {HTMLElement} element The element
|
|
1714
|
+
* @return {Sortable|undefined} The instance of Sortable
|
|
1715
|
+
*/
|
|
1716
|
+
Sortable.get = function(element) {
|
|
1642
1717
|
return element[expando];
|
|
1643
1718
|
};
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1719
|
+
/**
|
|
1720
|
+
* Mount a plugin to Sortable
|
|
1721
|
+
* @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted
|
|
1722
|
+
*/
|
|
1723
|
+
Sortable.mount = function() {
|
|
1724
|
+
for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) plugins[_key] = arguments[_key];
|
|
1725
|
+
if (plugins[0].constructor === Array) plugins = plugins[0];
|
|
1726
|
+
plugins.forEach(function(plugin) {
|
|
1648
1727
|
if (!plugin.prototype || !plugin.prototype.constructor) throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(plugin));
|
|
1649
|
-
if (plugin.utils) Sortable
|
|
1728
|
+
if (plugin.utils) Sortable.utils = _objectSpread2(_objectSpread2({}, Sortable.utils), plugin.utils);
|
|
1650
1729
|
PluginManager.mount(plugin);
|
|
1651
1730
|
});
|
|
1652
1731
|
};
|
|
1653
|
-
|
|
1654
|
-
|
|
1732
|
+
/**
|
|
1733
|
+
* Create sortable instance
|
|
1734
|
+
* @param {HTMLElement} el
|
|
1735
|
+
* @param {Object} [options]
|
|
1736
|
+
*/
|
|
1737
|
+
Sortable.create = function(el, options) {
|
|
1738
|
+
return new Sortable(el, options);
|
|
1655
1739
|
};
|
|
1656
|
-
Sortable
|
|
1740
|
+
Sortable.version = version;
|
|
1657
1741
|
var autoScrolls = [], scrollEl, scrollRootEl, scrolling = false, lastAutoScrollX, lastAutoScrollY, touchEvt$1, pointerElemChangedInterval;
|
|
1658
1742
|
function AutoScrollPlugin() {
|
|
1659
1743
|
function AutoScroll() {
|
|
@@ -1667,7 +1751,7 @@
|
|
|
1667
1751
|
for (var fn in this) if (fn.charAt(0) === "_" && typeof this[fn] === "function") this[fn] = this[fn].bind(this);
|
|
1668
1752
|
}
|
|
1669
1753
|
AutoScroll.prototype = {
|
|
1670
|
-
dragStarted: function dragStarted
|
|
1754
|
+
dragStarted: function dragStarted(_ref) {
|
|
1671
1755
|
var originalEvent = _ref.originalEvent;
|
|
1672
1756
|
if (this.sortable.nativeDraggable) on(document, "dragover", this._handleAutoScroll);
|
|
1673
1757
|
else if (this.options.supportPointer) on(document, "pointermove", this._handleFallbackAutoScroll);
|
|
@@ -1678,7 +1762,7 @@
|
|
|
1678
1762
|
var originalEvent = _ref2.originalEvent;
|
|
1679
1763
|
if (!this.options.dragOverBubble && !originalEvent.rootEl) this._handleAutoScroll(originalEvent);
|
|
1680
1764
|
},
|
|
1681
|
-
drop: function drop
|
|
1765
|
+
drop: function drop() {
|
|
1682
1766
|
if (this.sortable.nativeDraggable) off(document, "dragover", this._handleAutoScroll);
|
|
1683
1767
|
else {
|
|
1684
1768
|
off(document, "pointermove", this._handleFallbackAutoScroll);
|
|
@@ -1731,24 +1815,24 @@
|
|
|
1731
1815
|
});
|
|
1732
1816
|
}
|
|
1733
1817
|
function clearAutoScrolls() {
|
|
1734
|
-
autoScrolls.forEach(function(autoScroll
|
|
1735
|
-
clearInterval(autoScroll
|
|
1818
|
+
autoScrolls.forEach(function(autoScroll) {
|
|
1819
|
+
clearInterval(autoScroll.pid);
|
|
1736
1820
|
});
|
|
1737
1821
|
autoScrolls = [];
|
|
1738
1822
|
}
|
|
1739
1823
|
function clearPointerElemChangedInterval() {
|
|
1740
1824
|
clearInterval(pointerElemChangedInterval);
|
|
1741
1825
|
}
|
|
1742
|
-
var autoScroll = throttle(function(evt, options, rootEl
|
|
1826
|
+
var autoScroll = throttle(function(evt, options, rootEl, isFallback) {
|
|
1743
1827
|
if (!options.scroll) return;
|
|
1744
1828
|
var x = (evt.touches ? evt.touches[0] : evt).clientX, y = (evt.touches ? evt.touches[0] : evt).clientY, sens = options.scrollSensitivity, speed = options.scrollSpeed, winScroller = getWindowScrollingElement();
|
|
1745
1829
|
var scrollThisInstance = false, scrollCustomFn;
|
|
1746
|
-
if (scrollRootEl !== rootEl
|
|
1747
|
-
scrollRootEl = rootEl
|
|
1830
|
+
if (scrollRootEl !== rootEl) {
|
|
1831
|
+
scrollRootEl = rootEl;
|
|
1748
1832
|
clearAutoScrolls();
|
|
1749
1833
|
scrollEl = options.scroll;
|
|
1750
1834
|
scrollCustomFn = options.scrollFn;
|
|
1751
|
-
if (scrollEl === true) scrollEl = getParentAutoScrollElement(rootEl
|
|
1835
|
+
if (scrollEl === true) scrollEl = getParentAutoScrollElement(rootEl, true);
|
|
1752
1836
|
}
|
|
1753
1837
|
var layersOut = 0;
|
|
1754
1838
|
var currentParent = scrollEl;
|
|
@@ -1774,11 +1858,11 @@
|
|
|
1774
1858
|
if (vx != 0 || vy != 0) {
|
|
1775
1859
|
scrollThisInstance = true;
|
|
1776
1860
|
autoScrolls[layersOut].pid = setInterval(function() {
|
|
1777
|
-
if (isFallback && this.layer === 0) Sortable
|
|
1861
|
+
if (isFallback && this.layer === 0) Sortable.active._onTouchMove(touchEvt$1);
|
|
1778
1862
|
var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;
|
|
1779
1863
|
var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;
|
|
1780
1864
|
if (typeof scrollCustomFn === "function") {
|
|
1781
|
-
if (scrollCustomFn.call(Sortable
|
|
1865
|
+
if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== "continue") return;
|
|
1782
1866
|
}
|
|
1783
1867
|
scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY);
|
|
1784
1868
|
}.bind({ layer: layersOut }), 24);
|
|
@@ -1788,10 +1872,10 @@
|
|
|
1788
1872
|
} while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false)));
|
|
1789
1873
|
scrolling = scrollThisInstance;
|
|
1790
1874
|
}, 30);
|
|
1791
|
-
var drop = function drop
|
|
1792
|
-
var originalEvent = _ref.originalEvent, putSortable
|
|
1875
|
+
var drop = function drop(_ref) {
|
|
1876
|
+
var originalEvent = _ref.originalEvent, putSortable = _ref.putSortable, dragEl = _ref.dragEl, activeSortable = _ref.activeSortable, dispatchSortableEvent = _ref.dispatchSortableEvent, hideGhostForTarget = _ref.hideGhostForTarget, unhideGhostForTarget = _ref.unhideGhostForTarget;
|
|
1793
1877
|
if (!originalEvent) return;
|
|
1794
|
-
var toSortable = putSortable
|
|
1878
|
+
var toSortable = putSortable || activeSortable;
|
|
1795
1879
|
hideGhostForTarget();
|
|
1796
1880
|
var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent;
|
|
1797
1881
|
var target = document.elementFromPoint(touch.clientX, touch.clientY);
|
|
@@ -1799,8 +1883,8 @@
|
|
|
1799
1883
|
if (toSortable && !toSortable.el.contains(target)) {
|
|
1800
1884
|
dispatchSortableEvent("spill");
|
|
1801
1885
|
this.onSpill({
|
|
1802
|
-
dragEl
|
|
1803
|
-
putSortable
|
|
1886
|
+
dragEl,
|
|
1887
|
+
putSortable
|
|
1804
1888
|
});
|
|
1805
1889
|
}
|
|
1806
1890
|
};
|
|
@@ -1811,14 +1895,14 @@
|
|
|
1811
1895
|
this.startIndex = _ref2.oldDraggableIndex;
|
|
1812
1896
|
},
|
|
1813
1897
|
onSpill: function onSpill(_ref3) {
|
|
1814
|
-
var dragEl
|
|
1898
|
+
var dragEl = _ref3.dragEl, putSortable = _ref3.putSortable;
|
|
1815
1899
|
this.sortable.captureAnimationState();
|
|
1816
|
-
if (putSortable
|
|
1900
|
+
if (putSortable) putSortable.captureAnimationState();
|
|
1817
1901
|
var nextSibling = getChild(this.sortable.el, this.startIndex, this.options);
|
|
1818
|
-
if (nextSibling) this.sortable.el.insertBefore(dragEl
|
|
1819
|
-
else this.sortable.el.appendChild(dragEl
|
|
1902
|
+
if (nextSibling) this.sortable.el.insertBefore(dragEl, nextSibling);
|
|
1903
|
+
else this.sortable.el.appendChild(dragEl);
|
|
1820
1904
|
this.sortable.animateAll();
|
|
1821
|
-
if (putSortable
|
|
1905
|
+
if (putSortable) putSortable.animateAll();
|
|
1822
1906
|
},
|
|
1823
1907
|
drop
|
|
1824
1908
|
};
|
|
@@ -1826,10 +1910,10 @@
|
|
|
1826
1910
|
function Remove() {}
|
|
1827
1911
|
Remove.prototype = {
|
|
1828
1912
|
onSpill: function onSpill(_ref4) {
|
|
1829
|
-
var dragEl
|
|
1913
|
+
var dragEl = _ref4.dragEl;
|
|
1830
1914
|
var parentSortable = _ref4.putSortable || this.sortable;
|
|
1831
1915
|
parentSortable.captureAnimationState();
|
|
1832
|
-
dragEl
|
|
1916
|
+
dragEl.parentNode && dragEl.parentNode.removeChild(dragEl);
|
|
1833
1917
|
parentSortable.animateAll();
|
|
1834
1918
|
},
|
|
1835
1919
|
drop
|
|
@@ -1860,16 +1944,16 @@
|
|
|
1860
1944
|
completed(true);
|
|
1861
1945
|
cancel();
|
|
1862
1946
|
},
|
|
1863
|
-
drop: function drop
|
|
1864
|
-
var activeSortable = _ref3.activeSortable, putSortable
|
|
1865
|
-
var toSortable = putSortable
|
|
1947
|
+
drop: function drop(_ref3) {
|
|
1948
|
+
var activeSortable = _ref3.activeSortable, putSortable = _ref3.putSortable, dragEl = _ref3.dragEl;
|
|
1949
|
+
var toSortable = putSortable || this.sortable;
|
|
1866
1950
|
var options = this.options;
|
|
1867
1951
|
lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false);
|
|
1868
|
-
if (lastSwapEl && (options.swap || putSortable
|
|
1869
|
-
if (dragEl
|
|
1952
|
+
if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) {
|
|
1953
|
+
if (dragEl !== lastSwapEl) {
|
|
1870
1954
|
toSortable.captureAnimationState();
|
|
1871
1955
|
if (toSortable !== activeSortable) activeSortable.captureAnimationState();
|
|
1872
|
-
swapNodes(dragEl
|
|
1956
|
+
swapNodes(dragEl, lastSwapEl);
|
|
1873
1957
|
toSortable.animateAll();
|
|
1874
1958
|
if (toSortable !== activeSortable) activeSortable.animateAll();
|
|
1875
1959
|
}
|
|
@@ -1910,12 +1994,12 @@
|
|
|
1910
1994
|
selectedClass: "sortable-selected",
|
|
1911
1995
|
multiDragKey: null,
|
|
1912
1996
|
avoidImplicitDeselect: false,
|
|
1913
|
-
setData: function setData(dataTransfer, dragEl
|
|
1997
|
+
setData: function setData(dataTransfer, dragEl) {
|
|
1914
1998
|
var data = "";
|
|
1915
1999
|
if (multiDragElements.length && multiDragSortable === sortable) multiDragElements.forEach(function(multiDragElement, i) {
|
|
1916
2000
|
data += (!i ? "" : ", ") + multiDragElement.textContent;
|
|
1917
2001
|
});
|
|
1918
|
-
else data = dragEl
|
|
2002
|
+
else data = dragEl.textContent;
|
|
1919
2003
|
dataTransfer.setData("Text", data);
|
|
1920
2004
|
}
|
|
1921
2005
|
};
|
|
@@ -1943,23 +2027,23 @@
|
|
|
1943
2027
|
sortable._hideClone();
|
|
1944
2028
|
cancel();
|
|
1945
2029
|
},
|
|
1946
|
-
clone: function clone
|
|
1947
|
-
var sortable = _ref3.sortable, rootEl
|
|
2030
|
+
clone: function clone(_ref3) {
|
|
2031
|
+
var sortable = _ref3.sortable, rootEl = _ref3.rootEl, dispatchSortableEvent = _ref3.dispatchSortableEvent, cancel = _ref3.cancel;
|
|
1948
2032
|
if (!this.isMultiDrag) return;
|
|
1949
2033
|
if (!this.options.removeCloneOnHide) {
|
|
1950
2034
|
if (multiDragElements.length && multiDragSortable === sortable) {
|
|
1951
|
-
insertMultiDragClones(true, rootEl
|
|
2035
|
+
insertMultiDragClones(true, rootEl);
|
|
1952
2036
|
dispatchSortableEvent("clone");
|
|
1953
2037
|
cancel();
|
|
1954
2038
|
}
|
|
1955
2039
|
}
|
|
1956
2040
|
},
|
|
1957
2041
|
showClone: function showClone(_ref4) {
|
|
1958
|
-
var cloneNowShown = _ref4.cloneNowShown, rootEl
|
|
2042
|
+
var cloneNowShown = _ref4.cloneNowShown, rootEl = _ref4.rootEl, cancel = _ref4.cancel;
|
|
1959
2043
|
if (!this.isMultiDrag) return;
|
|
1960
|
-
insertMultiDragClones(false, rootEl
|
|
1961
|
-
multiDragClones.forEach(function(clone
|
|
1962
|
-
css(clone
|
|
2044
|
+
insertMultiDragClones(false, rootEl);
|
|
2045
|
+
multiDragClones.forEach(function(clone) {
|
|
2046
|
+
css(clone, "display", "");
|
|
1963
2047
|
});
|
|
1964
2048
|
cloneNowShown();
|
|
1965
2049
|
clonesHidden = false;
|
|
@@ -1970,9 +2054,9 @@
|
|
|
1970
2054
|
_ref5.sortable;
|
|
1971
2055
|
var cloneNowHidden = _ref5.cloneNowHidden, cancel = _ref5.cancel;
|
|
1972
2056
|
if (!this.isMultiDrag) return;
|
|
1973
|
-
multiDragClones.forEach(function(clone
|
|
1974
|
-
css(clone
|
|
1975
|
-
if (_this.options.removeCloneOnHide && clone
|
|
2057
|
+
multiDragClones.forEach(function(clone) {
|
|
2058
|
+
css(clone, "display", "none");
|
|
2059
|
+
if (_this.options.removeCloneOnHide && clone.parentNode) clone.parentNode.removeChild(clone);
|
|
1976
2060
|
});
|
|
1977
2061
|
cloneNowHidden();
|
|
1978
2062
|
clonesHidden = true;
|
|
@@ -1989,7 +2073,7 @@
|
|
|
1989
2073
|
});
|
|
1990
2074
|
dragStarted = true;
|
|
1991
2075
|
},
|
|
1992
|
-
dragStarted: function dragStarted
|
|
2076
|
+
dragStarted: function dragStarted(_ref7) {
|
|
1993
2077
|
var _this2 = this;
|
|
1994
2078
|
var sortable = _ref7.sortable;
|
|
1995
2079
|
if (!this.isMultiDrag) return;
|
|
@@ -2026,7 +2110,7 @@
|
|
|
2026
2110
|
}
|
|
2027
2111
|
},
|
|
2028
2112
|
revert: function revert(_ref9) {
|
|
2029
|
-
var fromSortable = _ref9.fromSortable, rootEl
|
|
2113
|
+
var fromSortable = _ref9.fromSortable, rootEl = _ref9.rootEl, sortable = _ref9.sortable, dragRect = _ref9.dragRect;
|
|
2030
2114
|
if (multiDragElements.length > 1) {
|
|
2031
2115
|
multiDragElements.forEach(function(multiDragElement) {
|
|
2032
2116
|
sortable.addAnimationState({
|
|
@@ -2038,21 +2122,21 @@
|
|
|
2038
2122
|
fromSortable.removeAnimationState(multiDragElement);
|
|
2039
2123
|
});
|
|
2040
2124
|
folding = false;
|
|
2041
|
-
insertMultiDragElements(!this.options.removeCloneOnHide, rootEl
|
|
2125
|
+
insertMultiDragElements(!this.options.removeCloneOnHide, rootEl);
|
|
2042
2126
|
}
|
|
2043
2127
|
},
|
|
2044
2128
|
dragOverCompleted: function dragOverCompleted(_ref10) {
|
|
2045
|
-
var sortable = _ref10.sortable, isOwner = _ref10.isOwner, insertion = _ref10.insertion, activeSortable = _ref10.activeSortable, parentEl
|
|
2129
|
+
var sortable = _ref10.sortable, isOwner = _ref10.isOwner, insertion = _ref10.insertion, activeSortable = _ref10.activeSortable, parentEl = _ref10.parentEl, putSortable = _ref10.putSortable;
|
|
2046
2130
|
var options = this.options;
|
|
2047
2131
|
if (insertion) {
|
|
2048
2132
|
if (isOwner) activeSortable._hideClone();
|
|
2049
2133
|
initialFolding = false;
|
|
2050
|
-
if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable
|
|
2134
|
+
if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) {
|
|
2051
2135
|
var dragRectAbsolute = getRect(dragEl$1, false, true, true);
|
|
2052
2136
|
multiDragElements.forEach(function(multiDragElement) {
|
|
2053
2137
|
if (multiDragElement === dragEl$1) return;
|
|
2054
2138
|
setRect(multiDragElement, dragRectAbsolute);
|
|
2055
|
-
parentEl
|
|
2139
|
+
parentEl.appendChild(multiDragElement);
|
|
2056
2140
|
});
|
|
2057
2141
|
folding = true;
|
|
2058
2142
|
}
|
|
@@ -2061,13 +2145,13 @@
|
|
|
2061
2145
|
if (multiDragElements.length > 1) {
|
|
2062
2146
|
var clonesHiddenBefore = clonesHidden;
|
|
2063
2147
|
activeSortable._showClone(sortable);
|
|
2064
|
-
if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) multiDragClones.forEach(function(clone
|
|
2148
|
+
if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) multiDragClones.forEach(function(clone) {
|
|
2065
2149
|
activeSortable.addAnimationState({
|
|
2066
|
-
target: clone
|
|
2150
|
+
target: clone,
|
|
2067
2151
|
rect: clonesFromRect
|
|
2068
2152
|
});
|
|
2069
|
-
clone
|
|
2070
|
-
clone
|
|
2153
|
+
clone.fromRect = clonesFromRect;
|
|
2154
|
+
clone.thisAnimationDuration = null;
|
|
2071
2155
|
});
|
|
2072
2156
|
} else activeSortable._showClone(sortable);
|
|
2073
2157
|
}
|
|
@@ -2091,11 +2175,11 @@
|
|
|
2091
2175
|
removeMultiDragElements();
|
|
2092
2176
|
}
|
|
2093
2177
|
},
|
|
2094
|
-
drop: function drop
|
|
2095
|
-
var evt = _ref12.originalEvent, rootEl
|
|
2096
|
-
var toSortable = putSortable
|
|
2178
|
+
drop: function drop(_ref12) {
|
|
2179
|
+
var evt = _ref12.originalEvent, rootEl = _ref12.rootEl, parentEl = _ref12.parentEl, sortable = _ref12.sortable, dispatchSortableEvent = _ref12.dispatchSortableEvent, oldIndex = _ref12.oldIndex, putSortable = _ref12.putSortable;
|
|
2180
|
+
var toSortable = putSortable || this.sortable;
|
|
2097
2181
|
if (!evt) return;
|
|
2098
|
-
var options = this.options, children = parentEl
|
|
2182
|
+
var options = this.options, children = parentEl.children;
|
|
2099
2183
|
if (!dragStarted) {
|
|
2100
2184
|
if (options.multiDragKey && !this.multiDragKeyDown) this._deselectMultiDrag();
|
|
2101
2185
|
toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1));
|
|
@@ -2103,7 +2187,7 @@
|
|
|
2103
2187
|
multiDragElements.push(dragEl$1);
|
|
2104
2188
|
dispatchEvent({
|
|
2105
2189
|
sortable,
|
|
2106
|
-
rootEl
|
|
2190
|
+
rootEl,
|
|
2107
2191
|
name: "select",
|
|
2108
2192
|
targetEl: dragEl$1,
|
|
2109
2193
|
originalEvent: evt
|
|
@@ -2122,15 +2206,15 @@
|
|
|
2122
2206
|
var filter = options.filter;
|
|
2123
2207
|
for (; i < n; i++) {
|
|
2124
2208
|
if (~multiDragElements.indexOf(children[i])) continue;
|
|
2125
|
-
if (!closest(children[i], options.draggable, parentEl
|
|
2209
|
+
if (!closest(children[i], options.draggable, parentEl, false)) continue;
|
|
2126
2210
|
if (filter && (typeof filter === "function" ? filter.call(sortable, evt, children[i], sortable) : filter.split(",").some(function(criteria) {
|
|
2127
|
-
return closest(children[i], criteria.trim(), parentEl
|
|
2211
|
+
return closest(children[i], criteria.trim(), parentEl, false);
|
|
2128
2212
|
}))) continue;
|
|
2129
2213
|
toggleClass(children[i], options.selectedClass, true);
|
|
2130
2214
|
multiDragElements.push(children[i]);
|
|
2131
2215
|
dispatchEvent({
|
|
2132
2216
|
sortable,
|
|
2133
|
-
rootEl
|
|
2217
|
+
rootEl,
|
|
2134
2218
|
name: "select",
|
|
2135
2219
|
targetEl: children[i],
|
|
2136
2220
|
originalEvent: evt
|
|
@@ -2144,7 +2228,7 @@
|
|
|
2144
2228
|
lastMultiDragSelect = null;
|
|
2145
2229
|
dispatchEvent({
|
|
2146
2230
|
sortable,
|
|
2147
|
-
rootEl
|
|
2231
|
+
rootEl,
|
|
2148
2232
|
name: "deselect",
|
|
2149
2233
|
targetEl: dragEl$1,
|
|
2150
2234
|
originalEvent: evt
|
|
@@ -2153,7 +2237,7 @@
|
|
|
2153
2237
|
}
|
|
2154
2238
|
if (dragStarted && this.isMultiDrag) {
|
|
2155
2239
|
folding = false;
|
|
2156
|
-
if ((parentEl
|
|
2240
|
+
if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) {
|
|
2157
2241
|
var dragRect = getRect(dragEl$1), multiDragIndex = index(dragEl$1, ":not(." + this.options.selectedClass + ")");
|
|
2158
2242
|
if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null;
|
|
2159
2243
|
toSortable.captureAnimationState();
|
|
@@ -2174,11 +2258,11 @@
|
|
|
2174
2258
|
}
|
|
2175
2259
|
removeMultiDragElements();
|
|
2176
2260
|
multiDragElements.forEach(function(multiDragElement) {
|
|
2177
|
-
if (children[multiDragIndex]) parentEl
|
|
2178
|
-
else parentEl
|
|
2261
|
+
if (children[multiDragIndex]) parentEl.insertBefore(multiDragElement, children[multiDragIndex]);
|
|
2262
|
+
else parentEl.appendChild(multiDragElement);
|
|
2179
2263
|
multiDragIndex++;
|
|
2180
2264
|
});
|
|
2181
|
-
if (oldIndex
|
|
2265
|
+
if (oldIndex === index(dragEl$1)) {
|
|
2182
2266
|
var update = false;
|
|
2183
2267
|
multiDragElements.forEach(function(multiDragElement) {
|
|
2184
2268
|
if (multiDragElement.sortableIndex !== index(multiDragElement)) {
|
|
@@ -2199,8 +2283,8 @@
|
|
|
2199
2283
|
}
|
|
2200
2284
|
multiDragSortable = toSortable;
|
|
2201
2285
|
}
|
|
2202
|
-
if (rootEl
|
|
2203
|
-
clone
|
|
2286
|
+
if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== "clone") multiDragClones.forEach(function(clone) {
|
|
2287
|
+
clone.parentNode && clone.parentNode.removeChild(clone);
|
|
2204
2288
|
});
|
|
2205
2289
|
},
|
|
2206
2290
|
nullingGlobal: function nullingGlobal() {
|
|
@@ -2254,10 +2338,10 @@
|
|
|
2254
2338
|
multiDragElements.push(el);
|
|
2255
2339
|
},
|
|
2256
2340
|
deselect: function deselect(el) {
|
|
2257
|
-
var sortable = el.parentNode[expando], index
|
|
2258
|
-
if (!sortable || !sortable.options.multiDrag || !~index
|
|
2341
|
+
var sortable = el.parentNode[expando], index = multiDragElements.indexOf(el);
|
|
2342
|
+
if (!sortable || !sortable.options.multiDrag || !~index) return;
|
|
2259
2343
|
toggleClass(el, sortable.options.selectedClass, false);
|
|
2260
|
-
multiDragElements.splice(index
|
|
2344
|
+
multiDragElements.splice(index, 1);
|
|
2261
2345
|
}
|
|
2262
2346
|
},
|
|
2263
2347
|
eventProperties: function eventProperties() {
|
|
@@ -2268,13 +2352,13 @@
|
|
|
2268
2352
|
multiDragElement,
|
|
2269
2353
|
index: multiDragElement.sortableIndex
|
|
2270
2354
|
});
|
|
2271
|
-
var newIndex
|
|
2272
|
-
if (folding && multiDragElement !== dragEl$1) newIndex
|
|
2273
|
-
else if (folding) newIndex
|
|
2274
|
-
else newIndex
|
|
2355
|
+
var newIndex;
|
|
2356
|
+
if (folding && multiDragElement !== dragEl$1) newIndex = -1;
|
|
2357
|
+
else if (folding) newIndex = index(multiDragElement, ":not(." + _this3.options.selectedClass + ")");
|
|
2358
|
+
else newIndex = index(multiDragElement);
|
|
2275
2359
|
newIndicies.push({
|
|
2276
2360
|
multiDragElement,
|
|
2277
|
-
index: newIndex
|
|
2361
|
+
index: newIndex
|
|
2278
2362
|
});
|
|
2279
2363
|
});
|
|
2280
2364
|
return {
|
|
@@ -2292,18 +2376,23 @@
|
|
|
2292
2376
|
} }
|
|
2293
2377
|
});
|
|
2294
2378
|
}
|
|
2295
|
-
function insertMultiDragElements(clonesInserted, rootEl
|
|
2379
|
+
function insertMultiDragElements(clonesInserted, rootEl) {
|
|
2296
2380
|
multiDragElements.forEach(function(multiDragElement, i) {
|
|
2297
|
-
var target = rootEl
|
|
2298
|
-
if (target) rootEl
|
|
2299
|
-
else rootEl
|
|
2381
|
+
var target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)];
|
|
2382
|
+
if (target) rootEl.insertBefore(multiDragElement, target);
|
|
2383
|
+
else rootEl.appendChild(multiDragElement);
|
|
2300
2384
|
});
|
|
2301
2385
|
}
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2386
|
+
/**
|
|
2387
|
+
* Insert multi-drag clones
|
|
2388
|
+
* @param {[Boolean]} elementsInserted Whether the multi-drag elements are inserted
|
|
2389
|
+
* @param {HTMLElement} rootEl
|
|
2390
|
+
*/
|
|
2391
|
+
function insertMultiDragClones(elementsInserted, rootEl) {
|
|
2392
|
+
multiDragClones.forEach(function(clone, i) {
|
|
2393
|
+
var target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)];
|
|
2394
|
+
if (target) rootEl.insertBefore(clone, target);
|
|
2395
|
+
else rootEl.appendChild(clone);
|
|
2307
2396
|
});
|
|
2308
2397
|
}
|
|
2309
2398
|
function removeMultiDragElements() {
|
|
@@ -2312,24 +2401,128 @@
|
|
|
2312
2401
|
multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement);
|
|
2313
2402
|
});
|
|
2314
2403
|
}
|
|
2315
|
-
Sortable
|
|
2316
|
-
Sortable
|
|
2317
|
-
Sortable
|
|
2318
|
-
Sortable
|
|
2319
|
-
return Sortable
|
|
2404
|
+
Sortable.mount(new AutoScrollPlugin());
|
|
2405
|
+
Sortable.mount(Remove, Revert);
|
|
2406
|
+
Sortable.mount(new SwapPlugin());
|
|
2407
|
+
Sortable.mount(new MultiDragPlugin());
|
|
2408
|
+
return Sortable;
|
|
2320
2409
|
}));
|
|
2321
2410
|
})))());
|
|
2322
|
-
|
|
2323
|
-
|
|
2411
|
+
/** 默认精确搜索字段 */
|
|
2412
|
+
var DEFAULT_EXACT_SEARCH_KEY = "bk_username";
|
|
2413
|
+
/** 用户类型 */
|
|
2414
|
+
var USER_TYPE = {
|
|
2324
2415
|
USER: "user",
|
|
2325
2416
|
VIRTUAL: "virtual",
|
|
2326
2417
|
CUSTOM: "custom",
|
|
2327
2418
|
USER_GROUP: "userGroup"
|
|
2328
2419
|
};
|
|
2420
|
+
//#endregion
|
|
2421
|
+
//#region src/hooks/use-api-config.ts
|
|
2422
|
+
var API_CONFIG_KEY = Symbol("bkUserSelectorApiConfig");
|
|
2423
|
+
var TENANT_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
2424
|
+
var globalApiConfig = {
|
|
2425
|
+
apiBaseUrl: "",
|
|
2426
|
+
tenantId: "",
|
|
2427
|
+
allowedApiOrigins: [],
|
|
2428
|
+
allowPrivateApiHost: false,
|
|
2429
|
+
allowCrossOriginCredentials: false
|
|
2430
|
+
};
|
|
2431
|
+
var getCurrentOrigin = () => {
|
|
2432
|
+
if (typeof window === "undefined" || !window.location?.origin) return "http://localhost";
|
|
2433
|
+
return window.location.origin;
|
|
2434
|
+
};
|
|
2435
|
+
var isPrivateIpv4 = (hostname) => {
|
|
2436
|
+
const segments = hostname.split(".").map(Number);
|
|
2437
|
+
if (segments.length !== 4 || segments.some(Number.isNaN)) return false;
|
|
2438
|
+
const [a, b] = segments;
|
|
2439
|
+
if (a === 10 || a === 127) return true;
|
|
2440
|
+
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
2441
|
+
if (a === 192 && b === 168) return true;
|
|
2442
|
+
if (a === 169 && b === 254) return true;
|
|
2443
|
+
if (a === 100 && b >= 64 && b <= 127) return true;
|
|
2444
|
+
return false;
|
|
2445
|
+
};
|
|
2446
|
+
var isPrivateHost = (hostname) => {
|
|
2447
|
+
const normalizedHost = hostname.toLowerCase();
|
|
2448
|
+
if (normalizedHost === "localhost" || normalizedHost === "[::1]" || normalizedHost === "::1") return true;
|
|
2449
|
+
if (isPrivateIpv4(normalizedHost)) return true;
|
|
2450
|
+
if (normalizedHost.startsWith("fc") || normalizedHost.startsWith("fd")) return true;
|
|
2451
|
+
return false;
|
|
2452
|
+
};
|
|
2453
|
+
var normalizeAllowedOrigins = (allowedApiOrigins = []) => {
|
|
2454
|
+
const currentOrigin = getCurrentOrigin();
|
|
2455
|
+
return Array.from(new Set(allowedApiOrigins.map((origin) => {
|
|
2456
|
+
try {
|
|
2457
|
+
const parsed = new URL(origin, currentOrigin);
|
|
2458
|
+
if (!["http:", "https:"].includes(parsed.protocol)) return "";
|
|
2459
|
+
return parsed.origin;
|
|
2460
|
+
} catch {
|
|
2461
|
+
return "";
|
|
2462
|
+
}
|
|
2463
|
+
}).filter(Boolean)));
|
|
2464
|
+
};
|
|
2465
|
+
var sanitizeApiBaseUrl = (apiBaseUrl, allowedApiOrigins = [], allowPrivateApiHost = false) => {
|
|
2466
|
+
if (!apiBaseUrl) return "";
|
|
2467
|
+
try {
|
|
2468
|
+
const parsed = new URL(apiBaseUrl, getCurrentOrigin());
|
|
2469
|
+
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
2470
|
+
console.warn("[bk-user-selector] apiBaseUrl 仅支持 http/https 协议");
|
|
2471
|
+
return "";
|
|
2472
|
+
}
|
|
2473
|
+
if (!allowPrivateApiHost && isPrivateHost(parsed.hostname)) {
|
|
2474
|
+
console.warn("[bk-user-selector] apiBaseUrl 指向私网或 localhost,已被安全策略拦截");
|
|
2475
|
+
return "";
|
|
2476
|
+
}
|
|
2477
|
+
const normalizedAllowedOrigins = normalizeAllowedOrigins(allowedApiOrigins);
|
|
2478
|
+
if (normalizedAllowedOrigins.length > 0 && !normalizedAllowedOrigins.includes(parsed.origin)) {
|
|
2479
|
+
console.warn("[bk-user-selector] apiBaseUrl 未命中 allowedApiOrigins 白名单,已被安全策略拦截");
|
|
2480
|
+
return "";
|
|
2481
|
+
}
|
|
2482
|
+
const normalizedPath = parsed.pathname.replace(/\/+$/, "");
|
|
2483
|
+
return `${parsed.origin}${normalizedPath}`;
|
|
2484
|
+
} catch {
|
|
2485
|
+
console.warn("[bk-user-selector] apiBaseUrl 格式非法,已被安全策略拦截");
|
|
2486
|
+
return "";
|
|
2487
|
+
}
|
|
2488
|
+
};
|
|
2489
|
+
var sanitizeTenantId = (tenantId) => {
|
|
2490
|
+
const normalizedTenantId = String(tenantId || "").trim();
|
|
2491
|
+
if (!normalizedTenantId) return "";
|
|
2492
|
+
if (!TENANT_ID_PATTERN.test(normalizedTenantId)) {
|
|
2493
|
+
console.warn("[bk-user-selector] tenantId 格式非法,已被安全策略拦截");
|
|
2494
|
+
return "";
|
|
2495
|
+
}
|
|
2496
|
+
return normalizedTenantId;
|
|
2497
|
+
};
|
|
2498
|
+
var getApiConfig = () => {
|
|
2499
|
+
return globalApiConfig;
|
|
2500
|
+
};
|
|
2501
|
+
var provideApiConfig = (apiBaseUrl, tenantId, allowedApiOrigins = [], allowPrivateApiHost = false, allowCrossOriginCredentials = false, callbacks = {}) => {
|
|
2502
|
+
const normalizedAllowedOrigins = normalizeAllowedOrigins(allowedApiOrigins);
|
|
2503
|
+
globalApiConfig = {
|
|
2504
|
+
apiBaseUrl: sanitizeApiBaseUrl(apiBaseUrl, normalizedAllowedOrigins, allowPrivateApiHost),
|
|
2505
|
+
tenantId: sanitizeTenantId(tenantId),
|
|
2506
|
+
allowedApiOrigins: normalizedAllowedOrigins,
|
|
2507
|
+
allowPrivateApiHost,
|
|
2508
|
+
allowCrossOriginCredentials,
|
|
2509
|
+
onError: callbacks.onError,
|
|
2510
|
+
onUnauthorized: callbacks.onUnauthorized
|
|
2511
|
+
};
|
|
2512
|
+
(0, vue.provide)(API_CONFIG_KEY, globalApiConfig);
|
|
2513
|
+
};
|
|
2514
|
+
//#endregion
|
|
2515
|
+
//#region src/hooks/use-jsonp.ts
|
|
2516
|
+
/**
|
|
2517
|
+
* 生成回调函数名
|
|
2518
|
+
*/
|
|
2329
2519
|
var generateCallbackName = () => {
|
|
2330
2520
|
return `__jsonp_callback_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
2331
2521
|
};
|
|
2332
|
-
|
|
2522
|
+
/**
|
|
2523
|
+
* JSONP 请求函数
|
|
2524
|
+
*/
|
|
2525
|
+
var jsonpRequest = (requestUrl, options = {}) => {
|
|
2333
2526
|
return new Promise((resolve, reject) => {
|
|
2334
2527
|
const url = (0, vue.unref)(requestUrl);
|
|
2335
2528
|
const { timeout = 1e3 * 60 * 2, params } = options;
|
|
@@ -2358,6 +2551,8 @@
|
|
|
2358
2551
|
document.head.appendChild(script);
|
|
2359
2552
|
});
|
|
2360
2553
|
};
|
|
2554
|
+
//#endregion
|
|
2555
|
+
//#region src/utils/logger.ts
|
|
2361
2556
|
var PREFIX = "[BkUserSelector]";
|
|
2362
2557
|
var LOG_LEVELS = {
|
|
2363
2558
|
debug: 0,
|
|
@@ -2369,10 +2564,16 @@
|
|
|
2369
2564
|
enabled: true,
|
|
2370
2565
|
level: "warn"
|
|
2371
2566
|
};
|
|
2567
|
+
/**
|
|
2568
|
+
* 检查是否应该输出日志
|
|
2569
|
+
*/
|
|
2372
2570
|
var shouldLog = (level) => {
|
|
2373
2571
|
return config.enabled && LOG_LEVELS[level] >= LOG_LEVELS[config.level];
|
|
2374
2572
|
};
|
|
2375
|
-
|
|
2573
|
+
/**
|
|
2574
|
+
* 日志工具
|
|
2575
|
+
*/
|
|
2576
|
+
var logger = {
|
|
2376
2577
|
debug: (message, ...args) => {
|
|
2377
2578
|
if (shouldLog("debug")) console.debug(`${PREFIX} ${message}`, ...args);
|
|
2378
2579
|
},
|
|
@@ -2386,32 +2587,132 @@
|
|
|
2386
2587
|
if (shouldLog("error")) console.error(`${PREFIX} ${message}`, error);
|
|
2387
2588
|
}
|
|
2388
2589
|
};
|
|
2389
|
-
|
|
2390
|
-
|
|
2590
|
+
/**
|
|
2591
|
+
* 安全调用用户回调
|
|
2592
|
+
* 用户回调如果抛错不应影响组件正常流程
|
|
2593
|
+
*/
|
|
2594
|
+
var safeInvoke = (handler, error) => {
|
|
2595
|
+
if (!handler) return;
|
|
2596
|
+
try {
|
|
2597
|
+
handler(error);
|
|
2598
|
+
} catch (err) {
|
|
2599
|
+
console.error(`${PREFIX} error handler threw:`, err);
|
|
2600
|
+
}
|
|
2391
2601
|
};
|
|
2392
|
-
|
|
2602
|
+
/**
|
|
2603
|
+
* 构造 ApiError 对象
|
|
2604
|
+
*/
|
|
2605
|
+
var buildApiError = (scene, cause, status, isUnauthorized = false) => ({
|
|
2606
|
+
scene,
|
|
2607
|
+
cause,
|
|
2608
|
+
status,
|
|
2609
|
+
isUnauthorized
|
|
2610
|
+
});
|
|
2611
|
+
/**
|
|
2612
|
+
* API 错误处理
|
|
2613
|
+
* - 打印错误日志(兜底)
|
|
2614
|
+
* - 触发 apiConfig.onError 回调
|
|
2615
|
+
* - 如果是 401,额外触发 apiConfig.onUnauthorized 回调
|
|
2616
|
+
*/
|
|
2617
|
+
var handleApiError = (operation, error, apiConfig, status, isUnauthorized = false) => {
|
|
2618
|
+
if (isUnauthorized) logger.warn(`${operation}: 登录态已失效,请重新登录`);
|
|
2619
|
+
else logger.error(`${operation}失败:`, error);
|
|
2620
|
+
const apiError = buildApiError(operation, error, status, isUnauthorized);
|
|
2621
|
+
if (isUnauthorized) safeInvoke(apiConfig?.onUnauthorized, apiError);
|
|
2622
|
+
safeInvoke(apiConfig?.onError, apiError);
|
|
2623
|
+
};
|
|
2624
|
+
/**
|
|
2625
|
+
* 参数校验警告
|
|
2626
|
+
*/
|
|
2627
|
+
var warnMissingParams = (operation, params) => {
|
|
2393
2628
|
logger.warn(`${operation}需要提供有效的参数: ${params.join(", ")}`);
|
|
2394
2629
|
};
|
|
2395
|
-
|
|
2396
|
-
|
|
2630
|
+
//#endregion
|
|
2631
|
+
//#region src/api/user.ts
|
|
2632
|
+
/**
|
|
2633
|
+
* 用户选择器相关API
|
|
2634
|
+
* @module api/user
|
|
2635
|
+
*/
|
|
2636
|
+
var UNAUTHORIZED_STATUS = 401;
|
|
2637
|
+
var resolveRequestCredentials = (url, allowCrossOriginCredentials) => {
|
|
2638
|
+
if (typeof window === "undefined" || !window.location?.origin) return "same-origin";
|
|
2639
|
+
try {
|
|
2640
|
+
if (new URL(url, window.location.origin).origin === window.location.origin) return "include";
|
|
2641
|
+
return allowCrossOriginCredentials ? "include" : "omit";
|
|
2642
|
+
} catch {
|
|
2643
|
+
return "same-origin";
|
|
2644
|
+
}
|
|
2645
|
+
};
|
|
2646
|
+
var resolveApiSecurityConfig = (apiBaseUrl, tenantId) => {
|
|
2647
|
+
const globalConfig = getApiConfig();
|
|
2648
|
+
const resolvedAllowPrivateApiHost = globalConfig.allowPrivateApiHost;
|
|
2649
|
+
const resolvedAllowedApiOrigins = globalConfig.allowedApiOrigins;
|
|
2650
|
+
return {
|
|
2651
|
+
allowCrossOriginCredentials: globalConfig.allowCrossOriginCredentials,
|
|
2652
|
+
apiBaseUrl: sanitizeApiBaseUrl(globalConfig.apiBaseUrl || apiBaseUrl, resolvedAllowedApiOrigins, resolvedAllowPrivateApiHost),
|
|
2653
|
+
tenantId: sanitizeTenantId(globalConfig.tenantId || tenantId),
|
|
2654
|
+
apiConfig: globalConfig
|
|
2655
|
+
};
|
|
2656
|
+
};
|
|
2657
|
+
/**
|
|
2658
|
+
* 统一处理响应状态码,401 时构造 ApiError 并触发回调,然后抛出错误
|
|
2659
|
+
*/
|
|
2660
|
+
var ensureResponseOk = (response, scene, apiConfig) => {
|
|
2661
|
+
if (response.ok) return;
|
|
2662
|
+
if (response.status === UNAUTHORIZED_STATUS) {
|
|
2663
|
+
const error = /* @__PURE__ */ new Error(`${scene}失败: 登录态已失效`);
|
|
2664
|
+
handleApiError(scene, error, apiConfig, response.status, true);
|
|
2665
|
+
throw error;
|
|
2666
|
+
}
|
|
2667
|
+
throw new Error(`${response.status} ${response.statusText}`);
|
|
2668
|
+
};
|
|
2669
|
+
/**
|
|
2670
|
+
* 从抛出的错误中尽力提取 HTTP 状态码
|
|
2671
|
+
*/
|
|
2672
|
+
var extractStatus = (error) => {
|
|
2673
|
+
if (typeof error === "object" && error !== null && "status" in error) {
|
|
2674
|
+
const status = error.status;
|
|
2675
|
+
return typeof status === "number" ? status : void 0;
|
|
2676
|
+
}
|
|
2677
|
+
if (error instanceof Error) {
|
|
2678
|
+
const match = /^(\d{3})\s/.exec(error.message);
|
|
2679
|
+
if (match) return Number(match[1]);
|
|
2680
|
+
}
|
|
2681
|
+
};
|
|
2682
|
+
/**
|
|
2683
|
+
* 获取本租户所有数据来源的租户信息
|
|
2684
|
+
* @param apiBaseUrl - API基础URL
|
|
2685
|
+
* @param tenantId - 租户ID
|
|
2686
|
+
* @returns 租户列表Promise
|
|
2687
|
+
*/
|
|
2688
|
+
var getTenants = async (apiBaseUrl, tenantId) => {
|
|
2689
|
+
const resolvedConfig = resolveApiSecurityConfig(apiBaseUrl, tenantId);
|
|
2690
|
+
if (!resolvedConfig.apiBaseUrl || !resolvedConfig.tenantId) {
|
|
2397
2691
|
warnMissingParams("获取租户信息", ["apiBaseUrl", "tenantId"]);
|
|
2398
2692
|
return [];
|
|
2399
2693
|
}
|
|
2400
2694
|
try {
|
|
2401
|
-
const url = `${apiBaseUrl}/api/v3/open-web/tenant/data-source-owner-tenants/`;
|
|
2695
|
+
const url = `${resolvedConfig.apiBaseUrl}/api/v3/open-web/tenant/data-source-owner-tenants/`;
|
|
2696
|
+
const requestCredentials = resolveRequestCredentials(url, resolvedConfig.allowCrossOriginCredentials);
|
|
2402
2697
|
const response = await fetch(url, {
|
|
2403
2698
|
method: "GET",
|
|
2404
|
-
headers: { "x-bk-tenant-id": tenantId },
|
|
2405
|
-
credentials:
|
|
2699
|
+
headers: { "x-bk-tenant-id": resolvedConfig.tenantId },
|
|
2700
|
+
credentials: requestCredentials
|
|
2406
2701
|
});
|
|
2407
|
-
|
|
2702
|
+
ensureResponseOk(response, "获取租户信息", resolvedConfig.apiConfig);
|
|
2408
2703
|
return (await response.json()).data || [];
|
|
2409
2704
|
} catch (error) {
|
|
2410
|
-
|
|
2705
|
+
const status = extractStatus(error);
|
|
2706
|
+
if (status !== UNAUTHORIZED_STATUS) handleApiError("获取租户信息", error, resolvedConfig.apiConfig, status, false);
|
|
2411
2707
|
return [];
|
|
2412
2708
|
}
|
|
2413
2709
|
};
|
|
2414
|
-
|
|
2710
|
+
/**
|
|
2711
|
+
* 模糊搜索用户
|
|
2712
|
+
* @param params - 搜索参数
|
|
2713
|
+
* @returns 用户列表Promise
|
|
2714
|
+
*/
|
|
2715
|
+
var searchUsers = async (params) => {
|
|
2415
2716
|
const { apiBaseUrl, tenantId, keyword, enableMultiTenantMode = true } = params;
|
|
2416
2717
|
if (!enableMultiTenantMode) try {
|
|
2417
2718
|
return await getUserList(apiBaseUrl, {
|
|
@@ -2422,7 +2723,8 @@
|
|
|
2422
2723
|
} catch {
|
|
2423
2724
|
return [];
|
|
2424
2725
|
}
|
|
2425
|
-
|
|
2726
|
+
const resolvedConfig = resolveApiSecurityConfig(apiBaseUrl, tenantId);
|
|
2727
|
+
if (!keyword || !resolvedConfig.apiBaseUrl || !resolvedConfig.tenantId) {
|
|
2426
2728
|
warnMissingParams("搜索用户", [
|
|
2427
2729
|
"apiBaseUrl",
|
|
2428
2730
|
"tenantId",
|
|
@@ -2431,20 +2733,27 @@
|
|
|
2431
2733
|
return [];
|
|
2432
2734
|
}
|
|
2433
2735
|
try {
|
|
2434
|
-
const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/search/?keyword=${encodeURIComponent(keyword)}`;
|
|
2736
|
+
const url = `${resolvedConfig.apiBaseUrl}/api/v3/open-web/tenant/users/-/search/?keyword=${encodeURIComponent(keyword)}`;
|
|
2737
|
+
const requestCredentials = resolveRequestCredentials(url, resolvedConfig.allowCrossOriginCredentials);
|
|
2435
2738
|
const response = await fetch(url, {
|
|
2436
2739
|
method: "GET",
|
|
2437
|
-
headers: { "x-bk-tenant-id": tenantId },
|
|
2438
|
-
credentials:
|
|
2740
|
+
headers: { "x-bk-tenant-id": resolvedConfig.tenantId },
|
|
2741
|
+
credentials: requestCredentials
|
|
2439
2742
|
});
|
|
2440
|
-
|
|
2743
|
+
ensureResponseOk(response, "搜索用户", resolvedConfig.apiConfig);
|
|
2441
2744
|
return (await response.json()).data || [];
|
|
2442
2745
|
} catch (error) {
|
|
2443
|
-
|
|
2746
|
+
const status = extractStatus(error);
|
|
2747
|
+
if (status !== UNAUTHORIZED_STATUS) handleApiError("搜索用户", error, resolvedConfig.apiConfig, status, false);
|
|
2444
2748
|
return [];
|
|
2445
2749
|
}
|
|
2446
2750
|
};
|
|
2447
|
-
|
|
2751
|
+
/**
|
|
2752
|
+
* 批量精准查找用户
|
|
2753
|
+
* @param params - 查找参数
|
|
2754
|
+
* @returns 查找到的用户列表Promise
|
|
2755
|
+
*/
|
|
2756
|
+
var lookupUsers = async (params) => {
|
|
2448
2757
|
const { apiBaseUrl, tenantId, exactSearchKey = "bk_username", usersList = [], enableMultiTenantMode = true } = params;
|
|
2449
2758
|
const users = usersList.filter(Boolean).map((user) => typeof user === "string" ? user.trim() : String(user).trim());
|
|
2450
2759
|
if (!enableMultiTenantMode) try {
|
|
@@ -2453,7 +2762,8 @@
|
|
|
2453
2762
|
} catch {
|
|
2454
2763
|
return [];
|
|
2455
2764
|
}
|
|
2456
|
-
|
|
2765
|
+
const resolvedConfig = resolveApiSecurityConfig(apiBaseUrl, tenantId);
|
|
2766
|
+
if (users.length === 0 || !resolvedConfig.apiBaseUrl || !resolvedConfig.tenantId) {
|
|
2457
2767
|
warnMissingParams("批量查找用户", [
|
|
2458
2768
|
"apiBaseUrl",
|
|
2459
2769
|
"tenantId",
|
|
@@ -2462,20 +2772,27 @@
|
|
|
2462
2772
|
return [];
|
|
2463
2773
|
}
|
|
2464
2774
|
try {
|
|
2465
|
-
const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/lookup/?lookups=${users.join(",")}&lookup_fields=${exactSearchKey}`;
|
|
2775
|
+
const url = `${resolvedConfig.apiBaseUrl}/api/v3/open-web/tenant/users/-/lookup/?lookups=${users.join(",")}&lookup_fields=${exactSearchKey}`;
|
|
2776
|
+
const requestCredentials = resolveRequestCredentials(url, resolvedConfig.allowCrossOriginCredentials);
|
|
2466
2777
|
const response = await fetch(url, {
|
|
2467
2778
|
method: "GET",
|
|
2468
|
-
headers: { "x-bk-tenant-id": tenantId },
|
|
2469
|
-
credentials:
|
|
2779
|
+
headers: { "x-bk-tenant-id": resolvedConfig.tenantId },
|
|
2780
|
+
credentials: requestCredentials
|
|
2470
2781
|
});
|
|
2471
|
-
|
|
2782
|
+
ensureResponseOk(response, "批量查找用户", resolvedConfig.apiConfig);
|
|
2472
2783
|
return (await response.json()).data || [];
|
|
2473
2784
|
} catch (error) {
|
|
2474
|
-
|
|
2785
|
+
const status = extractStatus(error);
|
|
2786
|
+
if (status !== UNAUTHORIZED_STATUS) handleApiError("批量查找用户", error, resolvedConfig.apiConfig, status, false);
|
|
2475
2787
|
return [];
|
|
2476
2788
|
}
|
|
2477
2789
|
};
|
|
2478
|
-
|
|
2790
|
+
/**
|
|
2791
|
+
* 将API返回的用户数据格式化为组件所需格式
|
|
2792
|
+
* @param users - API返回的用户列表
|
|
2793
|
+
* @returns 格式化后的用户列表
|
|
2794
|
+
*/
|
|
2795
|
+
var formatUsers = (users, enableMultiTenantMode = true) => {
|
|
2479
2796
|
if (!users || !Array.isArray(users)) return [];
|
|
2480
2797
|
if (!enableMultiTenantMode) return users.map((user) => ({
|
|
2481
2798
|
...user,
|
|
@@ -2492,7 +2809,13 @@
|
|
|
2492
2809
|
...user
|
|
2493
2810
|
}));
|
|
2494
2811
|
};
|
|
2495
|
-
|
|
2812
|
+
/**
|
|
2813
|
+
* 获取用户列表(兼容旧版本的人员选择器)
|
|
2814
|
+
* @param url - 请求的 URL
|
|
2815
|
+
* @param params - 请求参数
|
|
2816
|
+
* @returns 用户列表
|
|
2817
|
+
*/
|
|
2818
|
+
var getUserList = async (url, params) => {
|
|
2496
2819
|
const { userIds, keyword, pageSize = 20, page = 1, appCode = "bk-magicbox" } = params;
|
|
2497
2820
|
return (await jsonpRequest(url, { params: {
|
|
2498
2821
|
exact_lookups: userIds?.join(",") || void 0,
|
|
@@ -2502,9 +2825,23 @@
|
|
|
2502
2825
|
app_code: appCode
|
|
2503
2826
|
} }))?.results || [];
|
|
2504
2827
|
};
|
|
2505
|
-
|
|
2828
|
+
//#endregion
|
|
2829
|
+
//#region src/hooks/use-current-user.ts
|
|
2830
|
+
/**
|
|
2831
|
+
* 当前用户处理 Hook
|
|
2832
|
+
* @module hooks/useCurrentUser
|
|
2833
|
+
*/
|
|
2834
|
+
/**
|
|
2835
|
+
* 当前用户处理 Hook
|
|
2836
|
+
* @param options - 配置选项
|
|
2837
|
+
* @returns 当前用户相关方法
|
|
2838
|
+
*/
|
|
2839
|
+
var useCurrentUser = (options) => {
|
|
2506
2840
|
const { apiBaseUrl, tenantId, currentUserId, exactSearchKey = DEFAULT_EXACT_SEARCH_KEY, enableMultiTenantMode = true } = options;
|
|
2507
2841
|
const loading = (0, vue.ref)(false);
|
|
2842
|
+
/**
|
|
2843
|
+
* 获取当前用户信息
|
|
2844
|
+
*/
|
|
2508
2845
|
const fetchCurrentUser = async () => {
|
|
2509
2846
|
if (!currentUserId) return null;
|
|
2510
2847
|
loading.value = true;
|
|
@@ -2529,6 +2866,9 @@
|
|
|
2529
2866
|
fetchCurrentUser
|
|
2530
2867
|
};
|
|
2531
2868
|
};
|
|
2869
|
+
//#endregion
|
|
2870
|
+
//#region ../../node_modules/.pnpm/js-cookie@3.0.5/node_modules/js-cookie/dist/js.cookie.mjs
|
|
2871
|
+
/*! js-cookie v3.0.5 | MIT */
|
|
2532
2872
|
function assign(target) {
|
|
2533
2873
|
for (var i = 1; i < arguments.length; i++) {
|
|
2534
2874
|
var source = arguments[i];
|
|
@@ -2585,8 +2925,8 @@
|
|
|
2585
2925
|
withAttributes: function(attributes) {
|
|
2586
2926
|
return init(this.converter, assign({}, this.attributes, attributes));
|
|
2587
2927
|
},
|
|
2588
|
-
withConverter: function(converter
|
|
2589
|
-
return init(assign({}, this.converter, converter
|
|
2928
|
+
withConverter: function(converter) {
|
|
2929
|
+
return init(assign({}, this.converter, converter), this.attributes);
|
|
2590
2930
|
}
|
|
2591
2931
|
}, {
|
|
2592
2932
|
attributes: { value: Object.freeze(defaultAttributes) },
|
|
@@ -2594,22 +2934,30 @@
|
|
|
2594
2934
|
});
|
|
2595
2935
|
}
|
|
2596
2936
|
var api = init(defaultConverter, { path: "/" });
|
|
2937
|
+
//#endregion
|
|
2938
|
+
//#region src/locale/en-us.ts
|
|
2597
2939
|
var en_us_default = {
|
|
2598
2940
|
我: "Me",
|
|
2599
2941
|
请输入人员名称搜索: "Please enter the name of the user to search",
|
|
2942
|
+
最近选择: "Recent selections",
|
|
2600
2943
|
用户群组: "User Group",
|
|
2601
2944
|
无匹配人员: "No matching users",
|
|
2602
2945
|
虚拟账号: "Virtual Account",
|
|
2603
2946
|
用户: "User"
|
|
2604
2947
|
};
|
|
2948
|
+
//#endregion
|
|
2949
|
+
//#region src/locale/zh-cn.ts
|
|
2605
2950
|
var zh_cn_default = {
|
|
2606
2951
|
我: "我",
|
|
2607
2952
|
请输入人员名称搜索: "请输入人员名称搜索",
|
|
2953
|
+
最近选择: "最近选择",
|
|
2608
2954
|
用户群组: "用户群组",
|
|
2609
2955
|
无匹配人员: "无匹配人员",
|
|
2610
2956
|
虚拟账号: "虚拟账号",
|
|
2611
2957
|
用户: "用户"
|
|
2612
2958
|
};
|
|
2959
|
+
//#endregion
|
|
2960
|
+
//#region src/hooks/use-i18n.ts
|
|
2613
2961
|
var BLUEKINNG_LANGUAGE = "blueking_language";
|
|
2614
2962
|
var languageMap = {
|
|
2615
2963
|
"en-US": en_us_default,
|
|
@@ -2648,9 +2996,28 @@
|
|
|
2648
2996
|
t
|
|
2649
2997
|
};
|
|
2650
2998
|
};
|
|
2651
|
-
|
|
2999
|
+
//#endregion
|
|
3000
|
+
//#region src/hooks/use-input-handler.ts
|
|
3001
|
+
/**
|
|
3002
|
+
* 输入处理公共逻辑 Hook
|
|
3003
|
+
* @module hooks/useInputHandler
|
|
3004
|
+
*/
|
|
3005
|
+
/**
|
|
3006
|
+
* 输入处理公共逻辑 Hook
|
|
3007
|
+
* @param options - 配置选项
|
|
3008
|
+
* @returns 输入处理相关方法
|
|
3009
|
+
*/
|
|
3010
|
+
var useInputHandler = (options) => {
|
|
2652
3011
|
const { apiBaseUrl, tenantId, searchQuery, selectedUsers, allowCreate = false, freePaste = false, enableMultiTenantMode = true, maxCount = 0, onAddUser, onBatchAddUsers } = options;
|
|
2653
3012
|
const isPasting = (0, vue.ref)(false);
|
|
3013
|
+
/** 单次粘贴最多处理数量(后端限制) */
|
|
3014
|
+
const MAX_PASTE_USERS = 100;
|
|
3015
|
+
/** 批量查询每批数量(不超过后端限制) */
|
|
3016
|
+
const LOOKUP_BATCH_SIZE = 100;
|
|
3017
|
+
/**
|
|
3018
|
+
* 创建自定义用户对象
|
|
3019
|
+
* @param loginName - 用户登录名
|
|
3020
|
+
*/
|
|
2654
3021
|
const createCustomUser = (loginName) => ({
|
|
2655
3022
|
id: loginName,
|
|
2656
3023
|
name: loginName,
|
|
@@ -2658,19 +3025,47 @@
|
|
|
2658
3025
|
tenantId: "",
|
|
2659
3026
|
login_name: loginName
|
|
2660
3027
|
});
|
|
3028
|
+
/**
|
|
3029
|
+
* 解析粘贴文本为用户列表
|
|
3030
|
+
* @param text - 粘贴的文本
|
|
3031
|
+
*/
|
|
2661
3032
|
const parsePastedText = (text) => {
|
|
2662
|
-
|
|
3033
|
+
const normalizedUsers = text.split(/[,,;\n\s]+/).filter(Boolean).map((user) => user.trim().replace(/\s*\(.*?\)\s*/, "")).filter(Boolean);
|
|
3034
|
+
return Array.from(new Set(normalizedUsers)).slice(0, MAX_PASTE_USERS);
|
|
2663
3035
|
};
|
|
3036
|
+
/**
|
|
3037
|
+
* 将用户列表按指定大小分批
|
|
3038
|
+
* @param usersList - 用户列表
|
|
3039
|
+
* @param batchSize - 每批大小
|
|
3040
|
+
*/
|
|
3041
|
+
const chunkUsersList = (usersList, batchSize) => {
|
|
3042
|
+
const chunks = [];
|
|
3043
|
+
for (let i = 0; i < usersList.length; i += batchSize) chunks.push(usersList.slice(i, i + batchSize));
|
|
3044
|
+
return chunks;
|
|
3045
|
+
};
|
|
3046
|
+
/**
|
|
3047
|
+
* 合并用户列表并去重
|
|
3048
|
+
* @param existingUsers - 现有用户列表
|
|
3049
|
+
* @param newUsers - 新用户列表
|
|
3050
|
+
*/
|
|
2664
3051
|
const mergeUsers = (existingUsers, newUsers) => {
|
|
2665
3052
|
const userMap = /* @__PURE__ */ new Map();
|
|
2666
3053
|
for (const user of [...existingUsers, ...newUsers]) if (!userMap.has(user.id)) userMap.set(user.id, user);
|
|
2667
3054
|
return Array.from(userMap.values());
|
|
2668
3055
|
};
|
|
3056
|
+
/**
|
|
3057
|
+
* 处理 Enter 键创建自定义用户
|
|
3058
|
+
* @param event - 键盘事件
|
|
3059
|
+
*/
|
|
2669
3060
|
const handleEnterCreate = (event) => {
|
|
2670
3061
|
if (event.key !== "Enter" || !allowCreate || !searchQuery.value.trim()) return;
|
|
2671
3062
|
const customUser = createCustomUser(searchQuery.value.trim());
|
|
2672
3063
|
if (!selectedUsers.value.some((user) => user.id === customUser.id)) onAddUser(customUser);
|
|
2673
3064
|
};
|
|
3065
|
+
/**
|
|
3066
|
+
* 处理粘贴事件
|
|
3067
|
+
* @param event - 粘贴事件
|
|
3068
|
+
*/
|
|
2674
3069
|
const handlePaste = async (event) => {
|
|
2675
3070
|
event.preventDefault();
|
|
2676
3071
|
const pastedText = event.clipboardData?.getData("text")?.trim();
|
|
@@ -2679,13 +3074,19 @@
|
|
|
2679
3074
|
try {
|
|
2680
3075
|
const usersList = parsePastedText(pastedText);
|
|
2681
3076
|
if (usersList.length === 0) return;
|
|
2682
|
-
const
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
3077
|
+
const lookupBatches = chunkUsersList(usersList, LOOKUP_BATCH_SIZE);
|
|
3078
|
+
const lookupResults = [];
|
|
3079
|
+
for (const batch of lookupBatches) {
|
|
3080
|
+
const result = await lookupUsers({
|
|
3081
|
+
apiBaseUrl,
|
|
3082
|
+
tenantId,
|
|
3083
|
+
exactSearchKey: "login_name",
|
|
3084
|
+
usersList: batch,
|
|
3085
|
+
enableMultiTenantMode
|
|
3086
|
+
});
|
|
3087
|
+
lookupResults.push(...result);
|
|
3088
|
+
}
|
|
3089
|
+
const formattedUsers = formatUsers(lookupResults, enableMultiTenantMode);
|
|
2689
3090
|
if (onBatchAddUsers) {
|
|
2690
3091
|
let mergedUsers = mergeUsers(selectedUsers.value, formattedUsers);
|
|
2691
3092
|
if (freePaste) {
|
|
@@ -2708,7 +3109,20 @@
|
|
|
2708
3109
|
handlePaste
|
|
2709
3110
|
};
|
|
2710
3111
|
};
|
|
2711
|
-
|
|
3112
|
+
//#endregion
|
|
3113
|
+
//#region src/hooks/use-resize-observer.ts
|
|
3114
|
+
/**
|
|
3115
|
+
* ResizeObserver Hook
|
|
3116
|
+
* @module hooks/useResizeObserver
|
|
3117
|
+
*/
|
|
3118
|
+
/**
|
|
3119
|
+
* 监听元素大小变化的 Hook
|
|
3120
|
+
* @param target - 目标元素引用
|
|
3121
|
+
* @param callback - 大小变化时的回调函数
|
|
3122
|
+
* @param options - 配置选项
|
|
3123
|
+
* @returns 停止观察的函数
|
|
3124
|
+
*/
|
|
3125
|
+
var useResizeObserver = (target, callback, options = {}) => {
|
|
2712
3126
|
const { immediate = true } = options;
|
|
2713
3127
|
let observer = null;
|
|
2714
3128
|
const cleanup = () => {
|
|
@@ -2748,9 +3162,25 @@
|
|
|
2748
3162
|
(0, vue.onUnmounted)(cleanup);
|
|
2749
3163
|
return cleanup;
|
|
2750
3164
|
};
|
|
2751
|
-
|
|
3165
|
+
//#endregion
|
|
3166
|
+
//#region src/hooks/use-tenant-data.ts
|
|
3167
|
+
/**
|
|
3168
|
+
* 租户数据处理 Hook
|
|
3169
|
+
* @module hooks/useTenantData
|
|
3170
|
+
*/
|
|
3171
|
+
/**
|
|
3172
|
+
* 使用租户数据的Hook
|
|
3173
|
+
* @param apiBaseUrl - API基础URL
|
|
3174
|
+
* @param tenantId - 租户ID
|
|
3175
|
+
* @param enableMultiTenantMode - 是否启用多租户模式
|
|
3176
|
+
* @returns 租户数据和加载状态
|
|
3177
|
+
*/
|
|
3178
|
+
var useTenantData = (apiBaseUrl, tenantId, enableMultiTenantMode = true) => {
|
|
2752
3179
|
const tenants = (0, vue.ref)({});
|
|
2753
3180
|
const loading = (0, vue.ref)(false);
|
|
3181
|
+
/**
|
|
3182
|
+
* 获取租户数据
|
|
3183
|
+
*/
|
|
2754
3184
|
const fetchTenants = async () => {
|
|
2755
3185
|
if (!apiBaseUrl || !tenantId) {
|
|
2756
3186
|
console.warn("获取租户需要提供有效的API基础URL和租户ID");
|
|
@@ -2779,7 +3209,15 @@
|
|
|
2779
3209
|
fetchTenants
|
|
2780
3210
|
};
|
|
2781
3211
|
};
|
|
2782
|
-
|
|
3212
|
+
//#endregion
|
|
3213
|
+
//#region src/utils/common.ts
|
|
3214
|
+
/**
|
|
3215
|
+
* 防抖函数
|
|
3216
|
+
* @param fn - 需要防抖的函数
|
|
3217
|
+
* @param delay - 延迟时间(毫秒)
|
|
3218
|
+
* @returns 防抖后的函数
|
|
3219
|
+
*/
|
|
3220
|
+
var debounce = (fn, delay) => {
|
|
2783
3221
|
let timer = null;
|
|
2784
3222
|
return function(...args) {
|
|
2785
3223
|
if (timer) clearTimeout(timer);
|
|
@@ -2789,7 +3227,14 @@
|
|
|
2789
3227
|
}, delay);
|
|
2790
3228
|
};
|
|
2791
3229
|
};
|
|
2792
|
-
|
|
3230
|
+
/**
|
|
3231
|
+
* 计算标签容器可见数量
|
|
3232
|
+
* @param container - 容器元素
|
|
3233
|
+
* @param items - 项目元素列表
|
|
3234
|
+
* @param containerWidth - 容器宽度
|
|
3235
|
+
* @returns 可见项目数量
|
|
3236
|
+
*/
|
|
3237
|
+
var calculateVisibleTags = (container, items, containerWidth) => {
|
|
2793
3238
|
if (!container || !items.length) return 0;
|
|
2794
3239
|
let totalWidth = 0;
|
|
2795
3240
|
let visibleCount = 0;
|
|
@@ -2806,10 +3251,27 @@
|
|
|
2806
3251
|
}
|
|
2807
3252
|
return Math.max(1, visibleCount);
|
|
2808
3253
|
};
|
|
2809
|
-
|
|
3254
|
+
//#endregion
|
|
3255
|
+
//#region src/hooks/use-user-search.ts
|
|
3256
|
+
/**
|
|
3257
|
+
* 用户搜索 Hook
|
|
3258
|
+
* @module hooks/useUserSearch
|
|
3259
|
+
*/
|
|
3260
|
+
/**
|
|
3261
|
+
* 使用用户搜索的Hook
|
|
3262
|
+
* @param apiBaseUrl - API基础URL
|
|
3263
|
+
* @param tenantId - 租户ID
|
|
3264
|
+
* @param enableMultiTenantMode - 是否启用多租户模式
|
|
3265
|
+
* @returns 用户搜索相关状态和方法
|
|
3266
|
+
*/
|
|
3267
|
+
var useUserSearch = (apiBaseUrl, tenantId, enableMultiTenantMode = true) => {
|
|
2810
3268
|
const searchResults = (0, vue.ref)([]);
|
|
2811
3269
|
const loading = (0, vue.ref)(false);
|
|
2812
3270
|
const searchQuery = (0, vue.ref)("");
|
|
3271
|
+
/**
|
|
3272
|
+
* 执行用户搜索
|
|
3273
|
+
* @param keyword - 搜索关键词
|
|
3274
|
+
*/
|
|
2813
3275
|
const performSearch = async (keyword) => {
|
|
2814
3276
|
if (!keyword?.length) {
|
|
2815
3277
|
searchResults.value = [];
|
|
@@ -2837,11 +3299,18 @@
|
|
|
2837
3299
|
}
|
|
2838
3300
|
};
|
|
2839
3301
|
const debouncedSearch = debounce(performSearch, 300);
|
|
3302
|
+
/**
|
|
3303
|
+
* 处理输入变化
|
|
3304
|
+
* @param value - 输入值
|
|
3305
|
+
*/
|
|
2840
3306
|
const handleSearchInput = (value) => {
|
|
2841
3307
|
loading.value = true;
|
|
2842
3308
|
searchQuery.value = value.trim();
|
|
2843
3309
|
debouncedSearch(searchQuery.value);
|
|
2844
3310
|
};
|
|
3311
|
+
/**
|
|
3312
|
+
* 清空搜索
|
|
3313
|
+
*/
|
|
2845
3314
|
const clearSearch = () => {
|
|
2846
3315
|
searchQuery.value = "";
|
|
2847
3316
|
searchResults.value = [];
|
|
@@ -2856,8 +3325,23 @@
|
|
|
2856
3325
|
clearSearch
|
|
2857
3326
|
};
|
|
2858
3327
|
};
|
|
2859
|
-
|
|
3328
|
+
//#endregion
|
|
3329
|
+
//#region src/hooks/use-user-selection.ts
|
|
3330
|
+
/**
|
|
3331
|
+
* 用户选择公共逻辑 Hook
|
|
3332
|
+
* @module hooks/useUserSelection
|
|
3333
|
+
*/
|
|
3334
|
+
/**
|
|
3335
|
+
* 用户选择公共逻辑 Hook
|
|
3336
|
+
* @param options - 配置选项
|
|
3337
|
+
* @returns 用户选择相关方法
|
|
3338
|
+
*/
|
|
3339
|
+
var useUserSelection = (options) => {
|
|
2860
3340
|
const { selectedUserIds, excludeUserIds, userGroup, searchQuery } = options;
|
|
3341
|
+
/**
|
|
3342
|
+
* 创建自定义用户对象
|
|
3343
|
+
* @param loginName - 用户登录名
|
|
3344
|
+
*/
|
|
2861
3345
|
const createCustomUser = (loginName) => ({
|
|
2862
3346
|
id: loginName,
|
|
2863
3347
|
name: loginName,
|
|
@@ -2865,11 +3349,19 @@
|
|
|
2865
3349
|
tenantId: "",
|
|
2866
3350
|
login_name: loginName
|
|
2867
3351
|
});
|
|
3352
|
+
/**
|
|
3353
|
+
* 检查用户是否已选中
|
|
3354
|
+
* @param userId - 用户ID
|
|
3355
|
+
*/
|
|
2868
3356
|
const isUserSelected = (userId) => {
|
|
2869
3357
|
return selectedUserIds.value.includes(userId);
|
|
2870
3358
|
};
|
|
2871
|
-
|
|
2872
|
-
|
|
3359
|
+
/**
|
|
3360
|
+
* 过滤选项(排除已选和排除列表)
|
|
3361
|
+
* @param options - 原始选项列表
|
|
3362
|
+
*/
|
|
3363
|
+
const filterOptions = (options) => {
|
|
3364
|
+
return options.filter((user) => !isUserSelected(user.id)).filter((user) => !excludeUserIds?.value?.includes(user.id));
|
|
2873
3365
|
};
|
|
2874
3366
|
return {
|
|
2875
3367
|
createCustomUser,
|
|
@@ -2886,6 +3378,8 @@
|
|
|
2886
3378
|
})
|
|
2887
3379
|
};
|
|
2888
3380
|
};
|
|
3381
|
+
//#endregion
|
|
3382
|
+
//#region src/components/me-tag.vue?vue&type=script&setup=true&lang.ts
|
|
2889
3383
|
var me_tag_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
2890
3384
|
name: "MeTag",
|
|
2891
3385
|
__name: "me-tag",
|
|
@@ -2904,9 +3398,21 @@
|
|
|
2904
3398
|
emits: ["click"],
|
|
2905
3399
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
2906
3400
|
__expose();
|
|
3401
|
+
/**
|
|
3402
|
+
* "我"标签组件
|
|
3403
|
+
*/
|
|
2907
3404
|
const { t } = use_i18n_default();
|
|
3405
|
+
/**
|
|
3406
|
+
* 组件属性
|
|
3407
|
+
*/
|
|
2908
3408
|
const props = __props;
|
|
3409
|
+
/**
|
|
3410
|
+
* 组件事件
|
|
3411
|
+
*/
|
|
2909
3412
|
const emit = __emit;
|
|
3413
|
+
/**
|
|
3414
|
+
* 处理点击事件
|
|
3415
|
+
*/
|
|
2910
3416
|
const handleClick = () => {
|
|
2911
3417
|
if (props.isDisabled) return;
|
|
2912
3418
|
emit("click");
|
|
@@ -2924,11 +3430,15 @@
|
|
|
2924
3430
|
return __returned__;
|
|
2925
3431
|
}
|
|
2926
3432
|
});
|
|
2927
|
-
|
|
3433
|
+
//#endregion
|
|
3434
|
+
//#region \0plugin-vue:export-helper
|
|
3435
|
+
var _plugin_vue_export_helper_default = (sfc, props) => {
|
|
2928
3436
|
const target = sfc.__vccOpts || sfc;
|
|
2929
3437
|
for (const [key, val] of props) target[key] = val;
|
|
2930
3438
|
return target;
|
|
2931
3439
|
};
|
|
3440
|
+
//#endregion
|
|
3441
|
+
//#region src/components/me-tag.vue
|
|
2932
3442
|
function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
|
|
2933
3443
|
return $props.currentUserId ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
2934
3444
|
key: 0,
|
|
@@ -2936,14 +3446,22 @@
|
|
|
2936
3446
|
onClick: (0, vue.withModifiers)($setup.handleClick, ["stop"])
|
|
2937
3447
|
}, (0, vue.toDisplayString)($setup.t("我")), 3)) : (0, vue.createCommentVNode)("v-if", true);
|
|
2938
3448
|
}
|
|
2939
|
-
var me_tag_default = /* @__PURE__ */
|
|
3449
|
+
var me_tag_default = /* @__PURE__ */ _plugin_vue_export_helper_default(me_tag_vue_vue_type_script_setup_true_lang_default, [
|
|
2940
3450
|
["render", _sfc_render$3],
|
|
2941
3451
|
["__scopeId", "data-v-a1054364"],
|
|
2942
3452
|
["__file", "/Users/brooklin/project/bkui-monorepo/packages/bk-user-selector/src/components/me-tag.vue"]
|
|
2943
3453
|
]);
|
|
3454
|
+
//#endregion
|
|
3455
|
+
//#region src/assets/user-group.svg
|
|
2944
3456
|
var user_group_default = "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";
|
|
3457
|
+
//#endregion
|
|
3458
|
+
//#region src/assets/user.svg
|
|
2945
3459
|
var user_default = "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";
|
|
3460
|
+
//#endregion
|
|
3461
|
+
//#region src/assets/virtual.svg
|
|
2946
3462
|
var virtual_default = "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";
|
|
3463
|
+
//#endregion
|
|
3464
|
+
//#region src/components/user-render.ts
|
|
2947
3465
|
var user_render_default = (0, vue.defineComponent)({
|
|
2948
3466
|
name: "UserRender",
|
|
2949
3467
|
props: {
|
|
@@ -2980,13 +3498,13 @@
|
|
|
2980
3498
|
const loginName = user.login_name || user.bk_username || user.id;
|
|
2981
3499
|
return `${props.avatarBaseUrl}${loginName}.png?default_when_absent=true`;
|
|
2982
3500
|
};
|
|
2983
|
-
const defaultRender = (h
|
|
2984
|
-
return h
|
|
3501
|
+
const defaultRender = (h, props) => {
|
|
3502
|
+
return h("div", { style: {
|
|
2985
3503
|
display: "flex",
|
|
2986
3504
|
alignItems: "center"
|
|
2987
3505
|
} }, [
|
|
2988
|
-
props
|
|
2989
|
-
src: getAvatarUrl(props
|
|
3506
|
+
props.hasAvatar ? h("img", {
|
|
3507
|
+
src: getAvatarUrl(props.user),
|
|
2990
3508
|
style: {
|
|
2991
3509
|
width: "20px",
|
|
2992
3510
|
height: "20px",
|
|
@@ -2995,11 +3513,11 @@
|
|
|
2995
3513
|
flexShrink: 0
|
|
2996
3514
|
}
|
|
2997
3515
|
}) : null,
|
|
2998
|
-
h
|
|
2999
|
-
props
|
|
3516
|
+
h("span", props.user.name),
|
|
3517
|
+
props.user.tenantId !== props.tenantId && props.user.tenantId ? h("span", { style: {
|
|
3000
3518
|
color: "#f59500",
|
|
3001
3519
|
marginLeft: "4px"
|
|
3002
|
-
} }, `@${props
|
|
3520
|
+
} }, `@${props.tenants[props.user.tenantId] || props.user.tenantId}`) : null
|
|
3003
3521
|
]);
|
|
3004
3522
|
};
|
|
3005
3523
|
return () => {
|
|
@@ -3012,6 +3530,8 @@
|
|
|
3012
3530
|
};
|
|
3013
3531
|
}
|
|
3014
3532
|
});
|
|
3533
|
+
//#endregion
|
|
3534
|
+
//#region src/components/selection-popover.vue?vue&type=script&setup=true&lang.ts
|
|
3015
3535
|
var selection_popover_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
3016
3536
|
name: "SelectionPopover",
|
|
3017
3537
|
__name: "selection-popover",
|
|
@@ -3061,6 +3581,16 @@
|
|
|
3061
3581
|
required: false,
|
|
3062
3582
|
default: () => []
|
|
3063
3583
|
},
|
|
3584
|
+
recentUsers: {
|
|
3585
|
+
type: Array,
|
|
3586
|
+
required: false,
|
|
3587
|
+
default: () => []
|
|
3588
|
+
},
|
|
3589
|
+
recentUsersName: {
|
|
3590
|
+
type: String,
|
|
3591
|
+
required: false,
|
|
3592
|
+
default: ""
|
|
3593
|
+
},
|
|
3064
3594
|
renderListItem: {
|
|
3065
3595
|
type: Function,
|
|
3066
3596
|
required: false
|
|
@@ -3094,11 +3624,23 @@
|
|
|
3094
3624
|
emits: ["click-outside", "select-user"],
|
|
3095
3625
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
3096
3626
|
__expose();
|
|
3627
|
+
/**
|
|
3628
|
+
* 用户选择器下拉菜单组件
|
|
3629
|
+
*/
|
|
3097
3630
|
const { t } = use_i18n_default();
|
|
3098
3631
|
const slotContainerRef = (0, vue.ref)(null);
|
|
3099
3632
|
const contentContainerRef = (0, vue.ref)(null);
|
|
3633
|
+
/**
|
|
3634
|
+
* 组件属性
|
|
3635
|
+
*/
|
|
3100
3636
|
const props = __props;
|
|
3637
|
+
/**
|
|
3638
|
+
* 组件事件
|
|
3639
|
+
*/
|
|
3101
3640
|
const emit = __emit;
|
|
3641
|
+
/**
|
|
3642
|
+
* 按分组整理用户列表,如果有 userGroup, 则在最前面增加用户群组 userGroup
|
|
3643
|
+
*/
|
|
3102
3644
|
const groupedUsers = (0, vue.computed)(() => {
|
|
3103
3645
|
const groups = {};
|
|
3104
3646
|
if (Array.isArray(props.userGroup) && props.userGroup.length > 0) groups[props.userGroupName] = props.userGroup.map((group) => ({
|
|
@@ -3113,25 +3655,41 @@
|
|
|
3113
3655
|
});
|
|
3114
3656
|
return groups;
|
|
3115
3657
|
});
|
|
3658
|
+
const hasMainOptions = (0, vue.computed)(() => Object.values(groupedUsers.value).some((group) => group.length > 0));
|
|
3659
|
+
const hasRecentUsers = (0, vue.computed)(() => props.recentUsers.length > 0);
|
|
3660
|
+
const hasDropdownOptions = (0, vue.computed)(() => hasMainOptions.value || hasRecentUsers.value);
|
|
3661
|
+
/**
|
|
3662
|
+
* 判断用户是否为当前高亮项
|
|
3663
|
+
*/
|
|
3116
3664
|
const isHighlighted = (user) => {
|
|
3117
3665
|
if (props.highlightedIndex < 0 || !props.flatOptions.length) return false;
|
|
3118
|
-
return props.flatOptions[props.highlightedIndex]
|
|
3666
|
+
return props.flatOptions[props.highlightedIndex] === user;
|
|
3119
3667
|
};
|
|
3668
|
+
/**
|
|
3669
|
+
* 选择用户
|
|
3670
|
+
*/
|
|
3120
3671
|
const selectUser = (user) => {
|
|
3121
3672
|
emit("select-user", user);
|
|
3122
3673
|
};
|
|
3674
|
+
/**
|
|
3675
|
+
* 点击外部
|
|
3676
|
+
*/
|
|
3123
3677
|
const handleClickOutside = ({ event }) => {
|
|
3124
3678
|
const target = event.target;
|
|
3125
3679
|
if (slotContainerRef.value?.contains(target)) return;
|
|
3126
3680
|
if (contentContainerRef.value?.contains(target)) return;
|
|
3127
3681
|
emit("click-outside", event);
|
|
3128
3682
|
};
|
|
3683
|
+
/**
|
|
3684
|
+
* 监听高亮索引变化,自动滚动到高亮项
|
|
3685
|
+
*/
|
|
3129
3686
|
(0, vue.watch)(() => props.highlightedIndex, (newIndex) => {
|
|
3130
3687
|
if (newIndex < 0 || !contentContainerRef.value) return;
|
|
3131
3688
|
(0, vue.nextTick)(() => {
|
|
3132
3689
|
const highlightedElement = contentContainerRef.value?.querySelector(".user-option.is-highlighted");
|
|
3133
3690
|
if (highlightedElement) highlightedElement.scrollIntoView({
|
|
3134
3691
|
block: "nearest",
|
|
3692
|
+
inline: "nearest",
|
|
3135
3693
|
behavior: "auto"
|
|
3136
3694
|
});
|
|
3137
3695
|
});
|
|
@@ -3143,6 +3701,9 @@
|
|
|
3143
3701
|
props,
|
|
3144
3702
|
emit,
|
|
3145
3703
|
groupedUsers,
|
|
3704
|
+
hasMainOptions,
|
|
3705
|
+
hasRecentUsers,
|
|
3706
|
+
hasDropdownOptions,
|
|
3146
3707
|
isHighlighted,
|
|
3147
3708
|
selectUser,
|
|
3148
3709
|
handleClickOutside,
|
|
@@ -3163,15 +3724,28 @@
|
|
|
3163
3724
|
return __returned__;
|
|
3164
3725
|
}
|
|
3165
3726
|
});
|
|
3727
|
+
//#endregion
|
|
3728
|
+
//#region src/components/selection-popover.vue
|
|
3166
3729
|
var _hoisted_1$1 = { ref: "contentContainerRef" };
|
|
3167
3730
|
var _hoisted_2$1 = {
|
|
3168
3731
|
key: 0,
|
|
3169
3732
|
class: "no-data"
|
|
3170
3733
|
};
|
|
3171
|
-
var _hoisted_3$1 = {
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3734
|
+
var _hoisted_3$1 = {
|
|
3735
|
+
key: 0,
|
|
3736
|
+
class: "dropdown-panel dropdown-panel-main"
|
|
3737
|
+
};
|
|
3738
|
+
var _hoisted_4$1 = { class: "group-name" };
|
|
3739
|
+
var _hoisted_5 = { class: "group-count" };
|
|
3740
|
+
var _hoisted_6 = ["onClick"];
|
|
3741
|
+
var _hoisted_7 = {
|
|
3742
|
+
key: 1,
|
|
3743
|
+
class: "dropdown-panel dropdown-panel-recent"
|
|
3744
|
+
};
|
|
3745
|
+
var _hoisted_8 = { class: "group-name" };
|
|
3746
|
+
var _hoisted_9 = { class: "group-count" };
|
|
3747
|
+
var _hoisted_10 = ["onClick"];
|
|
3748
|
+
var _hoisted_11 = { ref: "slotContainerRef" };
|
|
3175
3749
|
function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
|
3176
3750
|
return (0, vue.openBlock)(), (0, vue.createBlock)($setup["Popover"], {
|
|
3177
3751
|
arrow: false,
|
|
@@ -3190,7 +3764,10 @@
|
|
|
3190
3764
|
mode: "spin",
|
|
3191
3765
|
size: "mini"
|
|
3192
3766
|
}, {
|
|
3193
|
-
default: (0, vue.withCtx)(() => [
|
|
3767
|
+
default: (0, vue.withCtx)(() => [!$setup.hasDropdownOptions ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$1, [(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)($props.emptyText), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
3768
|
+
key: 1,
|
|
3769
|
+
class: (0, vue.normalizeClass)(["dropdown-panels", { "is-two-column": $setup.hasMainOptions && $setup.hasRecentUsers }])
|
|
3770
|
+
}, [$setup.hasMainOptions ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)($setup.groupedUsers, (group, groupName) => {
|
|
3194
3771
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
3195
3772
|
key: groupName,
|
|
3196
3773
|
class: "user-group"
|
|
@@ -3198,7 +3775,7 @@
|
|
|
3198
3775
|
key: 0,
|
|
3199
3776
|
class: "group-header",
|
|
3200
3777
|
onClick: _cache[0] || (_cache[0] = (0, vue.withModifiers)(() => {}, ["prevent"]))
|
|
3201
|
-
}, [(0, vue.createElementVNode)("span",
|
|
3778
|
+
}, [(0, vue.createElementVNode)("span", _hoisted_4$1, (0, vue.toDisplayString)(groupName), 1), (0, vue.createElementVNode)("span", _hoisted_5, "(" + (0, vue.toDisplayString)(group.length) + ")", 1)])) : (0, vue.createCommentVNode)("v-if", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(group, (user) => {
|
|
3202
3779
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
3203
3780
|
key: user.id,
|
|
3204
3781
|
class: (0, vue.normalizeClass)(["user-option", { "is-highlighted": $setup.isHighlighted(user) }]),
|
|
@@ -3218,20 +3795,50 @@
|
|
|
3218
3795
|
"tenant-id",
|
|
3219
3796
|
"tenants",
|
|
3220
3797
|
"user"
|
|
3221
|
-
])], 42,
|
|
3798
|
+
])], 42, _hoisted_6);
|
|
3222
3799
|
}), 128))]);
|
|
3223
|
-
}), 128))]),
|
|
3800
|
+
}), 128))])) : (0, vue.createCommentVNode)("v-if", true), $setup.hasRecentUsers ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_7, [$props.recentUsersName ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
3801
|
+
key: 0,
|
|
3802
|
+
class: "group-header",
|
|
3803
|
+
onClick: _cache[2] || (_cache[2] = (0, vue.withModifiers)(() => {}, ["prevent"]))
|
|
3804
|
+
}, [(0, vue.createElementVNode)("span", _hoisted_8, (0, vue.toDisplayString)($props.recentUsersName), 1), (0, vue.createElementVNode)("span", _hoisted_9, "(" + (0, vue.toDisplayString)($props.recentUsers.length) + ")", 1)])) : (0, vue.createCommentVNode)("v-if", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)($props.recentUsers, (user) => {
|
|
3805
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
3806
|
+
key: user.id,
|
|
3807
|
+
class: (0, vue.normalizeClass)(["user-option", { "is-highlighted": $setup.isHighlighted(user) }]),
|
|
3808
|
+
onClick: (0, vue.withModifiers)(($event) => $setup.selectUser(user), ["prevent"]),
|
|
3809
|
+
onMousedown: _cache[3] || (_cache[3] = (0, vue.withModifiers)(() => {}, ["prevent"]))
|
|
3810
|
+
}, [(0, vue.createVNode)($setup["UserRender"], {
|
|
3811
|
+
"avatar-base-url": $props.avatarBaseUrl,
|
|
3812
|
+
"has-avatar": $props.hasAvatar,
|
|
3813
|
+
render: $props.renderListItem,
|
|
3814
|
+
"tenant-id": $props.tenantId,
|
|
3815
|
+
tenants: $props.tenants,
|
|
3816
|
+
user
|
|
3817
|
+
}, null, 8, [
|
|
3818
|
+
"avatar-base-url",
|
|
3819
|
+
"has-avatar",
|
|
3820
|
+
"render",
|
|
3821
|
+
"tenant-id",
|
|
3822
|
+
"tenants",
|
|
3823
|
+
"user"
|
|
3824
|
+
])], 42, _hoisted_10);
|
|
3825
|
+
}), 128))])) : (0, vue.createCommentVNode)("v-if", true)], 2))]),
|
|
3224
3826
|
_: 1
|
|
3225
3827
|
}, 8, ["loading"])], 512)]),
|
|
3226
|
-
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div",
|
|
3828
|
+
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_11, [(0, vue.renderSlot)(_ctx.$slots, "default", {}, void 0, true)], 512)]),
|
|
3227
3829
|
_: 3
|
|
3228
3830
|
}, 8, ["is-show", "width"]);
|
|
3229
3831
|
}
|
|
3230
|
-
var selection_popover_default = /* @__PURE__ */
|
|
3832
|
+
var selection_popover_default = /* @__PURE__ */ _plugin_vue_export_helper_default(selection_popover_vue_vue_type_script_setup_true_lang_default, [
|
|
3231
3833
|
["render", _sfc_render$2],
|
|
3232
3834
|
["__scopeId", "data-v-9173accf"],
|
|
3233
3835
|
["__file", "/Users/brooklin/project/bkui-monorepo/packages/bk-user-selector/src/components/selection-popover.vue"]
|
|
3234
3836
|
]);
|
|
3837
|
+
//#endregion
|
|
3838
|
+
//#region src/components/user-tag.vue?vue&type=script&setup=true&lang.ts
|
|
3839
|
+
/**
|
|
3840
|
+
* 用户标签组件
|
|
3841
|
+
*/
|
|
3235
3842
|
var user_tag_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
3236
3843
|
name: "UserTag",
|
|
3237
3844
|
__name: "user-tag",
|
|
@@ -3276,10 +3883,22 @@
|
|
|
3276
3883
|
emits: ["click", "close"],
|
|
3277
3884
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
3278
3885
|
__expose();
|
|
3886
|
+
/**
|
|
3887
|
+
* 组件属性
|
|
3888
|
+
*/
|
|
3889
|
+
/**
|
|
3890
|
+
* 组件事件
|
|
3891
|
+
*/
|
|
3279
3892
|
const emit = __emit;
|
|
3893
|
+
/**
|
|
3894
|
+
* 处理点击事件
|
|
3895
|
+
*/
|
|
3280
3896
|
const handleClick = () => {
|
|
3281
3897
|
emit("click");
|
|
3282
3898
|
};
|
|
3899
|
+
/**
|
|
3900
|
+
* 处理关闭事件
|
|
3901
|
+
*/
|
|
3283
3902
|
const handleClose = () => {
|
|
3284
3903
|
emit("close");
|
|
3285
3904
|
};
|
|
@@ -3301,6 +3920,8 @@
|
|
|
3301
3920
|
return __returned__;
|
|
3302
3921
|
}
|
|
3303
3922
|
});
|
|
3923
|
+
//#endregion
|
|
3924
|
+
//#region src/components/user-tag.vue
|
|
3304
3925
|
function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
|
|
3305
3926
|
return (0, vue.openBlock)(), (0, vue.createBlock)($setup["Tag"], {
|
|
3306
3927
|
class: (0, vue.normalizeClass)(["user-tag", {
|
|
@@ -3331,15 +3952,22 @@
|
|
|
3331
3952
|
_: 1
|
|
3332
3953
|
}, 8, ["class"]);
|
|
3333
3954
|
}
|
|
3334
|
-
var user_tag_default = /* @__PURE__ */
|
|
3955
|
+
var user_tag_default = /* @__PURE__ */ _plugin_vue_export_helper_default(user_tag_vue_vue_type_script_setup_true_lang_default, [
|
|
3335
3956
|
["render", _sfc_render$1],
|
|
3336
3957
|
["__scopeId", "data-v-d1173d20"],
|
|
3337
3958
|
["__file", "/Users/brooklin/project/bkui-monorepo/packages/bk-user-selector/src/components/user-tag.vue"]
|
|
3338
3959
|
]);
|
|
3960
|
+
//#endregion
|
|
3961
|
+
//#region src/components/user-selector.vue?vue&type=script&setup=true&lang.ts
|
|
3339
3962
|
var user_selector_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
3340
3963
|
name: "BkUserSelector",
|
|
3341
3964
|
__name: "user-selector",
|
|
3342
3965
|
props: {
|
|
3966
|
+
autoFocus: {
|
|
3967
|
+
type: Boolean,
|
|
3968
|
+
required: false,
|
|
3969
|
+
default: false
|
|
3970
|
+
},
|
|
3343
3971
|
draggable: {
|
|
3344
3972
|
type: Boolean,
|
|
3345
3973
|
required: false,
|
|
@@ -3380,6 +4008,21 @@
|
|
|
3380
4008
|
required: false,
|
|
3381
4009
|
default: false
|
|
3382
4010
|
},
|
|
4011
|
+
allowCrossOriginCredentials: {
|
|
4012
|
+
type: Boolean,
|
|
4013
|
+
required: false,
|
|
4014
|
+
default: true
|
|
4015
|
+
},
|
|
4016
|
+
allowedApiOrigins: {
|
|
4017
|
+
type: Array,
|
|
4018
|
+
required: false,
|
|
4019
|
+
default: () => []
|
|
4020
|
+
},
|
|
4021
|
+
allowPrivateApiHost: {
|
|
4022
|
+
type: Boolean,
|
|
4023
|
+
required: false,
|
|
4024
|
+
default: true
|
|
4025
|
+
},
|
|
3383
4026
|
apiBaseUrl: {
|
|
3384
4027
|
type: String,
|
|
3385
4028
|
required: true,
|
|
@@ -3435,6 +4078,11 @@
|
|
|
3435
4078
|
required: false,
|
|
3436
4079
|
default: ""
|
|
3437
4080
|
},
|
|
4081
|
+
recentUserIds: {
|
|
4082
|
+
type: Array,
|
|
4083
|
+
required: false,
|
|
4084
|
+
default: () => []
|
|
4085
|
+
},
|
|
3438
4086
|
renderListItem: {
|
|
3439
4087
|
type: Function,
|
|
3440
4088
|
required: false
|
|
@@ -3464,17 +4112,47 @@
|
|
|
3464
4112
|
"change",
|
|
3465
4113
|
"dragEnd",
|
|
3466
4114
|
"dragStart",
|
|
4115
|
+
"error",
|
|
3467
4116
|
"focus",
|
|
4117
|
+
"unauthorized",
|
|
3468
4118
|
"update:modelValue"
|
|
3469
4119
|
],
|
|
3470
4120
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
3471
|
-
|
|
4121
|
+
/**
|
|
4122
|
+
* 蓝鲸用户选择器组件
|
|
4123
|
+
* @module components/UserSelector
|
|
4124
|
+
*/
|
|
3472
4125
|
const { t } = use_i18n_default();
|
|
3473
4126
|
(0, bkui_vue.provideGlobalConfig)({ prefix: "bk" });
|
|
4127
|
+
/**
|
|
4128
|
+
* 组件属性
|
|
4129
|
+
*/
|
|
3474
4130
|
const props = __props;
|
|
4131
|
+
/**
|
|
4132
|
+
* 组件事件
|
|
4133
|
+
*/
|
|
3475
4134
|
const emit = __emit;
|
|
3476
|
-
const
|
|
4135
|
+
const handleApiError = (error) => {
|
|
4136
|
+
emit("error", error);
|
|
4137
|
+
};
|
|
4138
|
+
const handleApiUnauthorized = (error) => {
|
|
4139
|
+
emit("unauthorized", error);
|
|
4140
|
+
};
|
|
4141
|
+
provideApiConfig(props.apiBaseUrl, props.tenantId, props.allowedApiOrigins, props.allowPrivateApiHost, props.allowCrossOriginCredentials, {
|
|
4142
|
+
onError: handleApiError,
|
|
4143
|
+
onUnauthorized: handleApiUnauthorized
|
|
4144
|
+
});
|
|
4145
|
+
/**
|
|
4146
|
+
* 获取租户数据
|
|
4147
|
+
*/
|
|
4148
|
+
const { tenants } = useTenantData(props.apiBaseUrl, props.tenantId, props.enableMultiTenantMode);
|
|
4149
|
+
/**
|
|
4150
|
+
* 用户搜索
|
|
4151
|
+
*/
|
|
3477
4152
|
const { searchResults, loading: searchLoading, searchQuery, clearSearch, handleSearchInput } = useUserSearch(props.apiBaseUrl, props.tenantId, props.enableMultiTenantMode);
|
|
4153
|
+
/**
|
|
4154
|
+
* 当前用户处理
|
|
4155
|
+
*/
|
|
3478
4156
|
const { fetchCurrentUser } = useCurrentUser({
|
|
3479
4157
|
apiBaseUrl: props.apiBaseUrl,
|
|
3480
4158
|
tenantId: props.tenantId,
|
|
@@ -3482,18 +4160,30 @@
|
|
|
3482
4160
|
exactSearchKey: props.exactSearchKey,
|
|
3483
4161
|
enableMultiTenantMode: props.enableMultiTenantMode
|
|
3484
4162
|
});
|
|
4163
|
+
/**
|
|
4164
|
+
* DOM 引用
|
|
4165
|
+
*/
|
|
3485
4166
|
const containerRef = (0, vue.ref)(null);
|
|
3486
4167
|
const sortableContainerRef = (0, vue.ref)(null);
|
|
3487
4168
|
const collapsedContainerRef = (0, vue.ref)(null);
|
|
3488
4169
|
const frontInputRef = (0, vue.ref)(null);
|
|
3489
4170
|
const inlineInputRef = (0, vue.ref)(null);
|
|
3490
4171
|
const lastInputRef = (0, vue.ref)(null);
|
|
4172
|
+
/**
|
|
4173
|
+
* 组件状态
|
|
4174
|
+
*/
|
|
3491
4175
|
const isFocused = (0, vue.ref)(false);
|
|
3492
4176
|
const activeTagIndex = (0, vue.ref)(-1);
|
|
3493
4177
|
const sortableInstance = (0, vue.ref)(null);
|
|
3494
4178
|
const visibleUsers = (0, vue.ref)([]);
|
|
3495
4179
|
const hiddenCount = (0, vue.ref)(0);
|
|
3496
4180
|
const highlightedIndex = (0, vue.ref)(-1);
|
|
4181
|
+
const recentUsers = (0, vue.ref)([]);
|
|
4182
|
+
let recentUsersRequestId = 0;
|
|
4183
|
+
let recentUserIdsSnapshot = [];
|
|
4184
|
+
/**
|
|
4185
|
+
* 已选用户列表 (内部状态)
|
|
4186
|
+
*/
|
|
3497
4187
|
const selectedUsers = (0, vue.ref)([]);
|
|
3498
4188
|
const isTextareaMode = (0, vue.computed)(() => props.type === "textarea");
|
|
3499
4189
|
const textareaHeight = (0, vue.ref)(props.rows * 32);
|
|
@@ -3505,38 +4195,112 @@
|
|
|
3505
4195
|
overflowY: "auto"
|
|
3506
4196
|
};
|
|
3507
4197
|
});
|
|
4198
|
+
/**
|
|
4199
|
+
* 未聚焦状态下展示的用户列表:textarea 模式展示全部,input 模式展示折叠后的
|
|
4200
|
+
*/
|
|
3508
4201
|
const collapsedDisplayUsers = (0, vue.computed)(() => {
|
|
3509
4202
|
return isTextareaMode.value ? selectedUsers.value : visibleUsers.value;
|
|
3510
4203
|
});
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
4204
|
+
/**
|
|
4205
|
+
* 模型值 ID 列表
|
|
4206
|
+
*/
|
|
3514
4207
|
const modelValueIds = (0, vue.computed)(() => {
|
|
3515
4208
|
if (props.multiple) return Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
3516
4209
|
return props.modelValue ? [props.modelValue] : [];
|
|
3517
4210
|
});
|
|
4211
|
+
/**
|
|
4212
|
+
* 用 computed 处理国际化
|
|
4213
|
+
*/
|
|
3518
4214
|
const computedPlaceholder = (0, vue.computed)(() => props.placeholder || t("请输入人员名称搜索"));
|
|
3519
4215
|
const computedUserGroupName = (0, vue.computed)(() => props.userGroupName || t("用户群组"));
|
|
3520
4216
|
const computedEmptyText = (0, vue.computed)(() => props.emptyText || t("无匹配人员"));
|
|
4217
|
+
const computedRecentUsersName = (0, vue.computed)(() => t("最近选择"));
|
|
4218
|
+
/**
|
|
4219
|
+
* 已选用户ID列表
|
|
4220
|
+
*/
|
|
3521
4221
|
const selectedUserIds = (0, vue.computed)(() => selectedUsers.value.map((user) => user.id));
|
|
4222
|
+
const isUserMatchedByQuery = (user, query) => {
|
|
4223
|
+
if (!query) return true;
|
|
4224
|
+
return [
|
|
4225
|
+
user.id,
|
|
4226
|
+
user.name,
|
|
4227
|
+
user.bk_username,
|
|
4228
|
+
user.username,
|
|
4229
|
+
user.login_name,
|
|
4230
|
+
user.display_name,
|
|
4231
|
+
user.full_name
|
|
4232
|
+
].some((field) => String(field || "").includes(query));
|
|
4233
|
+
};
|
|
4234
|
+
const getLookupFields = (exactSearchKey) => {
|
|
4235
|
+
return exactSearchKey.split(",").map((field) => field.trim()).filter(Boolean);
|
|
4236
|
+
};
|
|
4237
|
+
const findUserByLookupId = (users, lookupId, lookupFields) => {
|
|
4238
|
+
return users.find((user) => {
|
|
4239
|
+
if (user.id === lookupId) return true;
|
|
4240
|
+
const indexedUser = user;
|
|
4241
|
+
return lookupFields.some((field) => String(indexedUser[field] || "") === lookupId);
|
|
4242
|
+
});
|
|
4243
|
+
};
|
|
4244
|
+
const sortUsersByLookupIds = (users, lookupIds, lookupFields) => {
|
|
4245
|
+
return lookupIds.map((lookupId) => findUserByLookupId(users, lookupId, lookupFields)).filter(Boolean);
|
|
4246
|
+
};
|
|
4247
|
+
const lookupFormattedUsersByIds = async (lookupIds) => {
|
|
4248
|
+
const primaryLookupFields = getLookupFields(props.exactSearchKey);
|
|
4249
|
+
const formattedUsers = formatUsers(await lookupUsers({
|
|
4250
|
+
apiBaseUrl: props.apiBaseUrl,
|
|
4251
|
+
tenantId: props.tenantId,
|
|
4252
|
+
exactSearchKey: props.exactSearchKey,
|
|
4253
|
+
usersList: lookupIds,
|
|
4254
|
+
enableMultiTenantMode: props.enableMultiTenantMode
|
|
4255
|
+
}), props.enableMultiTenantMode);
|
|
4256
|
+
const unresolvedIds = lookupIds.filter((lookupId) => !findUserByLookupId(formattedUsers, lookupId, primaryLookupFields));
|
|
4257
|
+
if (unresolvedIds.length === 0 || props.exactSearchKey === "bk_username") return sortUsersByLookupIds(formattedUsers, lookupIds, primaryLookupFields);
|
|
4258
|
+
const fallbackUsers = formatUsers(await lookupUsers({
|
|
4259
|
+
apiBaseUrl: props.apiBaseUrl,
|
|
4260
|
+
tenantId: props.tenantId,
|
|
4261
|
+
exactSearchKey: DEFAULT_EXACT_SEARCH_KEY,
|
|
4262
|
+
usersList: unresolvedIds,
|
|
4263
|
+
enableMultiTenantMode: props.enableMultiTenantMode
|
|
4264
|
+
}), props.enableMultiTenantMode);
|
|
4265
|
+
const mergedUsers = [...formattedUsers];
|
|
4266
|
+
fallbackUsers.forEach((user) => {
|
|
4267
|
+
if (!mergedUsers.some((item) => item.id === user.id)) mergedUsers.push(user);
|
|
4268
|
+
});
|
|
4269
|
+
return sortUsersByLookupIds(mergedUsers, lookupIds, [...new Set([...primaryLookupFields, DEFAULT_EXACT_SEARCH_KEY])]);
|
|
4270
|
+
};
|
|
4271
|
+
/**
|
|
4272
|
+
* 是否已达到最大选择数量
|
|
4273
|
+
*/
|
|
3522
4274
|
const isMaxCountReached = (0, vue.computed)(() => {
|
|
3523
4275
|
if (!props.maxCount || props.maxCount <= 0) return false;
|
|
3524
4276
|
return selectedUsers.value.length >= props.maxCount;
|
|
3525
4277
|
});
|
|
4278
|
+
/**
|
|
4279
|
+
* "我"标签是否禁用(已选中当前用户时禁用,或已达到最大数量)
|
|
4280
|
+
*/
|
|
3526
4281
|
const isMeTagDisabled = (0, vue.computed)(() => isMaxCountReached.value || !!props.currentUserId && selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId));
|
|
4282
|
+
/**
|
|
4283
|
+
* UserTag 公共属性
|
|
4284
|
+
*/
|
|
3527
4285
|
const userTagCommonProps = (0, vue.computed)(() => ({
|
|
3528
4286
|
avatarBaseUrl: props.avatarBaseUrl,
|
|
3529
4287
|
currentTenantId: props.tenantId,
|
|
3530
4288
|
hasAvatar: props.hasAvatar,
|
|
3531
4289
|
renderTag: props.renderTag,
|
|
3532
|
-
tenants
|
|
4290
|
+
tenants: tenants.value
|
|
3533
4291
|
}));
|
|
4292
|
+
/**
|
|
4293
|
+
* 使用用户选择公共逻辑 hook
|
|
4294
|
+
*/
|
|
3534
4295
|
const { filteredUserGroup, filterOptions, createCustomUser } = useUserSelection({
|
|
3535
4296
|
selectedUserIds,
|
|
3536
4297
|
excludeUserIds: (0, vue.toRef)(props, "excludeUserIds"),
|
|
3537
4298
|
userGroup: (0, vue.toRef)(props, "userGroup"),
|
|
3538
4299
|
searchQuery
|
|
3539
4300
|
});
|
|
4301
|
+
/**
|
|
4302
|
+
* 使用输入处理公共逻辑 hook
|
|
4303
|
+
*/
|
|
3540
4304
|
const { handlePaste } = useInputHandler({
|
|
3541
4305
|
apiBaseUrl: props.apiBaseUrl,
|
|
3542
4306
|
tenantId: props.tenantId,
|
|
@@ -3549,8 +4313,11 @@
|
|
|
3549
4313
|
onAddUser: addUser,
|
|
3550
4314
|
onBatchAddUsers: props.multiple ? updateSelectedUsers : void 0
|
|
3551
4315
|
});
|
|
4316
|
+
/**
|
|
4317
|
+
* 显示的选项(过滤后的搜索结果)
|
|
4318
|
+
*/
|
|
3552
4319
|
const displayOptions = (0, vue.computed)(() => filterOptions(searchResults.value));
|
|
3553
|
-
const
|
|
4320
|
+
const mainNavigableUsers = (0, vue.computed)(() => {
|
|
3554
4321
|
const userGroupOptions = filteredUserGroup.value.map((group) => ({
|
|
3555
4322
|
...group,
|
|
3556
4323
|
tenantId: "",
|
|
@@ -3564,6 +4331,27 @@
|
|
|
3564
4331
|
...virtualUsers
|
|
3565
4332
|
];
|
|
3566
4333
|
});
|
|
4334
|
+
const filteredRecentUsers = (0, vue.computed)(() => {
|
|
4335
|
+
const query = searchQuery.value.trim();
|
|
4336
|
+
return recentUsers.value.filter((user) => !selectedUserIds.value.includes(user.id)).filter((user) => !props.excludeUserIds.includes(user.id)).filter((user) => isUserMatchedByQuery(user, query));
|
|
4337
|
+
});
|
|
4338
|
+
/**
|
|
4339
|
+
* 下拉框显示状态
|
|
4340
|
+
*/
|
|
4341
|
+
const showDropdown = (0, vue.computed)(() => {
|
|
4342
|
+
return isFocused.value && (filteredUserGroup.value.length > 0 || filteredRecentUsers.value.length > 0 || searchQuery.value.trim() !== "");
|
|
4343
|
+
});
|
|
4344
|
+
/**
|
|
4345
|
+
* 扁平化的选项列表(合并 userGroup 和 displayOptions,用于键盘导航)
|
|
4346
|
+
* 顺序与 selection-popover.vue 中 groupedUsers 的渲染顺序保持一致:
|
|
4347
|
+
* 用户群组 → 普通用户 → 虚拟账号 → 最近选择
|
|
4348
|
+
*/
|
|
4349
|
+
const flatOptions = (0, vue.computed)(() => {
|
|
4350
|
+
return [...mainNavigableUsers.value, ...filteredRecentUsers.value];
|
|
4351
|
+
});
|
|
4352
|
+
/**
|
|
4353
|
+
* 输入框宽度(根据输入内容动态计算)
|
|
4354
|
+
*/
|
|
3567
4355
|
const inputWidth = (0, vue.computed)(() => {
|
|
3568
4356
|
const query = searchQuery.value;
|
|
3569
4357
|
if (!query) return "20px";
|
|
@@ -3572,6 +4360,9 @@
|
|
|
3572
4360
|
}, 0);
|
|
3573
4361
|
return `${Math.max(20, charWidth + 4)}px`;
|
|
3574
4362
|
});
|
|
4363
|
+
/**
|
|
4364
|
+
* 初始化已选用户数据
|
|
4365
|
+
*/
|
|
3575
4366
|
const initSelectedUsers = async () => {
|
|
3576
4367
|
const ids = modelValueIds.value;
|
|
3577
4368
|
if (ids.length === 0) {
|
|
@@ -3585,26 +4376,43 @@
|
|
|
3585
4376
|
type: USER_TYPE.USER_GROUP
|
|
3586
4377
|
}));
|
|
3587
4378
|
try {
|
|
3588
|
-
const
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
type: USER_TYPE.CUSTOM,
|
|
3600
|
-
tenantId: ""
|
|
3601
|
-
})));
|
|
3602
|
-
selectedUsers.value = ids.map((id) => selectedList.find((user) => user.id === id)).filter(Boolean);
|
|
4379
|
+
const selectedList = [...userGroupSelected, ...await lookupFormattedUsersByIds(ids)];
|
|
4380
|
+
if (props.allowCreate) {
|
|
4381
|
+
const lookupFields = [...new Set([...getLookupFields(props.exactSearchKey), DEFAULT_EXACT_SEARCH_KEY])];
|
|
4382
|
+
selectedList.push(...ids.filter((id) => !findUserByLookupId(selectedList, id, lookupFields)).map((id) => ({
|
|
4383
|
+
id,
|
|
4384
|
+
name: id,
|
|
4385
|
+
type: USER_TYPE.CUSTOM,
|
|
4386
|
+
tenantId: ""
|
|
4387
|
+
})));
|
|
4388
|
+
}
|
|
4389
|
+
selectedUsers.value = sortUsersByLookupIds(selectedList, ids, [...new Set([...getLookupFields(props.exactSearchKey), DEFAULT_EXACT_SEARCH_KEY])]);
|
|
3603
4390
|
} catch (error) {
|
|
3604
4391
|
console.error("获取选中用户信息失败:", error);
|
|
3605
4392
|
selectedUsers.value = [];
|
|
3606
4393
|
}
|
|
3607
4394
|
};
|
|
4395
|
+
const initRecentUsers = async () => {
|
|
4396
|
+
const ids = props.recentUserIds.filter(Boolean);
|
|
4397
|
+
const requestId = ++recentUsersRequestId;
|
|
4398
|
+
recentUserIdsSnapshot = [...ids];
|
|
4399
|
+
if (ids.length === 0) {
|
|
4400
|
+
recentUsers.value = [];
|
|
4401
|
+
return;
|
|
4402
|
+
}
|
|
4403
|
+
try {
|
|
4404
|
+
const formattedUsers = (await lookupFormattedUsersByIds(ids)).filter((user) => user.data_source_type !== USER_TYPE.VIRTUAL && user.type !== USER_TYPE.USER_GROUP);
|
|
4405
|
+
if (requestId !== recentUsersRequestId) return;
|
|
4406
|
+
recentUsers.value = formattedUsers;
|
|
4407
|
+
} catch (error) {
|
|
4408
|
+
if (requestId !== recentUsersRequestId) return;
|
|
4409
|
+
console.error("获取最近选择用户信息失败:", error);
|
|
4410
|
+
recentUsers.value = [];
|
|
4411
|
+
}
|
|
4412
|
+
};
|
|
4413
|
+
/**
|
|
4414
|
+
* 更新选中用户并触发事件
|
|
4415
|
+
*/
|
|
3608
4416
|
function updateSelectedUsers(users) {
|
|
3609
4417
|
selectedUsers.value = users;
|
|
3610
4418
|
if (props.multiple) {
|
|
@@ -3616,6 +4424,9 @@
|
|
|
3616
4424
|
emit("change", user);
|
|
3617
4425
|
}
|
|
3618
4426
|
}
|
|
4427
|
+
/**
|
|
4428
|
+
* 初始化排序功能
|
|
4429
|
+
*/
|
|
3619
4430
|
const initSortable = () => {
|
|
3620
4431
|
if (!props.draggable || !props.multiple || !sortableContainerRef.value) return;
|
|
3621
4432
|
if (sortableInstance.value) sortableInstance.value.destroy();
|
|
@@ -3636,6 +4447,9 @@
|
|
|
3636
4447
|
}
|
|
3637
4448
|
});
|
|
3638
4449
|
};
|
|
4450
|
+
/**
|
|
4451
|
+
* 计算可见用户
|
|
4452
|
+
*/
|
|
3639
4453
|
const calculateVisibleUsers = () => {
|
|
3640
4454
|
if (!selectedUsers.value.length) {
|
|
3641
4455
|
visibleUsers.value = [];
|
|
@@ -3659,18 +4473,24 @@
|
|
|
3659
4473
|
visibleUsers.value = selectedUsers.value.slice(0, visibleCount);
|
|
3660
4474
|
hiddenCount.value = Math.max(0, selectedUsers.value.length - visibleCount);
|
|
3661
4475
|
};
|
|
4476
|
+
/**
|
|
4477
|
+
* 处理聚焦
|
|
4478
|
+
*/
|
|
3662
4479
|
const handleFocus = () => {
|
|
3663
4480
|
isFocused.value = true;
|
|
3664
4481
|
activeTagIndex.value = selectedUsers.value.length - 1;
|
|
3665
4482
|
(0, vue.nextTick)(() => focusCurrentInput());
|
|
3666
4483
|
};
|
|
4484
|
+
/**
|
|
4485
|
+
* 延迟计算可见用户
|
|
4486
|
+
*/
|
|
3667
4487
|
const scheduleVisibleUsersCalculation = () => {
|
|
3668
4488
|
if (!isFocused.value) (0, vue.nextTick)(calculateVisibleUsers);
|
|
3669
4489
|
};
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
4490
|
+
/**
|
|
4491
|
+
* 主动失焦(供外部调用或内部复用)
|
|
4492
|
+
*/
|
|
4493
|
+
const blur = () => {
|
|
3674
4494
|
if (isFocused.value) emit("blur");
|
|
3675
4495
|
isFocused.value = false;
|
|
3676
4496
|
activeTagIndex.value = selectedUsers.value.length - 1;
|
|
@@ -3678,26 +4498,56 @@
|
|
|
3678
4498
|
highlightedIndex.value = -1;
|
|
3679
4499
|
scheduleVisibleUsersCalculation();
|
|
3680
4500
|
};
|
|
4501
|
+
/**
|
|
4502
|
+
* 处理失焦
|
|
4503
|
+
*/
|
|
4504
|
+
const handleClickOutside = (event) => {
|
|
4505
|
+
const target = event.target;
|
|
4506
|
+
const container = containerRef.value;
|
|
4507
|
+
if (container?.contains(target) || container === target) return;
|
|
4508
|
+
blur();
|
|
4509
|
+
};
|
|
4510
|
+
/**
|
|
4511
|
+
* 处理容器点击
|
|
4512
|
+
*/
|
|
3681
4513
|
const handleContainerClick = () => {
|
|
3682
4514
|
activeTagIndex.value = selectedUsers.value.length - 1;
|
|
3683
4515
|
(0, vue.nextTick)(() => focusCurrentInput());
|
|
3684
4516
|
};
|
|
4517
|
+
/**
|
|
4518
|
+
* 聚焦当前光标位置的输入框
|
|
4519
|
+
* activeTagIndex 语义:
|
|
4520
|
+
* -1 = 最前面(第一个标签之前)
|
|
4521
|
+
* 0 ~ length-1 = 对应标签后面
|
|
4522
|
+
*/
|
|
3685
4523
|
const focusCurrentInput = () => {
|
|
3686
4524
|
if (activeTagIndex.value === -1 && selectedUsers.value.length > 0) frontInputRef.value?.focus();
|
|
3687
4525
|
else if (activeTagIndex.value >= selectedUsers.value.length - 1) lastInputRef.value?.focus();
|
|
3688
4526
|
else inlineInputRef.value?.[0]?.focus();
|
|
3689
4527
|
};
|
|
4528
|
+
/**
|
|
4529
|
+
* 处理标签点击
|
|
4530
|
+
*/
|
|
3690
4531
|
const handleTagClick = (index) => {
|
|
3691
4532
|
activeTagIndex.value = index;
|
|
3692
4533
|
(0, vue.nextTick)(() => focusCurrentInput());
|
|
3693
4534
|
};
|
|
4535
|
+
/**
|
|
4536
|
+
* 处理输入框聚焦
|
|
4537
|
+
*/
|
|
3694
4538
|
const handleInputFocus = () => {
|
|
3695
4539
|
emit("focus");
|
|
3696
4540
|
isFocused.value = true;
|
|
3697
4541
|
};
|
|
4542
|
+
/**
|
|
4543
|
+
* 处理输入变化
|
|
4544
|
+
*/
|
|
3698
4545
|
const handleInput = () => {
|
|
3699
4546
|
handleSearchInput(searchQuery.value);
|
|
3700
4547
|
};
|
|
4548
|
+
/**
|
|
4549
|
+
* 添加当前用户("我")
|
|
4550
|
+
*/
|
|
3701
4551
|
const addCurrentUser = async () => {
|
|
3702
4552
|
if (!props.currentUserId || selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId)) return;
|
|
3703
4553
|
if (props.multiple && isMaxCountReached.value) return;
|
|
@@ -3712,11 +4562,17 @@
|
|
|
3712
4562
|
(0, vue.nextTick)(() => focusCurrentInput());
|
|
3713
4563
|
}
|
|
3714
4564
|
};
|
|
4565
|
+
/**
|
|
4566
|
+
* 处理粘贴事件
|
|
4567
|
+
*/
|
|
3715
4568
|
const onPaste = async (event) => {
|
|
3716
4569
|
await handlePaste(event);
|
|
3717
4570
|
activeTagIndex.value = selectedUsers.value.length - 1;
|
|
3718
4571
|
(0, vue.nextTick)(() => focusCurrentInput());
|
|
3719
4572
|
};
|
|
4573
|
+
/**
|
|
4574
|
+
* 处理键盘事件
|
|
4575
|
+
*/
|
|
3720
4576
|
const handleKeyDown = (event) => {
|
|
3721
4577
|
if (event.key === "Backspace" && !searchQuery.value && selectedUsers.value.length > 0) {
|
|
3722
4578
|
if (activeTagIndex.value >= 0) {
|
|
@@ -3760,6 +4616,12 @@
|
|
|
3760
4616
|
return;
|
|
3761
4617
|
}
|
|
3762
4618
|
};
|
|
4619
|
+
/**
|
|
4620
|
+
* 添加用户
|
|
4621
|
+
* activeTagIndex 语义:
|
|
4622
|
+
* -1 = 在最前面插入
|
|
4623
|
+
* 0 ~ length-1 = 在对应标签后面插入
|
|
4624
|
+
*/
|
|
3763
4625
|
function addUser(user) {
|
|
3764
4626
|
if (!user?.id) return;
|
|
3765
4627
|
if (props.multiple && isMaxCountReached.value) {
|
|
@@ -3792,6 +4654,9 @@
|
|
|
3792
4654
|
isFocused.value = true;
|
|
3793
4655
|
(0, vue.nextTick)(() => focusCurrentInput());
|
|
3794
4656
|
}
|
|
4657
|
+
/**
|
|
4658
|
+
* 移除用户(通过 x 按钮删除)
|
|
4659
|
+
*/
|
|
3795
4660
|
const removeUser = (user) => {
|
|
3796
4661
|
if (!user?.id) return;
|
|
3797
4662
|
const removedIndex = selectedUsers.value.findIndex((item) => item.id === user.id);
|
|
@@ -3802,9 +4667,15 @@
|
|
|
3802
4667
|
else if (activeTagIndex.value >= updatedUsers.length) activeTagIndex.value = updatedUsers.length - 1;
|
|
3803
4668
|
scheduleVisibleUsersCalculation();
|
|
3804
4669
|
};
|
|
4670
|
+
/**
|
|
4671
|
+
* 监听选中用户变化
|
|
4672
|
+
*/
|
|
3805
4673
|
(0, vue.watch)(selectedUsers, () => {
|
|
3806
4674
|
scheduleVisibleUsersCalculation();
|
|
3807
4675
|
}, { deep: true });
|
|
4676
|
+
/**
|
|
4677
|
+
* 监听聚焦状态变化
|
|
4678
|
+
*/
|
|
3808
4679
|
(0, vue.watch)(isFocused, (newVal) => {
|
|
3809
4680
|
if (isTextareaMode.value) {
|
|
3810
4681
|
const prevContainer = newVal ? collapsedContainerRef.value : containerRef.value?.querySelector(".tags-container.focused");
|
|
@@ -3812,35 +4683,73 @@
|
|
|
3812
4683
|
}
|
|
3813
4684
|
if (newVal) (0, vue.nextTick)(() => initSortable());
|
|
3814
4685
|
});
|
|
4686
|
+
/**
|
|
4687
|
+
* 监听 flatOptions 变化,重置高亮索引到第一项
|
|
4688
|
+
*/
|
|
3815
4689
|
(0, vue.watch)(flatOptions, (newOptions) => {
|
|
3816
4690
|
if (newOptions.length > 0 && showDropdown.value) highlightedIndex.value = 0;
|
|
3817
4691
|
else highlightedIndex.value = -1;
|
|
3818
4692
|
});
|
|
4693
|
+
/**
|
|
4694
|
+
* 监听用户群组变化
|
|
4695
|
+
*/
|
|
3819
4696
|
(0, vue.watch)(() => props.userGroup, () => {
|
|
3820
4697
|
initSelectedUsers();
|
|
3821
4698
|
});
|
|
4699
|
+
(0, vue.watch)(() => props.recentUserIds, () => {
|
|
4700
|
+
const newIds = props.recentUserIds.filter(Boolean);
|
|
4701
|
+
if (recentUserIdsSnapshot.length === newIds.length && recentUserIdsSnapshot.every((id, index) => id === newIds[index])) return;
|
|
4702
|
+
initRecentUsers();
|
|
4703
|
+
}, { deep: true });
|
|
4704
|
+
/**
|
|
4705
|
+
* 监听 modelValue 变化
|
|
4706
|
+
*/
|
|
3822
4707
|
(0, vue.watch)(() => props.modelValue, () => {
|
|
3823
4708
|
const currentIds = selectedUsers.value.map((u) => u.id);
|
|
3824
4709
|
const newIds = modelValueIds.value;
|
|
3825
4710
|
if (currentIds.length !== newIds.length || !currentIds.every((id, index) => id === newIds[index])) initSelectedUsers();
|
|
3826
4711
|
}, { deep: true });
|
|
4712
|
+
/**
|
|
4713
|
+
* 使用 ResizeObserver 监听容器大小变化
|
|
4714
|
+
*/
|
|
3827
4715
|
useResizeObserver(containerRef, () => {
|
|
3828
4716
|
scheduleVisibleUsersCalculation();
|
|
3829
4717
|
});
|
|
4718
|
+
let initPromise;
|
|
4719
|
+
/**
|
|
4720
|
+
* 组件挂载前初始化
|
|
4721
|
+
*/
|
|
3830
4722
|
(0, vue.onBeforeMount)(() => {
|
|
3831
|
-
initSelectedUsers();
|
|
4723
|
+
initPromise = Promise.all([initSelectedUsers(), initRecentUsers()]).then(() => void 0);
|
|
3832
4724
|
});
|
|
3833
|
-
|
|
4725
|
+
/**
|
|
4726
|
+
* 组件挂载后初始化
|
|
4727
|
+
*/
|
|
4728
|
+
(0, vue.onMounted)(async () => {
|
|
3834
4729
|
initSortable();
|
|
3835
4730
|
(0, vue.nextTick)(calculateVisibleUsers);
|
|
4731
|
+
if (props.autoFocus && !props.disabled) {
|
|
4732
|
+
await initPromise;
|
|
4733
|
+
await (0, vue.nextTick)();
|
|
4734
|
+
handleFocus();
|
|
4735
|
+
}
|
|
3836
4736
|
});
|
|
4737
|
+
/**
|
|
4738
|
+
* 组件卸载前清理
|
|
4739
|
+
*/
|
|
3837
4740
|
(0, vue.onUnmounted)(() => {
|
|
3838
4741
|
sortableInstance.value?.destroy();
|
|
3839
4742
|
});
|
|
4743
|
+
__expose({
|
|
4744
|
+
focus: handleFocus,
|
|
4745
|
+
blur
|
|
4746
|
+
});
|
|
3840
4747
|
const __returned__ = {
|
|
3841
4748
|
t,
|
|
3842
4749
|
props,
|
|
3843
4750
|
emit,
|
|
4751
|
+
handleApiError,
|
|
4752
|
+
handleApiUnauthorized,
|
|
3844
4753
|
tenants,
|
|
3845
4754
|
searchResults,
|
|
3846
4755
|
searchLoading,
|
|
@@ -3860,17 +4769,35 @@
|
|
|
3860
4769
|
visibleUsers,
|
|
3861
4770
|
hiddenCount,
|
|
3862
4771
|
highlightedIndex,
|
|
4772
|
+
recentUsers,
|
|
4773
|
+
get recentUsersRequestId() {
|
|
4774
|
+
return recentUsersRequestId;
|
|
4775
|
+
},
|
|
4776
|
+
set recentUsersRequestId(v) {
|
|
4777
|
+
recentUsersRequestId = v;
|
|
4778
|
+
},
|
|
4779
|
+
get recentUserIdsSnapshot() {
|
|
4780
|
+
return recentUserIdsSnapshot;
|
|
4781
|
+
},
|
|
4782
|
+
set recentUserIdsSnapshot(v) {
|
|
4783
|
+
recentUserIdsSnapshot = v;
|
|
4784
|
+
},
|
|
3863
4785
|
selectedUsers,
|
|
3864
4786
|
isTextareaMode,
|
|
3865
4787
|
textareaHeight,
|
|
3866
4788
|
textareaStyle,
|
|
3867
4789
|
collapsedDisplayUsers,
|
|
3868
|
-
showDropdown,
|
|
3869
4790
|
modelValueIds,
|
|
3870
4791
|
computedPlaceholder,
|
|
3871
4792
|
computedUserGroupName,
|
|
3872
4793
|
computedEmptyText,
|
|
4794
|
+
computedRecentUsersName,
|
|
3873
4795
|
selectedUserIds,
|
|
4796
|
+
isUserMatchedByQuery,
|
|
4797
|
+
getLookupFields,
|
|
4798
|
+
findUserByLookupId,
|
|
4799
|
+
sortUsersByLookupIds,
|
|
4800
|
+
lookupFormattedUsersByIds,
|
|
3874
4801
|
isMaxCountReached,
|
|
3875
4802
|
isMeTagDisabled,
|
|
3876
4803
|
userTagCommonProps,
|
|
@@ -3879,14 +4806,19 @@
|
|
|
3879
4806
|
createCustomUser,
|
|
3880
4807
|
handlePaste,
|
|
3881
4808
|
displayOptions,
|
|
4809
|
+
mainNavigableUsers,
|
|
4810
|
+
filteredRecentUsers,
|
|
4811
|
+
showDropdown,
|
|
3882
4812
|
flatOptions,
|
|
3883
4813
|
inputWidth,
|
|
3884
4814
|
initSelectedUsers,
|
|
4815
|
+
initRecentUsers,
|
|
3885
4816
|
updateSelectedUsers,
|
|
3886
4817
|
initSortable,
|
|
3887
4818
|
calculateVisibleUsers,
|
|
3888
4819
|
handleFocus,
|
|
3889
4820
|
scheduleVisibleUsersCalculation,
|
|
4821
|
+
blur,
|
|
3890
4822
|
handleClickOutside,
|
|
3891
4823
|
handleContainerClick,
|
|
3892
4824
|
focusCurrentInput,
|
|
@@ -3898,6 +4830,12 @@
|
|
|
3898
4830
|
handleKeyDown,
|
|
3899
4831
|
addUser,
|
|
3900
4832
|
removeUser,
|
|
4833
|
+
get initPromise() {
|
|
4834
|
+
return initPromise;
|
|
4835
|
+
},
|
|
4836
|
+
set initPromise(v) {
|
|
4837
|
+
initPromise = v;
|
|
4838
|
+
},
|
|
3901
4839
|
get Popover() {
|
|
3902
4840
|
return bkui_vue.Popover;
|
|
3903
4841
|
},
|
|
@@ -3918,6 +4856,8 @@
|
|
|
3918
4856
|
return __returned__;
|
|
3919
4857
|
}
|
|
3920
4858
|
});
|
|
4859
|
+
//#endregion
|
|
4860
|
+
//#region src/components/user-selector.vue
|
|
3921
4861
|
var _hoisted_1 = {
|
|
3922
4862
|
ref: "sortableContainerRef",
|
|
3923
4863
|
class: "tag-list"
|
|
@@ -3942,6 +4882,8 @@
|
|
|
3942
4882
|
"is-show": $setup.showDropdown,
|
|
3943
4883
|
loading: $setup.searchLoading,
|
|
3944
4884
|
options: $setup.displayOptions,
|
|
4885
|
+
"recent-users": $setup.filteredRecentUsers,
|
|
4886
|
+
"recent-users-name": $setup.computedRecentUsersName,
|
|
3945
4887
|
"render-list-item": $props.renderListItem,
|
|
3946
4888
|
"search-query": $setup.searchQuery,
|
|
3947
4889
|
"tenant-id": $props.tenantId,
|
|
@@ -4093,6 +5035,8 @@
|
|
|
4093
5035
|
"is-show",
|
|
4094
5036
|
"loading",
|
|
4095
5037
|
"options",
|
|
5038
|
+
"recent-users",
|
|
5039
|
+
"recent-users-name",
|
|
4096
5040
|
"render-list-item",
|
|
4097
5041
|
"search-query",
|
|
4098
5042
|
"tenant-id",
|
|
@@ -4101,12 +5045,15 @@
|
|
|
4101
5045
|
"user-group-name"
|
|
4102
5046
|
])], 2);
|
|
4103
5047
|
}
|
|
4104
|
-
var user_selector_default = /* @__PURE__ */
|
|
5048
|
+
var user_selector_default = /* @__PURE__ */ _plugin_vue_export_helper_default(user_selector_vue_vue_type_script_setup_true_lang_default, [
|
|
4105
5049
|
["render", _sfc_render],
|
|
4106
5050
|
["__scopeId", "data-v-089550be"],
|
|
4107
5051
|
["__file", "/Users/brooklin/project/bkui-monorepo/packages/bk-user-selector/src/components/user-selector.vue"]
|
|
4108
5052
|
]);
|
|
5053
|
+
//#endregion
|
|
5054
|
+
//#region src/vue3.ts
|
|
4109
5055
|
var vue3_default = user_selector_default;
|
|
5056
|
+
//#endregion
|
|
4110
5057
|
exports.BkUserSelector = user_selector_default;
|
|
4111
5058
|
exports.default = vue3_default;
|
|
4112
5059
|
});
|