Files
smart_storage_web/src/views/dashboardtest/components/top-center/pv8FourthDiesel.vue

1602 lines
50 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<ItemBox :title="$t('dashboard.stationTopo')" style="min-height: 560px;">
<div ref="svgLine" class="center-box">
<div v-loading="loading">
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:space="preserve"
class="circle-load-rect-svg"
viewBox="0 0 800 570"
>
<defs>
<defs>
<radialGradient id="RadialGradient1">
<stop offset="0%" stop-color="#fff" />
<stop offset="30%" stop-color="#0171c1" />
<stop offset="50%" stop-color="#035088" />
<stop offset="100%" stop-color="#02395a" />
</radialGradient>
</defs>
<marker
id="markerCircle"
markerWidth="15"
markerHeight="15"
refX="5"
refY="5"
>
<circle
cx="5"
cy="5"
r="5"
style="stroke: none; fill: url(#RadialGradient1)"
/>
</marker>
<marker
id="markerArrow"
markerWidth="13"
markerHeight="13"
refX="2"
refY="6"
orient="auto"
>
<path d="M2,2 L2,11 L10,6 L2,2" style="fill: black" />
</marker>
</defs>
<!-- //线条 -->
<!-- top -->
<polyline
points="120,50 650,50"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<!-- center -->
<polyline
points="405,50 405,330"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="370,50 370,330"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="210,50 210,150"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="610,50 610,150"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="120,150 310,150"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="525,150 700,150"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<!-- <rect
x="383"
y="80"
width="4"
height="281"
:style="{ fill: 'rgba(100,100,100,0)', stroke: 'transparent',cursor: 'pointer' }"
@click="lookDeviceDetail('line-bottom-center')"
/> -->
<!-- <polyline
points="385,100 460,100"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/> -->
<!-- bottom -->
<polyline
points="210,330 370,330"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="210,330 210,400"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="405,330 610,330"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="610,330 610,400"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="120,400 310,400"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="525,400 700,400"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="120,150 120,220"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="210,150 210,220"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="310,150 310,220"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="525,150 525,220"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="610,150 610,220"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="700,150 700,220"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="120,400 120,470"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="210,400 210,470"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="310,400 310,465"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="525,400 525,470"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="610,400 610,470"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<polyline
points="700,400 700,465"
fill="none"
class="g-rect-path"
stroke="#0094FF"
stroke-dasharray="3 3"
/>
<!-- <rect
x="383"
y="361"
width="272"
height="4"
:style="{ fill: 'rgba(100,100,100,0)', stroke: 'transparent',cursor: 'pointer' }"
@click="lookDeviceDetail('line-bottom-right')"
/> -->
<!-- top -->
<circle
cx="120"
cy="50"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="650"
cy="50"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<!-- 动点 -->
<circle
cx="120"
cy="50"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="0s"
:path="dotData.lineTopLeft"
/>
</circle>
<!-- <circle
cx="385"
cy="400"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineCenter"
/>
</circle> -->
<circle
cx="650"
cy="50"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="0s"
:path="dotData.lineTopRight"
/>
</circle>
<!-- center -->
<!-- 1PV-动画点 -->
<circle
cx="120"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="120"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 2PV-动画点 -->
<circle
cx="210"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="210"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 1-动画点 -->
<circle
cx="310"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="310"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 3PV-动画点 -->
<circle
cx="525"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="525"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 4PV-动画点 -->
<circle
cx="610"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="610"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 2-动画点 -->
<circle
cx="700"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="700"
cy="215"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomRight"
/>
</circle>
<!-- bottom -->
<!-- 5PV-动画点 -->
<circle
cx="120"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="120"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 6PV-动画点 -->
<circle
cx="210"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="210"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 3-动画点 -->
<circle
cx="310"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="310"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 7PV-动画点 -->
<circle
cx="525"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="525"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 8PV-动画点 -->
<circle
cx="610"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="610"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomLeft"
/>
</circle>
<!-- 4-动画点 -->
<circle
cx="700"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/>
<circle
cx="700"
cy="465"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
>
<animateMotion
repeatCount="indefinite"
dur="4s"
begin="2s"
:path="dotData.lineBottomRight"
/>
</circle>
<!-- <circle
cx="385"
cy="400"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/> -->
<!-- <circle
cx="603"
cy="417"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/> -->
<!-- <circle
cx="385"
cy="400"
r="8"
style="stroke: none; fill: url(#RadialGradient1)"
/> -->
<!-- 图片和文字 -->
<!-- 市电 -->
<image
:xlink:href="configData.grid"
x="50"
y="20"
width="50"
height="60"
/>
<image
:xlink:href="configData.house"
x="670"
y="20"
width="40"
height="60"
/>
<!-- pcs1 -->
<image
:xlink:href="configData.pcs2"
x="190"
y="75"
width="40"
height="60"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pcs-1')"
/>
<!-- pcs2 -->
<image
:xlink:href="configData.pcs2"
x="590"
y="75"
width="40"
height="60"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pcs-2')"
/>
<!-- pcs3 -->
<image
:xlink:href="configData.pcs2"
x="190"
y="330"
width="40"
height="60"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pcs-3')"
/>
<!-- pcs4 -->
<image
:xlink:href="configData.pcs2"
x="590"
y="330"
width="40"
height="60"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pcs-4')"
/>
<!-- 1PV -->
<image
:xlink:href="frameImg"
x="100"
y="225"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pv-1')"
/>
<!-- DCDC -->
<image
:xlink:href="DCImg"
x="105"
y="165"
width="28"
height="28"
/>
<!-- 2PV -->
<image
:xlink:href="frameImg"
x="190"
y="225"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pv-2')"
/>
<!-- DCDC -->
<image
:xlink:href="DCImg"
x="195"
y="165"
width="28"
height="28"
/>
<!-- 1 -->
<image
:xlink:href="cabinetImg"
x="290"
y="225"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-bms-1')"
/>
<!-- 3PV -->
<image
:xlink:href="frameImg"
x="510"
y="225"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pv-3')"
/>
<!-- 3DCDC -->
<image
:xlink:href="DCImg"
x="510"
y="165"
width="28"
height="28"
/>
<!-- 4PV -->
<image
:xlink:href="frameImg"
x="595"
y="225"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pv-4')"
/>
<!-- 4DCDC -->
<image
:xlink:href="DCImg"
x="595"
y="165"
width="28"
height="28"
/>
<!-- 2 -->
<image
:xlink:href="cabinetImg"
x="680"
y="225"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-bms-2')"
/>
<!-- 5PV -->
<image
:xlink:href="frameImg"
x="100"
y="475"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pv-5')"
/>
<!-- 5DCDC -->
<image
:xlink:href="DCImg"
x="105"
y="415"
width="28"
height="28"
/>
<!-- 6PV -->
<image
:xlink:href="frameImg"
x="190"
y="475"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pv-6')"
/>
<!-- 6DCDC -->
<image
:xlink:href="DCImg"
x="195"
y="415"
width="28"
height="28"
/>
<!-- 3 -->
<image
:xlink:href="cabinetImg"
x="290"
y="475"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-bms-3')"
/>
<!-- 7PV -->
<image
:xlink:href="frameImg"
x="505"
y="475"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pv-7')"
/>
<!-- 7DCDC -->
<image
:xlink:href="DCImg"
x="510"
y="415"
width="28"
height="28"
/>
<!-- 8PV -->
<image
:xlink:href="frameImg"
x="595"
y="475"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-pv-8')"
/>
<!-- 8DCDC -->
<image
:xlink:href="DCImg"
x="595"
y="415"
width="28"
height="28"
/>
<!-- 4 -->
<image
:xlink:href="cabinetImg"
x="680"
y="475"
width="40"
height="40"
style="cursor: pointer;"
@click="lookDeviceDetail('triad-bms-4')"
/>
<!-- ACDC -->
<g v-for="(item,index) in acdcCenterData" :key="item.id">
<text x="415" :y="160 + ( 20 * index)" fill="#ffffff" font-size="14">
{{ item.name }}
</text>
<text :x="countChineseAndEnglishCharacters(item.name,lang === 'zh_CN'?415:360)" :y="160 + ( 20 * index)" fill="#FFB800" font-size="14">
{{ item.value }}
</text>
</g>
<!-- 左侧 -->
<foreignObject
:x="10"
:y="275"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="$t('dashboard.dcPwoer')"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="cursor: default;font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText($t('dashboard.dcPwoer'), 100) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<foreignObject
:x="10"
:y="295"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="$t('dashboard.dischargeCapacity')"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="cursor: default;font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText($t('dashboard.dischargeCapacity'), 85) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<foreignObject
:x="420"
:y="275"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="$t('dashboard.dcPwoer')"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="cursor: default;font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText($t('dashboard.dcPwoer'), 100) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<foreignObject
:x="420"
:y="295"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="$t('dashboard.dischargeCapacity')"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="cursor: default;font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText($t('dashboard.dischargeCapacity'), 85) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<foreignObject
:x="10"
:y="525"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="$t('dashboard.dcPwoer')"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="cursor: default;font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText($t('dashboard.dcPwoer'), 100) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<foreignObject
:x="10"
:y="545"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="$t('dashboard.dischargeCapacity')"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="cursor: default;font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText($t('dashboard.dischargeCapacity'), 85) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<foreignObject
:x="420"
:y="525"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="$t('dashboard.dcPwoer')"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="cursor: default;font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText($t('dashboard.dcPwoer'), 100) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<foreignObject
:x="420"
:y="545"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="$t('dashboard.dischargeCapacity')"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="cursor: default;font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText($t('dashboard.dischargeCapacity'), 85) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<!-- 1PV -->
<text x="100" y="290" fill="#FFB800" font-size="14">{{ pvData.pv1.length ? pvData.pv1[0].value : '' }}</text>
<text x="100" y="310" fill="#FFB800" font-size="14">{{ pvData.pv1.length > 1 ? pvData.pv1[1].value : '' }}</text>
<!-- 2PV -->
<text x="190" y="290" fill="#FFB800" font-size="14">{{ pvData.pv2.length ? pvData.pv2[0].value : '' }}</text>
<text x="185" y="310" fill="#FFB800" font-size="14">{{ pvData.pv2.length > 1 ? pvData.pv2[1].value : '' }}</text>
<!-- 1BMS -->
<g v-for="(item,index) in bmsData.bms1" :key="item.id">
<text x="250" :y="290 + ( 20 * index)" fill="#ffffff" font-size="14">{{ item.name }}</text>
<text :x="calculateValueX(item.name,250)" :y="290 + ( 20 * index)" fill="#FFB800" font-size="14">{{ item.value }}</text>
</g>
<!-- 3PV -->
<text x="510" y="290" fill="#FFB800" font-size="14">{{ pvData.pv3.length ? pvData.pv3[0].value : '' }}</text>
<text x="510" y="310" fill="#FFB800" font-size="14">{{ pvData.pv3.length > 1 ? pvData.pv3[1].value : '' }}</text>
<!-- 4PV -->
<text x="595" y="290" fill="#FFB800" font-size="14">{{ pvData.pv4.length ? pvData.pv4[0].value : '' }}</text>
<text x="595" y="310" fill="#FFB800" font-size="14">{{ pvData.pv4.length > 1 ? pvData.pv4[1].value : '' }}</text>
<!-- 2BMS -->
<g v-for="(item,index) in bmsData.bms2" :key="item.id">
<text x="665" :y="290 + ( 20 * index)" fill="#ffffff" font-size="14">
{{ item.name }}
</text>
<text :x="calculateValueX(item.name,665)" :y="290 + ( 20 * index)" fill="#FFB800" font-size="14">
{{ item.value }}
</text>
</g>
<!-- 5PV -->
<text x="100" y="540" fill="#FFB800" font-size="14">{{ pvData.pv5.length ? pvData.pv5[0].value : '' }}</text>
<text x="100" y="560" fill="#FFB800" font-size="14">{{ pvData.pv5.length > 1 ? pvData.pv5[1].value : '' }}</text>
<!-- 6PV -->
<text x="190" y="540" fill="#FFB800" font-size="14">{{ pvData.pv6.length ? pvData.pv6[0].value : '' }}</text>
<text x="185" y="560" fill="#FFB800" font-size="14">{{ pvData.pv6.length > 1 ? pvData.pv6[1].value : '' }}</text>
<!-- 3BMS -->
<g v-for="(item,index) in bmsData.bms3" :key="item.id">
<text x="265" :y="540 + ( 20 * index)" fill="#ffffff" font-size="14">
{{ item.name }}
</text>
<text :x="calculateValueX(item.name,265)" :y="540 + ( 20 * index)" fill="#FFB800" font-size="14">
{{ item.value }}
</text>
</g>
<!-- 7PV -->
<text x="505" y="540" fill="#FFB800" font-size="14">{{ pvData.pv7.length ? pvData.pv7[0].value : '' }}</text>
<text x="505" y="560" fill="#FFB800" font-size="14">{{ pvData.pv7.length > 1 ? pvData.pv7[1].value : '' }}</text>
<!-- 8PV -->
<text x="595" y="540" fill="#FFB800" font-size="14">{{ pvData.pv8.length ? pvData.pv8[0].value : '' }}</text>
<text x="595" y="560" fill="#FFB800" font-size="14">{{ pvData.pv8.length > 1 ? pvData.pv8[1].value : '' }}</text>
<!-- 4BMS -->
<g v-for="(item,index) in bmsData.bms4" :key="item.id">
<text x="665" :y="540 + ( 20 * index)" fill="#ffffff" font-size="14">
{{ item.name }}
</text>
<text :x="calculateValueX(item.name,665)" :y="540 + ( 20 * index)" fill="#FFB800" font-size="14">
{{ item.value }}
</text>
</g>
<!-- 1PCS -->
<g v-for="(item,index) in pcsData.pcs1" :key="item.id">
<foreignObject
:x="40"
:y="105 + (20 * index) - 14"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="item.name"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText(item.name, 90) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<text :x="calculateValueX(item.name,40)" :y="105 + ( 20 * index)" fill="#FFB800" font-size="14">
{{ item.value }}
</text>
</g>
<!-- 2PCS -->
<g v-for="(item,index) in pcsData.pcs2" :key="item.id">
<foreignObject
:x="430"
:y="105 + (20 * index) - 14"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="item.name"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText(item.name, 90) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<text :x="calculateValueX(item.name,430)" :y="105 + ( 20 * index)" fill="#FFB800" font-size="14">
{{ item.value }}
</text>
</g>
<!-- 3PCS -->
<g v-for="(item,index) in pcsData.pcs3" :key="item.id">
<foreignObject
:x="40"
:y="355 + (20 * index) - 14"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="item.name"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText(item.name, 90) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<text :x="calculateValueX(item.name,40)" :y="355 + ( 20 * index)" fill="#FFB800" font-size="14">
{{ item.value }}
</text>
</g>
<!-- 4PCS -->
<g v-for="(item,index) in pcsData.pcs4" :key="item.id">
<foreignObject
:x="430"
:y="355 + (20 * index) - 14"
width="150"
height="20"
style="overflow: visible;"
>
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: center;">
<el-tooltip
:content="item.name"
placement="top"
:open-delay="400"
effect="dark"
popper-class="svg-tooltip"
>
<span style="font-size: 14px;font-family: sans-serif;color: #ffffff;max-width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis">
{{ truncateText(item.name, 90) }}
</span>
</el-tooltip>
</div>
</foreignObject>
<text :x="calculateValueX(item.name,430)" :y="355 + ( 20 * index)" fill="#FFB800" font-size="14">
{{ item.value }}
</text>
</g>
</svg>
</div>
</div>
<DispositionPointData
:disposition-show="show_point_dispostion"
:max="4"
:page-location="pageLocation"
@close="closePoint"
@getData="getDynamicPointData"
/>
</ItemBox>
</template>
<script>
import gridImg from '@/assets/images/wxjd/grid.png'
import ammeterImg from '@/assets/images/wxjd/ammeter.png'
import cabinetImg from '@/assets/images/wxjd/cabinet.png'
import chargingPileImg from '@/assets/images/home-office.png'
import distributionCabinetImg from '@/assets/images/wxjd/guiImg.png'
import frameImg from '@/assets/images/wxjd/frame.png'
import cangImg from '@/assets/images/home-cang.png'
import { DynamicConfigPoint } from '@/api/home-page/index'
import config from './config'
import { changeTheme } from '@/utils/index'
import DCImg from '@/assets/images/wxjd/DC.png'
import DynamoImg from '@/assets/images/wxjd/cyfdj.png'
export default {
name: 'Index',
props: {
stationType: {
type: Number,
default: 0
},
stationId: {
type: Number,
default: 0
}
},
data() {
return {
gridImg,
ammeterImg,
cabinetImg,
chargingPileImg,
distributionCabinetImg,
cangImg,
frameImg,
DCImg,
DynamoImg,
dotData: {
lineTop: 'M 0,0 0,0',
lineTopLeft: 'M 0,0 0,0',
lineBottomLeft: 'M 0,0 0,0 0,0',
lineBottomRight: 'M 0,0 0,0 0,0',
lineBottomLeftTwo: 'M 0,0 0,0 0,0',
lineBottomRightTwo: 'M 0,0 0,0 0,0'
},
partList: [
{ soc: 0, soh: 0, activePowerPCS: 0.0, reactivePowerPCS: 0.0 },
{ soc: 0, soh: 0, activePowerPCS: 0.0, reactivePowerPCS: 0.0 },
{ soc: 0, soh: 0, activePowerPCS: 0.0, reactivePowerPCS: 0.0 },
{ soc: 0, soh: 0, activePowerPCS: 0.0, reactivePowerPCS: 0.0 }
],
loading: false,
activePowerTotal: {},
show_point_dispostion: false,
pageLocation: '',
permissionId: null,
pvData: {
pv1: [],
pv2: [],
pv3: [],
pv4: [],
pv5: [],
pv6: [],
pv7: [],
pv8: []
},
bmsData: {
bms1: [],
bms2: [],
bms3: [],
bms4: []
},
pcsData: {
pcs1: [],
pcs2: [],
pcs3: [],
pcs4: []
},
pcsCenterData: [],
pcsRightData: [],
acdcCenterData: [],
ammeterData: [],
configData: {}
}
},
computed: {
lang() {
return this.$store.getters.language
}
},
watch: {},
created() {
const result = changeTheme()
this.configData = config[result]
this.configData.grid = DynamoImg
setTimeout(() => {
if (this.$store.getters.menuList.length) {
this.permissionId = this.$store.getters.menuList.find(item => {
return item.url === this.$route.path
}).id
}
}, 300)
},
mounted() {},
methods: {
isChineseDominant(text) {
const chineseRegex = /[\u4e00-\u9fa5]/g
const chineseCount = (text.match(chineseRegex) || []).length
return chineseCount / text.length > 0.5
},
// 修改截断逻辑:按字符类型统一视觉宽度
truncateText(text, baseMaxWidth = 90) {
if (!text) return ''
// 1. 按文本类型设置“最大可显示字符数”(视觉宽度相近)
const isChinese = this.isChineseDominant(text)
const maxChars = isChinese ? 8 : 15 // 中文8字 ≈ 英文15字母14px sans-serif下
// 2. 先按字符数截断(避免过长文本循环过多)
const truncated = text.slice(0, maxChars)
let finalText = truncated
// 3. 精确测量:如果截断后加...仍超宽,继续缩减
while (this.measureTextWidth(finalText + '...') > baseMaxWidth && finalText.length > 0) {
finalText = finalText.slice(0, -1)
}
// 4. 补充...(如果有截断)
return finalText + (finalText.length < text.length ? '...' : '')
},
// 精确测量文本渲染宽度(像素)- 保持不变
measureTextWidth(text, font = '14px sans-serif') {
if (!this._textMeasurementCanvas) {
this._textMeasurementCanvas = document.createElement('canvas')
}
const ctx = this._textMeasurementCanvas.getContext('2d')
ctx.font = font
return ctx.measureText(text).width
},
// 计算value的x坐标基于统一后的截断文本宽度
calculateValueX(name, baseX = 205) {
const truncatedName = this.truncateText(name) // 无需传maxWidth内部统一处理
const nameWidth = this.measureTextWidth(truncatedName)
const spacing = 6 // 固定间距(因截断文本视觉宽度一致,间距会统一)
return baseX + nameWidth + spacing
},
countChineseAndEnglishCharacters(str, x) {
var chineseCount = str.match(/[\u4e00-\u9fa5]/g) ? str.match(/[\u4e00-\u9fa5]/g).length : 0
var englishCount = str.match(/[a-zA-Z]/g) ? str.match(/[a-zA-Z]/g).length : 0
var otherCount = str.length - chineseCount - englishCount
const obj = { otherCount: otherCount, chineseCount: chineseCount, englishCount: englishCount }
return (obj.englishCount * 11) + (obj.chineseCount * 16) + (obj.otherCount * 8) + x
},
lookDeviceDetail(val) { // 查看设备详情
this.pageLocation = val
this.show_point_dispostion = true
},
closePoint() {
this.show_point_dispostion = false
},
async getpcsCenter() {
this.loading = true
try {
const res = await DynamicConfigPoint({
pageLocation: 'triad-pcs-center',
permissionId: this.permissionId,
stationId: this.stationId })
this.pcsCenterData = res.data
} catch (error) {
// console.log(error);
} finally {
this.loading = false
}
},
// async getstsCenter() {
// this.loading = true
// try {
// const res = await DynamicConfigPoint({
// pageLocation: 'triad-sts-center',
// permissionId: this.permissionId,
// stationId: this.stationId })
// this.stsCenterData = res.data
// } catch (error) {
// // console.log(error);
// } finally {
// this.loading = false
// }
// },
async getacdcCenter() {
this.loading = true
try {
const res = await DynamicConfigPoint({
pageLocation: 'triad-acdc-center',
permissionId: this.permissionId,
stationId: this.stationId })
this.acdcCenterData = res.data
} catch (error) {
// console.log(error);
} finally {
this.loading = false
}
},
async getLineStatus(type) {
this.loading = true
try {
const res = await DynamicConfigPoint({
pageLocation: type,
permissionId: this.permissionId,
stationId: this.stationId })
if (type === 'line-bottom-left') {
if (res.data?.length) {
if (res.data[0].value > 0) {
this.dotData.lineBottomLeft = 'M 283,0, 280, 0, 0 ,0'
} else if (res.data[0].value < 0) {
this.dotData.lineBottomLeft = 'M 0,0 281,0 281,0'
} else {
this.dotData.lineBottomLeft = ''
}
} else {
this.dotData.lineBottomLeft = ''
}
} else if (type === 'line-bottom-right') {
if (res.data?.length) {
if (res.data[0].value > 0) {
this.dotData.lineBottomRight = 'M -271, 0 , -271 , 0 , 0 , 0'
} else if (res.data[0].value < 0) {
this.dotData.lineBottomRight = 'M 0,0 -271,0 -271,0'
} else {
this.dotData.lineBottomRight = ''
}
} else {
this.dotData.lineBottomRight = ''
}
} else if (type === 'line-bottom-center') {
if (res.data?.length) {
if (res.data[0].value > 0) {
this.dotData.lineCenter = 'M 0,-283,0,0,0,0'
} else if (res.data[0].value < 0) {
this.dotData.lineCenter = 'M 0,0,0,0,0,-283'
} else {
this.dotData.lineCenter = ''
}
} else {
this.dotData.lineCenter = ''
}
} else if (type === 'line-top-left') {
if (res.data?.length) {
if (res.data[0].value > 0) {
this.dotData.lineTopLeft = 'M 230,0 0,0'
} else if (res.data[0].value < 0) {
this.dotData.lineTopLeft = 'M 0,0 225,0'
} else {
this.dotData.lineTopLeft = ''
}
} else {
this.dotData.lineTopLeft = ''
}
} else if (type === 'line-top-right') {
if (res.data?.length) {
if (res.data[0].value > 0) {
this.dotData.lineTopRight = 'M -230,0 0,0'
} else if (res.data[0].value < 0) {
this.dotData.lineTopRight = 'M 0,0 -225,0'
} else {
this.dotData.lineTopRight = ''
}
} else {
this.dotData.lineTopRight = ''
}
}
} catch (error) {
// console.log(error);
} finally {
this.loading = false
}
},
// 批量调用8次请求并发
async batchGetPV() {
this.loading = true // 统一开启加载,避免多次切换
try {
// 生成1-8的数组循环创建请求Promise
const requestPromises = Array.from({ length: 8 }, (_, index) => {
const num = index + 1 // 索引0→1索引7→8
return DynamicConfigPoint({
pageLocation: 'triad-pv-' + num,
permissionId: this.permissionId,
stationId: this.stationId
})
})
// 并发执行所有请求,等待全部完成
const resList = await Promise.all(requestPromises)
// 遍历结果赋值到pvData对应属性pv1-pv8
resList.forEach((res, index) => {
const num = index + 1
this.pvData['pv' + num] = res.data
})
} catch (error) {
console.error('批量请求失败:', error)
// 可选单个请求失败时的全局提示如this.$message.error('数据加载失败')
} finally {
this.loading = false // 统一关闭加载,无论成功/失败
}
},
async getammeter() {
this.loading = true
try {
const res = await DynamicConfigPoint({
pageLocation: 'triad-ammeter',
permissionId: this.permissionId,
stationId: this.stationId })
this.ammeterData = res.data
} catch (error) {
// console.log(error);
} finally {
this.loading = false
}
},
async batchGetPcs() {
this.loading = true
try {
// 生成1-4的数组循环创建请求Promise
const requestPromises = Array.from({ length: 4 }, (_, index) => {
const num = index + 1
return DynamicConfigPoint({
pageLocation: 'triad-pcs-' + num,
permissionId: this.permissionId,
stationId: this.stationId
})
})
// 并发执行所有请求,等待全部完成
const resList = await Promise.all(requestPromises)
// 遍历结果赋值到pvData对应属性pv1-pv8
resList.forEach((res, index) => {
const num = index + 1
this.pcsData['pcs' + num] = res.data
})
} catch (error) {
// console.log(error);
} finally {
this.loading = false
}
},
async batchGetBms() {
this.loading = true
try {
// 生成1-8的数组循环创建请求Promise
const requestPromises = Array.from({ length: 4 }, (_, index) => {
const num = index + 1
return DynamicConfigPoint({
pageLocation: 'triad-bms-' + num,
permissionId: this.permissionId,
stationId: this.stationId
})
})
// 并发执行所有请求,等待全部完成
const resList = await Promise.all(requestPromises)
// 遍历结果赋值到pvData对应属性pv1-pv8
resList.forEach((res, index) => {
const num = index + 1
this.bmsData['bms' + num] = res.data
})
} catch (error) {
// console.log(error);
} finally {
this.loading = false
}
},
getData() {
this.batchGetPcs()
this.batchGetBms()
// this.getpcsCenter()
// this.getstsCenter()
this.getacdcCenter()
this.batchGetPV()
this.getammeter()
this.getLineStatus('line-bottom-left')
this.getLineStatus('line-bottom-center')
this.getLineStatus('line-bottom-right')
this.getLineStatus('line-top-left')
this.getLineStatus('line-top-right')
this.$forceUpdate()
},
getDynamicPointData() {
this.getData()
}
}
}
</script>
<style lang="scss" scoped>
.center-box {
width: 100%;
height: 100%;
box-sizing: border-box;
& > div {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
svg {
width: 100%;
height: 100%;
max-height: 100%;
display: block;
}
}
@mixin move-round($duration, $delay) {
fill: none;
stroke-width: 5;
stroke-linejoin: round;
stroke-linecap: round;
stroke-dasharray: 3, 900;
stroke-dashoffset: 0;
animation: lineMove $duration $delay cubic-bezier(0, 0, 0.74, 0.74) infinite;
}
@keyframes lineMove {
0% {
stroke-dashoffset: -850;
}
100% {
stroke-dashoffset: -0;
}
}
.g-rect-fill-two {
@include move-round(3.5s, 1s);
}
</style>