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.
205 lines
5.4 KiB
205 lines
5.4 KiB
<script lang="ts" setup>
|
|
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
import { getEXANowListReal } from '@/api/alert/exa'
|
|
|
|
const props = defineProps<{
|
|
path: string
|
|
default: ''
|
|
|
|
}>()
|
|
|
|
// const { data } = toRefs(props)
|
|
const svgContent = ref<string>('')
|
|
const svgError = ref<string>('')
|
|
const point = ref<{ itemNameArray: string[] }>({ itemNameArray: [] })
|
|
// const pointElements = ref<NodeListOf<SVGElement> | undefined>()
|
|
// 监听数据变化
|
|
watch(
|
|
() => props.path,
|
|
(newValue, oldValue) => {
|
|
// 下方信息不会打印在控制台中
|
|
console.log('a has changed', newValue)
|
|
if (newValue !== oldValue && newValue !== '' && newValue != null)
|
|
loadSvg()
|
|
},
|
|
{ immediate: true },
|
|
|
|
)
|
|
// 加载SVG文件
|
|
async function loadSvg() {
|
|
console.log('加载SVG文件...')
|
|
if (!props.path) {
|
|
svgError.value = '未提供SVG路径'
|
|
return
|
|
}
|
|
|
|
svgError.value = ''
|
|
try {
|
|
// 判断路径是否为完整URL
|
|
let url = props.path
|
|
if (!url.startsWith('http') && !url.startsWith('/')) {
|
|
// 如果是相对路径,尝试从assets加载
|
|
url = new URL(`../../../../assets/${url}`, import.meta.url).href
|
|
}
|
|
|
|
// 添加时间戳参数以清除浏览器缓存
|
|
const timestamp = new Date().getTime()
|
|
if (url.includes('?'))
|
|
url += `&t=${timestamp}`
|
|
else
|
|
url += `?t=${timestamp}`
|
|
|
|
const response = await fetch(url)
|
|
|
|
if (!response.ok)
|
|
throw new Error(`无法加载SVG: ${response.statusText}`)
|
|
|
|
svgContent.value = await response.text()
|
|
|
|
// 等待DOM更新后应用实时数据
|
|
await nextTick()
|
|
document.querySelector('.svg-container > svg')?.removeAttribute('width')
|
|
document.querySelector('.svg-container > svg')?.removeAttribute('height')
|
|
|
|
// updateRealtimeValues()
|
|
}
|
|
catch (error) {
|
|
console.error('加载SVG失败:', error)
|
|
svgError.value = `加载失败: ${error instanceof Error ? error.message : String(error)}`
|
|
}
|
|
}
|
|
|
|
// 更新SVG中的实时数据
|
|
async function updateRealtimeValues() {
|
|
if (!svgContent.value)
|
|
return
|
|
try {
|
|
const svgElement = document.querySelector('.svg-container > svg')
|
|
svgElement?.removeAttribute('width')
|
|
svgElement?.removeAttribute('height')
|
|
// 获取SVG元素
|
|
if (!svgElement)
|
|
return
|
|
|
|
// 处理拥有point-name属性的元素
|
|
const pointElements = svgElement.querySelectorAll('[point-name]')
|
|
const pointList: string[] = []
|
|
|
|
// 使用同步方式收集point-name
|
|
pointElements.forEach((element) => {
|
|
const pointName = element.getAttribute('point-name')
|
|
if (pointName)
|
|
pointList.push(pointName)
|
|
})
|
|
|
|
point.value = { itemNameArray: pointList }
|
|
const res = await getEXANowListReal(point.value)
|
|
|
|
if (res && res.ReturnValue === 1 && res.ValueArray) {
|
|
const dataValues = res.ValueArray
|
|
|
|
if (pointElements) {
|
|
pointElements.forEach((element, index) => {
|
|
// 不区分大小写比较标签名
|
|
const value = dataValues[index] || ''
|
|
|
|
// 设置文本内容,不再受标签名条件限制
|
|
element.textContent = String(value)
|
|
|
|
// 同时设置data-value属性便于调试和样式控制
|
|
element.setAttribute('data-value', String(value))
|
|
})
|
|
}
|
|
}
|
|
}
|
|
catch (error) {
|
|
console.error('更新实时数据失败:', error)
|
|
}
|
|
}
|
|
|
|
const updateInterval = ref<NodeJS.Timeout | null>(null)
|
|
|
|
onMounted(() => {
|
|
// 设置定时器并保存引用,以便在组件卸载时清除
|
|
updateInterval.value = setInterval(() => {
|
|
console.log('定时更新数据...')
|
|
updateRealtimeValues()
|
|
}, 1000)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
// 清理定时器等资源
|
|
clearInterval(updateInterval.value!)
|
|
})
|
|
|
|
// 全屏方案
|
|
function toggleFullscreen() {
|
|
const container = $refs.svgContainer
|
|
if (isFullscreen())
|
|
exitFullscreen()
|
|
else
|
|
this.requestFullscreen(container)
|
|
}
|
|
// 检查当前是否处于全屏状态
|
|
function isFullscreen() {
|
|
return document.fullscreenElement
|
|
|| document.mozFullScreenElement
|
|
|| document.webkitFullscreenElement
|
|
|| document.msFullscreenElement
|
|
}
|
|
// 打开全屏
|
|
function requestFullscreen(element) {
|
|
if (element.requestFullscreen) {
|
|
element.requestFullscreen()
|
|
}
|
|
else if (element.mozRequestFullScreen) { // Firefox
|
|
element.mozRequestFullScreen()
|
|
}
|
|
else if (element.webkitRequestFullscreen) { // Chrome, Safari and Opera
|
|
element.webkitRequestFullscreen()
|
|
}
|
|
else if (element.msRequestFullscreen) { // IE/Edge
|
|
element.msRequestFullscreen()
|
|
}
|
|
}
|
|
// 关闭全屏
|
|
function exitFullscreen() {
|
|
if (document.exitFullscreen) {
|
|
document.exitFullscreen()
|
|
}
|
|
else if (document.mozCancelFullScreen) { // Firefox
|
|
document.mozCancelFullScreen()
|
|
}
|
|
else if (document.webkitExitFullscreen) { // Chrome, Safari and Opera
|
|
document.webkitExitFullscreen()
|
|
}
|
|
else if (document.msExitFullscreen) { // IE/Edge
|
|
document.msExitFullscreen()
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<!-- <Card class="enter-y !my-1" :title="data.Header || 'SVG可视化'"> -->
|
|
<div v-if="svgError" class="h-40 flex items-center justify-center text-red-500">
|
|
{{ svgError }}
|
|
</div>
|
|
<div v-else class="svg-container" 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%;
|
|
cursor: pointer; /* 点击时可以手动触发数据更新 */
|
|
}
|
|
</style>
|
|
|