gaoluyang
2026-06-29 27cd042df9aca0383a49f3514bc21958dd890912
src/views/im/home/composables/useSelectedItems.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,75 @@
import { computed, type ComputedRef, type Ref } from 'vue'
/**
 * ä¸‰æ€é€‰æ‹©é¢æ¿çš„「已选数 + å·²é€‰é¡¹åˆ—表」派生
 *
 * - ä¸‰æ€ä¼˜å…ˆçº§ï¼ˆä¸Ž dialog-picker-contract å¯¹é½ï¼‰ï¼šhide > locked > disabled
 *   - hide:永远剔除,不计数 / ä¸è¿›å·²é€‰åˆ—表
 *   - locked:默认勾选 + è®¡æ•° + ä¼˜å…ˆæŽ’在前面;即使被外部塞进 disabledIds ä¹Ÿèƒœå‡º
 *   - disabled:仅过滤 selectedIds,不计数 / ä¸è¿›å·²é€‰åˆ—表
 * - é¡ºåºï¼šlockedIds åœ¨å‰ï¼ŒselectedIds ç´§éšï¼›æŒ‰æ•°ç»„顺序即为「点击顺序」
 *
 * FriendPickerPanel / GroupMemberPickerPanel å…±ç”¨ï¼Œé¿å…ä¸¤ä¾§ 25 è¡ŒåŒæž„ computed å„写一份;
 * Panel å†…部的 isLocked / isDisabled / isSelected ç­‰æ¨¡æ¿åˆ¤å®šå‡½æ•°ä»å„自维护,本 composable åªæ‰¿æ‹…派生量
 */
export function useSelectedItems<T>(
  selectedIds: () => readonly number[],
  lockedIds: () => readonly number[],
  disabledIds: () => readonly number[],
  hideIds: () => readonly number[],
  byId: ComputedRef<Map<number, T>> | Ref<Map<number, T>>
): {
  selectedCount: ComputedRef<number>
  selectedItems: ComputedRef<T[]>
} {
  const hideSet = computed(() => new Set(hideIds()))
  const disabledSet = computed(() => new Set(disabledIds()))
  const selectedCount = computed(() => {
    const merged = new Set<number>()
    for (const id of selectedIds()) {
      if (hideSet.value.has(id) || disabledSet.value.has(id)) {
        continue
      }
      merged.add(id)
    }
    // locked ä»…被 hide è¿‡æ»¤ï¼›å¥‘约里 locked èƒœè¿‡ disabled,确保锁定项始终计入
    for (const id of lockedIds()) {
      if (hideSet.value.has(id)) {
        continue
      }
      merged.add(id)
    }
    return merged.size
  })
  const selectedItems = computed(() => {
    const seen = new Set<number>()
    const result: T[] = []
    // locked åœ¨å‰ï¼›ä»…被 hide è¿‡æ»¤
    for (const id of lockedIds()) {
      if (seen.has(id) || hideSet.value.has(id)) {
        continue
      }
      const item = byId.value.get(id)
      if (item) {
        seen.add(id)
        result.push(item)
      }
    }
    // selectedIds ç´§éšï¼›é¢å¤–过滤 disabled
    for (const id of selectedIds()) {
      if (seen.has(id) || disabledSet.value.has(id) || hideSet.value.has(id)) {
        continue
      }
      const item = byId.value.get(id)
      if (item) {
        seen.add(id)
        result.push(item)
      }
    }
    return result
  })
  return { selectedCount, selectedItems }
}