MPVN_CMP/frontend/src/views/EnergyOverview.vue

53 lines
2.2 KiB
Vue
Raw Normal View History

<template>
<div class="overview">
<div class="hero">
<div class="number">{{ totalPower }}</div>
<div class="label">实时总功率 kW</div>
</div>
<div class="grid">
<div class="card"><EnergyChart :points="points" /></div>
<div class="card">
<h3>能耗排行榜</h3>
<ul>
<li v-for="(item,i) in ranking" :key="i">{{ item.name }} <b>{{ item.kw }}</b> kW</li>
</ul>
</div>
<div class="card">
<h3>地图</h3>
<div class="map">项目分布Mock</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import axios from 'axios'
import EnergyChart from '@/components/EnergyChart/index.vue'
const base = (import.meta as any).env.VITE_BACKEND_URL || 'http://localhost:3001'
const totalPower = ref(0)
const points = ref<{ t:number, v:number }[]>([])
const ranking = ref<{ name:string, kw:number }[]>([])
async function refresh() {
const { data } = await axios.get(`${base}/energy/realtime`)
totalPower.value = data.totalPower
points.value.push({ t: Date.now(), v: data.totalPower }); if (points.value.length > 50) points.value.shift()
ranking.value = data.subitems.map((s:any) => ({ name: s.name, kw: s.kw })).sort((a,b) => b.kw - a.kw)
}
function loop() { refresh(); setTimeout(loop, 3000) }
onMounted(loop)
</script>
<style scoped>
.overview { padding: 16px; background: #0b132b; color: #fff; min-height: 100%; }
.hero { text-align: center; margin-bottom: 16px; }
.number { font-size: 56px; font-weight: 800; letter-spacing: 2px; animation: roll 1s ease-in-out; }
@keyframes roll { from { transform: translateY(10px); opacity: 0 } to { transform: translateY(0); opacity: 1 } }
.grid { display: grid; grid-template-columns: 2fr 1fr; grid-template-rows: 320px 320px; gap: 16px; }
.card { background: #1c2541; border-radius: 12px; padding: 12px; }
.map { height: 280px; border-radius: 8px; background: linear-gradient(135deg,#162447,#1f4068); display: flex; align-items: center; justify-content: center; opacity: .85 }
ul { list-style: none; padding: 0; margin: 0; }
li { display: flex; justify-content: space-between; padding: 8px 12px; background: #243b55; margin-bottom: 8px; border-radius: 8px; }
</style>