index.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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"></svg-icon>
  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" @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. const props = defineProps({
  31. modelValue: {
  32. type: String,
  33. require: true
  34. },
  35. width: {
  36. type: String,
  37. require: false,
  38. default: '400px'
  39. }
  40. });
  41. const emit = defineEmits(['update:modelValue']);
  42. const visible = ref(false);
  43. const { modelValue, width } = toRefs(props);
  44. const iconNames = ref<string[]>(icons);
  45. const filterValue = ref('');
  46. /**
  47. * 筛选图标
  48. */
  49. const filterIcons = () => {
  50. if (filterValue.value) {
  51. iconNames.value = icons.filter(iconName =>
  52. iconName.includes(filterValue.value)
  53. );
  54. } else {
  55. iconNames.value = icons;
  56. }
  57. }
  58. /**
  59. * 选择图标
  60. * @param iconName 选择的图标名称
  61. */
  62. const selectedIcon = (iconName: string) => {
  63. emit('update:modelValue', iconName);
  64. visible.value = false;
  65. }
  66. </script>
  67. <style scoped lang="scss">
  68. .el-divider--horizontal {
  69. margin: 10px auto !important;
  70. }
  71. .icon-list {
  72. display: flex;
  73. flex-wrap: wrap;
  74. padding-left: 10px;
  75. margin-top: 10px;
  76. .icon-item {
  77. cursor: pointer;
  78. width: 10%;
  79. margin: 0 10px 10px 0;
  80. padding: 5px;
  81. display: flex;
  82. flex-direction: column;
  83. justify-items: center;
  84. align-items: center;
  85. border: 1px solid #ccc;
  86. &:hover {
  87. border-color: var(--el-color-primary);
  88. color: var(--el-color-primary);
  89. transition: all 0.2s;
  90. transform: scaleX(1.1);
  91. }
  92. }
  93. }
  94. </style>