feat: 修复菜单图标bug

This commit is contained in:
2026-10-08 20:06:43 +08:00
parent 1650383670
commit 123a73e5ca
@@ -1,5 +1,10 @@
<template>
<div ref="svgContainer" class="svg-icon" :style="{ 'font-size': size + 'px' }"></div>
<span class="svg-icon" :style="{ fontSize: size + 'px', width: size + 'px', height: size + 'px' }">
<i v-if="failed" class="el-icon-picture-outline" aria-hidden="true"></i>
<i v-else-if="isFontIcon" :class="fontIconClass" aria-hidden="true"></i>
<img v-else-if="isImageUrl" :src="iconName" alt="" style="width: 100%; height: 100%; object-fit: contain" @error="failed = true" />
<span v-else ref="svgContainer" style="display: inline-flex; width: 100%; height: 100%; overflow: hidden"></span>
</span>
</template>
<script>
@@ -16,21 +21,66 @@ module.exports = {
},
data() {
return {}
return { failed: false, requestId: 0 }
},
methods: {},
created() {
if (this.name) {
fetch("/assets/platform/img/svg/" + this.name + ".svg")
.then(async (res) => {
const svg = await res.text()
if (this.$refs.svgContainer) {
this.$refs.svgContainer.innerHTML = ""
this.$refs.svgContainer.innerHTML = svg
}
})
.catch(() => {})
computed: {
iconName() {
return (this.name || "").trim()
},
isFontIcon() {
return /^(?:fa(?:s|r|b|l|d)?(?:\s|$)|fa-|el-icon-|ti-)/.test(this.iconName)
},
fontIconClass() {
return this.iconName.startsWith("fa-") ? "fa " + this.iconName : this.iconName
},
isImageUrl() {
return /^(?:https?:\/\/|\/|\.\.?\/|data:image\/)/i.test(this.iconName)
}
},
watch: {
name() {
this.loadIcon()
}
},
methods: {
async loadIcon() {
const requestId = ++this.requestId
this.failed = false
await this.$nextTick()
if (requestId !== this.requestId) return
const container = this.$refs.svgContainer
if (container) container.textContent = ""
if (!this.iconName || this.isFontIcon || this.isImageUrl) return
const fileName = this.iconName.replace(/\.svg$/i, "")
if (!/^[\w-]+$/.test(fileName)) {
this.failed = true
return
}
try {
const response = await fetch("/assets/platform/img/svg/" + encodeURIComponent(fileName) + ".svg")
if (!response.ok) throw new Error("图标请求失败")
const document = new DOMParser().parseFromString(await response.text(), "image/svg+xml")
const svg = document.documentElement
if (document.querySelector("parsererror") || svg.localName !== "svg" || svg.namespaceURI !== "http://www.w3.org/2000/svg") {
throw new Error("图标响应不是有效SVG")
}
if (requestId !== this.requestId || !this.$refs.svgContainer) return
svg.style.setProperty("width", "100%", "important")
svg.style.setProperty("height", "100%", "important")
svg.style.setProperty("max-width", "100%", "important")
svg.style.setProperty("max-height", "100%", "important")
svg.style.setProperty("fill", "currentColor")
this.$refs.svgContainer.appendChild(svg)
} catch (error) {
if (requestId === this.requestId) this.failed = true
}
}
},
mounted() {
this.loadIcon()
},
beforeDestroy() {
this.requestId++
}
}
</script>
@@ -38,8 +88,19 @@ module.exports = {
<style scoped>
.svg-icon {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
overflow: hidden;
vertical-align: middle;
line-height: 1;
font-size: 20px;
}
.svg-icon > i {
font-size: inherit;
line-height: 1;
margin: 0;
}
.svg-icon svg {
width: 1em;
height: 1em;