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