index.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <template>
  2. <div class="relative" :style="{ width: width }">
  3. <el-input v-model="modelValue" readonly @click="visible = !visible" placeholder="点击选择图标">
  4. <template #prepend>
  5. <svg-icon :icon-class="modelValue as string" />
  6. </template>
  7. </el-input>
  8. <el-popover shadow="none" :visible="visible" placement="bottom-end" trigger="click" :width="450">
  9. <template #reference>
  10. <div @click="visible = !visible" class="cursor-pointer text-[#999] absolute right-[10px] top-0 height-[32px] leading-[32px]">
  11. <i-ep-caret-top v-show="visible"></i-ep-caret-top>
  12. <i-ep-caret-bottom v-show="!visible"></i-ep-caret-bottom>
  13. </div>
  14. </template>
  15. <el-input class="p-2" v-model="filterValue" placeholder="搜索图标" clearable @input="filterIcons" />
  16. <el-scrollbar height="w-[200px]">
  17. <ul class="icon-list">
  18. <el-tooltip v-for="(iconName, index) in iconNames" :key="index" :content="iconName" placement="bottom" effect="light">
  19. <li :class="['icon-item', {active: modelValue == iconName}]" @click="selectedIcon(iconName)">
  20. <svg-icon color="var(--el-text-color-regular)" :icon-class="iconName" />
  21. </li>
  22. </el-tooltip>
  23. </ul>
  24. </el-scrollbar>
  25. </el-popover>
  26. </div>
  27. </template>
  28. <script setup lang="ts">
  29. import icons from '@/components/IconSelect/requireIcons';
  30. import { propTypes } from '@/utils/propTypes';
  31. const props = defineProps({
  32. modelValue: propTypes.string.isRequired,
  33. width: propTypes.string.def('400px')
  34. });
  35. const emit = defineEmits(['update:modelValue']);
  36. const visible = ref(false);
  37. const { modelValue, width } = toRefs(props);
  38. const iconNames = ref<string[]>(icons);
  39. const filterValue = ref('');
  40. /**
  41. * 筛选图标
  42. */
  43. const filterIcons = () => {
  44. if (filterValue.value) {
  45. iconNames.value = icons.filter(iconName =>
  46. iconName.includes(filterValue.value)
  47. );
  48. } else {
  49. iconNames.value = icons;
  50. }
  51. }
  52. /**
  53. * 选择图标
  54. * @param iconName 选择的图标名称
  55. */
  56. const selectedIcon = (iconName: string) => {
  57. emit('update:modelValue', iconName);
  58. visible.value = false;
  59. }
  60. </script>
  61. <style scoped lang="scss">
  62. .el-scrollbar {
  63. max-height: calc(50vh - 100px)!important;
  64. overflow-y: auto;
  65. }
  66. .el-divider--horizontal {
  67. margin: 10px auto !important;
  68. }
  69. .icon-list {
  70. display: flex;
  71. flex-wrap: wrap;
  72. padding-left: 10px;
  73. margin-top: 10px;
  74. .icon-item {
  75. cursor: pointer;
  76. width: 10%;
  77. margin: 0 10px 10px 0;
  78. padding: 5px;
  79. display: flex;
  80. flex-direction: column;
  81. justify-items: center;
  82. align-items: center;
  83. border: 1px solid #ccc;
  84. &:hover {
  85. border-color: var(--el-color-primary);
  86. color: var(--el-color-primary);
  87. transition: all 0.2s;
  88. transform: scaleX(1.1);
  89. }
  90. }
  91. .active {
  92. border-color: var(--el-color-primary);
  93. color: var(--el-color-primary);
  94. }
  95. }
  96. </style>