|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 432 KiB |
|
After Width: | Height: | Size: 247 KiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 325 KiB |
|
After Width: | Height: | Size: 325 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 467 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 432 KiB |
|
After Width: | Height: | Size: 467 KiB |
@ -0,0 +1,49 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { ref, watch } from 'vue' |
||||
|
import { Card } from 'ant-design-vue' |
||||
|
import ExpandAltOutlined from '@ant-design/icons-vue/ExpandAltOutlined' |
||||
|
import Svg from './svg.vue' |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
data: { |
||||
|
type: Object, |
||||
|
default: () => {}, |
||||
|
}, |
||||
|
}) |
||||
|
const path = ref<string>('') |
||||
|
|
||||
|
watch( |
||||
|
() => props.data, |
||||
|
(newValue, oldValue) => { |
||||
|
// 下方信息不会打印在控制台中 |
||||
|
console.log('a has changed', newValue, oldValue) |
||||
|
path.value = newValue.path |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
const svgRef: any = ref(null) |
||||
|
|
||||
|
function fullScreen() { |
||||
|
// 检查子组件实例是否已经挂载 |
||||
|
if (svgRef.value) { |
||||
|
// 通过 .value 访问子组件实例,并调用其暴露的方法 |
||||
|
svgRef.value.toggleFullscreen() |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<Card class="enter-y !my-1" :title="props.data.Header"> |
||||
|
<template #extra> |
||||
|
<ExpandAltOutlined style="cursor:pointer" @click="fullScreen" /> |
||||
|
</template> |
||||
|
<Svg ref="svgRef" :path="path" /> |
||||
|
</Card> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
::v-deep .ant-card-body { |
||||
|
padding: 5px; |
||||
|
height:calc(46vh - 60px); |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,205 @@ |
|||||
|
<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> |
||||
@ -0,0 +1,287 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue' |
||||
|
import { getEXANowListReal } from '@/api/alert/exa' |
||||
|
|
||||
|
const props = defineProps<{ |
||||
|
path: string |
||||
|
}>() |
||||
|
|
||||
|
// 定义SVG容器的引用 |
||||
|
const svgContainer = ref<HTMLElement>() |
||||
|
|
||||
|
// 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')?.setAttribute('width', '100%') |
||||
|
document.querySelector('.svg-container > svg')?.setAttribute('height', '100%') |
||||
|
document.querySelector('.svg-container > svg')?.setAttribute('preserveAspectRatio', 'none') |
||||
|
// 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?.setAttribute('width', '100%') |
||||
|
svgElement?.setAttribute('height', '100%') |
||||
|
svgElement?.setAttribute('preserveAspectRatio', 'none') |
||||
|
|
||||
|
// 获取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 = svgContainer.value |
||||
|
if (!container) |
||||
|
return |
||||
|
|
||||
|
if (isFullscreen()) |
||||
|
exitFullscreen() |
||||
|
else |
||||
|
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() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 2. 使用 defineExpose 将 greet 方法暴露给父组件 |
||||
|
defineExpose({ |
||||
|
toggleFullscreen, |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<div class="svg-wrapper"> |
||||
|
<!-- 控制栏 |
||||
|
<div class="svg-controls"> |
||||
|
<h3 class="svg-title"> |
||||
|
SVG可视化 |
||||
|
</h3> |
||||
|
<button class="fullscreen-btn" title="切换全屏" @click="toggleFullscreen"> |
||||
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"> |
||||
|
<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" /> |
||||
|
</svg> |
||||
|
</button> |
||||
|
</div> --> |
||||
|
|
||||
|
<!-- SVG内容 --> |
||||
|
<div v-if="svgError" class="h-40 flex items-center justify-center text-red-500"> |
||||
|
{{ svgError }} |
||||
|
</div> |
||||
|
<div v-else ref="svgContainer" class="svg-container" v-html="svgContent" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
.svg-wrapper { |
||||
|
width:100%; |
||||
|
height:100%; |
||||
|
border: 1px solid #e8e8e8; |
||||
|
border-radius: 6px; |
||||
|
/* overflow: auto; */ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/* .svg-controls { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 10px 16px; |
||||
|
background-color: #f5f5f5; |
||||
|
border-bottom: 1px solid #e8e8e8; |
||||
|
} |
||||
|
|
||||
|
.svg-title { |
||||
|
margin: 0; |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
} */ |
||||
|
|
||||
|
.svg-container { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
width: 100%; |
||||
|
height:100%; |
||||
|
min-height: 300px; |
||||
|
overflow: auto; |
||||
|
} |
||||
|
|
||||
|
/* 全屏状态样式 */ |
||||
|
:global(.svg-wrapper:fullscreen), |
||||
|
:global(.svg-wrapper:-webkit-full-screen), |
||||
|
:global(.svg-wrapper:-moz-full-screen), |
||||
|
:global(.svg-wrapper:-ms-fullscreen) { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
border: none; |
||||
|
border-radius: 0; |
||||
|
} |
||||
|
|
||||
|
:global(.svg-wrapper:fullscreen) .svg-container, |
||||
|
:global(.svg-wrapper:-webkit-full-screen) .svg-container, |
||||
|
:global(.svg-wrapper:-moz-full-screen) .svg-container, |
||||
|
:global(.svg-wrapper:-ms-fullscreen) .svg-container { |
||||
|
flex: 1; |
||||
|
padding: 20px; |
||||
|
width:100%; |
||||
|
height:100%; |
||||
|
} |
||||
|
|
||||
|
/* SVG内容自适应 */ |
||||
|
.svg-container { |
||||
|
/* max-width: 100%; |
||||
|
max-height: 100%; */ |
||||
|
height:100%; |
||||
|
width:100% |
||||
|
|
||||
|
} |
||||
|
|
||||
|
svg { |
||||
|
height:98%; |
||||
|
width:100%; |
||||
|
} |
||||
|
</style> |
||||
@ -1,68 +0,0 @@ |
|||||
<script lang="ts" setup> |
|
||||
import { onMounted, ref } from 'vue' |
|
||||
import WorkbenchHeader from './components/WorkbenchHeader.vue' |
|
||||
import ProjectCard from './components/ProjectCard.vue' |
|
||||
import DynamicInfo from './components/DynamicInfo.vue' |
|
||||
import StaticImg from './components/staticImg.vue' |
|
||||
import ParameterInfo from './components/ParameterInfo.vue' |
|
||||
import Operation from './components/Operation.vue' |
|
||||
import data from './components/demo.json' |
|
||||
import { PageWrapper } from '@/components/Page' |
|
||||
|
|
||||
const loading = ref(true) |
|
||||
|
|
||||
onMounted(() => { |
|
||||
const htmlRoot = document.getElementsByClassName('workbench') |
|
||||
// let theme = window.localStorage.getItem('__APP__DARK__MODE__') |
|
||||
const theme = 'dark' |
|
||||
|
|
||||
if (htmlRoot && theme) { |
|
||||
for (let i = 0; i < htmlRoot.length; i++) |
|
||||
htmlRoot[i].setAttribute('data-theme', theme) |
|
||||
} |
|
||||
// theme = htmlRoot = null |
|
||||
}) |
|
||||
|
|
||||
setTimeout(() => { |
|
||||
loading.value = false |
|
||||
}, 500) |
|
||||
</script> |
|
||||
|
|
||||
<template> |
|
||||
<div class="workbench m-1" data-theme="light"> |
|
||||
<WorkbenchHeader class="workbench m-1" data-theme="light" :data="data" /> |
|
||||
<div class="enter-y workbench h-92 md:flex" data-theme="light"> |
|
||||
<StaticImg data-theme="light" class="workbench m-1 w-full md:w-1/4" :loading="loading" :data="data.LeftUp" /> |
|
||||
<ProjectCard data-theme="light" class="enter-y workbench m-1 w-full md:w-1/2" :loading="loading" :data="data.LeftMidUp" /> |
|
||||
<div class="enter-y w-full !mr-4 md:w-1/4"> |
|
||||
<DynamicInfo :loading="loading" data-theme="light" class="workbench enter-y m-1 h-35 w-full" :data="data.RightMidUp" /> |
|
||||
<Operation data-theme="light" class="workbench enter-y m-1 h-54 w-full" :loading="loading" :data="data.RightUp" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="enter-y workbench h-95 md:flex" data-theme="light"> |
|
||||
<StaticImg data-theme="light" class="workbench m-1 w-full md:w-1/2" :loading="loading" :data="data.LeftDown" /> |
|
||||
<ParameterInfo data-theme="light" class="workbench m-1 w-full md:w-1/2" :loading="loading" :data="data.RightDown" /> |
|
||||
</div> |
|
||||
<!-- <div class="enter-y w-full !mr-4 lg:w-7/10"> |
|
||||
<StaticImg :loading="loading" :data="data.LeftUp" class="enter-y" /> |
|
||||
</div> --> |
|
||||
|
|
||||
<!-- <div class="enter-y w-full !mr-4 lg:w-7/10"> |
|
||||
<ProjectCard :loading="loading" class="enter-y" /> |
|
||||
<DynamicInfo :loading="loading" class="enter-y !my-4" /> |
|
||||
</div> |
|
||||
<div class="enter-y w-full lg:w-3/10"> |
|
||||
<QuickNav :loading="loading" class="enter-y" /> |
|
||||
|
|
||||
<Card class="enter-y !my-4" :loading="loading"> |
|
||||
<img class="mx-auto h-30 xl:h-50" src="@/assets/svg/illustration.svg"> |
|
||||
</Card> |
|
||||
|
|
||||
<SaleRadar :loading="loading" class="enter-y" /> |
|
||||
</div> --> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<style lang="less"> |
|
||||
|
|
||||
</style> |
|
||||