feat: 调整综合pue

This commit is contained in:
huanghao1412 2024-07-11 16:50:49 +08:00
parent e6a18a6405
commit f644f80f50
7 changed files with 188 additions and 192 deletions

4
.env
View File

@ -3,9 +3,9 @@ VITE_DEV_PORT = '8080'
# development path # development path
# VITE_DEV_PATH = 'http://192.168.0.34:11887' # VITE_DEV_PATH = 'http://192.168.0.34:11887'
VITE_DEV_PATH = 'http://192.168.0.34:18077' VITE_DEV_PATH = 'http://192.168.0.34:8022'
# VITE_DEV_PATH = 'http://192.168.0.120:3001' # VITE_DEV_PATH = 'http://192.168.0.120:3001'
VITE_DEV_TOKEN = '71705982-1d76-473c-bb81-d15776f0f6aa' VITE_DEV_TOKEN = '1f19219c-e6a2-4c51-b442-e8607d1571ed'
# production path # production path
VITE_PRO_PATH = 'http://192.168.0.235:8177' VITE_PRO_PATH = 'http://192.168.0.235:8177'

View File

@ -195,7 +195,8 @@ let currentVideo: any = ref({})
const getVideos = (ids: number[], alarmIds: number[]) => { const getVideos = (ids: number[], alarmIds: number[]) => {
if(ids.length) { if(ids.length) {
publicInterface('/dcim/video_monitor/other_device', 'get_alarm_device', {device_uids: ids.toString()}).then((res: any) => { publicInterface('/dcim/video_monitor/other_device', 'get_alarm_device', {device_uids: ids.toString()}).then((res: any) => {
if(res.errcode !== '00000') return // if(res.errcode !== '00000') return
if(!res?.data) return
let arr:any = [] let arr:any = []
ids.forEach(id => { ids.forEach(id => {
if(typeof id === 'number') { if(typeof id === 'number') {

View File

@ -247,27 +247,18 @@
<circle cx="102" cy="80" r="2" style="fill:#091c38" /> <circle cx="102" cy="80" r="2" style="fill:#091c38" />
</g> </g>
</g> </g>
<!-- <rect x="72" y="186" width="60" height="10" style="fill:url(#linear-gradient-pue-2)" />-->
<!-- <text transform="translate(81 189.89)" style="font-size:12px;fill:#fff;font-family:PingFang-SC-Regular, PingFang SC-Regular">{{value[1].label}}</text>-->
<!-- <text transform="translate(82 221)" style="font-size:20px;fill:#4dca59;font-family:PingFang-SC-Bold, PingFang SC-Bold;font-weight:700">{{ value[1].value }}</text>-->
<!-- <rect y="186" width="60" height="10" style="fill:url(#linear-gradient-pue-3)" />-->
<!-- <text transform="translate(9 189.89)" style="font-size:12px;fill:#fff;font-family:PingFang-SC-Regular, PingFang SC-Regular">{{value[2].label}}</text>-->
<!-- <text transform="translate(10 221)" style="font-size:20px;fill:#4dca59;font-family:PingFang-SC-Bold, PingFang SC-Bold;font-weight:700">{{ value[2].value }}</text>-->
<!-- <rect x="144" y="186" width="60" height="10" style="fill:url(#linear-gradient-pue-4)" />-->
<!-- <text transform="translate(153 189.89)" style="font-size:12px;fill:#fff;font-family:PingFang-SC-Regular, PingFang SC-Regular">{{value[3].label}}</text>-->
<!-- <text transform="translate(154 221)" style="font-size:20px;fill:#4dca59;font-family:PingFang-SC-Bold, PingFang SC-Bold;font-weight:700">{{ value[3].value }}</text>-->
</g> </g>
</svg> </svg>
<div class="sideBox"> <div class="sideBox">
<div class="item"> <div class="item">
<div class="rect"></div> <div class="rect"></div>
<div class="label">{{value[2].label}}</div> <div class="label">{{value[1].label}}</div>
<div class="value">{{value[2].value}}</div> <div class="value">{{value[1].value}}</div>
</div> </div>
<div class="item"> <div class="item">
<div class="rect"></div> <div class="rect"></div>
<div class="label">{{value[1].label}}</div> <div class="label">{{value[2].label}}</div>
<div class="value">{{value[1].value}}</div> <div class="value">{{value[2].value}}</div>
</div> </div>
<div class="item"> <div class="item">
<div class="rect"></div> <div class="rect"></div>

View File

@ -14,41 +14,23 @@ export const option = {
} }
export const customData = { export const customData = {
title: '综合PUE', title: '综合PUE',
enable: false,
id: null,
circle: { circle: {
title: '实时PUE', title: '昨日PUE',
id: null },
center: {
title1: '实时PUE',
title2: '上周PUE',
title3: '上月PUE',
},
right: {
title1: '总功率(kWh)',
calculation1: '',
title2: 'IT功率(kW)',
calculation2: '',
title3: '其他功率(kW)',
}, },
leftBottom: [
{
title: '昨日PUE',
id: null
},
{
title: '上周PUE',
id: null
},
{
title: '上月PUE',
id: null
}
],
right: [
{
title: '总市电负载',
unit: '(kWh)',
id: null
},
{
title: 'IT用电负载',
unit: '(kWh)',
id: null
},
{
title: '其他负载',
unit: '(kWh)',
id: null
}
],
showInterval: true, showInterval: true,
} }

View File

@ -2,48 +2,48 @@
<setting-item-box name="标题" :alone="true"> <setting-item-box name="标题" :alone="true">
<n-input v-model:value="props.customData.title" size="small" placeholder="请输入"/> <n-input v-model:value="props.customData.title" size="small" placeholder="请输入"/>
</setting-item-box> </setting-item-box>
<setting-item-box name="启用">
<n-space>
<n-switch v-model:value="props.customData.enable" size="small"/>
</n-space>
</setting-item-box>
<setting-item-box name="报表ID" alone>
<setting-item name="控制左边和中间的ID">
<n-input v-model:value="props.customData.id" size="small" placeholder="请输入"/>
</setting-item>
</setting-item-box>
<setting-item-box name="仪表盘"> <setting-item-box name="仪表盘">
<setting-item name="标题"> <setting-item name="标题">
<n-input v-model:value="props.customData.circle.title" size="small" placeholder="请输入"/> <n-input v-model:value="props.customData.circle.title" size="small" placeholder="请输入"/>
</setting-item> </setting-item>
<setting-item name="id">
<n-input v-model:value="props.customData.circle.id" size="small" placeholder="请输入"/>
</setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="左下部分"> <setting-item-box name="中间">
<setting-item name="标题1"> <setting-item name="标题1">
<n-input v-model:value="props.customData.leftBottom[1].title" size="small" placeholder="请输入"/> <n-input v-model:value="props.customData.center.title1" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="id1">
<n-input v-model:value="props.customData.leftBottom[1].id" size="small" placeholder="请输入"/>
</setting-item> </setting-item>
<setting-item name="标题2"> <setting-item name="标题2">
<n-input v-model:value="props.customData.leftBottom[0].title" size="small" placeholder="请输入"/> <n-input v-model:value="props.customData.center.title2" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="id2">
<n-input v-model:value="props.customData.leftBottom[0].id" size="small" placeholder="请输入"/>
</setting-item> </setting-item>
<setting-item name="标题3"> <setting-item name="标题3">
<n-input v-model:value="props.customData.leftBottom[2].title" size="small" placeholder="请输入"/> <n-input v-model:value="props.customData.center.title3" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="id3">
<n-input v-model:value="props.customData.leftBottom[2].id" size="small" placeholder="请输入"/>
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="右半部分"> <setting-item-box name="右边">
<template v-for="i in 3" :key="i"> <setting-item name="标题1">
<setting-item :name="'标题' + i"> <n-input v-model:value="props.customData.right.title1" size="small" placeholder="请输入"/>
<n-input v-model:value="props.customData.right[i - 1].title" size="small" placeholder="请输入"/> </setting-item>
</setting-item> <setting-item name="公式1">
<setting-item :name="'单位' + i"> <n-input v-model:value="props.customData.right.calculation1" size="small" placeholder="请输入"/>
<n-input v-model:value="props.customData.right[i - 1].unit" size="small" placeholder="请输入"/> </setting-item>
</setting-item> <setting-item name="标题2">
<setting-item :name="'id' + i"> <n-input v-model:value="props.customData.right.title2" size="small" placeholder="请输入"/>
<n-input v-model:value="props.customData.right[i - 1].id" size="small" placeholder="请输入"/> </setting-item>
</setting-item> <setting-item name="公式2">
<setting-item name=""> <n-input v-model:value="props.customData.right.calculation2" size="small" placeholder="请输入"/>
</setting-item> </setting-item>
</template> <setting-item name="标题3">
<n-input v-model:value="props.customData.right.title3" size="small" placeholder="请输入"/>
</setting-item>
</setting-item-box> </setting-item-box>
</template> </template>

View File

@ -3,7 +3,7 @@
<BorderBox :title="customData?.title"> <BorderBox :title="customData?.title">
<div class="inner"> <div class="inner">
<div class="left"> <div class="left">
<VCircle :value="value" style="height: 100%;width: 100%"/> <VCircle :value="circleArr" style="height: 100%;width: 100%"/>
</div> </div>
<div class="right"> <div class="right">
<div class="item" v-for="(item, i) in rightArr" :key="i"> <div class="item" v-for="(item, i) in rightArr" :key="i">
@ -12,7 +12,7 @@
</div> </div>
<v-chart class="leftBox" :option="item.option" autoresize :update-options="{ notMerge: true, replaceMerge: ['series'] }"/> <v-chart class="leftBox" :option="item.option" autoresize :update-options="{ notMerge: true, replaceMerge: ['series'] }"/>
<div class="rightBox"> <div class="rightBox">
<div>{{item.label}} {{item.unit}}</div> <div>{{item.label}}</div>
<!-- <div>{{item.unit}}</div>--> <!-- <div>{{item.unit}}</div>-->
<div>{{item.value}}</div> <div>{{item.value}}</div>
</div> </div>
@ -24,7 +24,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, shallowReactive, watch, toRefs, reactive, onMounted, onUnmounted, computed } from 'vue' import { PropType, shallowReactive, watch, toRefs, reactive, onMounted, onUnmounted, ref, computed } from 'vue'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { customData as customDataConfig } from './config' import { customData as customDataConfig } from './config'
import { useChartDataFetch } from '@/hooks' import { useChartDataFetch } from '@/hooks'
@ -63,18 +63,28 @@ const customData: Ref<typeof customDataConfig> = computed(() => {
return props.chartConfig.customData as typeof customDataConfig return props.chartConfig.customData as typeof customDataConfig
}) })
const values = reactive(['1.000', '0.000', '0.000', '0.000']) // 1 123 123
const value = computed(() => { const dataArr = ref([1, 0, 0, 0, 0, 0, 0])
let arr = []
arr.push({label: customData.value.circle.title, id: customData.value.circle.id, value: values[0]}) const circleArr = computed(() => {
customData.value.leftBottom.forEach((item, i) => { let arr = [
arr.push({label: item.title, id: item.id, value: values[i + 1]}) { label: customData.value.circle.title, value: formatNumber(dataArr.value[0]) },
}) { label: customData.value.center.title1, value: formatNumber(dataArr.value[1]) },
{ label: customData.value.center.title2, value: formatNumber(dataArr.value[2]) },
{ label: customData.value.center.title3, value: formatNumber(dataArr.value[3]) },
]
return arr return arr
}) })
const getPointData = (id: string) => {
return publicInterface('/dcim/system/custom_large_screen', 'get_point_value', id) const rightArr = computed(() => {
} let arr = [
{ label: customData.value.right.title1, value: formatNumber(dataArr.value[4]), option: option1.value },
{ label: customData.value.right.title2, value: formatNumber(dataArr.value[5]), option: option2.value },
{ label: customData.value.right.title3, value: formatNumber(dataArr.value[6]), option: option3.value },
]
return arr
})
const formatNumber = (num: number) => { const formatNumber = (num: number) => {
// 使 toFixed(3) // 使 toFixed(3)
const formattedNum = num.toFixed(3); const formattedNum = num.toFixed(3);
@ -85,27 +95,8 @@ const formatNumber = (num: number) => {
const result = parts.join('.'); const result = parts.join('.');
return result; return result;
} }
watch(() => value.value.map(_ => _.id).toString(), async (v, o) => {
if(v === o) return
let diffIndex = -1
let ids = v.split(',')
let oIds = o.split(',')
ids.forEach((id, i) => {
if(id !== oIds[i]) diffIndex = i
})
let id = ids[diffIndex]
if(id !== null && id !== '') {
let res = await getPointData(id) as any
if(res.errcode === '00000') {
values[diffIndex] = formatNumber(Number(res.data.value))
}
}
else {
values[diffIndex] = diffIndex === 0 ? '1.000' : '0.000'
}
})
const option1 = { const option1 = ref({
title: [], title: [],
grid: { grid: {
top: '0%', top: '0%',
@ -191,8 +182,8 @@ const option1 = {
barGap: '-100%', // barGap: '-100%', //
z: 1 z: 1
}] }]
} })
const option2 = { const option2 = ref({
title: [ title: [
{ {
text: '0', text: '0',
@ -297,8 +288,8 @@ const option2 = {
barGap: '-100%', // barGap: '-100%', //
z: 1 z: 1
}] }]
} })
const option3 = { const option3 = ref({
title: [ title: [
{ {
text: '0', text: '0',
@ -403,86 +394,116 @@ const option3 = {
barGap: '-100%', // barGap: '-100%', //
z: 1 z: 1
}] }]
})
const getLeftData = async () => {
dataArr.value[0] = 1
if(customData.value.id) {
const params = {
duration: 3, // 234
start_time: moment().subtract(1, 'days').startOf('day').format('yyyy-MM-DD HH:mm:ss'),
end_time: moment().startOf('day').format('yyyy-MM-DD HH:mm:ss'),
strategy_ids: [Number(customData.value.id)]
}
let res = await publicInterface('/dynamic_report/err', 'err', params)
if(res && res.data) {
const resData = res.data.tables.data
let field0DataLength = resData.length //
let field0Total = 0
if (parseFloat(resData[0]['field0']) > 0) {
// 0
field0Total += parseFloat(resData[0]['field0'])
} else {
//
field0DataLength--
}
// 24
if (field0DataLength > 0) {
// this.building_one_day_pue = (parseFloat(field1Total / field1DataLength)).toFixed(2) // 2
dataArr.value[0] = field0Total / field0DataLength
} else {
dataArr.value[0] = 0
}
}
}
} }
const values1 = reactive([0, 0, 0])
const options = reactive([option1, option2, option3])
const rightArr = computed(() => {
let arr: {label: string, unit: string, id: string | null, value: number, option: any}[] = []
customData.value.right.forEach((item, i) => {
arr.push({
label: item.title,
unit: item.unit,
id: item.id,
value: values1[i],
option: options[i]
})
})
return arr
})
watch(() => rightArr.value.map(_ => _.id).toString(), async (v, o) => { const getCenterData = async () => {
if(v === o) return dataArr.value[2] = 0
let diffIndex = -1 dataArr.value[3] = 0
let ids = v.split(',') if(customData.value.id) {
let oIds = o.split(',') const params = {
ids.forEach((id, i) => { strategy_ids: [Number(customData.value.id)]
if(id !== oIds[i]) diffIndex = i }
}) let res = await publicInterface('/dynamic_report/err', 'pue_dashboard', params)
let id = ids[diffIndex] if(res && res.data && res.data.length) {
if(id !== null && id !== '') { dataArr.value[2] = Number(res.data[0].week_avg_pue)
let res = await getPointData(id) as any dataArr.value[3] = Number(res.data[0].month_avg_pue)
if(res.errcode === '00000') {
values1[diffIndex] = Number(res.data.value)
} }
} }
else {
values1[diffIndex] = 0
}
})
const getData = () => {
let ids = value.value.map(_ => _.id) as (string | null)[]
ids = ids.concat(rightArr.value.map(_ => _.id))
ids.forEach((id, i) => {
if(id !== null && id !== '') {
getPointData(id).then((res: any) => {
if(res.errcode === '00000') {
if (i < 4) values[i] = formatNumber(Number(res.data.value))
else values1[i - 4] = res.data.value
}
})
}
else {
if (i < 4) values[i] = i === 0 ? '1.000' : '0.000'
else values1[i - 4] = 0
}
})
} }
let timer:unknown
watch(() => values1, () => { const getRightData = async () => {
if(values1[0] !== 0 && values1[1] !== 0) { //
let percent = ((values1[1] / values1[0]) * 100).toFixed(0) dataArr.value[1] = 0
options[1].series[0].data[0].value = Number(percent) dataArr.value[4] = 0
options[1].title[0].text = percent dataArr.value[5] = 0
dataArr.value[6] = 0
option2.value.series[0].data[0].value = 0
option2.value.title[0].text = '0'
option3.value.series[0].data[0].value = 0
option3.value.title[0].text = '0'
let item = {
time_out: 60,
fmt: 2,
abs: true
} }
else { let params = [
options[1].series[0].data[0].value = 0 { ...item, calculation: customData.value.right.calculation1, name: 'a' },
options[1].title[0].text = '0' { ...item, calculation: customData.value.right.calculation2, name: 'b' },
]
let res = await publicInterface('/dcim/dems/device_point', 'get_value_by_point_uid_calculation', params)
if(res && res.data) {
res.data = res.data.map(Number)
dataArr.value[4] = res.data[0]
dataArr.value[5] = res.data[1]
let percent5 = 0, percent6 = 0
if(res.data[0] !== 0) {
percent5 = res.data[1] / res.data[0]
percent6 = 1 - percent5
dataArr.value[1] = res.data[0] / res.data[1]
}
else dataArr.value[1] = 0
dataArr.value[6] = res.data[0] - res.data[1]
option2.value.series[0].data[0].value = 100 * percent5
option2.value.title[0].text = (100 * percent5).toFixed(0)
option3.value.series[0].data[0].value = 100 * percent6
option3.value.title[0].text = (100 * percent6).toFixed(0)
} }
if(values1[0] !== 0 && values1[2] !== 0) { }
let percent = ((values1[2] / values1[0]) * 100).toFixed(0)
options[2].series[0].data[0].value = Number(percent)
options[2].title[0].text = percent const getData = async () => {
if(!customData.value.enable) {
dataArr.value = [1, 0, 0, 0, 0, 0, 0]
option2.value.series[0].data[0].value = 0
option2.value.title[0].text = '0'
option3.value.series[0].data[0].value = 0
option3.value.title[0].text = '0'
return
} }
else { getLeftData()
options[2].series[0].data[0].value = 0 getCenterData()
options[2].title[0].text = '0' getRightData()
} }
}, {
deep: true watch(() => customData.value.enable, () => {
getData()
}) })
let timer: unknown
watch(() => [props.chartConfig.request.requestInterval, props.chartConfig.request.requestIntervalUnit].join('&&'), v => { watch(() => [props.chartConfig.request.requestInterval, props.chartConfig.request.requestIntervalUnit].join('&&'), v => {
if(!isPreview()) return if(!isPreview()) return
if(props.chartConfig.request.requestInterval) { if(props.chartConfig.request.requestInterval) {
@ -517,6 +538,7 @@ onUnmounted(() => {
height: 100%; height: 100%;
display: flex; display: flex;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden;
.left{ .left{
flex: 6; flex: 6;
min-width: 60%; min-width: 60%;

View File

@ -131,11 +131,11 @@ onUnmounted(() => {
display: flex; display: flex;
background: rgba(65, 150, 255, 0.08); background: rgba(65, 150, 255, 0.08);
color: #999; color: #999;
height: 20px; height: 30px;
line-height: 20px; line-height: 30px;
font-size: 12px; font-size: 14px;
padding-left: 10px; padding-left: 10px;
margin-bottom: 5px; margin-bottom: 8px;
&:nth-last-child(1) { &:nth-last-child(1) {
margin-bottom: 0; margin-bottom: 0;
} }
@ -153,7 +153,7 @@ onUnmounted(() => {
} }
&:nth-child(3) { &:nth-child(3) {
flex: none; flex: none;
width: 80px; width: 90px;
} }
} }
.col1{ .col1{
@ -163,7 +163,7 @@ onUnmounted(() => {
&:nth-child(3) { &:nth-child(3) {
color: rgb(0, 255, 255); color: rgb(0, 255, 255);
.value{ .value{
width: 49px; width: 59px;
} }
} }
} }