feat: 更新IconSelect组件,支持未分类图标并优化图标数据处理逻辑

This commit is contained in:
chansee97 2025-06-18 17:14:57 +08:00
parent bc968dc7f7
commit 3e4e9005de

View File

@ -1,6 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import { mapEntries } from 'radash'
interface Props { interface Props {
disabled?: boolean disabled?: boolean
} }
@ -14,12 +12,13 @@ interface IconList {
icons: string[] icons: string[]
title: string title: string
total: number total: number
categories: Record<string, string[]> categories?: Record<string, string[]>
uncategorized?: string[]
} }
const value = defineModel('value', { type: String }) const value = defineModel('value', { type: String })
// // https://icon-sets.iconify.design/
const nameList = ['icon-park-outline', 'carbon'] const nameList = ['icon-park-outline', 'carbon', 'ant-design']
// //
async function fetchIconList(name: string): Promise<IconList> { async function fetchIconList(name: string): Promise<IconList> {
@ -28,47 +27,39 @@ async function fetchIconList(name: string): Promise<IconList> {
// //
async function fetchIconAllList(nameList: string[]) { async function fetchIconAllList(nameList: string[]) {
const namePromises = nameList.map(name => fetchIconList(name)) //
const targets = await Promise.all(namePromises) const targets = await Promise.all(nameList.map(fetchIconList))
return targets.map((i) => { //
i.icons = Object.entries(i.categories).reduce((prev, next) => { const iconList = targets.map((item) => {
const [_key, value] = next const icons = [
return prev.concat(value) ...(item.categories ? Object.values(item.categories).flat() : []),
}, [] as string[]) ...(item.uncategorized ? Object.values(item.uncategorized).flat() : []),
return i ]
}) return { ...item, icons }
}
// svg
function getSvgName(path: string) {
const regex = /\/([^/]+)\.svg$/
const match = path.match(regex)
if (match) {
const fileName = match[1]
return fileName
}
return path
}
//
function generateLocalIconList() {
const localSvgList = import.meta.glob('@/assets/svg-icons/*.svg', {
query: '?raw',
import: 'default',
eager: true,
}) })
return mapEntries(localSvgList, (key, value) => { //
return [getSvgName(key), value] const svgNames = Object.keys(import.meta.glob('@/assets/svg-icons/*.svg')).map(
path => path.split('/').pop()?.replace('.svg', ''),
).filter(Boolean) as string[] // undefined string[]
//
iconList.unshift({
prefix: 'local',
title: 'Local Icons',
icons: svgNames,
total: svgNames.length,
uncategorized: svgNames,
}) })
return iconList
} }
const iconList = shallowRef<IconList[]>([]) const iconList = shallowRef<IconList[]>([])
const LocalIconList = shallowRef({})
onMounted(async () => { onMounted(async () => {
iconList.value = await fetchIconAllList(nameList) iconList.value = await fetchIconAllList(nameList)
LocalIconList.value = generateLocalIconList()
}) })
// tab // tab
@ -76,17 +67,19 @@ const currentTab = shallowRef(0)
// tag // tag
const currentTag = shallowRef('') const currentTag = shallowRef('')
// tab
function handleChangeTab(index: number) {
currentTab.value = index
currentTag.value = ''
}
// //
const searchValue = ref('') const searchValue = ref('')
// //
const currentPage = shallowRef(1) const currentPage = shallowRef(1)
// tab
function handleChangeTab(index: number) {
currentTab.value = index
currentTag.value = ''
currentPage.value = 1
}
// tag // tag
function handleSelectIconTag(icon: string) { function handleSelectIconTag(icon: string) {
currentTag.value = currentTag.value === icon ? '' : icon currentTag.value = currentTag.value === icon ? '' : icon
@ -99,7 +92,7 @@ const icons = computed(() => {
return [] return []
const hasTag = !!currentTag.value const hasTag = !!currentTag.value
return hasTag return hasTag
? iconList.value[currentTab.value]?.categories[currentTag.value] || [] ? iconList.value[currentTab.value]?.categories?.[currentTag.value] || [] // 使
: iconList.value[currentTab.value].icons || [] : iconList.value[currentTab.value].icons || []
}) })
@ -150,18 +143,6 @@ function clearIcon() {
</template> </template>
<n-tabs :value="currentTab" type="line" animated placement="left" @update:value="handleChangeTab"> <n-tabs :value="currentTab" type="line" animated placement="left" @update:value="handleChangeTab">
<n-tab-pane name="local" tab="local">
<n-flex :size="2">
<n-el
v-for="(_icon, key) in LocalIconList" :key="key"
class="hover:(text-[var(--primary-color)] ring-1) ring-[var(--primary-color)] p-1 rounded flex-center"
:title="`local:${key}`"
@click="handleSelectIcon(`local:${key}`)"
>
<nova-icon :icon="`local:${key}`" :size="24" />
</n-el>
</n-flex>
</n-tab-pane>
<n-tab-pane v-for="(list, index) in iconList" :key="list.prefix" :name="index" :tab="list.title"> <n-tab-pane v-for="(list, index) in iconList" :key="list.prefix" :name="index" :tab="list.title">
<n-flex vertical> <n-flex vertical>
<n-flex size="small"> <n-flex size="small">