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
# 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_TOKEN = '71705982-1d76-473c-bb81-d15776f0f6aa'
VITE_DEV_TOKEN = '1f19219c-e6a2-4c51-b442-e8607d1571ed'
# production path
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[]) => {
if(ids.length) {
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 = []
ids.forEach(id => {
if(typeof id === 'number') {

View File

@ -247,27 +247,18 @@
<circle cx="102" cy="80" r="2" style="fill:#091c38" />
</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>
</svg>
<div class="sideBox">
<div class="item">
<div class="rect"></div>
<div class="label">{{value[2].label}}</div>
<div class="value">{{value[2].value}}</div>
<div class="label">{{value[1].label}}</div>
<div class="value">{{value[1].value}}</div>
</div>
<div class="item">
<div class="rect"></div>
<div class="label">{{value[1].label}}</div>
<div class="value">{{value[1].value}}</div>
<div class="label">{{value[2].label}}</div>
<div class="value">{{value[2].value}}</div>
</div>
<div class="item">
<div class="rect"></div>

View File

@ -14,41 +14,23 @@ export const option = {
}
export const customData = {
title: '综合PUE',
enable: false,
id: null,
circle: {
title: '实时PUE',
id: null
title: '昨日PUE',
},
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,
}

View File

@ -2,48 +2,48 @@
<setting-item-box name="标题" :alone="true">
<n-input v-model:value="props.customData.title" size="small" placeholder="请输入"/>
</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 name="标题">
<n-input v-model:value="props.customData.circle.title" size="small" placeholder="请输入"/>
</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 name="左下部分">
<setting-item-box name="中间">
<setting-item name="标题1">
<n-input v-model:value="props.customData.leftBottom[1].title" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="id1">
<n-input v-model:value="props.customData.leftBottom[1].id" size="small" placeholder="请输入"/>
<n-input v-model:value="props.customData.center.title1" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="标题2">
<n-input v-model:value="props.customData.leftBottom[0].title" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="id2">
<n-input v-model:value="props.customData.leftBottom[0].id" size="small" placeholder="请输入"/>
<n-input v-model:value="props.customData.center.title2" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="标题3">
<n-input v-model:value="props.customData.leftBottom[2].title" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="id3">
<n-input v-model:value="props.customData.leftBottom[2].id" size="small" placeholder="请输入"/>
<n-input v-model:value="props.customData.center.title3" size="small" placeholder="请输入"/>
</setting-item>
</setting-item-box>
<setting-item-box name="右半部分">
<template v-for="i in 3" :key="i">
<setting-item :name="'标题' + i">
<n-input v-model:value="props.customData.right[i - 1].title" size="small" placeholder="请输入"/>
</setting-item>
<setting-item :name="'单位' + i">
<n-input v-model:value="props.customData.right[i - 1].unit" size="small" placeholder="请输入"/>
</setting-item>
<setting-item :name="'id' + i">
<n-input v-model:value="props.customData.right[i - 1].id" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="">
</setting-item>
</template>
<setting-item-box name="右边">
<setting-item name="标题1">
<n-input v-model:value="props.customData.right.title1" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="公式1">
<n-input v-model:value="props.customData.right.calculation1" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="标题2">
<n-input v-model:value="props.customData.right.title2" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="公式2">
<n-input v-model:value="props.customData.right.calculation2" size="small" placeholder="请输入"/>
</setting-item>
<setting-item name="标题3">
<n-input v-model:value="props.customData.right.title3" size="small" placeholder="请输入"/>
</setting-item>
</setting-item-box>
</template>

View File

@ -3,7 +3,7 @@
<BorderBox :title="customData?.title">
<div class="inner">
<div class="left">
<VCircle :value="value" style="height: 100%;width: 100%"/>
<VCircle :value="circleArr" style="height: 100%;width: 100%"/>
</div>
<div class="right">
<div class="item" v-for="(item, i) in rightArr" :key="i">
@ -12,7 +12,7 @@
</div>
<v-chart class="leftBox" :option="item.option" autoresize :update-options="{ notMerge: true, replaceMerge: ['series'] }"/>
<div class="rightBox">
<div>{{item.label}} {{item.unit}}</div>
<div>{{item.label}}</div>
<!-- <div>{{item.unit}}</div>-->
<div>{{item.value}}</div>
</div>
@ -24,7 +24,7 @@
</template>
<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 { customData as customDataConfig } from './config'
import { useChartDataFetch } from '@/hooks'
@ -63,18 +63,28 @@ const customData: Ref<typeof customDataConfig> = computed(() => {
return props.chartConfig.customData as typeof customDataConfig
})
const values = reactive(['1.000', '0.000', '0.000', '0.000'])
const value = computed(() => {
let arr = []
arr.push({label: customData.value.circle.title, id: customData.value.circle.id, value: values[0]})
customData.value.leftBottom.forEach((item, i) => {
arr.push({label: item.title, id: item.id, value: values[i + 1]})
})
// 1 123 123
const dataArr = ref([1, 0, 0, 0, 0, 0, 0])
const circleArr = computed(() => {
let arr = [
{ 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
})
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) => {
// 使 toFixed(3)
const formattedNum = num.toFixed(3);
@ -85,27 +95,8 @@ const formatNumber = (num: number) => {
const result = parts.join('.');
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: [],
grid: {
top: '0%',
@ -191,8 +182,8 @@ const option1 = {
barGap: '-100%', //
z: 1
}]
}
const option2 = {
})
const option2 = ref({
title: [
{
text: '0',
@ -297,8 +288,8 @@ const option2 = {
barGap: '-100%', //
z: 1
}]
}
const option3 = {
})
const option3 = ref({
title: [
{
text: '0',
@ -403,86 +394,116 @@ const option3 = {
barGap: '-100%', //
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) => {
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') {
values1[diffIndex] = Number(res.data.value)
const getCenterData = async () => {
dataArr.value[2] = 0
dataArr.value[3] = 0
if(customData.value.id) {
const params = {
strategy_ids: [Number(customData.value.id)]
}
let res = await publicInterface('/dynamic_report/err', 'pue_dashboard', params)
if(res && res.data && res.data.length) {
dataArr.value[2] = Number(res.data[0].week_avg_pue)
dataArr.value[3] = Number(res.data[0].month_avg_pue)
}
}
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, () => {
if(values1[0] !== 0 && values1[1] !== 0) {
let percent = ((values1[1] / values1[0]) * 100).toFixed(0)
options[1].series[0].data[0].value = Number(percent)
options[1].title[0].text = percent
const getRightData = async () => {
//
dataArr.value[1] = 0
dataArr.value[4] = 0
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 {
options[1].series[0].data[0].value = 0
options[1].title[0].text = '0'
let params = [
{ ...item, calculation: customData.value.right.calculation1, name: 'a' },
{ ...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 {
options[2].series[0].data[0].value = 0
options[2].title[0].text = '0'
}
}, {
deep: true
getLeftData()
getCenterData()
getRightData()
}
watch(() => customData.value.enable, () => {
getData()
})
let timer: unknown
watch(() => [props.chartConfig.request.requestInterval, props.chartConfig.request.requestIntervalUnit].join('&&'), v => {
if(!isPreview()) return
if(props.chartConfig.request.requestInterval) {
@ -517,6 +538,7 @@ onUnmounted(() => {
height: 100%;
display: flex;
overflow-y: auto;
overflow-x: hidden;
.left{
flex: 6;
min-width: 60%;

View File

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