1181 lines
30 KiB
Vue
1181 lines
30 KiB
Vue
<template>
|
||
<div class="mian">
|
||
<div class="title">
|
||
<div class="left">
|
||
<div class="left-first" id="time">--:--:--</div>
|
||
<div class="left-second" id="date">----</div>
|
||
</div>
|
||
<div class="center">南川区综合服务中心数智管理平台物业大屏</div>
|
||
<div class="right">
|
||
<div>{{ weekDay }}</div>
|
||
<div>晴</div>
|
||
<div>40℃</div>
|
||
<div class="logout" @click="logout">
|
||
<img
|
||
src="../../../assets/return.png"
|
||
style="width: 1.5rem; height: 1.5rem"
|
||
/>
|
||
<div>退出</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="header">
|
||
<div class="header-item">
|
||
<span class="header-label">今年用电量</span>
|
||
<span class="header-value orange">180</span>
|
||
<span class="header-unit">亿kwh</span>
|
||
</div>
|
||
<div class="header-item">
|
||
<span class="header-label">本月用电总量</span>
|
||
<span class="header-value green">1.8</span>
|
||
<span class="header-unit">亿kwh</span>
|
||
</div>
|
||
<div class="header-item">
|
||
<span class="header-label">今年用水总量</span>
|
||
<span class="header-value blue">2600</span>
|
||
<span class="header-unit">万吨</span>
|
||
</div>
|
||
<div class="header-item">
|
||
<span class="header-label">本月用水总量</span>
|
||
<span class="header-value purple">30</span>
|
||
<span class="header-unit">万吨</span>
|
||
</div>
|
||
<div class="header-item">
|
||
<span class="header-label">设备总数</span>
|
||
<span class="header-value green">500</span>
|
||
<span class="header-unit">台</span>
|
||
</div>
|
||
</div>
|
||
<div class="contents">
|
||
<div class="content">
|
||
<div class="content-left">
|
||
<div class="first">
|
||
<div
|
||
ref="barChart"
|
||
class="bar-chart"
|
||
style="width: 100%; height:242px"
|
||
></div>
|
||
</div>
|
||
<div class="second">
|
||
<div ref="powerChart" class="power-chart"></div>
|
||
</div>
|
||
<div class="third">
|
||
<div ref="envChart" class="env-chart"></div>
|
||
</div>
|
||
</div>
|
||
<div class="content-center">
|
||
<div class="content-center-first">
|
||
<div class="first-item">
|
||
<div class="item"></div>
|
||
</div>
|
||
</div>
|
||
<div class="content-center-second">
|
||
<div>
|
||
<EchartsUI
|
||
ref="water"
|
||
height="100%"
|
||
width="150px"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<EchartsUI
|
||
ref="electricity"
|
||
height="100%"
|
||
width="150px"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<EchartsUI
|
||
ref="accessControl"
|
||
height="100%"
|
||
width="150px"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<EchartsUI
|
||
ref="camera"
|
||
height="100%"
|
||
width="150px"
|
||
/>
|
||
</div>
|
||
<!-- <div class="second-item" @click="changeToPersonnelDuty">-->
|
||
<!-- <div>-->
|
||
<!-- <div class="second-item-box1">645</div>-->
|
||
<!-- <div class="second-item-box-label">采购部</div>-->
|
||
<!-- </div>-->
|
||
<!-- <div>-->
|
||
<!-- <div class="second-item-box2">729</div>-->
|
||
<!-- <div class="second-item-box-label">研发部</div>-->
|
||
<!-- </div>-->
|
||
<!-- <div>-->
|
||
<!-- <div class="second-item-box3">648</div>-->
|
||
<!-- <div class="second-item-box-label">安保部</div>-->
|
||
<!-- </div>-->
|
||
<!-- <div>-->
|
||
<!-- <div class="second-item-box4">786</div>-->
|
||
<!-- <div class="second-item-box-label">人事部</div>-->
|
||
<!-- </div>-->
|
||
<!-- <div>-->
|
||
<!-- <div class="second-item-box5">645</div>-->
|
||
<!-- <div class="second-item-box-label">财务部</div>-->
|
||
<!-- </div>-->
|
||
<!-- </div>-->
|
||
</div>
|
||
</div>
|
||
<div class="content-right">
|
||
<div class="first">
|
||
<!-- <div ref="waterChart" class="water-chart"></div>-->
|
||
<!-- <div ref="pie3dChart" class="pie3d-chart"></div> -->
|
||
<div class="mt-8" style="position: relative">
|
||
<div
|
||
class="flex items-center justify-between p-5"
|
||
>
|
||
<Radio.Group v-model:value="timeUnit" size="small">
|
||
<Radio.Button value="1" style="background-color: transparent;color: #fff">电量</Radio.Button>
|
||
</Radio.Group>
|
||
<DatePicker
|
||
v-model:value="selectedDate"
|
||
picker="month"
|
||
placeholder="请选择月份"
|
||
style="width: 130px;height: 25px;background-color: transparent;"
|
||
@change="handleDateChange"
|
||
class="white-text-datepicker"
|
||
/>
|
||
</div>
|
||
<div v-if="timeUnit == 1">
|
||
<AnalyticsTrends
|
||
ref="analyticsTrendsRef"
|
||
:selected-date="selectedDate"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="second">
|
||
<div class="second-box">
|
||
<div class="box-content" v-for="(item,index) in warning" :key="index">
|
||
<div class="box-content-label">{{ item.typeName }}</div>
|
||
<div class="box-content-num">{{item.total}}</div>
|
||
</div>
|
||
</div>
|
||
<!-- <div ref="waterChart" class="water-chart"></div> -->
|
||
</div>
|
||
<div class="third">
|
||
<!-- <div ref="deviceChart" class="device-chart"></div>-->
|
||
<div class="third-item">
|
||
<div class="third-title">会议室总数</div>
|
||
<div class="third-num">{{todayMeetCount?.meetCount}}</div>
|
||
</div>
|
||
<div class="third-item">
|
||
<div class="third-title">当日预约会议室总数</div>
|
||
<div class="third-num">{{todayMeetCount?.timeQuantity}}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import {getStatistics,getworkOrder,getTodayMeetCount,getHydropower,getAccessControl,getCamera,queryTwentyfourRunningDatasByPlNos} from '#/api/analytics';
|
||
import AnalyticsTrends from './analytics-trends.vue';
|
||
import { Radio } from 'ant-design-vue';
|
||
import {EchartsUI, useEcharts} from "@vben/plugins/echarts";
|
||
|
||
//预警类型
|
||
const warning = ref([])
|
||
async function getWarning() {
|
||
warning.value = await getStatistics();
|
||
}
|
||
//tab选择
|
||
const timeUnit = ref(1);
|
||
// 月份选择
|
||
const selectedDate = ref<any>(null);
|
||
const paramDate = ref(null);
|
||
|
||
const analyticsTrendsRef = ref<InstanceType<typeof AnalyticsTrends> | null>(
|
||
null,
|
||
);
|
||
const handleDateChange = (date: any) => {
|
||
paramDate.value = date.format('YYYY-MM');
|
||
// 调用子组件的方法
|
||
if (
|
||
analyticsTrendsRef.value &&
|
||
analyticsTrendsRef.value.getMeterRecordTrend
|
||
) {
|
||
analyticsTrendsRef.value.getMeterRecordTrend(paramDate);
|
||
}
|
||
};
|
||
//会议室
|
||
const todayMeetCount = ref();
|
||
const handleTodayMeetCount = async () => {
|
||
todayMeetCount.value = await getTodayMeetCount();
|
||
};
|
||
// 水
|
||
const water = ref();
|
||
const { renderEcharts: renderWater } = useEcharts(water);
|
||
async function fetchWater() {
|
||
const data = await getHydropower()
|
||
const waterData = [
|
||
{ name: '离线', value: data.water.off },
|
||
{ name: '在线', value: data.water.on }
|
||
];
|
||
renderWater({
|
||
title: {
|
||
text: '水',
|
||
left: 'center',
|
||
top: 'bottom',
|
||
padding: [0, 0, 15, 0],
|
||
textStyle: {
|
||
color: '#fff',
|
||
fontSize: 16,
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'item'
|
||
},
|
||
series: [
|
||
{
|
||
type: 'pie',
|
||
radius: ['40%', '70%'],
|
||
avoidLabelOverlap: false,
|
||
itemStyle: {
|
||
borderRadius: 5,
|
||
borderColor: '#fff',
|
||
borderWidth: 1
|
||
},
|
||
label: {
|
||
show: false,
|
||
position: 'center'
|
||
},
|
||
emphasis: {
|
||
label: {
|
||
show: true,
|
||
fontSize: 10,
|
||
}
|
||
},
|
||
labelLine: {
|
||
show: false
|
||
},
|
||
data:waterData
|
||
}
|
||
]
|
||
})
|
||
}
|
||
// 电
|
||
const electricity = ref();
|
||
const { renderEcharts: renderElectricity } = useEcharts(electricity);
|
||
async function fetchElectricity() {
|
||
const data = await getHydropower()
|
||
const electricityData = [
|
||
{ name: '离线', value: data.power.off },
|
||
{ name: '在线', value: data.power.on }
|
||
];
|
||
renderElectricity({
|
||
title: {
|
||
text: '电',
|
||
left: 'center',
|
||
top: 'bottom',
|
||
padding: [0, 0, 15, 0],
|
||
textStyle: {
|
||
color: '#fff',
|
||
fontSize: 16,
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'item'
|
||
},
|
||
series: [
|
||
{
|
||
type: 'pie',
|
||
radius: ['40%', '70%'],
|
||
avoidLabelOverlap: false,
|
||
itemStyle: {
|
||
borderRadius: 5,
|
||
borderColor: '#fff',
|
||
borderWidth: 1
|
||
},
|
||
label: {
|
||
show: false,
|
||
position: 'center'
|
||
},
|
||
emphasis: {
|
||
label: {
|
||
show: true,
|
||
fontSize: 10,
|
||
}
|
||
},
|
||
labelLine: {
|
||
show: false
|
||
},
|
||
data:electricityData
|
||
}
|
||
]
|
||
})
|
||
}
|
||
// 门禁
|
||
const accessControl = ref();
|
||
const { renderEcharts: renderAccessControl } = useEcharts(accessControl);
|
||
async function fetchAccessControl() {
|
||
const data = await getAccessControl()
|
||
const accessControlData = [
|
||
{ name: '离线', value: data.off },
|
||
{ name: '在线', value: data.on }
|
||
];
|
||
renderAccessControl({
|
||
title: {
|
||
text: '门禁',
|
||
left: 'center',
|
||
top: 'bottom',
|
||
padding: [0, 0, 15, 0],
|
||
textStyle: {
|
||
color: '#fff',
|
||
fontSize: 16,
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'item'
|
||
},
|
||
series: [
|
||
{
|
||
type: 'pie',
|
||
radius: ['40%', '70%'],
|
||
avoidLabelOverlap: false,
|
||
itemStyle: {
|
||
borderRadius: 5,
|
||
borderColor: '#fff',
|
||
borderWidth: 1
|
||
},
|
||
label: {
|
||
show: false,
|
||
position: 'center'
|
||
},
|
||
emphasis: {
|
||
label: {
|
||
show: true,
|
||
fontSize: 10,
|
||
}
|
||
},
|
||
labelLine: {
|
||
show: false
|
||
},
|
||
data:accessControlData
|
||
}
|
||
]
|
||
})
|
||
}
|
||
// 摄像头
|
||
const camera = ref();
|
||
const { renderEcharts: renderCamera } = useEcharts(camera);
|
||
async function fetchCamera() {
|
||
const data = await getCamera()
|
||
const cameraData = [
|
||
{ name: '离线', value: data.off },
|
||
{ name: '在线', value: data.on }
|
||
];
|
||
renderCamera({
|
||
title: {
|
||
text: '摄像头',
|
||
left: 'center',
|
||
top: 'bottom',
|
||
padding: [0, 0, 15, 0],
|
||
textStyle: {
|
||
color: '#fff',
|
||
fontSize: 16,
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'item'
|
||
},
|
||
series: [
|
||
{
|
||
type: 'pie',
|
||
radius: ['40%', '70%'],
|
||
avoidLabelOverlap: false,
|
||
itemStyle: {
|
||
borderRadius: 5,
|
||
borderColor: '#fff',
|
||
borderWidth: 1
|
||
},
|
||
label: {
|
||
show: false,
|
||
position: 'center'
|
||
},
|
||
emphasis: {
|
||
label: {
|
||
show: true,
|
||
fontSize: 10,
|
||
}
|
||
},
|
||
labelLine: {
|
||
show: false
|
||
},
|
||
data:cameraData
|
||
}
|
||
]
|
||
})
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||
import { useRouter } from 'vue-router';
|
||
import * as echarts from 'echarts';
|
||
import 'echarts-gl';
|
||
import { renderPie3DChart } from '#/utils/pie3d';
|
||
import {
|
||
addChartToResizeManager,
|
||
removeChartFromResizeManager,
|
||
} from '#/utils/echartsResize';
|
||
import { useFlexibleRem } from '#/utils/useFlexibleRem';
|
||
import {DatePicker} from "ant-design-vue";
|
||
import {getCamera} from "#/api/analytics";
|
||
useFlexibleRem();
|
||
// 路由
|
||
const router = useRouter();
|
||
|
||
// 图表实例
|
||
const barChart = ref<HTMLElement>();
|
||
const powerChart = ref<HTMLElement>();
|
||
const envChart = ref<HTMLElement>();
|
||
const waterChart = ref<HTMLElement>();
|
||
const deviceChart = ref<HTMLElement>();
|
||
const pie3dChart = ref<HTMLElement>();
|
||
|
||
// 定时器
|
||
let timer: number | null = null;
|
||
|
||
// 星期几
|
||
const weekDay = ref('');
|
||
|
||
// 图表实例
|
||
let barChartInstance: echarts.ECharts | null = null;
|
||
let powerChartInstance: echarts.ECharts | null = null;
|
||
let envChartInstance: echarts.ECharts | null = null;
|
||
let waterChartInstance: echarts.ECharts | null = null;
|
||
let deviceChartInstance: echarts.ECharts | null = null;
|
||
let pie3dChartInstance: any = null;
|
||
|
||
// 退出方法
|
||
const logout = () => {
|
||
router.push('/navigation');
|
||
};
|
||
|
||
// 更新时间
|
||
const updateTime = () => {
|
||
const now = new Date();
|
||
const time = now.toLocaleTimeString('zh-CN', { hour12: false });
|
||
const date =
|
||
now.getFullYear() +
|
||
'.' +
|
||
String(now.getMonth() + 1).padStart(2, '0') +
|
||
'.' +
|
||
String(now.getDate()).padStart(2, '0');
|
||
|
||
// 获取星期几
|
||
const weekDays = ['日', '一', '二', '三', '四', '五', '六'];
|
||
weekDay.value = '星期' + weekDays[now.getDay()];
|
||
|
||
const timeElement = document.getElementById('time');
|
||
const dateElement = document.getElementById('date');
|
||
|
||
if (timeElement) timeElement.innerText = time;
|
||
if (dateElement) dateElement.innerText = date;
|
||
};
|
||
|
||
|
||
// 初始化柱状图
|
||
const initBarChart = async () => {
|
||
if (!barChart.value) return;
|
||
const myChart = echarts.init(barChart.value);
|
||
const workOrder = await getworkOrder();
|
||
const title = workOrder.map((item) => {return item.type})
|
||
const statuses = ['已派单', '处理中', '已完成', '创建工单'];
|
||
const seriesData = statuses.map(status => {
|
||
return {
|
||
name: status,
|
||
type: 'bar',
|
||
emphasis: { focus: 'series' },
|
||
data: workOrder.map(item => item.statusCounts[status])
|
||
};
|
||
});
|
||
myChart.setOption({
|
||
tooltip: {},
|
||
legend: {
|
||
data: statuses, // 图例数据,与series中的name对应
|
||
top: 10, // 位置控制
|
||
textStyle: {
|
||
color: '#fff'
|
||
}
|
||
},
|
||
grid: { left: 40, right: 20, top: 50, bottom: 25 },
|
||
xAxis: { data: title ,axisLabel: { color: '#fff' },},
|
||
yAxis: {axisLabel: { color: '#fff' },},
|
||
series:seriesData,
|
||
});
|
||
};
|
||
|
||
// 初始化预约情况图表
|
||
const initPowerChart = () => {
|
||
if (!powerChart.value) return;
|
||
const chart = echarts.init(powerChart.value);
|
||
const option = {
|
||
tooltip: { trigger: 'axis' },
|
||
grid: { left: 40, right: 50, top: 62, bottom: 20 },
|
||
xAxis: {
|
||
type: 'category',
|
||
data: Array.from({ length: 19 }, (_, i) => i + 6),
|
||
axisLine: { lineStyle: { color: '#3ec6ff' } },
|
||
axisLabel: { color: '#fff' },
|
||
name: '小时',
|
||
nameTextStyle: { color: '#fff' },
|
||
nameLocation: 'end',
|
||
nameGap: 5,
|
||
},
|
||
yAxis: {
|
||
type: 'value',
|
||
name: '次',
|
||
nameTextStyle: { color: '#fff' },
|
||
nameLocation: 'end',
|
||
nameGap: 10,
|
||
axisLine: { lineStyle: { color: '#3ec6ff' } },
|
||
axisLabel: { color: '#fff' },
|
||
splitLine: { lineStyle: { color: '#1e90ff22' } },
|
||
},
|
||
series: [
|
||
{
|
||
data: [
|
||
80, 120, 100, 130, 150, 180, 200, 220, 250, 285, 230, 200, 180, 150,
|
||
120, 100, 80, 60, 40,
|
||
],
|
||
type: 'line',
|
||
smooth: true,
|
||
symbol: 'circle',
|
||
symbolSize: 0,
|
||
itemStyle: { color: '#3ec6ff' },
|
||
lineStyle: { width: 1 },
|
||
areaStyle: {
|
||
color: new echarts.graphic.LinearGradient(
|
||
0,
|
||
0,
|
||
0,
|
||
1, // 上→下
|
||
[
|
||
{ offset: 0, color: '#32B7E9' },
|
||
{ offset: 1, color: 'rgba(50,183,233,0)' },
|
||
],
|
||
),
|
||
},
|
||
},
|
||
],
|
||
};
|
||
chart.setOption(option);
|
||
powerChartInstance = chart;
|
||
addChartToResizeManager(chart);
|
||
};
|
||
|
||
// 人流车流
|
||
const initEnvChart = async () => {
|
||
if (!envChart.value) return;
|
||
const data = await queryTwentyfourRunningDatasByPlNos()
|
||
const inCounts = data.data.inCounts
|
||
const staticTimeStrs = data.data.staticTimeStrs
|
||
console.log(data)
|
||
const chart = echarts.init(envChart.value);
|
||
const option = {
|
||
tooltip: { trigger: 'axis' },
|
||
grid: { left: 40, right: 20, top: 40, bottom: 30 },
|
||
xAxis: {
|
||
type: 'category',
|
||
data: staticTimeStrs,
|
||
axisLine: { lineStyle: { color: '#3ec6ff' } },
|
||
axisLabel: { color: '#fff' },
|
||
},
|
||
yAxis: {
|
||
type: 'value',
|
||
axisLine: { lineStyle: { color: '#3ec6ff' } },
|
||
axisLabel: { color: '#fff' },
|
||
splitLine: { lineStyle: { color: '#1e90ff22' } },
|
||
},
|
||
series: [
|
||
{
|
||
name: '车流',
|
||
data: inCounts,
|
||
type: 'line',
|
||
smooth: true,
|
||
itemStyle: { color: '#b388ff' },
|
||
lineStyle: { width: 3 },
|
||
areaStyle: { color: 'rgba(179,136,255,0.2)' },
|
||
symbol: 'circle',
|
||
symbolSize: 0,
|
||
},
|
||
// {
|
||
// name: '去年',
|
||
// data: [80, 120, 100, 180, 150, 120, 60, 40],
|
||
// type: 'line',
|
||
// smooth: true,
|
||
// itemStyle: { color: '#ffb300' },
|
||
// lineStyle: { width: 3 },
|
||
// areaStyle: { color: 'rgba(255,179,0,0.15)' },
|
||
// symbol: 'circle',
|
||
// symbolSize: 0,
|
||
// },
|
||
],
|
||
};
|
||
chart.setOption(option);
|
||
envChartInstance = chart;
|
||
addChartToResizeManager(chart);
|
||
};
|
||
|
||
// 初始化水表图表
|
||
const initWaterChart = () => {
|
||
if (!waterChart.value) return;
|
||
|
||
const chart = echarts.init(waterChart.value);
|
||
const option = {
|
||
tooltip: { trigger: 'axis' },
|
||
legend: {
|
||
data: ['今日', '平均'],
|
||
textStyle: { color: '#fff' },
|
||
right: 20,
|
||
top: 10,
|
||
},
|
||
grid: { left: 40, right: 20, top: 40, bottom: 30 },
|
||
xAxis: {
|
||
type: 'category',
|
||
data: Array.from({ length: 19 }, (_, i) => i + 6),
|
||
axisLine: { lineStyle: { color: '#3ec6ff' } },
|
||
axisLabel: { color: '#fff' },
|
||
},
|
||
yAxis: {
|
||
type: 'value',
|
||
axisLine: { lineStyle: { color: '#3ec6ff' } },
|
||
axisLabel: { color: '#fff' },
|
||
splitLine: { lineStyle: { color: '#1e90ff22' } },
|
||
},
|
||
series: [
|
||
{
|
||
name: '今日',
|
||
data: [
|
||
1.2, 2.1, 1.8, 2.5, 3.0, 3.8, 4.2, 4.5, 4.8, 4.8, 4.0, 3.2, 2.5, 2.0,
|
||
1.5, 1.0, 0.8, 0.5, 0.2,
|
||
],
|
||
type: 'line',
|
||
smooth: true,
|
||
symbol: 'circle',
|
||
symbolSize: 0,
|
||
itemStyle: { color: '#3ec6ff' },
|
||
lineStyle: { width: 1 },
|
||
areaStyle: {
|
||
color: new echarts.graphic.LinearGradient(
|
||
0,
|
||
0,
|
||
0,
|
||
1, // 上→下
|
||
[
|
||
{ offset: 0, color: '#32B7E9' },
|
||
{ offset: 1, color: 'rgba(50,183,233,0)' },
|
||
],
|
||
),
|
||
},
|
||
},
|
||
{
|
||
name: '平均',
|
||
data: Array(19).fill(2.5),
|
||
type: 'line',
|
||
smooth: true,
|
||
symbol: 'none',
|
||
itemStyle: { color: '#ff6b00' },
|
||
lineStyle: { width: 1, type: 'solid', color: '#ff6b00' },
|
||
},
|
||
],
|
||
};
|
||
chart.setOption(option);
|
||
waterChartInstance = chart;
|
||
addChartToResizeManager(chart);
|
||
};
|
||
|
||
// 初始化设备图表
|
||
const initDeviceChart = () => {
|
||
if (!deviceChart.value) return;
|
||
|
||
const chart = echarts.init(deviceChart.value);
|
||
const option = {
|
||
grid: { left: 60, right: 40, top: 10, bottom: 30 },
|
||
xAxis: {
|
||
type: 'value',
|
||
axisLine: { lineStyle: { color: '#8697BA' } },
|
||
axisLabel: { color: '#fff' },
|
||
splitLine: { show: false },
|
||
},
|
||
yAxis: {
|
||
type: 'category',
|
||
data: ['门禁', '监控', '水表'],
|
||
axisLine: { lineStyle: { color: '#8697BA' } },
|
||
axisLabel: { color: '#A1B2C2' },
|
||
},
|
||
series: [
|
||
{
|
||
name: '设备数',
|
||
type: 'bar',
|
||
data: [650, 120, 40],
|
||
barWidth: 12,
|
||
itemStyle: {
|
||
color: function (params: any) {
|
||
const colors = [
|
||
new echarts.graphic.LinearGradient(
|
||
0,
|
||
0,
|
||
0,
|
||
1, // 上→下
|
||
[
|
||
{ offset: 0, color: '#2986B1' },
|
||
{ offset: 1, color: '#6941FF' },
|
||
],
|
||
),
|
||
new echarts.graphic.LinearGradient(
|
||
0,
|
||
0,
|
||
0,
|
||
1, // 上→下
|
||
[
|
||
{ offset: 0, color: '#33FF99' },
|
||
{ offset: 1, color: '#00908E' },
|
||
],
|
||
),
|
||
new echarts.graphic.LinearGradient(
|
||
0,
|
||
0,
|
||
0,
|
||
1, // 上→下
|
||
[
|
||
{ offset: 0, color: '#01B4FF' },
|
||
{ offset: 1, color: '#0336FF' },
|
||
],
|
||
),
|
||
];
|
||
return colors[params.dataIndex];
|
||
},
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: 'right',
|
||
color: '#fff',
|
||
},
|
||
},
|
||
],
|
||
};
|
||
chart.setOption(option);
|
||
deviceChartInstance = chart;
|
||
addChartToResizeManager(chart);
|
||
};
|
||
|
||
// 初始化3D饼图
|
||
const initPie3DChart = () => {
|
||
if (!pie3dChart.value) return;
|
||
|
||
pie3dChartInstance = renderPie3DChart(pie3dChart.value, {
|
||
data: [
|
||
{ name: 'A区域', value: 20, itemStyle: { color: '#3ffbff' } },
|
||
{ name: 'D区域', value: 20, itemStyle: { color: '#b388ff' } },
|
||
{ name: 'C区域', value: 45, itemStyle: { color: '#ff9900' } },
|
||
{ name: 'B区域', value: 15, itemStyle: { color: '#3f6bff' } },
|
||
],
|
||
hoverHeightScale: 2,
|
||
selectOffset: 0.1,
|
||
distance: 220,
|
||
boxHeight: 5,
|
||
});
|
||
if (pie3dChartInstance) {
|
||
addChartToResizeManager(pie3dChartInstance);
|
||
}
|
||
};
|
||
|
||
// const changeToPersonnelDuty=()=>{
|
||
// router.push('/property/attendanceManagement/workforceManagement')
|
||
// }
|
||
|
||
// 组件挂载时初始化
|
||
onMounted(() => {
|
||
getWarning()
|
||
handleTodayMeetCount()
|
||
fetchWater()
|
||
fetchElectricity()
|
||
fetchAccessControl()
|
||
fetchCamera()
|
||
|
||
updateTime();
|
||
timer = setInterval(updateTime, 1000);
|
||
initBarChart();
|
||
initPowerChart();
|
||
initEnvChart();
|
||
initWaterChart();
|
||
initDeviceChart();
|
||
initPie3DChart();
|
||
});
|
||
|
||
// 组件卸载时清理
|
||
onBeforeUnmount(() => {
|
||
if (timer) {
|
||
clearInterval(timer);
|
||
}
|
||
|
||
// 从管理器中移除图表
|
||
if (barChartInstance) {
|
||
removeChartFromResizeManager(barChartInstance);
|
||
barChartInstance.dispose();
|
||
}
|
||
if (powerChartInstance) {
|
||
removeChartFromResizeManager(powerChartInstance);
|
||
powerChartInstance.dispose();
|
||
}
|
||
if (envChartInstance) {
|
||
removeChartFromResizeManager(envChartInstance);
|
||
envChartInstance.dispose();
|
||
}
|
||
if (waterChartInstance) {
|
||
removeChartFromResizeManager(waterChartInstance);
|
||
waterChartInstance.dispose();
|
||
}
|
||
if (deviceChartInstance) {
|
||
removeChartFromResizeManager(deviceChartInstance);
|
||
deviceChartInstance.dispose();
|
||
}
|
||
if (pie3dChartInstance) {
|
||
removeChartFromResizeManager(pie3dChartInstance);
|
||
pie3dChartInstance.dispose();
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.white-text-datepicker :deep(.ant-picker-input > input::placeholder) {
|
||
color: #fff !important;
|
||
}
|
||
.white-text-datepicker :deep(.ant-picker-input > input) {
|
||
color: white !important;
|
||
}
|
||
.white-text-datepicker :deep(.ant-picker-suffix > .anticon) {
|
||
color: white !important;
|
||
}
|
||
@font-face {
|
||
font-family: 'ShiShangZhongHeiJianTi';
|
||
src: url('../../../assets/fonts/时尚中黑简体.ttf') format('truetype');
|
||
font-weight: normal;
|
||
font-style: normal;
|
||
}
|
||
.mian {
|
||
height: 100vh;
|
||
background: url('../../../assets/property/bg1.png');
|
||
background-size: 100% 100%;
|
||
background-color: #081b3a;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.title {
|
||
height: 5.375rem;
|
||
align-items: center;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
.left {
|
||
display: flex;
|
||
width: 18.3125rem;
|
||
.left-first {
|
||
padding-left: 2.3125rem;
|
||
font-size: 1.875rem;
|
||
width: 10.5rem;
|
||
color: #ffffff;
|
||
}
|
||
.left-second {
|
||
width: 6.5rem;
|
||
font-family: ShiShangZhongHeiJianTi;
|
||
font-weight: 400;
|
||
font-size: 1.25rem;
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
.center {
|
||
font-size: 1.9rem;
|
||
color: #fff;
|
||
text-align: center;
|
||
font-weight: bold;
|
||
letter-spacing: 0.1em;
|
||
text-shadow:
|
||
0 0 10px #1e90ff,
|
||
0 0 20px #1e90ff;
|
||
}
|
||
.right {
|
||
width: 17.3125rem;
|
||
display: flex;
|
||
font-family: ShiShangZhongHeiJianTi;
|
||
font-weight: 400;
|
||
font-size: 1.25rem;
|
||
color: #ffffff;
|
||
gap: 0.75rem;
|
||
.logout {
|
||
display: flex;
|
||
cursor: pointer;
|
||
align-items: center;
|
||
gap: 0.2rem;
|
||
}
|
||
}
|
||
}
|
||
.header {
|
||
margin-top: 1.125rem;
|
||
margin-left: 4.625rem;
|
||
margin-right: 4.25rem;
|
||
height: 6rem;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
.header-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 1.5rem;
|
||
border-radius: 0.5rem;
|
||
box-shadow:
|
||
0 0 10px #0ff2,
|
||
0 0 20px #0ff2 inset;
|
||
}
|
||
.header-label {
|
||
color: #fff;
|
||
font-size: 1rem;
|
||
margin-right: 0.5rem;
|
||
letter-spacing: 0.05em;
|
||
}
|
||
|
||
.header-value {
|
||
font-size: 1.5rem;
|
||
font-weight: bold;
|
||
margin: 0 0.2rem;
|
||
font-family: ShiShangZhongHeiJianTi;
|
||
}
|
||
|
||
.header-value.orange {
|
||
color: #ffb300;
|
||
}
|
||
.header-value.green {
|
||
color: #00ffb0;
|
||
}
|
||
.header-value.blue {
|
||
color: #3ec6ff;
|
||
}
|
||
.header-value.purple {
|
||
color: #b388ff;
|
||
}
|
||
|
||
.header-unit {
|
||
color: #fff;
|
||
font-size: 1rem;
|
||
margin-left: 0.2rem;
|
||
}
|
||
}
|
||
.header div {
|
||
width: 20.125rem;
|
||
}
|
||
.contents {
|
||
flex: 1;
|
||
.content {
|
||
height: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin: 0 2.25rem 2.25rem 2.25rem;
|
||
.content-left {
|
||
width: 32.6875rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
.first {
|
||
height: 16.81rem;
|
||
.pie3d-title {
|
||
color: #fff;
|
||
font-size: 1.1rem;
|
||
font-weight: bold;
|
||
margin-bottom: 0.3rem;
|
||
}
|
||
.pie3d-water {
|
||
color: #fff;
|
||
font-size: 0.95rem;
|
||
margin-bottom: 0.2rem;
|
||
}
|
||
.pie3d-water-num {
|
||
font-size: 1.3rem;
|
||
color: #3ec6ff;
|
||
background: #0a1e3a;
|
||
border-radius: 0.2rem;
|
||
padding: 0 0.2rem;
|
||
margin: 0 0.2rem;
|
||
letter-spacing: 0.1em;
|
||
}
|
||
.pie3d-chart {
|
||
width: 100%;
|
||
height: 176px;
|
||
min-height: unset;
|
||
margin: 0 auto;
|
||
}
|
||
.bar-chart {
|
||
margin-top: 35px;
|
||
}
|
||
}
|
||
.second {
|
||
height: 12rem;
|
||
/* margin-top:2.25rem; */
|
||
/* margin-bottom: 2rem; */
|
||
.power-chart {
|
||
height: 100%;
|
||
/* margin-top: 0.2rem; */
|
||
}
|
||
}
|
||
.third {
|
||
height: 12.12rem;
|
||
.env-chart {
|
||
height: 12rem;
|
||
}
|
||
}
|
||
}
|
||
.content-center {
|
||
width: 47.5rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
.content-center-first {
|
||
height: 30.9rem;
|
||
.first-item {
|
||
height: 100%;
|
||
width: 100%;
|
||
background: url('../../../assets/property/center-bg.png');
|
||
background-size: 95% 95%;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
}
|
||
}
|
||
.content-center-second {
|
||
height: 12.5rem;
|
||
display: flex;
|
||
justify-content: space-around;
|
||
}
|
||
}
|
||
.content-right {
|
||
width: 32.68rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
.first {
|
||
height: 16.81rem;
|
||
//background-color: red;
|
||
.water-chart {
|
||
height: 100%;
|
||
/* margin-top: 0.2rem; */
|
||
}
|
||
}
|
||
.second {
|
||
height: 11rem;
|
||
margin-top: 2rem;
|
||
margin-bottom: 2rem;
|
||
.second-box {
|
||
margin-left: 0.5rem;
|
||
margin-top: 3.5rem;
|
||
display: flex;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
.box-content {
|
||
height: 7rem;
|
||
width: 7rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
.box-content-label {
|
||
font-family: Microsoft YaHei;
|
||
font-weight: 400;
|
||
font-size: 0.8rem;
|
||
color: #c4d6ff;
|
||
line-height: 2rem;
|
||
}
|
||
.box-content-num {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
width: 6rem;
|
||
height: 6rem;
|
||
background: url('../../../assets/property/customer-circle.png');
|
||
background-size: 100% 100%;
|
||
font-family: Microsoft YaHei;
|
||
font-weight: 400;
|
||
font-size: 1.2rem;
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.third {
|
||
padding: 5rem;
|
||
height: 13.12rem;
|
||
display: flex;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
.third-item{
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
.third-title{
|
||
font-family: Microsoft YaHei;
|
||
font-weight: 400;
|
||
font-size: 0.8rem;
|
||
color: #c4d6ff;
|
||
line-height: 2rem;
|
||
}
|
||
.third-num{
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
width: 6rem;
|
||
height: 4rem;
|
||
background: url('../../../assets/monitor/device-alerts-bg2.png');
|
||
background-size: 100% 100%;
|
||
|
||
font-family: Microsoft YaHei;
|
||
font-weight: 400;
|
||
font-size: 1.2rem;
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
.device-chart {
|
||
height: 10rem;
|
||
margin-top: 2rem;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.pie3d-title {
|
||
color: #fff;
|
||
font-size: 1.1rem;
|
||
font-weight: bold;
|
||
margin-bottom: 0.3rem;
|
||
}
|
||
.pie3d-water {
|
||
color: #fff;
|
||
font-size: 0.95rem;
|
||
margin-bottom: 0.2rem;
|
||
}
|
||
.pie3d-water-num {
|
||
font-size: 1.3rem;
|
||
color: #3ec6ff;
|
||
background: #0a1e3a;
|
||
border-radius: 0.2rem;
|
||
padding: 0 0.2rem;
|
||
margin: 0 0.2rem;
|
||
letter-spacing: 0.1em;
|
||
}
|
||
.pie3d-chart {
|
||
width: 100%;
|
||
height: 176px;
|
||
min-height: unset;
|
||
margin: 0 auto;
|
||
}
|
||
</style>
|