mirror of
https://github.com/chansee97/nova-admin.git
synced 2025-09-05 06:35:49 +08:00
feat: 更新IconSelect组件,支持未分类图标并优化图标数据处理逻辑
This commit is contained in:
parent
bc968dc7f7
commit
3e4e9005de
@ -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">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user