feat: 修复菜单图标bug
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
<template>
|
<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>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -16,21 +21,66 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return { failed: false, requestId: 0 }
|
||||||
},
|
},
|
||||||
methods: {},
|
computed: {
|
||||||
created() {
|
iconName() {
|
||||||
if (this.name) {
|
return (this.name || "").trim()
|
||||||
fetch("/assets/platform/img/svg/" + this.name + ".svg")
|
},
|
||||||
.then(async (res) => {
|
isFontIcon() {
|
||||||
const svg = await res.text()
|
return /^(?:fa(?:s|r|b|l|d)?(?:\s|$)|fa-|el-icon-|ti-)/.test(this.iconName)
|
||||||
if (this.$refs.svgContainer) {
|
},
|
||||||
this.$refs.svgContainer.innerHTML = ""
|
fontIconClass() {
|
||||||
this.$refs.svgContainer.innerHTML = svg
|
return this.iconName.startsWith("fa-") ? "fa " + this.iconName : this.iconName
|
||||||
|
},
|
||||||
|
isImageUrl() {
|
||||||
|
return /^(?:https?:\/\/|\/|\.\.?\/|data:image\/)/i.test(this.iconName)
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
.catch(() => {})
|
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>
|
</script>
|
||||||
@@ -38,8 +88,19 @@ module.exports = {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: 1;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
.svg-icon > i {
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: 1;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
.svg-icon svg {
|
.svg-icon svg {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
|
|||||||
Reference in New Issue
Block a user