|
@@ -0,0 +1,621 @@
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import {computed, onMounted, ref} from 'vue';
|
|
|
|
|
+import request from "@/utils/request.js";
|
|
|
|
|
+import {ElMessage} from "element-plus";
|
|
|
|
|
+import ECharts from 'vue-echarts';
|
|
|
|
|
+import 'echarts';
|
|
|
|
|
+import {parseTime} from "@/utils/ruoyi.js";
|
|
|
|
|
+
|
|
|
|
|
+// Data refs
|
|
|
|
|
+const newElectricityData = ref(null);
|
|
|
|
|
+const electricityRecords = ref([]);
|
|
|
|
|
+const loading = ref(false);
|
|
|
|
|
+const tableLoading = ref(false);
|
|
|
|
|
+const totalRecords = ref(0);
|
|
|
|
|
+const currentPage = ref(1);
|
|
|
|
|
+const pageSize = ref(10);
|
|
|
|
|
+const searchQuery = ref('');
|
|
|
|
|
+const dateRange = ref([]);
|
|
|
|
|
+const props = defineProps({
|
|
|
|
|
+ tableNumber: {
|
|
|
|
|
+ type: String,
|
|
|
|
|
+ required: true
|
|
|
|
|
+ },
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// Computed properties for dashboard metrics
|
|
|
|
|
+const formattedVoltages = computed(() => {
|
|
|
|
|
+ if (!newElectricityData.value) return {a: '0', b: '0', c: '0'};
|
|
|
|
|
+ return {
|
|
|
|
|
+ a: parseFloat(newElectricityData.value.aVoltage || 0).toFixed(2),
|
|
|
|
|
+ b: parseFloat(newElectricityData.value.bVoltage || 0).toFixed(2),
|
|
|
|
|
+ c: parseFloat(newElectricityData.value.cVoltage || 0).toFixed(2)
|
|
|
|
|
+ };
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const formattedCurrents = computed(() => {
|
|
|
|
|
+ if (!newElectricityData.value) return {a: '0', b: '0', c: '0'};
|
|
|
|
|
+ return {
|
|
|
|
|
+ a: parseFloat(newElectricityData.value.aCurrent || 0).toFixed(2),
|
|
|
|
|
+ b: parseFloat(newElectricityData.value.bCurrent || 0).toFixed(2),
|
|
|
|
|
+ c: parseFloat(newElectricityData.value.cCurrent || 0).toFixed(2)
|
|
|
|
|
+ };
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const totalPowerConsumption = computed(() => {
|
|
|
|
|
+ if (!newElectricityData.value) return '0';
|
|
|
|
|
+ return parseFloat(newElectricityData.value.totalElectricity || 0).toFixed(2);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// Chart options
|
|
|
|
|
+const voltageChartOption = computed(() => {
|
|
|
|
|
+ if (!electricityRecords.value.length) return {};
|
|
|
|
|
+
|
|
|
|
|
+ const data = electricityRecords.value.slice().reverse();
|
|
|
|
|
+ return {
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis'
|
|
|
|
|
+ },
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ data: ['A相电压', 'B相电压', 'C相电压']
|
|
|
|
|
+ },
|
|
|
|
|
+ grid: {
|
|
|
|
|
+ left: '3%',
|
|
|
|
|
+ right: '4%',
|
|
|
|
|
+ bottom: '3%',
|
|
|
|
|
+ containLabel: true
|
|
|
|
|
+ },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ boundaryGap: false,
|
|
|
|
|
+ data: data.map(item => {
|
|
|
|
|
+ const date = new Date(item.createTime);
|
|
|
|
|
+ return `${date.getHours()}:${date.getMinutes()}`;
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ name: '电压 (V)'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'A相电压',
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ data: data.map(item => parseFloat(item.aVoltage || 0))
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'B相电压',
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ data: data.map(item => parseFloat(item.bVoltage || 0))
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'C相电压',
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ data: data.map(item => parseFloat(item.cVoltage || 0))
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ };
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const powerChartOption = computed(() => {
|
|
|
|
|
+ if (!electricityRecords.value.length) return {};
|
|
|
|
|
+
|
|
|
|
|
+ const data = electricityRecords.value.slice().reverse();
|
|
|
|
|
+ return {
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis'
|
|
|
|
|
+ },
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ data: ['总有功功率', 'A相功率', 'B相功率', 'C相功率']
|
|
|
|
|
+ },
|
|
|
|
|
+ grid: {
|
|
|
|
|
+ left: '3%',
|
|
|
|
|
+ right: '4%',
|
|
|
|
|
+ bottom: '3%',
|
|
|
|
|
+ containLabel: true
|
|
|
|
|
+ },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ boundaryGap: false,
|
|
|
|
|
+ data: data.map(item => {
|
|
|
|
|
+ const date = new Date(item.createTime);
|
|
|
|
|
+ return `${date.getHours()}:${date.getMinutes()}`;
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ name: '功率 (kW)'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: '总有功功率',
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ data: data.map(item => parseFloat(item.totalActivePower || 0))
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'A相功率',
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ data: data.map(item => parseFloat(item.aActivePower || 0))
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'B相功率',
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ data: data.map(item => parseFloat(item.bActivePower || 0))
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'C相功率',
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ data: data.map(item => parseFloat(item.cActivePower || 0))
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ };
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// Methods
|
|
|
|
|
+const getNewElectricityData = async () => {
|
|
|
|
|
+ loading.value = true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const arr = [{
|
|
|
|
|
+ column: "create_time",
|
|
|
|
|
+ type: "orderByDesc"
|
|
|
|
|
+ }];
|
|
|
|
|
+
|
|
|
|
|
+ const res = await request.get("/messageParse/getAll", {
|
|
|
|
|
+ params: {
|
|
|
|
|
+ conditionJson: encodeURIComponent(JSON.stringify(arr))
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (res.code !== 200) {
|
|
|
|
|
+ ElMessage.error(res.msg);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (res.data.length === 0) {
|
|
|
|
|
+ ElMessage.warning("暂无数据");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ newElectricityData.value = res.data[0];
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ ElMessage.error("获取最新电表数据失败");
|
|
|
|
|
+ console.error(error);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ loading.value = false;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const getElectricityData = async () => {
|
|
|
|
|
+ tableLoading.value = true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const conditions = [{
|
|
|
|
|
+ column: "create_time",
|
|
|
|
|
+ type: "orderByDesc"
|
|
|
|
|
+ }];
|
|
|
|
|
+ conditions.push({
|
|
|
|
|
+ column: "table_number",
|
|
|
|
|
+ type: "eq",
|
|
|
|
|
+ value: props.tableNumber
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // Add search condition if query exists
|
|
|
|
|
+ if (searchQuery.value) {
|
|
|
|
|
+ conditions.push({
|
|
|
|
|
+ column: "table_number",
|
|
|
|
|
+ type: "like",
|
|
|
|
|
+ value: searchQuery.value
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (dateRange.value && dateRange.value.length === 2) {
|
|
|
|
|
+
|
|
|
|
|
+ conditions.push({
|
|
|
|
|
+ column: "create_time",
|
|
|
|
|
+ type: "between",
|
|
|
|
|
+ value: parseTime(dateRange.value[0]) + ',' + parseTime(dateRange.value[1])
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const res = await request.get("/messageParse/findByPage", {
|
|
|
|
|
+ params: {
|
|
|
|
|
+ pageNum: currentPage.value,
|
|
|
|
|
+ pageSize: pageSize.value,
|
|
|
|
|
+ conditionJson: encodeURIComponent(JSON.stringify(conditions))
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (res.code !== 200) {
|
|
|
|
|
+ ElMessage.error(res.msg);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ electricityRecords.value = res.data.records;
|
|
|
|
|
+ totalRecords.value = res.data.total;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ ElMessage.error("获取电表数据列表失败");
|
|
|
|
|
+ console.error(error);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ tableLoading.value = false;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const handlePageChange = (page) => {
|
|
|
|
|
+ currentPage.value = page;
|
|
|
|
|
+ getElectricityData();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const handleSizeChange = (size) => {
|
|
|
|
|
+ pageSize.value = size;
|
|
|
|
|
+ currentPage.value = 1;
|
|
|
|
|
+ getElectricityData();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const handleSearch = () => {
|
|
|
|
|
+ currentPage.value = 1;
|
|
|
|
|
+ getElectricityData();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const refreshData = () => {
|
|
|
|
|
+ getNewElectricityData();
|
|
|
|
|
+ getElectricityData();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// Format date for display
|
|
|
|
|
+const formatDate = (dateString) => {
|
|
|
|
|
+ if (!dateString) return '';
|
|
|
|
|
+ const date = new Date(dateString);
|
|
|
|
|
+ return date.toLocaleString();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// Lifecycle hooks
|
|
|
|
|
+onMounted(() => {
|
|
|
|
|
+ getNewElectricityData();
|
|
|
|
|
+ getElectricityData();
|
|
|
|
|
+
|
|
|
|
|
+ // Set up auto-refresh every 30 seconds
|
|
|
|
|
+ const refreshInterval = setInterval(refreshData, 30000);
|
|
|
|
|
+
|
|
|
|
|
+ // Clean up interval on component unmount
|
|
|
|
|
+ onUnmounted(() => {
|
|
|
|
|
+ clearInterval(refreshInterval);
|
|
|
|
|
+ });
|
|
|
|
|
+});
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="electricity-dashboard p-4">
|
|
|
|
|
+ <!-- Dashboard Cards -->
|
|
|
|
|
+ <el-row :gutter="20" class="mb-6">
|
|
|
|
|
+ <el-col :xs="24" :sm="12" :md="6">
|
|
|
|
|
+ <el-card shadow="hover" class="h-full">
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <div class="flex items-center">
|
|
|
|
|
+ <i class="el-icon-data-line mr-2"></i>
|
|
|
|
|
+ <span>总用电量</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <div class="text-center">
|
|
|
|
|
+ <h3 class="text-3xl font-bold text-blue-600">{{ totalPowerConsumption }}</h3>
|
|
|
|
|
+ <p class="text-gray-500">千瓦时 (kWh)</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+
|
|
|
|
|
+ <el-col :xs="24" :sm="12" :md="6">
|
|
|
|
|
+ <el-card shadow="hover" class="h-full">
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <div class="flex items-center">
|
|
|
|
|
+ <i class="el-icon-lightning mr-2"></i>
|
|
|
|
|
+ <span>电压 (V)</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <div class="grid grid-cols-3 gap-2 text-center">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <h4 class="text-sm text-gray-500">A相</h4>
|
|
|
|
|
+ <p class="text-lg font-semibold text-green-600">{{ formattedVoltages.a }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <h4 class="text-sm text-gray-500">B相</h4>
|
|
|
|
|
+ <p class="text-lg font-semibold text-green-600">{{ formattedVoltages.b }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <h4 class="text-sm text-gray-500">C相</h4>
|
|
|
|
|
+ <p class="text-lg font-semibold text-green-600">{{ formattedVoltages.c }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+
|
|
|
|
|
+ <el-col :xs="24" :sm="12" :md="6">
|
|
|
|
|
+ <el-card shadow="hover" class="h-full">
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <div class="flex items-center">
|
|
|
|
|
+ <i class="el-icon-connection mr-2"></i>
|
|
|
|
|
+ <span>电流 (A)</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <div class="grid grid-cols-3 gap-2 text-center">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <h4 class="text-sm text-gray-500">A相</h4>
|
|
|
|
|
+ <p class="text-lg font-semibold text-orange-600">{{ formattedCurrents.a }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <h4 class="text-sm text-gray-500">B相</h4>
|
|
|
|
|
+ <p class="text-lg font-semibold text-orange-600">{{ formattedCurrents.b }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <h4 class="text-sm text-gray-500">C相</h4>
|
|
|
|
|
+ <p class="text-lg font-semibold text-orange-600">{{ formattedCurrents.c }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+
|
|
|
|
|
+ <el-col :xs="24" :sm="12" :md="6">
|
|
|
|
|
+ <el-card shadow="hover" class="h-full">
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <div class="flex items-center">
|
|
|
|
|
+ <i class="el-icon-timer mr-2"></i>
|
|
|
|
|
+ <span>最后更新时间</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <div class="text-center">
|
|
|
|
|
+ <h3 class="text-lg font-semibold text-gray-700">
|
|
|
|
|
+ {{ newElectricityData ? formatDate(newElectricityData.createTime) : '暂无数据' }}
|
|
|
|
|
+ </h3>
|
|
|
|
|
+ <el-button type="primary" size="small" @click="refreshData" :loading="loading" class="mt-2">
|
|
|
|
|
+ 刷新数据
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Charts -->
|
|
|
|
|
+ <el-row :gutter="20" class="mb-6">
|
|
|
|
|
+ <el-col :xs="24" :lg="12">
|
|
|
|
|
+ <el-card shadow="hover">
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
|
|
+ <span>电压趋势</span>
|
|
|
|
|
+ <el-tooltip content="显示最近10条记录的电压变化趋势">
|
|
|
|
|
+ <i class="el-icon-question"></i>
|
|
|
|
|
+ </el-tooltip>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <div class="h-80">
|
|
|
|
|
+ <e-charts v-if="electricityRecords.length" :option="voltageChartOption" autoresize/>
|
|
|
|
|
+ <div v-else class="h-full flex items-center justify-center text-gray-400">
|
|
|
|
|
+ 暂无数据
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+
|
|
|
|
|
+ <el-col :xs="24" :lg="12">
|
|
|
|
|
+ <el-card shadow="hover">
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
|
|
+ <span>功率趋势</span>
|
|
|
|
|
+ <el-tooltip content="显示最近10条记录的功率变化趋势">
|
|
|
|
|
+ <i class="el-icon-question"></i>
|
|
|
|
|
+ </el-tooltip>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <div class="h-80">
|
|
|
|
|
+ <e-charts v-if="electricityRecords.length" :option="powerChartOption" autoresize/>
|
|
|
|
|
+ <div v-else class="h-full flex items-center justify-center text-gray-400">
|
|
|
|
|
+ 暂无数据
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Data Table -->
|
|
|
|
|
+ <el-card shadow="hover">
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <div class="flex flex-wrap items-center justify-between gap-4">
|
|
|
|
|
+ <h3 class="text-lg font-medium">电表历史数据</h3>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="flex flex-wrap items-center gap-4">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="searchQuery"
|
|
|
|
|
+ placeholder="搜索表号"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ @keyup.enter="handleSearch"
|
|
|
|
|
+ class="w-60"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #append>
|
|
|
|
|
+ <el-button @click="handleSearch">
|
|
|
|
|
+ <i class="el-icon-search"></i>
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-input>
|
|
|
|
|
+
|
|
|
|
|
+ <el-date-picker
|
|
|
|
|
+ v-model="dateRange"
|
|
|
|
|
+ type="daterange"
|
|
|
|
|
+ range-separator="至"
|
|
|
|
|
+ start-placeholder="开始日期"
|
|
|
|
|
+ end-placeholder="结束日期"
|
|
|
|
|
+ @change="handleSearch"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <el-button type="primary" @click="refreshData" :loading="tableLoading">
|
|
|
|
|
+ <i class="el-icon-refresh mr-1"></i> 刷新
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
|
|
+ <el-table
|
|
|
|
|
+ :data="electricityRecords"
|
|
|
|
|
+ stripe
|
|
|
|
|
+ border
|
|
|
|
|
+ style="width: 100%"
|
|
|
|
|
+ v-loading="tableLoading"
|
|
|
|
|
+ height="500"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-table-column prop="tableNumber" label="表号" min-width="120"/>
|
|
|
|
|
+ <el-table-column label="电压 (V)" min-width="220">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div class="grid grid-cols-3 gap-2">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">A相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.aVoltage || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">B相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.bVoltage || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">C相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.cVoltage || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="电流 (A)" min-width="220">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div class="grid grid-cols-3 gap-2">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">A相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.aCurrent || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">B相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.bCurrent || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">C相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.cCurrent || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="有功功率 (kW)" min-width="220">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">总:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.totalActivePower || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="grid grid-cols-3 gap-2 mt-1">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">A相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.aActivePower || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">B相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.bActivePower || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">C相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.cActivePower || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="功率因数" min-width="220">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">总:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.totalPower || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="grid grid-cols-3 gap-2 mt-1">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">A相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.aPower || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">B相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.bPower || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">C相:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.cPower || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="totalElectricity" label="总用电量 (kWh)" min-width="120"/>
|
|
|
|
|
+ <el-table-column label="分时电量 (kWh)" min-width="220">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div class="grid grid-cols-2 gap-2">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">尖峰:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.sharpActivePowerConsumption || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">峰:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.peakActivePowerConsumption || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">平:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.averageActivePowerConsumption || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span class="text-xs text-gray-500">谷:</span>
|
|
|
|
|
+ <span>{{ parseFloat(scope.row.valleyActivePower || 0).toFixed(2) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="state" label="状态" min-width="100"/>
|
|
|
|
|
+ <el-table-column label="创建时间" min-width="180">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ {{ formatDate(scope.row.createTime) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="flex justify-center mt-4">
|
|
|
|
|
+ <el-pagination
|
|
|
|
|
+ background
|
|
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
|
|
+ :total="totalRecords"
|
|
|
|
|
+ :page-size="pageSize"
|
|
|
|
|
+ :current-page="currentPage"
|
|
|
|
|
+ :page-sizes="[10, 20, 50, 100]"
|
|
|
|
|
+ @size-change="handleSizeChange"
|
|
|
|
|
+ @current-change="handlePageChange"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+.electricity-dashboard {
|
|
|
|
|
+ .el-card {
|
|
|
|
|
+ transition: all 0.3s;
|
|
|
|
|
+
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ transform: translateY(-5px);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Custom scrollbar for tables */
|
|
|
|
|
+ :deep(.el-table__body-wrapper) {
|
|
|
|
|
+ &::-webkit-scrollbar {
|
|
|
|
|
+ width: 6px;
|
|
|
|
|
+ height: 6px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
|
|
+ background: #dcdfe6;
|
|
|
|
|
+ border-radius: 3px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
|
|
+ background: #f5f7fa;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|
|
|
|
|
+
|