|
|
@@ -0,0 +1,504 @@
|
|
|
+<template>
|
|
|
+ <div class="hardware-data">
|
|
|
+ <!-- 标题 -->
|
|
|
+ <div class="module-title">硬件数据</div>
|
|
|
+
|
|
|
+ <!-- 智能电表部分 -->
|
|
|
+ <div class="data-section">
|
|
|
+ <div class="device-info">
|
|
|
+ <div class="device-icon electric"></div>
|
|
|
+ <div>
|
|
|
+ <div class="device-count">8921</div>
|
|
|
+ <div class="device-name">智能电表</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="data-cards">
|
|
|
+ <div class="data-card">
|
|
|
+ <div class="data-label">年度用电</div>
|
|
|
+ <div>
|
|
|
+ <div class="data-value">428921</div>
|
|
|
+ <div class="data-unit">kW·h</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="data-card">
|
|
|
+ <div class="data-label">月均用电</div>
|
|
|
+ <div>
|
|
|
+ <div class="data-value">18921</div>
|
|
|
+ <div class="data-unit">kW·h</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="data-card">
|
|
|
+ <div class="data-label">日均用电</div>
|
|
|
+ <div>
|
|
|
+ <div class="data-value">8921</div>
|
|
|
+ <div class="data-unit">kW·h</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="data-card">
|
|
|
+ <div class="data-label">开关次数</div>
|
|
|
+ <div>
|
|
|
+ <div class="data-value">887</div>
|
|
|
+ <div class="data-unit">近12个月</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="charts-container">
|
|
|
+ <div ref="powerChart" class="chart-item"></div>
|
|
|
+ <div ref="waterChart" class="chart-item"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 智能水表部分 -->
|
|
|
+ <div class="data-section">
|
|
|
+ <div class="device-info">
|
|
|
+ <div class="device-icon water"></div>
|
|
|
+ <div class="device-name">智能水表</div>
|
|
|
+ <div class="device-count">8921</div>
|
|
|
+ </div>
|
|
|
+ <div class="data-cards">
|
|
|
+ <div class="data-card">
|
|
|
+ <div class="data-label">年度用水</div>
|
|
|
+ <div>
|
|
|
+ <div class="data-value">89321</div>
|
|
|
+ <div class="data-unit">m³</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="data-card">
|
|
|
+ <div class="data-label">月均用水</div>
|
|
|
+ <div>
|
|
|
+ <div class="data-value">9212</div>
|
|
|
+ <div class="data-unit">m³</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="data-card">
|
|
|
+ <div class="data-label">日均用水</div>
|
|
|
+ <div>
|
|
|
+ <div class="data-value">921</div>
|
|
|
+ <div class="data-unit">m³</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="data-card">
|
|
|
+ <div class="data-label">开关次数</div>
|
|
|
+ <div>
|
|
|
+ <div class="data-value">887</div>
|
|
|
+ <div class="data-unit">近12个月</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import * as echarts from 'echarts'
|
|
|
+export default {
|
|
|
+ name: 'HardwareData',
|
|
|
+ data () {
|
|
|
+ return {
|
|
|
+ powerChartInstance: null,
|
|
|
+ waterChartInstance: null,
|
|
|
+ // 模拟月度数据
|
|
|
+ monthlyData: [
|
|
|
+ { month: '十二月', power: 220000, water: 180000 },
|
|
|
+ { month: '一月', power: 210000, water: 170000 },
|
|
|
+ { month: '二月', power: 230000, water: 190000 },
|
|
|
+ { month: '三月', power: 225000, water: 185000 },
|
|
|
+ { month: '四月', power: 215000, water: 175000 },
|
|
|
+ { month: '五月', power: 200000, water: 160000 },
|
|
|
+ { month: '六月', power: 205000, water: 165000 },
|
|
|
+ { month: '七月', power: 210000, water: 170000 },
|
|
|
+ { month: '八月', power: 215000, water: 175000 },
|
|
|
+ { month: '九月', power: 220000, water: 180000 },
|
|
|
+ { month: '十月', power: 225000, water: 185000 },
|
|
|
+ { month: '十一月', power: 230000, water: 190000 }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted () {
|
|
|
+ this.initPowerChart()
|
|
|
+ this.initWaterChart()
|
|
|
+ window.addEventListener('resize', this.handleResize)
|
|
|
+ },
|
|
|
+ beforeDestroy () {
|
|
|
+ window.removeEventListener('resize', this.handleResize)
|
|
|
+ if (this.powerChartInstance) {
|
|
|
+ this.powerChartInstance.dispose()
|
|
|
+ }
|
|
|
+ if (this.waterChartInstance) {
|
|
|
+ this.waterChartInstance.dispose()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 初始化用电量柱状图
|
|
|
+ initPowerChart () {
|
|
|
+ this.powerChartInstance = echarts.init(this.$refs.powerChart)
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
|
+ borderColor: 'rgba(64, 158, 255, 0.3)',
|
|
|
+ textStyle: {
|
|
|
+ color: '#fff'
|
|
|
+ },
|
|
|
+ formatter: (params) => {
|
|
|
+ let result = ``
|
|
|
+ params.forEach((param) => {
|
|
|
+ result += `${param.name}<br/>${
|
|
|
+ param.seriesName
|
|
|
+ }: ${param.value.toLocaleString()}<br/>`
|
|
|
+ })
|
|
|
+ return result
|
|
|
+ }
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '1%',
|
|
|
+ right: '1%',
|
|
|
+ top: '5%',
|
|
|
+ bottom: '2%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: this.monthlyData.map((item) => item.month),
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.3)',
|
|
|
+ type: 'dashed'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.7)',
|
|
|
+ fontSize: 11,
|
|
|
+ interval: 0
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ show: true,
|
|
|
+ // 将坐标轴内的线设置为虚线
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.3)',
|
|
|
+ type: 'dashed'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ axisLine: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.7)',
|
|
|
+ fontSize: 11
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.1)',
|
|
|
+ type: 'dashed',
|
|
|
+ width: 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '用电量',
|
|
|
+ type: 'bar',
|
|
|
+ data: this.monthlyData.map((item) => item.power),
|
|
|
+ barWidth: '30%',
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [
|
|
|
+ { offset: 0, color: '#FCE2B4' },
|
|
|
+ { offset: 1, color: '#F66757' }
|
|
|
+ ]),
|
|
|
+ borderRadius: [20, 20, 0, 0]
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ position: 'top',
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 10,
|
|
|
+ formatter: (params) =>
|
|
|
+ params.value >= 10000
|
|
|
+ ? (params.value / 10000).toFixed(1) + '万'
|
|
|
+ : params.value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ this.powerChartInstance.setOption(option)
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化用水量柱状图
|
|
|
+ initWaterChart () {
|
|
|
+ this.waterChartInstance = echarts.init(this.$refs.waterChart)
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
|
+ borderColor: 'rgba(64, 158, 255, 0.3)',
|
|
|
+ textStyle: {
|
|
|
+ color: '#fff'
|
|
|
+ },
|
|
|
+ formatter: (params) => {
|
|
|
+ let result = ``
|
|
|
+ params.forEach((param) => {
|
|
|
+ result += `${param.name}<br/>${
|
|
|
+ param.seriesName
|
|
|
+ }: ${param.value.toLocaleString()}<br/>`
|
|
|
+ })
|
|
|
+ return result
|
|
|
+ }
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '1%',
|
|
|
+ right: '1%',
|
|
|
+ top: '2%',
|
|
|
+ bottom: '5%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: this.monthlyData.map((item) => item.month),
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.3)',
|
|
|
+ type: 'dashed'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.7)',
|
|
|
+ fontSize: 11,
|
|
|
+ interval: 0,
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ show: true,
|
|
|
+ // 将坐标轴内的线设置为虚线
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.3)',
|
|
|
+ type: 'dashed'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ // 反转 y 轴的 min 和 max,实现“倒立”
|
|
|
+ min: 400000,
|
|
|
+ max: 0,
|
|
|
+ axisLine: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.7)',
|
|
|
+ fontSize: 11
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(160, 179, 214, 0.1)',
|
|
|
+ type: 'dashed',
|
|
|
+ width: 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '用水量',
|
|
|
+ type: 'bar',
|
|
|
+ data: this.monthlyData.map((item) => item.water),
|
|
|
+ barWidth: '30%',
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color: '#3AB3E3' },
|
|
|
+ { offset: 1, color: '#1620D4' }
|
|
|
+ ]),
|
|
|
+ borderRadius: [0, 0, 20, 20]
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ position: 'bottom',
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 10,
|
|
|
+ formatter: (params) =>
|
|
|
+ params.value >= 10000
|
|
|
+ ? (params.value / 10000).toFixed(1) + '万'
|
|
|
+ : params.value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ this.waterChartInstance.setOption(option)
|
|
|
+ },
|
|
|
+
|
|
|
+ handleResize () {
|
|
|
+ if (this.powerChartInstance) {
|
|
|
+ this.powerChartInstance.resize()
|
|
|
+ }
|
|
|
+ if (this.waterChartInstance) {
|
|
|
+ this.waterChartInstance.resize()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ @import "@/assets/css/theme.scss";
|
|
|
+
|
|
|
+ .hardware-data {
|
|
|
+ background: var(--content-bg);
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 20px;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .module-title {
|
|
|
+ color: var(--title-primary);
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 500;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-section {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-info {
|
|
|
+ text-align: right;
|
|
|
+ background: var(--title-bg);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 20px;
|
|
|
+ justify-content: space-between;
|
|
|
+ border: 1px solid rgba(64, 158, 255, 0.1);
|
|
|
+ border-radius: 6px;
|
|
|
+ padding: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-icon {
|
|
|
+ width: 48px;
|
|
|
+ height: 48px;
|
|
|
+ border-radius: 50%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-icon.electric {
|
|
|
+ background: linear-gradient(135deg, #ff8c00 0%, #ffd700 100%);
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-icon.water {
|
|
|
+ background: linear-gradient(135deg, #00bfff 0%, #87ceeb 100%);
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-icon::after {
|
|
|
+ content: "";
|
|
|
+ position: absolute;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ background-size: contain;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-position: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-icon.electric::after {
|
|
|
+ background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path d="M12 2C13.1 2 14 .9 14 0H10C10 .9 10.9 2 12 2M15.78 9H14.22L14 12H10L9.78 9H8.22L7.79 14H9.2L9.5 17H14.5L14.8 14H16.21L15.78 9M12 4C10.9 4 10 4.9 10 6S10.9 8 12 8 14 7.1 14 6 13.1 4 12 4Z"/></svg>');
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-icon.water::after {
|
|
|
+ background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path d="M12 2C13.1 2 14 .9 14 0H10C10 .9 10.9 2 12 2M12 18.5C11.45 18.5 11 18.05 11 17.5C11 16.95 11.45 16.5 12 16.5C12.55 16.5 13 16.95 13 17.5C13 18.05 12.55 18.5 12 18.5M12 12C9.79 12 8 13.79 8 16H16C16 13.79 14.21 12 12 12M12 4C9.79 4 8 5.79 8 8H16C16 5.79 14.21 4 12 4M3 20V22H13V20H3M16.5 18.21L17.79 16.93L19.5 18.65L23.07 15.07L24.5 16.45L19.5 21.45L16.5 18.21Z"/></svg>');
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-name {
|
|
|
+ color: #fea373;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-count {
|
|
|
+ color: #fff;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 500;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-cards {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ // gap: 20px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ background: var(--title-bg);
|
|
|
+ border: 1px solid rgba(64, 158, 255, 0.1);
|
|
|
+ border-radius: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-card {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ border-right: 1px solid rgba(64, 158, 255, 0.3);
|
|
|
+ text-align: right;
|
|
|
+ padding: 10px 20px;
|
|
|
+ &:last-child {
|
|
|
+ border-right: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-label {
|
|
|
+ color: var(--primary);
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-value {
|
|
|
+ color: #fff;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ margin-bottom: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-unit {
|
|
|
+ color: #fea373;
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 修改为两个图表容器 */
|
|
|
+ .charts-container {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ // min-height: 600px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart-item {
|
|
|
+ flex: 1;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ min-height: 300px;
|
|
|
+ }
|
|
|
+</style>
|