86 lines
2.3 KiB
Vue
86 lines
2.3 KiB
Vue
<template>
|
|
<text class="fa-icon" :class="fontClass" :style="iconStyle">{{ iconChar }}</text>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
import { FA_ICONS } from '@/utils/fa-icons.js'
|
|
|
|
const props = defineProps({
|
|
name: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
type: {
|
|
type: String,
|
|
default: 'solid'
|
|
},
|
|
color: {
|
|
type: String,
|
|
default: 'inherit'
|
|
},
|
|
size: {
|
|
type: [Number, String],
|
|
default: 16
|
|
}
|
|
})
|
|
|
|
// 菜单图标在数据库里常以完整 Font Awesome 类名字符串存储(如 "fas fa-dashboard"、
|
|
// "fa-brands fa-cash-app"、"far fa-trash-can"),而 FA_ICONS 的键是去前缀的裸名字。
|
|
// 这里统一归一化:解析出裸图标名与字重(solid/regular/brands),
|
|
// 使同一份图标数据在移动端也能正确渲染;已是裸名字(如 "chevron-left")时原样返回。
|
|
const parsed = computed(() => {
|
|
const raw = String(props.name || '').trim()
|
|
if (!raw) return { name: '', brands: false }
|
|
// 完整类名:按空白拆 token,取以 fa- 开头且非样式字重(fa-solid/regular/brands)的最后一段
|
|
if (/\bfa-(solid|regular|light|thin|duotone|brands)\b|\bfas\b|\bfar\b|\bfal\b|\bfab\b/.test(raw)) {
|
|
const tokens = raw.split(/\s+/)
|
|
let brands = false
|
|
let icon = ''
|
|
for (const t of tokens) {
|
|
if (/^(fa-brands|fab)$/.test(t)) brands = true
|
|
else if (/^(fa-solid|fas|fa-regular|far|fa-light|fal|fa-thin|fa-duotone)$/.test(t)) continue
|
|
else if (t.startsWith('fa-')) icon = t.slice(3)
|
|
else if (t && t !== 'fa') icon = t
|
|
}
|
|
return { name: icon, brands }
|
|
}
|
|
// 裸名字:可能仍带一个 fa- 前缀,去掉后查表
|
|
return { name: raw.replace(/^fa-/, ''), brands: props.type === 'brands' }
|
|
})
|
|
|
|
const iconChar = computed(() => FA_ICONS[parsed.value.name] || '')
|
|
|
|
const fontClass = computed(() =>
|
|
parsed.value.brands ? 'fa-font-brands' : 'fa-font-solid'
|
|
)
|
|
|
|
const iconStyle = computed(() => ({
|
|
color: props.color,
|
|
fontSize: typeof props.size === 'number' ? `${props.size}px` : props.size,
|
|
lineHeight: 1
|
|
}))
|
|
</script>
|
|
|
|
<style scoped>
|
|
.fa-icon {
|
|
display: inline-block;
|
|
font-style: normal;
|
|
vertical-align: middle;
|
|
}
|
|
</style>
|
|
|
|
<style>
|
|
.fa-font-solid {
|
|
font-family: 'Font Awesome 7 Free';
|
|
font-weight: 900;
|
|
font-style: normal;
|
|
}
|
|
|
|
.fa-font-brands {
|
|
font-family: 'Font Awesome 7 Brands';
|
|
font-weight: 400;
|
|
font-style: normal;
|
|
}
|
|
</style>
|