gaoluyang
昨天 b64a0deae5b5d33f9e20671a68936b27f0b9b00b
src/views/im/manager/group/components/select.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,129 @@
<script lang="ts" setup>
import type { ImManagerGroupApi } from '#/api/im/manager/group';
import { computed, ref, useAttrs, watch } from 'vue';
import { IconifyIcon } from '#/packages/icons/src';
import { Input, Tooltip } from 'ant-design-vue';
import { getManagerGroup } from '#/api/im/manager/group';
import GroupSelectDialog from './select-dialog.vue';
defineOptions({ name: 'ImManagerGroupSelect', inheritAttrs: false });
const props = withDefaults(
  defineProps<{
    allowClear?: boolean;
    disabled?: boolean;
    modelValue?: number;
    placeholder?: string;
  }>(),
  {
    allowClear: true,
    disabled: false,
    modelValue: undefined,
    placeholder: '请选择群',
  },
);
const emit = defineEmits<{
  change: [item: ImManagerGroupApi.Group | undefined];
  'update:modelValue': [value: number | undefined];
}>();
const attrs = useAttrs();
const dialogRef = ref<InstanceType<typeof GroupSelectDialog>>(); // ç¾¤é€‰æ‹©å¼¹çª—
const hovering = ref(false); // é¼ æ ‡æ˜¯å¦æ‚¬åœ
const selectedItem = ref<ImManagerGroupApi.Group>(); // å·²é€‰ç¾¤
/** è¾“入框显示文本 */
const displayLabel = computed(() => selectedItem.value?.name ?? '');
/** æ˜¯å¦æ˜¾ç¤ºæ¸…除图标 */
const showClear = computed(() => {
  return props.allowClear && !props.disabled && hovering.value && props.modelValue != null;
});
/** æ ¹æ®ç¼–号查询群信息(用于编辑回显) */
async function resolveItemById(id: number | undefined) {
  if (id == null) {
    selectedItem.value = undefined;
    return;
  }
  if (selectedItem.value?.id === id) {
    return;
  }
  selectedItem.value = await getManagerGroup(id);
}
watch(() => props.modelValue, resolveItemById, { immediate: true });
/** æ¸…空已选群 */
function clearSelected() {
  selectedItem.value = undefined;
  emit('update:modelValue', undefined);
  emit('change', undefined);
}
/** æ‰“开群选择弹窗 */
function handleClick(event: MouseEvent) {
  if (props.disabled) {
    return;
  }
  const target = event.target as HTMLElement;
  if (showClear.value && target.closest('.ant-input-suffix')) {
    event.stopPropagation();
    clearSelected();
    return;
  }
  dialogRef.value?.open(props.modelValue == null ? [] : [props.modelValue]);
}
/** å¼¹çª—选中回调 */
function handleSelected(rows: ImManagerGroupApi.Group[]) {
  const item = rows[0];
  if (!item) {
    return;
  }
  selectedItem.value = item;
  emit('update:modelValue', item.id);
  emit('change', item);
}
</script>
<template>
  <div
    v-bind="attrs"
    class="w-full"
    :class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'"
    @click="handleClick"
    @mouseenter="hovering = true"
    @mouseleave="hovering = false"
  >
    <Tooltip :mouse-enter-delay="0.5" :open="selectedItem ? undefined : false">
      <template #title>
        <div v-if="selectedItem" class="leading-6">
          <div>群名称:{{ selectedItem.name || '-' }}</div>
          <div>群主:{{ selectedItem.ownerNickname || '-' }}</div>
          <div>成员数:{{ selectedItem.memberCount ?? '-' }}</div>
        </div>
      </template>
      <Input
        :disabled="disabled"
        :placeholder="placeholder"
        :value="displayLabel"
        readonly
      >
        <template #suffix>
          <IconifyIcon
            class="size-4"
            :icon="showClear ? 'lucide:circle-x' : 'lucide:search'"
          />
        </template>
      </Input>
    </Tooltip>
  </div>
  <GroupSelectDialog ref="dialogRef" @selected="handleSelected" />
</template>