53 lines
2.2 KiB
Vue
53 lines
2.2 KiB
Vue
<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>
|
||
|