feat: 修复菜单图标bug
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user