@blueking/bk-user-selector 0.1.8 → 0.1.9

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.
@@ -6,7 +6,7 @@
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}\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*/";
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.user-option.is-disabled[data-v-9173accf] {\n cursor: not-allowed;\n opacity: 0.5;\n}\n.user-option.is-disabled[data-v-9173accf]:hover, .user-option.is-disabled.is-highlighted[data-v-9173accf] {\n background-color: transparent;\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 },
@@ -3008,7 +3008,7 @@
3008
3008
  * @returns 输入处理相关方法
3009
3009
  */
3010
3010
  var useInputHandler = (options) => {
3011
- const { apiBaseUrl, tenantId, searchQuery, selectedUsers, allowCreate = false, freePaste = false, enableMultiTenantMode = true, maxCount = 0, onAddUser, onBatchAddUsers } = options;
3011
+ const { apiBaseUrl, tenantId, searchQuery, selectedUsers, allowCreate = false, freePaste = false, enableMultiTenantMode = true, maxCount = 0, isUserDisabled = () => false, onAddUser, onBatchAddUsers } = options;
3012
3012
  const isPasting = (0, vue.ref)(false);
3013
3013
  /** 单次粘贴最多处理数量(后端限制) */
3014
3014
  const MAX_PASTE_USERS = 100;
@@ -3060,7 +3060,7 @@
3060
3060
  const handleEnterCreate = (event) => {
3061
3061
  if (event.key !== "Enter" || !allowCreate || !searchQuery.value.trim()) return;
3062
3062
  const customUser = createCustomUser(searchQuery.value.trim());
3063
- if (!selectedUsers.value.some((user) => user.id === customUser.id)) onAddUser(customUser);
3063
+ if (!selectedUsers.value.some((user) => user.id === customUser.id) && !isUserDisabled(customUser)) onAddUser(customUser);
3064
3064
  };
3065
3065
  /**
3066
3066
  * 处理粘贴事件
@@ -3086,11 +3086,11 @@
3086
3086
  });
3087
3087
  lookupResults.push(...result);
3088
3088
  }
3089
- const formattedUsers = formatUsers(lookupResults, enableMultiTenantMode);
3089
+ const formattedUsers = formatUsers(lookupResults, enableMultiTenantMode).filter((user) => !isUserDisabled(user));
3090
3090
  if (onBatchAddUsers) {
3091
3091
  let mergedUsers = mergeUsers(selectedUsers.value, formattedUsers);
3092
3092
  if (freePaste) {
3093
- for (const loginName of usersList) if (!mergedUsers.some((item) => item.login_name === loginName || item.id === loginName)) mergedUsers.push(createCustomUser(loginName));
3093
+ for (const loginName of usersList) if (!mergedUsers.some((item) => item.login_name === loginName || item.id === loginName) && !isUserDisabled(loginName)) mergedUsers.push(createCustomUser(loginName));
3094
3094
  }
3095
3095
  if (maxCount > 0 && mergedUsers.length > maxCount) mergedUsers = mergedUsers.slice(0, maxCount);
3096
3096
  onBatchAddUsers(mergedUsers);
@@ -3337,7 +3337,7 @@
3337
3337
  * @returns 用户选择相关方法
3338
3338
  */
3339
3339
  var useUserSelection = (options) => {
3340
- const { selectedUserIds, excludeUserIds, userGroup, searchQuery } = options;
3340
+ const { selectedUserIds, excludeUserIds, disabledUserFields, disabledUserIds, userGroup, searchQuery } = options;
3341
3341
  /**
3342
3342
  * 创建自定义用户对象
3343
3343
  * @param loginName - 用户登录名
@@ -3357,15 +3357,38 @@
3357
3357
  return selectedUserIds.value.includes(userId);
3358
3358
  };
3359
3359
  /**
3360
+ * 检查用户是否被禁用
3361
+ * @param user - 用户对象或用户ID
3362
+ */
3363
+ const isUserDisabled = (user) => {
3364
+ const ids = disabledUserIds?.value ?? [];
3365
+ if (typeof user === "string") return ids.includes(user);
3366
+ const fields = disabledUserFields?.value?.length ? disabledUserFields.value : ["id"];
3367
+ const indexedUser = user;
3368
+ return fields.some((field) => {
3369
+ const value = field === "id" ? user.id : indexedUser[field];
3370
+ return value !== void 0 && value !== null && ids.includes(String(value));
3371
+ });
3372
+ };
3373
+ /**
3360
3374
  * 过滤选项(排除已选和排除列表)
3361
3375
  * @param options - 原始选项列表
3362
3376
  */
3363
3377
  const filterOptions = (options) => {
3364
3378
  return options.filter((user) => !isUserSelected(user.id)).filter((user) => !excludeUserIds?.value?.includes(user.id));
3365
3379
  };
3380
+ /**
3381
+ * 过滤可导航选项(排除已选、排除列表和禁用列表)
3382
+ * @param options - 原始选项列表
3383
+ */
3384
+ const filterNavigableOptions = (options) => {
3385
+ return filterOptions(options).filter((user) => !isUserDisabled(user));
3386
+ };
3366
3387
  return {
3367
3388
  createCustomUser,
3389
+ filterNavigableOptions,
3368
3390
  isUserSelected,
3391
+ isUserDisabled,
3369
3392
  filterOptions,
3370
3393
  filteredUserGroup: (0, vue.computed)(() => {
3371
3394
  if (!userGroup?.value?.length) return [];
@@ -3546,6 +3569,16 @@
3546
3569
  required: false,
3547
3570
  default: "auto"
3548
3571
  },
3572
+ disabledUserFields: {
3573
+ type: Array,
3574
+ required: false,
3575
+ default: () => ["id"]
3576
+ },
3577
+ disabledUserIds: {
3578
+ type: Array,
3579
+ required: false,
3580
+ default: () => []
3581
+ },
3549
3582
  emptyText: {
3550
3583
  type: String,
3551
3584
  required: false,
@@ -3666,9 +3699,20 @@
3666
3699
  return props.flatOptions[props.highlightedIndex] === user;
3667
3700
  };
3668
3701
  /**
3702
+ * 判断用户是否禁用
3703
+ */
3704
+ const isUserDisabled = (user) => {
3705
+ const indexedUser = user;
3706
+ return props.disabledUserFields.some((field) => {
3707
+ const value = field === "id" ? user.id : indexedUser[field];
3708
+ return value !== void 0 && value !== null && props.disabledUserIds.includes(String(value));
3709
+ });
3710
+ };
3711
+ /**
3669
3712
  * 选择用户
3670
3713
  */
3671
3714
  const selectUser = (user) => {
3715
+ if (isUserDisabled(user)) return;
3672
3716
  emit("select-user", user);
3673
3717
  };
3674
3718
  /**
@@ -3705,6 +3749,7 @@
3705
3749
  hasRecentUsers,
3706
3750
  hasDropdownOptions,
3707
3751
  isHighlighted,
3752
+ isUserDisabled,
3708
3753
  selectUser,
3709
3754
  handleClickOutside,
3710
3755
  get Loading() {
@@ -3737,14 +3782,14 @@
3737
3782
  };
3738
3783
  var _hoisted_4$1 = { class: "group-name" };
3739
3784
  var _hoisted_5 = { class: "group-count" };
3740
- var _hoisted_6 = ["onClick"];
3785
+ var _hoisted_6 = ["aria-disabled", "onClick"];
3741
3786
  var _hoisted_7 = {
3742
3787
  key: 1,
3743
3788
  class: "dropdown-panel dropdown-panel-recent"
3744
3789
  };
3745
3790
  var _hoisted_8 = { class: "group-name" };
3746
3791
  var _hoisted_9 = { class: "group-count" };
3747
- var _hoisted_10 = ["onClick"];
3792
+ var _hoisted_10 = ["aria-disabled", "onClick"];
3748
3793
  var _hoisted_11 = { ref: "slotContainerRef" };
3749
3794
  function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
3750
3795
  return (0, vue.openBlock)(), (0, vue.createBlock)($setup["Popover"], {
@@ -3778,7 +3823,11 @@
3778
3823
  }, [(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) => {
3779
3824
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
3780
3825
  key: user.id,
3781
- class: (0, vue.normalizeClass)(["user-option", { "is-highlighted": $setup.isHighlighted(user) }]),
3826
+ "aria-disabled": $setup.isUserDisabled(user),
3827
+ class: (0, vue.normalizeClass)(["user-option", {
3828
+ "is-highlighted": $setup.isHighlighted(user),
3829
+ "is-disabled": $setup.isUserDisabled(user)
3830
+ }]),
3782
3831
  onClick: (0, vue.withModifiers)(($event) => $setup.selectUser(user), ["prevent"]),
3783
3832
  onMousedown: _cache[1] || (_cache[1] = (0, vue.withModifiers)(() => {}, ["prevent"]))
3784
3833
  }, [(0, vue.createVNode)($setup["UserRender"], {
@@ -3804,7 +3853,11 @@
3804
3853
  }, [(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
3854
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
3806
3855
  key: user.id,
3807
- class: (0, vue.normalizeClass)(["user-option", { "is-highlighted": $setup.isHighlighted(user) }]),
3856
+ "aria-disabled": $setup.isUserDisabled(user),
3857
+ class: (0, vue.normalizeClass)(["user-option", {
3858
+ "is-highlighted": $setup.isHighlighted(user),
3859
+ "is-disabled": $setup.isUserDisabled(user)
3860
+ }]),
3808
3861
  onClick: (0, vue.withModifiers)(($event) => $setup.selectUser(user), ["prevent"]),
3809
3862
  onMousedown: _cache[3] || (_cache[3] = (0, vue.withModifiers)(() => {}, ["prevent"]))
3810
3863
  }, [(0, vue.createVNode)($setup["UserRender"], {
@@ -4043,6 +4096,11 @@
4043
4096
  required: false,
4044
4097
  default: false
4045
4098
  },
4099
+ disabledUserIds: {
4100
+ type: Array,
4101
+ required: false,
4102
+ default: () => []
4103
+ },
4046
4104
  emptyText: {
4047
4105
  type: String,
4048
4106
  required: false,
@@ -4234,6 +4292,13 @@
4234
4292
  const getLookupFields = (exactSearchKey) => {
4235
4293
  return exactSearchKey.split(",").map((field) => field.trim()).filter(Boolean);
4236
4294
  };
4295
+ const disabledUserFields = (0, vue.computed)(() => [...new Set([
4296
+ "id",
4297
+ ...getLookupFields(props.exactSearchKey),
4298
+ DEFAULT_EXACT_SEARCH_KEY,
4299
+ "login_name",
4300
+ "username"
4301
+ ])]);
4237
4302
  const findUserByLookupId = (users, lookupId, lookupFields) => {
4238
4303
  return users.find((user) => {
4239
4304
  if (user.id === lookupId) return true;
@@ -4278,7 +4343,7 @@
4278
4343
  /**
4279
4344
  * "我"标签是否禁用(已选中当前用户时禁用,或已达到最大数量)
4280
4345
  */
4281
- const isMeTagDisabled = (0, vue.computed)(() => isMaxCountReached.value || !!props.currentUserId && selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId));
4346
+ const isMeTagDisabled = (0, vue.computed)(() => isMaxCountReached.value || !!props.currentUserId && props.disabledUserIds.includes(props.currentUserId) || !!props.currentUserId && selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId));
4282
4347
  /**
4283
4348
  * UserTag 公共属性
4284
4349
  */
@@ -4292,8 +4357,10 @@
4292
4357
  /**
4293
4358
  * 使用用户选择公共逻辑 hook
4294
4359
  */
4295
- const { filteredUserGroup, filterOptions, createCustomUser } = useUserSelection({
4360
+ const { filteredUserGroup, filterOptions, filterNavigableOptions, createCustomUser, isUserDisabled } = useUserSelection({
4296
4361
  selectedUserIds,
4362
+ disabledUserFields,
4363
+ disabledUserIds: (0, vue.toRef)(props, "disabledUserIds"),
4297
4364
  excludeUserIds: (0, vue.toRef)(props, "excludeUserIds"),
4298
4365
  userGroup: (0, vue.toRef)(props, "userGroup"),
4299
4366
  searchQuery
@@ -4310,6 +4377,7 @@
4310
4377
  freePaste: props.freePaste,
4311
4378
  enableMultiTenantMode: props.enableMultiTenantMode,
4312
4379
  maxCount: props.maxCount,
4380
+ isUserDisabled,
4313
4381
  onAddUser: addUser,
4314
4382
  onBatchAddUsers: props.multiple ? updateSelectedUsers : void 0
4315
4383
  });
@@ -4318,13 +4386,14 @@
4318
4386
  */
4319
4387
  const displayOptions = (0, vue.computed)(() => filterOptions(searchResults.value));
4320
4388
  const mainNavigableUsers = (0, vue.computed)(() => {
4321
- const userGroupOptions = filteredUserGroup.value.map((group) => ({
4389
+ const userGroupOptions = filterNavigableOptions(filteredUserGroup.value.map((group) => ({
4322
4390
  ...group,
4323
4391
  tenantId: "",
4324
4392
  type: USER_TYPE.USER_GROUP
4325
- }));
4326
- const normalUsers = displayOptions.value.filter((user) => user.data_source_type !== USER_TYPE.VIRTUAL);
4327
- const virtualUsers = displayOptions.value.filter((user) => user.data_source_type === USER_TYPE.VIRTUAL);
4393
+ })));
4394
+ const selectableOptions = filterNavigableOptions(displayOptions.value);
4395
+ const normalUsers = selectableOptions.filter((user) => user.data_source_type !== USER_TYPE.VIRTUAL);
4396
+ const virtualUsers = selectableOptions.filter((user) => user.data_source_type === USER_TYPE.VIRTUAL);
4328
4397
  return [
4329
4398
  ...userGroupOptions,
4330
4399
  ...normalUsers,
@@ -4347,7 +4416,7 @@
4347
4416
  * 用户群组 → 普通用户 → 虚拟账号 → 最近选择
4348
4417
  */
4349
4418
  const flatOptions = (0, vue.computed)(() => {
4350
- return [...mainNavigableUsers.value, ...filteredRecentUsers.value];
4419
+ return [...mainNavigableUsers.value, ...filterNavigableOptions(filteredRecentUsers.value)];
4351
4420
  });
4352
4421
  /**
4353
4422
  * 输入框宽度(根据输入内容动态计算)
@@ -4549,10 +4618,11 @@
4549
4618
  * 添加当前用户("我")
4550
4619
  */
4551
4620
  const addCurrentUser = async () => {
4552
- if (!props.currentUserId || selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId)) return;
4621
+ if (!props.currentUserId || props.disabledUserIds.includes(props.currentUserId) || selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId)) return;
4553
4622
  if (props.multiple && isMaxCountReached.value) return;
4554
4623
  const currentUser = await fetchCurrentUser();
4555
4624
  if (currentUser) {
4625
+ if (isUserDisabled(currentUser)) return;
4556
4626
  if (!props.multiple) updateSelectedUsers([currentUser]);
4557
4627
  else if (!selectedUsers.value.some((item) => item.id === currentUser.id)) updateSelectedUsers([...selectedUsers.value, currentUser]);
4558
4628
  clearSearch();
@@ -4624,6 +4694,7 @@
4624
4694
  */
4625
4695
  function addUser(user) {
4626
4696
  if (!user?.id) return;
4697
+ if (isUserDisabled(user)) return;
4627
4698
  if (props.multiple && isMaxCountReached.value) {
4628
4699
  clearSearch();
4629
4700
  highlightedIndex.value = -1;
@@ -4795,6 +4866,7 @@
4795
4866
  selectedUserIds,
4796
4867
  isUserMatchedByQuery,
4797
4868
  getLookupFields,
4869
+ disabledUserFields,
4798
4870
  findUserByLookupId,
4799
4871
  sortUsersByLookupIds,
4800
4872
  lookupFormattedUsersByIds,
@@ -4803,7 +4875,9 @@
4803
4875
  userTagCommonProps,
4804
4876
  filteredUserGroup,
4805
4877
  filterOptions,
4878
+ filterNavigableOptions,
4806
4879
  createCustomUser,
4880
+ isUserDisabled,
4807
4881
  handlePaste,
4808
4882
  displayOptions,
4809
4883
  mainNavigableUsers,
@@ -4875,6 +4949,8 @@
4875
4949
  }, [(0, vue.createCommentVNode)(" 下拉选项列表 "), (0, vue.createVNode)($setup["SelectionPopover"], {
4876
4950
  "avatar-base-url": $props.avatarBaseUrl,
4877
4951
  "container-width": $setup.containerRef ? $setup.containerRef.offsetWidth : "auto",
4952
+ "disabled-user-fields": $setup.disabledUserFields,
4953
+ "disabled-user-ids": $props.disabledUserIds,
4878
4954
  "empty-text": $setup.computedEmptyText,
4879
4955
  "flat-options": $setup.flatOptions,
4880
4956
  "has-avatar": $props.hasAvatar,
@@ -5028,6 +5104,8 @@
5028
5104
  }, 8, [
5029
5105
  "avatar-base-url",
5030
5106
  "container-width",
5107
+ "disabled-user-fields",
5108
+ "disabled-user-ids",
5031
5109
  "empty-text",
5032
5110
  "flat-options",
5033
5111
  "has-avatar",
package/vue3/vue3.css CHANGED
@@ -82,6 +82,13 @@
82
82
  .user-option[data-v-9173accf]:hover, .user-option.is-highlighted[data-v-9173accf] {
83
83
  background-color: #f5f7fa;
84
84
  }
85
+ .user-option.is-disabled[data-v-9173accf] {
86
+ cursor: not-allowed;
87
+ opacity: 0.5;
88
+ }
89
+ .user-option.is-disabled[data-v-9173accf]:hover, .user-option.is-disabled.is-highlighted[data-v-9173accf] {
90
+ background-color: transparent;
91
+ }
85
92
  .dropdown-panel[data-v-9173accf] .user-render,
86
93
  .dropdown-panel[data-v-9173accf] .user-main,
87
94
  .dropdown-panel[data-v-9173accf] .user-name,