From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/components/Icon/src/IconSelect.vue |  239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 239 insertions(+), 0 deletions(-)

diff --git a/src/components/Icon/src/IconSelect.vue b/src/components/Icon/src/IconSelect.vue
new file mode 100644
index 0000000..76cc6d5
--- /dev/null
+++ b/src/components/Icon/src/IconSelect.vue
@@ -0,0 +1,239 @@
+<script lang="ts" setup>
+import { CSSProperties } from 'vue'
+import { cloneDeep } from 'lodash-es'
+import { IconJson } from '@/components/Icon/src/data'
+
+defineOptions({ name: 'IconSelect' })
+
+type ParameterCSSProperties = (item?: string) => CSSProperties | undefined
+
+const props = defineProps({
+  modelValue: {
+    require: false,
+    type: String
+  },
+  clearable: {
+    require: false,
+    type: Boolean
+  }
+})
+const emit = defineEmits<{ (e: 'update:modelValue', v: string) }>()
+
+const visible = ref(false)
+const inputValue = toRef(props, 'modelValue')
+const iconList = ref(IconJson)
+const icon = ref('add-location')
+const currentActiveType = ref('ep:')
+// 娣辨嫹璐濆浘鏍囨暟鎹紝鍓嶇鍋氭悳绱�
+const copyIconList = cloneDeep(iconList.value)
+
+const pageSize = ref(96)
+const currentPage = ref(1)
+
+// 鎼滅储鏉′欢
+const filterValue = ref('')
+
+const tabsList = [
+  {
+    label: 'Element Plus',
+    name: 'ep:'
+  },
+  {
+    label: 'Font Awesome 4',
+    name: 'fa:'
+  },
+  {
+    label: 'Font Awesome 5 Solid',
+    name: 'fa-solid:'
+  }
+]
+
+const pageList = computed(() => {
+  if (currentPage.value === 1) {
+    return copyIconList[currentActiveType.value]
+      ?.filter((v) => v.includes(filterValue.value))
+      .slice(currentPage.value - 1, pageSize.value)
+  } else {
+    return copyIconList[currentActiveType.value]
+      ?.filter((v) => v.includes(filterValue.value))
+      .slice(
+        pageSize.value * (currentPage.value - 1),
+        pageSize.value * (currentPage.value - 1) + pageSize.value
+      )
+  }
+})
+const iconCount = computed(() => {
+  return copyIconList[currentActiveType.value] == undefined
+    ? 0
+    : copyIconList[currentActiveType.value].length
+})
+
+const iconItemStyle = computed((): ParameterCSSProperties => {
+  return (item) => {
+    if (inputValue.value === currentActiveType.value + item) {
+      return {
+        borderColor: 'var(--el-color-primary)',
+        color: 'var(--el-color-primary)'
+      }
+    }
+  }
+})
+
+function handleClick({ props }) {
+  currentPage.value = 1
+  currentActiveType.value = props.name
+  emit('update:modelValue', currentActiveType.value + iconList.value[currentActiveType.value][0])
+  icon.value = iconList.value[currentActiveType.value][0]
+}
+
+function onChangeIcon(item) {
+  icon.value = item
+  emit('update:modelValue', currentActiveType.value + item)
+  visible.value = false
+}
+
+function onCurrentChange(page) {
+  currentPage.value = page
+}
+
+function clearIcon() {
+  icon.value = ''
+  emit('update:modelValue', '')
+  visible.value = false
+}
+
+watch(
+  () => {
+    return props.modelValue
+  },
+  () => {
+    if (props.modelValue && props.modelValue.indexOf(':') >= 0) {
+      currentActiveType.value = props.modelValue.substring(0, props.modelValue.indexOf(':') + 1)
+      icon.value = props.modelValue.substring(props.modelValue.indexOf(':') + 1)
+    }
+  }
+)
+watch(
+  () => {
+    return filterValue.value
+  },
+  () => {
+    currentPage.value = 1
+  }
+)
+</script>
+
+<template>
+  <div class="selector">
+    <ElInput v-model="inputValue" @click="visible = !visible" :clearable="props.clearable" @clear="clearIcon">
+      <template #append>
+        <ElPopover
+          :popper-options="{
+            placement: 'auto'
+          }"
+          :visible="visible"
+          :width="355"
+          popper-class="pure-popper"
+          trigger="click"
+        >
+          <template #reference>
+            <div
+              class="h-32px w-40px flex cursor-pointer items-center justify-center"
+              @click="visible = !visible"
+            >
+              <Icon :icon="currentActiveType + icon" />
+            </div>
+          </template>
+
+          <ElInput v-model="filterValue" class="p-2" clearable placeholder="鎼滅储鍥炬爣" />
+          <ElDivider border-style="dashed" />
+
+          <ElTabs v-model="currentActiveType" @tab-click="handleClick">
+            <ElTabPane
+              v-for="(pane, index) in tabsList"
+              :key="index"
+              :label="pane.label"
+              :name="pane.name"
+            >
+              <ElDivider border-style="dashed" class="tab-divider" />
+              <ElScrollbar height="220px">
+                <ul class="ml-2 flex flex-wrap">
+                  <li
+                    v-for="(item, key) in pageList"
+                    :key="key"
+                    :style="iconItemStyle(item)"
+                    :title="item"
+                    class="icon-item mr-2 mt-1 w-1/10 flex cursor-pointer items-center justify-center border border-solid p-2"
+                    @click="onChangeIcon(item)"
+                  >
+                    <Icon :icon="currentActiveType + item" />
+                  </li>
+                </ul>
+              </ElScrollbar>
+            </ElTabPane>
+          </ElTabs>
+          <ElDivider border-style="dashed" />
+
+          <ElPagination
+            :current-page="currentPage"
+            :page-size="pageSize"
+            :total="iconCount"
+            background
+            class="h-10 flex items-center justify-center"
+            layout="prev, pager, next"
+            size="small"
+            @current-change="onCurrentChange"
+          />
+        </ElPopover>
+      </template>
+    </ElInput>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.el-divider--horizontal {
+  margin: 1px auto !important;
+}
+
+.tab-divider.el-divider--horizontal {
+  margin: 0 !important;
+}
+
+.icon-item {
+  &:hover {
+    color: var(--el-color-primary);
+    border-color: var(--el-color-primary);
+    transform: scaleX(1.05);
+    transition: all 0.4s;
+  }
+}
+
+:deep(.el-tabs__nav-next) {
+  font-size: 15px;
+  line-height: 32px;
+  box-shadow: -5px 0 5px -6px #ccc;
+}
+
+:deep(.el-tabs__nav-prev) {
+  font-size: 15px;
+  line-height: 32px;
+  box-shadow: 5px 0 5px -6px #ccc;
+}
+
+:deep(.el-input-group__append) {
+  padding: 0;
+}
+
+:deep(.el-tabs__item) {
+  height: 30px;
+  font-size: 12px;
+  font-weight: normal;
+  line-height: 30px;
+}
+
+:deep(.el-tabs__header),
+:deep(.el-tabs__nav-wrap) {
+  position: static;
+  margin: 0;
+}
+</style>

--
Gitblit v1.8.0