You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
3.9 KiB

<script lang="ts" setup>
import { nextTick, onMounted, onUnmounted, ref, toRefs, watch } from 'vue'
import { getEXANowListReal } from '@/api/alert/exa'
const props = defineProps<{
data: string
}>()
const { data } = toRefs(props)
const svgContent = ref<string>('')
const isLoading = ref<boolean>(true)
const svgError = ref<string>('')
const point = ref<{ itemNameArray: string[] }>({ itemNameArray: [] })
const pointElements = ref<NodeListOf<SVGElement> | undefined>()
let updateInterval: number | undefined
// 加载SVG文件
async function loadSvg() {
if (!data.value) {
svgError.value = '未提供SVG路径'
isLoading.value = false
return
}
isLoading.value = true
svgError.value = ''
// 判断路径是否为完整URL
let url = data.value
if (!url.startsWith('http') && !url.startsWith('/')) {
// 如果是相对路径,尝试从assets加载
url = new URL(`../../../../assets/${url}`, import.meta.url).href
}
const response = await fetch(url)
if (!response.ok)
throw new Error(`无法加载SVG: ${response.statusText}`)
svgContent.value = await response.text()
const svgElement = document.querySelector('.svg-container > svg')
svgElement?.removeAttribute('width')
svgElement?.removeAttribute('height')
try {
// 获取SVG元素
const svgElement = document.querySelector('.svg-container > svg')
if (!svgElement)
return
// 处理拥有point-name属性的元素
pointElements.value = svgElement.querySelectorAll('[point-name]')
const pointList: string[] = []
pointElements.value.forEach(async (element) => {
const pointName = element.getAttribute('point-name')
pointName && pointList.push(pointName)
})
point.value = { itemNameArray: pointList }
// 等待DOM更新后应用实时数据
await nextTick()
// updateRealtimeValues()
}
catch (error) {
console.error('加载SVG失败:', error)
svgError.value = `加载失败: ${error instanceof Error ? error.message : String(error)}`
}
finally {
isLoading.value = false
}
}
// 更新SVG中的实时数据
async function updateRealtimeValues() {
if (!svgContent.value || isLoading.value)
return
try {
const res = await getEXANowListReal(point.value)
if (res.ReturnValue && res.ReturnValue === 1) {
const data = res.ValueArray
console.log(data)
if (pointElements.value) {
pointElements.value.forEach((element, index) => {
console.log(element)
console.log(element.tagName)
// 根据元素类型设置不同的属性
if (element.tagName === 'text' || element.tagName === 'tspan' || element.tagName === 'DIV')
console.log(element.tagName)
element.textContent = String(data[index] || '')
})
}
}
}
catch (error) {
console.error('更新实时数据失败:', error)
}
}
// 监听数据变化
watch(
() => data.value,
() => {
loadSvg()
},
{ immediate: true },
)
onMounted(() => {
loadSvg()
// updateRealtimeValues()
setInterval(() => {
updateRealtimeValues()
}, 3000) // 每2秒更新一次实时数据
})
onUnmounted(() => {
// 清理定时器等资源
clearInterval(updateInterval)
})
</script>
<template>
<!-- <Card class="enter-y !my-1" :title="data.Header || 'SVG可视化'"> -->
<div v-if="isLoading" class="h-40 flex items-center justify-center">
加载中...
</div>
<div v-else-if="svgError" class="h-40 flex items-center justify-center text-red-500">
{{ svgError }}
</div>
<div v-else class="svg-container" @click="updateRealtimeValues" v-html="svgContent" />
<!-- </Card> -->
</template>
<style scoped>
::v-deep .ant-card-body {
padding: 10px;
overflow: auto;
}
.svg-container {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
min-height: 300px;
cursor: pointer; /* 点击时可以手动触发数据更新 */
}
.svg-container > svg {
max-width: 100%;
max-height: 100%;
}
</style>