系统总览图表加载销毁优化

This commit is contained in:
ym1026
2025-09-04 11:12:20 +08:00
parent 369f7165cb
commit 61ed4f355f
21 changed files with 683 additions and 699 deletions

8
web/package-lock.json generated
View File

@@ -13,6 +13,7 @@
"core-js": "^3.8.3", "core-js": "^3.8.3",
"echarts": "^6.0.0", "echarts": "^6.0.0",
"moment": "^2.30.1", "moment": "^2.30.1",
"qs": "^6.12.3",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.0.3", "vue-router": "^4.0.3",
"vuex": "^4.0.0" "vuex": "^4.0.0"
@@ -5236,7 +5237,6 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bind-apply-helpers": "^1.0.2", "call-bind-apply-helpers": "^1.0.2",
@@ -10779,7 +10779,6 @@
"version": "1.13.4", "version": "1.13.4",
"resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz", "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@@ -12124,7 +12123,6 @@
"version": "6.13.0", "version": "6.13.0",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz", "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"side-channel": "^1.0.6" "side-channel": "^1.0.6"
@@ -13125,7 +13123,6 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz", "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
@@ -13145,7 +13142,6 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.0.tgz", "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
@@ -13162,7 +13158,6 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bound": "^1.0.2", "call-bound": "^1.0.2",
@@ -13181,7 +13176,6 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bound": "^1.0.2", "call-bound": "^1.0.2",

View File

@@ -16,7 +16,8 @@
"moment": "^2.30.1", "moment": "^2.30.1",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.0.3", "vue-router": "^4.0.3",
"vuex": "^4.0.0" "vuex": "^4.0.0",
"qs": "^6.12.3"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.16", "@babel/core": "^7.12.16",

View File

@@ -29,32 +29,32 @@ export default {
curList: [ curList: [
{ {
name: '日光伏设备告警', name: '日光伏设备告警',
key: 'key1', key: 'solar_num_err',
lineColor: '#22E4FF', lineColor: '#22E4FF',
value: 1111, value: 1111,
d: '' d: ''
}, },
{ {
name: '日储能设备告警', name: '日储能设备告警',
key: 'key2', key: 'storage_num_err',
lineColor: '#0E68E4', lineColor: '#0E68E4',
value: 0, value: 0,
d: '' d: ''
}, },
{ {
name: '日充电设备告警', name: '日充电设备告警',
key: 'key3', key: 'charge_num_err',
lineColor: '#00BAAD', lineColor: '#00BAAD',
value: 0, value: 0,
d: '' d: ''
}, },
{ // {
name: '日负荷设备告警', // name: '日负荷设备告警',
key: 'key4', // key: 'key4',
lineColor: '#FF8D1A', // lineColor: '#FF8D1A',
value: 0, // value: 0,
d: '' // d: ''
} // }
], ],
faultChart: null, faultChart: null,
lineChartData: { lineChartData: {
@@ -91,7 +91,7 @@ export default {
} }
}, },
mounted() {}, mounted() {},
onBeforeUnmount() { beforeUnmount() {
this.faultChart = null this.faultChart = null
window.removeEventListener('resize', this.handleResize) window.removeEventListener('resize', this.handleResize)
}, },
@@ -102,9 +102,9 @@ export default {
}, },
processData(data, keys) { processData(data, keys) {
data.sort((a, b) => { data.sort((a, b) => {
return new Date(a.date) - new Date(b.date) return new Date(a.dt) - new Date(b.dt)
}) })
const dates = data.map((item) => item.date) const dates = data.map((item) => item.dt)
const values = [] const values = []
keys.forEach((item, index) => { keys.forEach((item, index) => {
values[index] = data.map((dataValue) => dataValue[keys[index]]) values[index] = data.map((dataValue) => dataValue[keys[index]])
@@ -181,6 +181,7 @@ export default {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
axisLabel: { axisLabel: {
interval: 4,
color: '#fff' color: '#fff'
} }
}, },

View File

@@ -29,7 +29,7 @@ export default {
curList: [ curList: [
{ {
name: '日充电电量', name: '日充电电量',
key: 'chargeElect', key: 'charge_elect',
lineColor: '#00BBA3', lineColor: '#00BBA3',
colorStart: ' rgba(10, 250, 106, 0.15)', colorStart: ' rgba(10, 250, 106, 0.15)',
colorEnd: ' rgba(171, 255, 249, 0.3)', colorEnd: ' rgba(171, 255, 249, 0.3)',
@@ -38,7 +38,7 @@ export default {
}, },
{ {
name: '日充电次数', name: '日充电次数',
key: 'chargeNum', key: 'charge_num',
lineColor: '#3F80F2', lineColor: '#3F80F2',
colorStart: ' rgba(99, 151, 235, 0.3)', colorStart: ' rgba(99, 151, 235, 0.3)',
colorEnd: ' rgba(24, 109, 245, 0.3)', colorEnd: ' rgba(24, 109, 245, 0.3)',
@@ -49,7 +49,7 @@ export default {
curListEcharts: [ curListEcharts: [
{ {
name: '日充电电量', name: '日充电电量',
key: 'chargeElect', key: 'charge_elect',
lineColor: '#00BBA3', lineColor: '#00BBA3',
colorStart: ' rgba(10, 250, 106, 0.15)', colorStart: ' rgba(10, 250, 106, 0.15)',
colorEnd: ' rgba(171, 255, 249, 0.3)', colorEnd: ' rgba(171, 255, 249, 0.3)',
@@ -58,7 +58,7 @@ export default {
}, },
{ {
name: '日充电收益', name: '日充电收益',
key: 'incomeCharge', key: 'income_charge',
lineColor: '#3F80F2', lineColor: '#3F80F2',
colorStart: ' rgba(99, 151, 235, 0.3)', colorStart: ' rgba(99, 151, 235, 0.3)',
colorEnd: ' rgba(24, 109, 245, 0.3)', colorEnd: ' rgba(24, 109, 245, 0.3)',
@@ -67,7 +67,7 @@ export default {
} }
], ],
chargeChart: null, chargeChart: null,
lineChartData: { chargeChartData: {
ydata: [], ydata: [],
xdata: [] xdata: []
} }
@@ -75,41 +75,46 @@ export default {
}, },
watch: { watch: {
total: { total: {
handler(n) { handler(newVal,oldVal) {
if (n) { if (newVal!==oldVal) {
let that = this this.curList.forEach((item) => {
that.curList.forEach((item) => { item.value = this.total[item.key]
item.value = that.total[item.key]
}) })
} }
}, },
deep: true, // 深度监听
immediate: true
}, },
deviceInfo: { deviceInfo: {
handler(n) { handler(newVal,oldVal) {
this.$nextTick(() => { if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.drawLineChart() this.$nextTick(() => {
}) this.drawLineChart()
} })
// immediate: true }
},
deep: true // 确保深度比较
} }
}, },
mounted() {}, mounted() {},
onBeforeUnmount() { beforeUnmount() {
this.chargeChart = null
window.removeEventListener('resize', this.handleResize) window.removeEventListener('resize', this.handleResize)
if(this.chargeChart){
this.chargeChart.dispose()
this.chargeChart = null
}
}, },
methods: { methods: {
handleResize() { handleResize() {
this.chargeChart.resize() if(this.chargeChart){
this.chargeChart.resize()
}
}, },
processData(data, keys) { processData(data, keys) {
data.sort((a, b) => { data.sort((a, b) => {
return new Date(a.date) - new Date(b.date) return new Date(a.dt) - new Date(b.dt)
}) })
const dates = data.map((item) => item.date) const dates = data.map((item) => item.dt)
const values = [] const values = []
keys.forEach((item, index) => { keys.forEach((item, index) => {
values[index] = data.map((dataValue) => dataValue[keys[index]]) values[index] = data.map((dataValue) => dataValue[keys[index]])
@@ -125,9 +130,9 @@ export default {
const keyList = this.curListEcharts.map((item) => item.key) const keyList = this.curListEcharts.map((item) => item.key)
const result = this.processData(this.deviceInfo, keyList) const result = this.processData(this.deviceInfo, keyList)
this.lineChartData.xdata = result.dates this.chargeChartData.xdata = result.dates
arr.forEach((item, index) => { arr.forEach((item, index) => {
this.lineChartData.ydata[index] = { this.chargeChartData.ydata[index] = {
name: item.name, name: item.name,
smooth: true, smooth: true,
type: 'line', type: 'line',
@@ -162,7 +167,11 @@ export default {
drawLineChart(activeKey) { drawLineChart(activeKey) {
this.getChargeData(activeKey) this.getChargeData(activeKey)
if(this.chargeChart){
this.chargeChart.dispose()
}
const chartDom = document.getElementById('charge-chart') const chartDom = document.getElementById('charge-chart')
if (!chartDom) return;
let chargeChart = this.$echarts.init(chartDom) let chargeChart = this.$echarts.init(chartDom)
this.chargeChart = chargeChart this.chargeChart = chargeChart
const option = { const option = {
@@ -186,7 +195,7 @@ export default {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: this.lineChartData.xdata, data: this.chargeChartData.xdata,
axisLine: { axisLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -200,12 +209,18 @@ export default {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
axisLabel: { axisLabel: {
interval: 4,
color: '#fff' color: '#fff'
} }
}, },
series: this.lineChartData.ydata series: this.chargeChartData.ydata
} }
option && chargeChart.setOption(option) option && chargeChart.setOption(option)
this.setupResizeListener()
},
setupResizeListener(){
window.removeEventListener('resize', this.handleResize);
window.addEventListener('resize', this.handleResize) window.addEventListener('resize', this.handleResize)
} }
} }

View File

@@ -17,9 +17,9 @@
export default { export default {
name: '', name: '',
props: { props: {
total:{ total: {
type:Object, type: Object,
default:()=>{} default: () => {}
}, },
deviceInfo: { deviceInfo: {
type: Array, type: Array,
@@ -28,68 +28,75 @@ export default {
}, },
data() { data() {
return { return {
uid:'1',
curList: [ curList: [
{ {
name: '日充电电量', name: '日充电电量',
key: 'storageElectIn', key: 'storage_elect_in',
lineColor: '#22E4FF', lineColor: '#22E4FF',
value: 0, value: 0,
d: 'kW·h' d: 'kW·h'
}, },
{ {
name: '日放电电量', name: '日放电电量',
key: 'storageElectOut', key: 'storage_elect_out',
lineColor: '#0E68E4', lineColor: '#0E68E4',
value: 0, value: 0,
d: 'kW·h' d: 'kW·h'
} }
], ],
faultChart: null, energyChart: null,
lineChartData: { energyChartData: {
ydata: [], ydata: [],
xdata: [] xdata: []
} }
} }
}, },
watch: { watch: {
total:{ total: {
handler(n){ handler(newVal,oldVal) {
if(n){ if (newVal!==oldVal) {
let that=this let that = this
that.curList.forEach((item)=>{ that.curList.forEach((item) => {
item.value=that.total[item.key] item.value = that.total[item.key]
})
}
},
},
deviceInfo: {
handler(newVal,oldVal) {
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.$nextTick(() => {
this.drawLineChart()
}) })
} }
}, },
deep: true, // 深度监听 deep: true // 确保深度比较
immediate: true,
},
deviceInfo: {
handler(n) {
this.$nextTick(() => {
this.drawLineChart()
})
}
// immediate: true
} }
}, },
mounted() {}, mounted() {},
onBeforeUnmount() { beforeUnmount() {
this.faultChart = null
window.removeEventListener('resize', this.handleResize) window.removeEventListener('resize', this.handleResize)
if(this.energyChart){
this.energyChart.dispose()
this.energyChart = null
}
}, },
methods: { methods: {
handleResize() { handleResize() {
this.faultChart.resize() if(this.energyChart){
this.energyChart.resize()
}
}, },
processData(data, keys) { processData(data, keys) {
data.sort((a, b) => { data.sort((a, b) => {
return new Date(a.date) - new Date(b.date) return new Date(a.dt) - new Date(b.dt)
}) })
const dates = data.map((item) => item.date) const dates = data.map((item) => item.dt)
const values = [] const values = []
keys.forEach((item, index) => { keys.forEach((item, index) => {
values[index] = data.map((dataValue) => dataValue[keys[index]]) values[index] = data.map((dataValue) => dataValue[keys[index]])
@@ -105,9 +112,9 @@ export default {
const keyList = this.curList.map((item) => item.key) const keyList = this.curList.map((item) => item.key)
const result = this.processData(this.deviceInfo, keyList) const result = this.processData(this.deviceInfo, keyList)
this.lineChartData.xdata = result.dates this.energyChartData.xdata = result.dates
arr.forEach((item, index) => { arr.forEach((item, index) => {
this.lineChartData.ydata[index] = { this.energyChartData.ydata[index] = {
name: item.name, name: item.name,
smooth: true, smooth: true,
type: 'bar', type: 'bar',
@@ -128,9 +135,13 @@ export default {
drawLineChart(activeKey) { drawLineChart(activeKey) {
this.getChargeData(activeKey) this.getChargeData(activeKey)
if(this.energyChart){
this.energyChart.dispose()
}
const chartDom = document.getElementById('energy-chart') const chartDom = document.getElementById('energy-chart')
let faultChart = this.$echarts.init(chartDom) if (!chartDom) return;
this.faultChart = faultChart let energyChart = this.$echarts.init(chartDom)
this.energyChart = energyChart
const option = { const option = {
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
@@ -147,12 +158,12 @@ export default {
grid: { grid: {
left: '3%', left: '3%',
right: '4%', right: '4%',
bottom: '5%', bottom: '3%',
containLabel: true containLabel: true
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: this.lineChartData.xdata, data: this.energyChartData.xdata,
axisLine: { axisLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -166,12 +177,17 @@ export default {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
axisLabel: { axisLabel: {
interval: 4,
color: '#fff' color: '#fff'
} }
}, },
series: this.lineChartData.ydata series: this.energyChartData.ydata
} }
option && faultChart.setOption(option) option && energyChart.setOption(option)
this.setupResizeListener()
},
setupResizeListener(){
window.removeEventListener('resize', this.handleResize);
window.addEventListener('resize', this.handleResize) window.addEventListener('resize', this.handleResize)
} }
} }

View File

@@ -9,7 +9,7 @@
</div> </div>
</div> </div>
<component :is="item.componentId" :props-total="deviceInfo.allTotal" :props-info="deviceInfo[item.infoKey]" ></component> <component :is="item.componentId" :props-total="deviceInfo.allTotal" :props-info="deviceInfo[item.infoKey]" ></component>
<!-- -->
</div> </div>
</div> </div>
@@ -34,17 +34,13 @@ import StatisticalInfo from '@/components/Home/Modal/StatisticalInfo.vue'
import Revenue from '@/components/Home/Modal/Revenue.vue' import Revenue from '@/components/Home/Modal/Revenue.vue'
import Utilization from '@/components/Home/Modal/Utilization.vue' import Utilization from '@/components/Home/Modal/Utilization.vue'
import DisCharge from '@/components/Home/Modal/DisCharge.vue' import DisCharge from '@/components/Home/Modal/DisCharge.vue'
import Operational from '@/components/Home/Operational.vue'
import { getReq, postReq } from '@/request/api' import { getReq, postReq } from '@/request/api'
import Charge from '@/components/Home/Charge.vue'
import Alarm from '@/components/Home/Alarm.vue'
import Map from '@/components/Home/Map_tianditu.vue'
import EnvInfo from './Modal/EnvInfo.vue' import EnvInfo from './Modal/EnvInfo.vue'
export default { export default {
name: 'Home', name: 'Home',
components: {Map}, components: {},
data() { data() {
return { return {
deviceInfo: {}, deviceInfo: {},
@@ -113,215 +109,105 @@ export default {
( this.deviceInfo = { ( this.deviceInfo = {
alarm: [ alarm: [
{ {
date: '2025-08-30', dt: '2025-08-30',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-29', dt: '2025-08-29',
key1: 8, key1: 8,
key2: 5, key2: 5,
key3: 5, key3: 5,
key4: 7 key4: 7
}, },
{ {
date: '2025-08-28', dt: '2025-08-28',
key1: 0, key1: 0,
key2: 10, key2: 10,
key3: 20, key3: 20,
key4: 4 key4: 4
}, },
{ {
date: '2025-08-27', dt: '2025-08-27',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-26', dt: '2025-08-26',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-25', dt: '2025-08-25',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-24', dt: '2025-08-24',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-23', dt: '2025-08-23',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-22', dt: '2025-08-22',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-21', dt: '2025-08-21',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-20', dt: '2025-08-20',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-19', dt: '2025-08-19',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-18', dt: '2025-08-18',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
}, },
{ {
date: '2025-08-17', dt: '2025-08-17',
key1: 10, key1: 10,
key2: 0, key2: 0,
key3: 15, key3: 15,
key4: 5 key4: 5
} }
], ],
energy: [
{
date: '2025-08-30',
key1: '2',
key2: '2'
},
{
date: '2025-08-29',
key1: '2',
key2: '2'
},
{
date: '2025-08-28',
key1: '2',
key2: '2'
},
{
date: '2025-08-27',
key1: '2',
key2: '2'
},
{
date: '2025-08-26',
key1: '2',
key2: '2'
},
{
date: '2025-08-25',
key1: '2',
key2: '2'
},
{
date: '2025-08-24',
key1: '2',
key2: '2'
}
],
charge: [
{
date: '2025-08-30',
key1: '2',
key2: '2'
},
{
date: '2025-08-29',
key1: '2',
key2: '2'
},
{
date: '2025-08-28',
key1: '2',
key2: '2'
},
{
date: '2025-08-27',
key1: '2',
key2: '2'
},
{
date: '2025-08-26',
key1: '2',
key2: '2'
},
{
date: '2025-08-25',
key1: '2',
key2: '2'
},
{
date: '2025-08-24',
key1: '2',
key2: '2'
}
],
pv: [
{
date: '2025-08-30',
key1: '2',
key2: '2'
},
{
date: '2025-08-29',
key1: '2',
key2: '2'
},
{
date: '2025-08-28',
key1: '2',
key2: '2'
},
{
date: '2025-08-27',
key1: '2',
key2: '2'
},
{
date: '2025-08-26',
key1: '2',
key2: '2'
},
{
date: '2025-08-25',
key1: '2',
key2: '2'
},
{
date: '2025-08-24',
key1: '2',
key2: '2'
}
]
}), }),

View File

@@ -20,70 +20,75 @@ export default {
name: '日充电电量', name: '日充电电量',
key: 'key1', key: 'key1',
lineColor: '#9BD801', lineColor: '#9BD801',
value:0, value: 0,
d:'kW·h' d: 'kW·h'
}, },
{ {
name: '日放电电量', name: '日放电电量',
key: 'key2', key: 'key2',
lineColor: '#3DFEFA', lineColor: '#3DFEFA',
value:0, value: 0,
d:'kW·h' d: 'kW·h'
}, }
], ],
disChargeChart: null, disChargeChart: null,
lineChartData: { disChargeChartData: {
ydata: [], ydata: [],
xdata: [] xdata: []
}, }
} }
}, },
watch: { watch: {
propsInfo: { propsInfo: {
handler(n) { handler(newVal, oldVal) {
this.$nextTick(() => { if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.drawLineChart() this.$nextTick(() => {
}) this.drawLineChart()
} })
// immediate: true }
},
deep: true // 确保深度比较
} }
}, },
mounted() {}, mounted() {},
onBeforeUnmount() { beforeUnmount() {
this.disChargeChart = null
window.removeEventListener('resize', this.handleResize) window.removeEventListener('resize', this.handleResize)
if (this.disChargeChart) {
this.disChargeChart.dispose()
this.disChargeChart = null
}
}, },
methods: { methods: {
handleResize() { handleResize() {
this.disChargeChart.resize() if (this.disChargeChart) {
this.disChargeChart.resize()
}
}, },
processData(data, keys) { processData(data, keys) {
data.sort((a, b) => { data.sort((a, b) => {
return new Date(a.date) - new Date(b.date) return new Date(a.date) - new Date(b.date)
}) })
const dates = data.map((item) => item.date) const dates = data.map((item) => item.dt)
const values=[] const values = []
keys.forEach((item,index)=>{ keys.forEach((item, index) => {
values[index] = data.map((dataValue) => dataValue[keys[index]])
values[index]= data.map((dataValue)=>dataValue[keys[index]])
}) })
return { return {
dates, dates,
values, values
} }
}, },
getDisChargeData() { getDisChargeData() {
const arr=this.curList const arr = this.curList
const keyList=this.curList.map((item)=>item.key) const keyList = this.curList.map((item) => item.key)
const result = this.processData(this.propsInfo, keyList) const result = this.processData(this.propsInfo, keyList)
this.lineChartData.xdata = result.dates this.disChargeChartData.xdata = result.dates
arr.forEach((item, index) => { arr.forEach((item, index) => {
this.lineChartData.ydata[index] = { this.disChargeChartData.ydata[index] = {
name: item.name, name: item.name,
smooth: false, smooth: false,
type: 'line', type: 'line',
@@ -98,15 +103,18 @@ export default {
global: false, global: false,
showSymbol: false, showSymbol: false,
data:result.values[index] data: result.values[index]
} }
}) })
}, },
drawLineChart(activeKey) { drawLineChart(activeKey) {
this.getDisChargeData(activeKey) this.getDisChargeData(activeKey)
if (this.disChargeChart) {
this.disChargeChart.dispose()
}
const chartDom = document.getElementById('disCharge-chart') const chartDom = document.getElementById('disCharge-chart')
if (!chartDom) return
let disChargeChart = this.$echarts.init(chartDom) let disChargeChart = this.$echarts.init(chartDom)
this.disChargeChart = disChargeChart this.disChargeChart = disChargeChart
const option = { const option = {
@@ -130,7 +138,7 @@ export default {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: this.lineChartData.xdata, data: this.disChargeChartData.xdata,
axisLine: { axisLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -147,9 +155,13 @@ export default {
color: '#fff' color: '#fff'
} }
}, },
series: this.lineChartData.ydata series: this.disChargeChartData.ydata
} }
option && disChargeChart.setOption(option) option && disChargeChart.setOption(option)
this.setupResizeListener()
},
setupResizeListener() {
window.removeEventListener('resize', this.handleResize)
window.addEventListener('resize', this.handleResize) window.addEventListener('resize', this.handleResize)
} }
} }
@@ -158,8 +170,7 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.disCharge { .disCharge {
height:calc(100% - 45px); height: calc(100% - 45px);
#disCharge-chart { #disCharge-chart {
height: 100%; height: 100%;
@@ -177,12 +188,12 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
& > div:last-child{ & > div:last-child {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: end; align-items: end;
} }
.mark { .mark {
font-size: 16px; font-size: 16px;
margin-right: 2px; margin-right: 2px;
@@ -194,7 +205,7 @@ export default {
rgba(61, 254, 250, 0.15) 49.2%, rgba(61, 254, 250, 0.15) 49.2%,
rgba(61, 254, 250, 0) 100% rgba(61, 254, 250, 0) 100%
); );
.d{ .d {
margin-left: 1px; margin-left: 1px;
font-size: 12px; font-size: 12px;
} }

View File

@@ -80,15 +80,13 @@ export default {
}, },
watch: { watch: {
propsTotal: { propsTotal: {
handler(n) { handler(newVal, oldVal) {
if (n) { if (newVal !== oldVal) {
this.list.forEach((item) => { this.list.forEach((item) => {
item.value = this.propsTotal[item.key] item.value = this.propsTotal[item.key]
}) })
} }
}, }
deep: true,
immediate: true
} }
}, },
mounted() {}, mounted() {},

View File

@@ -90,15 +90,14 @@ export default {
}, },
watch: { watch: {
propsTotal: { propsTotal: {
handler(n) { handler(newVal, oldVal) {
if (n) { if (newVal !== oldVal) {
this.list.forEach((item) => { this.list.forEach((item) => {
item.value = this.propsTotal[item.key] item.value = this.propsTotal[item.key]
}) })
} }
}, },
deep: true,
immediate: true
} }
}, },
mounted() {}, mounted() {},

View File

@@ -3,13 +3,13 @@
<div class="content-left"> <div class="content-left">
<div v-for="item in leftList" :key="item.key" :class="`item ${item.class}`"> <div v-for="item in leftList" :key="item.key" :class="`item ${item.class}`">
<div> <div>
<span>{{ item.value ? item.value :0}}</span <span>{{ item.value ? item.value : 0 }}</span
><span class="d">{{ item.d }}</span> ><span class="d">{{ item.d }}</span>
</div> </div>
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
</div> </div>
</div> </div>
<div style="text-align: center;font-weight: 500;"> <div style="text-align: center; font-weight: 500">
<div class="online-icon"></div> <div class="online-icon"></div>
<span>{{ curStatus }}</span> <span>{{ curStatus }}</span>
</div> </div>
@@ -17,7 +17,7 @@
<div class="content-right"> <div class="content-right">
<div v-for="item in rightList" :key="item.key" :class="`item ${item.class}`"> <div v-for="item in rightList" :key="item.key" :class="`item ${item.class}`">
<div> <div>
<span>{{ item.value ? item.value :0 }}</span <span>{{ item.value ? item.value : 0 }}</span
><span class="d">{{ item.d }}</span> ><span class="d">{{ item.d }}</span>
</div> </div>
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
@@ -27,7 +27,6 @@
</template> </template>
<script> <script>
export default { export default {
name: '', name: '',
props: { props: {
@@ -42,7 +41,7 @@ export default {
}, },
data() { data() {
return { return {
curStatus:'充电', curStatus: '充电',
list: [ list: [
{ {
key: 'tianshu', key: 'tianshu',
@@ -99,15 +98,13 @@ export default {
}, },
watch: { watch: {
propsTotal: { propsTotal: {
handler(n) { handler(newVal, oldVal) {
if (n) { if (newVal !== oldVal) {
this.list.forEach((item) => { this.list.forEach((item) => {
item.value = this.propsTotal[item.key] item.value = this.propsTotal[item.key]
}) })
} }
}, }
deep: true,
immediate: true
} }
}, },
mounted() {}, mounted() {},

View File

@@ -29,7 +29,7 @@ export default {
], ],
revenueChart: null, revenueChart: null,
lineChartData: { RevenueChartData: {
ydata: [], ydata: [],
xdata: [] xdata: []
}, },
@@ -38,29 +38,37 @@ export default {
}, },
watch: { watch: {
propsInfo: { propsInfo: {
handler(n) { handler(newVal, oldVal) {
this.$nextTick(() => { if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.drawLineChart() this.$nextTick(() => {
}) this.drawLineChart()
} })
// immediate: true }
},
deep: true // 确保深度比较
} }
}, },
mounted() {}, mounted() {},
onBeforeUnmount() { beforeUnmount() {
this.revenueChart = null
window.removeEventListener('resize', this.handleResize) window.removeEventListener('resize', this.handleResize)
if (this.revenueChart) {
this.revenueChart.dispose()
this.revenueChart = null
}
}, },
methods: { methods: {
handleResize() { handleResize() {
this.revenueChart.resize() if (this.revenueChart) {
this.revenueChart.resize()
}
}, },
processData(data, keys) { processData(data, keys) {
data.sort((a, b) => { data.sort((a, b) => {
return new Date(a.date) - new Date(b.date) return new Date(a.date) - new Date(b.date)
}) })
const dates = data.map((item) => item.date) const dates = data.map((item) => item.dt)
const values=[] const values=[]
keys.forEach((item,index)=>{ keys.forEach((item,index)=>{
@@ -77,9 +85,9 @@ export default {
const keyList=this.curList.map((item)=>item.key) const keyList=this.curList.map((item)=>item.key)
const result = this.processData(this.propsInfo, keyList) const result = this.processData(this.propsInfo, keyList)
this.lineChartData.xdata = result.dates this.RevenueChartData.xdata = result.dates
arr.forEach((item, index) => { arr.forEach((item, index) => {
this.lineChartData.ydata[index] = { this.RevenueChartData.ydata[index] = {
name: item.name, name: item.name,
smooth: true, smooth: true,
type: 'line', type: 'line',
@@ -115,7 +123,11 @@ export default {
drawLineChart(activeKey) { drawLineChart(activeKey) {
this.getRevenueData(activeKey) this.getRevenueData(activeKey)
if (this.revenueChart) {
this.revenueChart.dispose()
}
const chartDom = document.getElementById('revenue-chart') const chartDom = document.getElementById('revenue-chart')
if (!chartDom) return
let revenueChart = this.$echarts.init(chartDom) let revenueChart = this.$echarts.init(chartDom)
this.revenueChart = revenueChart this.revenueChart = revenueChart
const option = { const option = {
@@ -139,7 +151,7 @@ export default {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: this.lineChartData.xdata, data: this.RevenueChartData.xdata,
axisLine: { axisLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -156,9 +168,14 @@ export default {
color: '#fff' color: '#fff'
} }
}, },
series: this.lineChartData.ydata series: this.RevenueChartData.ydata
} }
option && revenueChart.setOption(option) option && revenueChart.setOption(option)
this.setupResizeListener()
},
setupResizeListener() {
window.removeEventListener('resize', this.handleResize)
window.addEventListener('resize', this.handleResize) window.addEventListener('resize', this.handleResize)
} }
} }

View File

@@ -81,15 +81,13 @@ export default {
}, },
watch: { watch: {
propsTotal: { propsTotal: {
handler(n) { handler(newVal, oldVal) {
if (n) { if (newVal !== oldVal) {
this.list.forEach((item) => { this.list.forEach((item) => {
item.value = this.propsTotal[item.key] item.value = this.propsTotal[item.key]
}) })
} }
}, }
deep: true,
immediate: true
} }
}, },
mounted() {}, mounted() {},

View File

@@ -21,63 +21,68 @@ export default {
key: 'key1', key: 'key1',
lineColor: '#F69B52', lineColor: '#F69B52',
value:0, value: 0,
d:'kW·h' d: 'kW·h'
}, }
], ],
utilizationChart: null, utilizationChart: null,
lineChartData: { utilizationChartData: {
ydata: [], ydata: [],
xdata: [] xdata: []
}, }
} }
}, },
watch: { watch: {
propsInfo: { propsInfo: {
handler(n) { handler(newVal, oldVal) {
this.$nextTick(() => { if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.drawLineChart() this.$nextTick(() => {
}) this.drawLineChart()
} })
// immediate: true }
},
deep: true // 确保深度比较
} }
}, },
mounted() {}, mounted() {},
onBeforeUnmount() { beforeUnmount() {
this.utilizationChart = null
window.removeEventListener('resize', this.handleResize) window.removeEventListener('resize', this.handleResize)
if (this.utilizationChart) {
this.utilizationChart.dispose()
this.utilizationChart = null
}
}, },
methods: { methods: {
handleResize() { handleResize() {
this.utilizationChart.resize() if (this.utilizationChart) {
this.utilizationChart.resize()
}
}, },
processData(data, keys) { processData(data, keys) {
data.sort((a, b) => { data.sort((a, b) => {
return new Date(a.date) - new Date(b.date) return new Date(a.date) - new Date(b.date)
}) })
const dates = data.map((item) => item.date) const dates = data.map((item) => item.dt)
const values=[] const values = []
keys.forEach((item,index)=>{ keys.forEach((item, index) => {
values[index] = data.map((dataValue) => dataValue[keys[index]])
values[index]= data.map((dataValue)=>dataValue[keys[index]])
}) })
return { return {
dates, dates,
values, values
} }
}, },
getUtilizationData() { getUtilizationData() {
const arr=this.curList const arr = this.curList
const keyList=this.curList.map((item)=>item.key) const keyList = this.curList.map((item) => item.key)
const result = this.processData(this.propsInfo, keyList) const result = this.processData(this.propsInfo, keyList)
this.lineChartData.xdata = result.dates this.utilizationChartData.xdata = result.dates
arr.forEach((item, index) => { arr.forEach((item, index) => {
this.lineChartData.ydata[index] = { this.utilizationChartData.ydata[index] = {
name: item.name, name: item.name,
smooth: false, smooth: false,
type: 'line', type: 'line',
@@ -92,15 +97,18 @@ export default {
global: false, global: false,
showSymbol: false, showSymbol: false,
data:result.values[index] data: result.values[index]
} }
}) })
}, },
drawLineChart(activeKey) { drawLineChart(activeKey) {
this.getUtilizationData(activeKey) this.getUtilizationData(activeKey)
if (this.utilizationChart) {
this.utilizationChart.dispose()
}
const chartDom = document.getElementById('utilization-chart') const chartDom = document.getElementById('utilization-chart')
if (!chartDom) return
let utilizationChart = this.$echarts.init(chartDom) let utilizationChart = this.$echarts.init(chartDom)
this.utilizationChart = utilizationChart this.utilizationChart = utilizationChart
const option = { const option = {
@@ -124,7 +132,7 @@ export default {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: this.lineChartData.xdata, data: this.utilizationChartData.xdata,
axisLine: { axisLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -141,9 +149,13 @@ export default {
color: '#fff' color: '#fff'
} }
}, },
series: this.lineChartData.ydata series: this.utilizationChartData.ydata
} }
option && utilizationChart.setOption(option) option && utilizationChart.setOption(option)
this.setupResizeListener()
},
setupResizeListener() {
window.removeEventListener('resize', this.handleResize)
window.addEventListener('resize', this.handleResize) window.addEventListener('resize', this.handleResize)
} }
} }
@@ -152,10 +164,10 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.utilization { .utilization {
height:calc(100% - 45px); height: calc(100% - 45px);
#utilization-chart { #utilization-chart {
height:100%; height: 100%;
} }
} }
@@ -170,12 +182,12 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
& > div:last-child{ & > div:last-child {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: end; align-items: end;
} }
.mark { .mark {
font-size: 16px; font-size: 16px;
margin-right: 2px; margin-right: 2px;
@@ -187,7 +199,7 @@ export default {
rgba(61, 254, 250, 0.15) 49.2%, rgba(61, 254, 250, 0.15) 49.2%,
rgba(61, 254, 250, 0) 100% rgba(61, 254, 250, 0) 100%
); );
.d{ .d {
margin-left: 1px; margin-left: 1px;
font-size: 12px; font-size: 12px;
} }

View File

@@ -39,7 +39,7 @@ export default {
}, },
{ {
name: '利用率', name: '利用率',
key: 'key2', key: 'usage_rate',
percentKey: 'connector_off_percent', percentKey: 'connector_off_percent',
lineColor: lineColor:
'linear-gradient(90deg, rgba(53, 120, 124, 1) 0%, rgba(102, 225, 223, 1) 100%);', 'linear-gradient(90deg, rgba(53, 120, 124, 1) 0%, rgba(102, 225, 223, 1) 100%);',
@@ -50,17 +50,16 @@ export default {
}, },
watch: { watch: {
total:{ total:{
handler(n){ handler(newVal,oldVal) {
if(n){ if (newVal!==oldVal) {
let that=this let that=this
that.curList.forEach((item)=>{ that.curList.forEach((item)=>{
item.value=that.total[item.key] item.value=that.total[item.key]
}) })
} }
}, }
deep: true, // 深度监听
immediate: true,
} }
}, },

View File

@@ -31,21 +31,21 @@ export default {
curList: [ curList: [
{ {
name: '日发电量', name: '日发电量',
key: 'solarElectGen', key: 'solar_elect_gen',
lineColor: '#22E4FF', lineColor: '#22E4FF',
value: 0, value: 0,
d: 'kW·h' d: 'kW·h'
}, },
{ {
name: '日入网电量', name: '日入网电量',
key: 'solarElectGrid', key: 'solar_elect_grid',
lineColor: '#0E68E4', lineColor: '#0E68E4',
value: 0, value: 0,
d: 'kW·h' d: 'kW·h'
} }
], ],
faultChart: null, pvChart: null,
lineChartData: { pvChartData: {
ydata: [], ydata: [],
xdata: [] xdata: []
}, },
@@ -58,41 +58,46 @@ export default {
}, },
watch: { watch: {
total: { total: {
handler(n) { handler(newVal, oldVal) {
if (n) { if (newVal !== oldVal) {
let that = this let that = this
that.curList.forEach((item) => { that.curList.forEach((item) => {
item.value = that.total[item.key] item.value = that.total[item.key]
}) })
} }
}, }
deep: true, // 深度监听
immediate: true
}, },
deviceInfo: { deviceInfo: {
handler(n) { handler(newVal, oldVal) {
this.$nextTick(() => { if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.drawLineChart() this.$nextTick(() => {
}) this.drawLineChart()
} })
// immediate: true }
},
deep: true // 确保深度比较
} }
}, },
mounted() {}, mounted() {},
onBeforeUnmount() { beforeUnmount() {
this.faultChart = null
window.removeEventListener('resize', this.handleResize) window.removeEventListener('resize', this.handleResize)
if (this.pvChart) {
this.pvChart.dispose()
this.pvChart = null
}
}, },
methods: { methods: {
handleResize() { handleResize() {
this.faultChart.resize() if (this.pvChart) {
this.pvChart.resize()
}
}, },
processData(data, keys) { processData(data, keys) {
data.sort((a, b) => { data.sort((a, b) => {
return new Date(a.date) - new Date(b.date) return new Date(a.dt) - new Date(b.dt)
}) })
const dates = data.map((item) => item.date) const dates = data.map((item) => item.dt)
const values = [] const values = []
keys.forEach((item, index) => { keys.forEach((item, index) => {
values[index] = data.map((dataValue) => dataValue[keys[index]]) values[index] = data.map((dataValue) => dataValue[keys[index]])
@@ -108,9 +113,9 @@ export default {
const keyList = this.curList.map((item) => item.key) const keyList = this.curList.map((item) => item.key)
const result = this.processData(this.deviceInfo, keyList) const result = this.processData(this.deviceInfo, keyList)
this.lineChartData.xdata = result.dates this.pvChartData.xdata = result.dates
arr.forEach((item, index) => { arr.forEach((item, index) => {
this.lineChartData.ydata[index] = { this.pvChartData.ydata[index] = {
name: item.name, name: item.name,
smooth: true, smooth: true,
type: 'bar', type: 'bar',
@@ -131,9 +136,13 @@ export default {
drawLineChart(activeKey) { drawLineChart(activeKey) {
this.getChargeData(activeKey) this.getChargeData(activeKey)
if (this.pvChart) {
this.pvChart.dispose()
}
const chartDom = document.getElementById('pv-chart') const chartDom = document.getElementById('pv-chart')
let faultChart = this.$echarts.init(chartDom) if (!chartDom) return
this.faultChart = faultChart let pvChart = this.$echarts.init(chartDom)
this.pvChart = pvChart
const option = { const option = {
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
@@ -155,7 +164,7 @@ export default {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: this.lineChartData.xdata, data: this.pvChartData.xdata,
axisLine: { axisLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -169,12 +178,17 @@ export default {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
axisLabel: { axisLabel: {
interval: 4,
color: '#fff' color: '#fff'
} }
}, },
series: this.lineChartData.ydata series: this.pvChartData.ydata
} }
option && faultChart.setOption(option) option && pvChart.setOption(option)
this.setupResizeListener()
},
setupResizeListener() {
window.removeEventListener('resize', this.handleResize)
window.addEventListener('resize', this.handleResize) window.addEventListener('resize', this.handleResize)
} }
} }

View File

@@ -26,6 +26,10 @@
export default { export default {
name: '', name: '',
props: { props: {
infoKey: {
type: String,
default:''
},
total: { total: {
type: Object, type: Object,
default: () => {} default: () => {}
@@ -39,42 +43,42 @@ export default {
return { return {
curList: [ curList: [
{ {
key: 'launchDate', key: 'runDays', //根据launch_date字段计算得出
value: 20, value: 20,
d: '天', d: '天',
label: '系统运行天数', label: '系统运行天数',
class: 'item-1' class: 'item-1'
}, },
{ {
key: 'incomeTotal', key: 'income_total',
value: 10, value: 10,
d: '元', d: '元',
label: '累计收益', label: '累计收益',
class: 'item-2' class: 'item-2'
}, },
{ {
key: 'solarDeviceNum', key: 'solar_device_num',
value: 20, value: 20,
d: '', d: '',
label: '光伏设备数量', label: '光伏设备数量',
class: 'item-3' class: 'item-3'
}, },
{ {
key: '"stationNum', key: 'storage_device_num',
value: 20, value: 20,
d: '', d: '',
label: '储能预制舱数量', label: '储能预制舱数量',
class: 'item-4' class: 'item-4'
}, },
{ {
key: 'solarElectGen', key: 'solar_elect_gen',
value: 20, value: 20,
d: '', d: '',
label: '光伏设备累计发电量', label: '光伏设备累计发电量',
class: 'item-5' class: 'item-5'
}, },
{ {
key: 'capacityTotal', key: 'capacity_total',
value: 20, value: 20,
d: '', d: '',
label: '储能总容量', label: '储能总容量',
@@ -91,21 +95,23 @@ export default {
return this.curList.filter((_, index) => index % 2 !== 0).slice(0, 3) // 右列取前3个奇数索引 return this.curList.filter((_, index) => index % 2 !== 0).slice(0, 3) // 右列取前3个奇数索引
} }
}, },
watch: { watch: {
total: { total: {
handler(n) { handler(newVal,oldVal) {
if (n) { if (newVal&&newVal!==oldVal) {
let that = this this.curList.forEach((item) => {
that.curList.forEach((item) => { item.value = newVal[item.key] || 0;
item.value = that.total[item.key] });
})
} }
}, },
deep: true, // 深度监听 immediate: true,
immediate: true deep: true
} }
}, },
mounted() {}, mounted() {
console.log(this.total,'total')
},
methods: {} methods: {}
} }
</script> </script>

View File

@@ -341,9 +341,9 @@ export default {
processData(keysList, dataKey, data) { processData(keysList, dataKey, data) {
const keys = keysList.map((item) => item.key) const keys = keysList.map((item) => item.key)
data.sort((a, b) => { data.sort((a, b) => {
return new Date(a.date) - new Date(b.date) return new Date(a.dt) - new Date(b.dt)
}) })
const dates = data.map((item) => item.date) const dates = data.map((item) => item.dt)
const values = [] const values = []
keys.forEach((item, index) => { keys.forEach((item, index) => {

View File

@@ -1,16 +1,26 @@
import request from "@/request/index.js"; import request from '@/request/index.js'
export function postReq(data, url) { import qs from 'qs'
export function postReq(url, data) {
return request({ return request({
method: "post", method: 'post',
url, url,
data, data: {
}); ...data,
token: localStorage.getItem('token')
}
})
} }
export function getReq(data, url) { export function getReq(url, data) {
// const query = qs.stringify(data, { indices: false }) const query = qs.stringify(
{
...data,
token: localStorage.getItem('token')
},
{ indices: false }
)
return request({ return request({
method: "get", method: 'get',
url: url + "?" + data, url: url + '?' + query
}); })
} }

View File

@@ -1,16 +1,16 @@
import axios from "axios"; import axios from 'axios'
// import openNotification from "../utils/notification"; // import openNotification from "../utils/notification";
// let { config } = window; // let { config } = window;
// let { baseUrl } = config; // let { baseUrl } = config;
const service = axios.create({ const service = axios.create({
// baseURL: baseUrl, // baseURL: baseUrl,
baseURL: "", baseURL: '',
timeout: 120000, timeout: 120000
}); })
service.interceptors.request.use((config) => { service.interceptors.request.use((config) => {
const webConfig = config; const webConfig = config
// if (!["/user/login", "/config/getConfig"].includes(config.url)) { // if (!["/user/login", "/config/getConfig"].includes(config.url)) {
// if (localStorage.getItem("token")) { // if (localStorage.getItem("token")) {
// webConfig.headers = { // webConfig.headers = {
@@ -19,24 +19,24 @@ service.interceptors.request.use((config) => {
// } // }
// } // }
return webConfig; return webConfig
}); })
service.interceptors.response.use( service.interceptors.response.use(
(response) => { (response) => {
// 排除以下接口的错误提示 // 排除以下接口的错误提示
const { url } = response.config; const { url } = response.config
const urls = ["/light/", "/serve/delete", "/user/checkRandom"]; const urls = ['/light/', '/serve/delete', '/user/checkRandom']
const urlFlag = urls.map((item) => { const urlFlag = urls.map((item) => {
return url.includes(item); return url.includes(item)
}); })
const res = response.data; const res = response.data
if (res.code !== 200) { if (res.code !== 200) {
if (res.code == 401 || res.tip == "校验token过期") { if (res.code == 401 || res.tip == '校验token过期') {
setTimeout(() => { setTimeout(() => {
window.$wujie?.props.jump({ path: "/login" }); window.$wujie?.props.jump({ path: '/login' })
}, 1000); }, 1000)
} else if (urlFlag.every((item) => item === false)) { } else if (urlFlag.every((item) => item === false)) {
// openNotification({ // openNotification({
// status: "error", // status: "error",
@@ -44,18 +44,18 @@ service.interceptors.response.use(
// }); // });
} }
} }
return res; return res
}, },
(error) => { (error) => {
// console.log(error, 'error 此处添加监控超时处理') // console.log(error, 'error 此处添加监控超时处理')
if ( if (
error.name === "AxiosError" && error.name === 'AxiosError' &&
error.message === "timeout of 120000ms exceeded" && error.message === 'timeout of 120000ms exceeded' &&
error.code === "ECONNABORTED" error.code === 'ECONNABORTED'
) { ) {
return error; return error
} }
} }
); )
export default service; export default service

View File

@@ -1,17 +1,24 @@
<template> <template>
<div class="Home"> <div class="Home">
<div class="content-left"> <div class="content-left">
<div v-for="(item, i) in leftList" :key="i" :class="`grid-item ${item.class}`"> <div
v-for="item in leftList"
:key="item.componentId"
:class="`grid-item ${item.class}`"
>
<div class="tool"> <div class="tool">
<div class="title"> <div class="title">
<i class="iconfont icon-hebing linear-text"></i> <i class="iconfont icon-hebing linear-text"></i>
<span class="linear-text">{{ item.title }}</span> <span class="linear-text">{{ item.title }}</span>
</div> </div>
</div> </div>
<component <component
:is="item.componentId" :is="item.componentId"
:info-key="item.infoKey"
:device-info="deviceInfo[item.infoKey]" :device-info="deviceInfo[item.infoKey]"
:total="deviceInfo.allTotal" :total="item.infoKey === 'onLineTotal' ? deviceInfo.onLine : deviceInfo.allTotal"
></component> ></component>
</div> </div>
</div> </div>
@@ -19,7 +26,12 @@
<Map @changeStation="getCurrentStation"></Map> <Map @changeStation="getCurrentStation"></Map>
</div> </div>
<div class="content-right"> <div class="content-right">
<div v-for="(item, i) in rightList" :key="i" :class="`grid-item ${item.class}`"> <div
v-for="item in rightList"
:key="item.componentId"
:class="`grid-item ${item.class}`"
>
<div class="tool"> <div class="tool">
<div class="title"> <div class="title">
<i class="iconfont icon-hebing linear-text"></i> <i class="iconfont icon-hebing linear-text"></i>
@@ -29,7 +41,7 @@
<component <component
:is="item.componentId" :is="item.componentId"
:device-info="deviceInfo[item.infoKey]" :device-info="deviceInfo[item.infoKey]"
:total="deviceInfo.allTotal" :total="item.infoKey === 'onLineTotal' ? deviceInfo.onLine : deviceInfo.allTotal"
></component> ></component>
</div> </div>
</div> </div>
@@ -50,6 +62,8 @@ export default {
components: { Map }, components: { Map },
data() { data() {
return { return {
showFlag: false,
stationId: null, stationId: null,
deviceInfo: {}, deviceInfo: {},
list: [ list: [
@@ -57,13 +71,13 @@ export default {
title: '运行状况', title: '运行状况',
class: 'online-status', class: 'online-status',
componentId: onLine, componentId: onLine,
infoKey: 'onLine' infoKey: 'onLineTotal'
}, },
{ {
title: '运行分析', title: '运行分析',
class: 'stats-cards', class: 'stats-cards',
componentId: Operational, componentId: Operational,
infoKey: 'stats' infoKey: ''
}, },
{ {
title: '储能设备', title: '储能设备',
@@ -106,226 +120,227 @@ export default {
}, },
async mounted() { async mounted() {
await Promise.all([ await Promise.all([
(this.deviceInfo = { // (this.deviceInfo = {
alarm: [ // alarm: [
{ // {
date: '2025-08-30', // date: '2025-08-30',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-29', // date: '2025-08-29',
key1: 8, // key1: 8,
key2: 5, // key2: 5,
key3: 5, // key3: 5,
key4: 7 // key4: 7
}, // },
{ // {
date: '2025-08-28', // date: '2025-08-28',
key1: 0, // key1: 0,
key2: 10, // key2: 10,
key3: 20, // key3: 20,
key4: 4 // key4: 4
}, // },
{ // {
date: '2025-08-27', // date: '2025-08-27',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-26', // date: '2025-08-26',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-25', // date: '2025-08-25',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-24', // date: '2025-08-24',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-23', // date: '2025-08-23',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-22', // date: '2025-08-22',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-21', // date: '2025-08-21',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-20', // date: '2025-08-20',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-19', // date: '2025-08-19',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-18', // date: '2025-08-18',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
}, // },
{ // {
date: '2025-08-17', // date: '2025-08-17',
key1: 10, // key1: 10,
key2: 0, // key2: 0,
key3: 15, // key3: 15,
key4: 5 // key4: 5
} // }
], // ],
energy: [ // energy: [
{ // {
date: '2025-08-30', // date: '2025-08-30',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-29', // date: '2025-08-29',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-28', // date: '2025-08-28',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-27', // date: '2025-08-27',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-26', // date: '2025-08-26',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-25', // date: '2025-08-25',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-24', // date: '2025-08-24',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
} // }
], // ],
charge: [ // charge: [
{ // {
date: '2025-08-30', // date: '2025-08-30',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-29', // date: '2025-08-29',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-28', // date: '2025-08-28',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-27', // date: '2025-08-27',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-26', // date: '2025-08-26',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-25', // date: '2025-08-25',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-24', // date: '2025-08-24',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
} // }
], // ],
pv: [ // pv: [
{ // {
date: '2025-08-30', // date: '2025-08-30',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-29', // date: '2025-08-29',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-28', // date: '2025-08-28',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-27', // date: '2025-08-27',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-26', // date: '2025-08-26',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-25', // date: '2025-08-25',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
}, // },
{ // {
date: '2025-08-24', // date: '2025-08-24',
key1: '2', // key1: '2',
key2: '2' // key2: '2'
} // }
], // ],
allTotal: {} // allTotal: {}
}), // }),
this.getOnLineList(), this.getOnLineList(),
this.getStatTotalList(), this.getStatTotalList(),
this.getStatDayList(1), this.getStatDayList(1),
this.getStatDayList(2), this.getStatDayList(2),
this.getStatDayList(3) this.getStatDayList(3)
]) ])
// this.showFlag=true
}, },
methods: { methods: {
@@ -337,21 +352,29 @@ export default {
async getOnLineList() { async getOnLineList() {
try { try {
// token: 用户TOKEN // token: 用户TOKEN
const res = await getReq({}, '/queryStatSystem') const res = await getReq('/api/queryStatSystem')
if (res.code === 200) { if (res.errcode === 0) {
this.deviceInfo.onLine = res.data this.deviceInfo.onLine = JSON.parse(JSON.stringify(res.data))
this.deviceInfo.onLine.runDays = this.getRunDays(res.data.launch_date)
console.log(JSON.parse(JSON.stringify(res.data)), this.deviceInfo.onLine, '111111111111')
} else { } else {
throw res throw res
} }
} catch (error) { } catch (error) {
this.deviceInfo.onLine = { this.deviceInfo.onLine = {}
launchDate:11,
incomeTotal:12,
solarDeviceNum:10,
stationNum:15
}
} }
}, },
getRunDays(date) {
const launchDate = new Date(date)
const today = new Date() // 替换为当前日期
const timeDiff = today - launchDate // 毫秒差
const daysRun = Math.ceil(timeDiff / (1000 * 60 * 60 * 24)) // 转换为天数
console.log(`从 2023-01-01 到今天已经运行了 ${daysRun}`)
return daysRun
},
// 查询系统累计统计信息 // 查询系统累计统计信息
async getStatTotalList() { async getStatTotalList() {
try { try {
@@ -360,22 +383,27 @@ export default {
// station_id:场站ID为0或不传查询所有场站总计 // station_id:场站ID为0或不传查询所有场站总计
// category:类别1:储能设备,2:充电设备,3:光伏设备,为0或不传查询所有类别总计 // category:类别1:储能设备,2:充电设备,3:光伏设备,为0或不传查询所有类别总计
const query = { const query = {
// date: date: new Date(),
// station_id:this.stationId stationId: this.stationId,
// category:0 category: 0
} }
const res = await postReq(query, '/queryStatTotal') const res = await getReq('/api/queryStatTotal', query)
if (res.code === 200) { if (res.errcode === 0) {
this.deviceInfo.allTotal = res.data this.deviceInfo.allTotal = res.data
this.deviceInfo.allTotal.incomeTotal= const { income_charge: incomeCharge, income_elect: incomeElect } =
this.deviceInfo.allTotal.incomeCharge+ this.deviceInfo.allTotal.incomeElect this.deviceInfo.allTotal
this.deviceInfo.allTotal.incomeTotal = +incomeCharge + +incomeElect
console.log(
this.deviceInfo.allTotal.incomeTotal,
incomeCharge,
incomeElect,
' this.deviceInfo.allTotal.incomeTotal'
)
} else { } else {
throw res throw res
} }
} catch (error) { } catch (error) {
this.deviceInfo.allTotal = { this.deviceInfo.allTotal = {
storageElectIn: 2, storageElectIn: 2,
storageElectOut: 5, storageElectOut: 5,
chargeElect: 4, chargeElect: 4,
@@ -385,11 +413,22 @@ export default {
solarElectGen: 7, solarElectGen: 7,
solarElectGrid: 7 solarElectGrid: 7
} }
this.deviceInfo.allTotal.incomeTotal= this.deviceInfo.allTotal.incomeTotal =
this.deviceInfo.allTotal.incomeCharge+ this.deviceInfo.allTotal.incomeElect this.deviceInfo.allTotal.incomeCharge + this.deviceInfo.allTotal.incomeElect
} }
}, },
getDateDaysAgo(daysAgo) {
const date = new Date()
date.setDate(date.getDate() - daysAgo)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
},
// 示例获取7天前的日期
// 查询场站日统计信息 // 查询场站日统计信息
async getStatDayList(category) { async getStatDayList(category) {
try { try {
@@ -398,31 +437,16 @@ export default {
// start_date开始日期格式yyyy-mm-dd // start_date开始日期格式yyyy-mm-dd
// end_date结束日期格式yyyy-mm-dd // end_date结束日期格式yyyy-mm-dd
const query = { const query = {
stationId:this.stationId, stationId: this.stationId,
category, category,
// start_date: start_date: this.getDateDaysAgo(7 - 1),
// end_date: end_date: this.getDateDaysAgo(0)
} }
const arr=[{ const arr = { 1: 'energy', 2: 'charge', 3: 'pv' }
type:1, const res = await getReq('/api/queryStatDayList', query)
label:'储能设备', if (res.errcode === 0) {
infoKey:'energy' this.list.forEach((item) => {
}, this.deviceInfo[arr[category]] = res.data
{
type:2,
label:'充电设备',
infoKey:'charge'
},
{
type:3,
label:'光伏设备',
infoKey:'pv'
},
]
const res = await postReq(query, '/queryStatDayList')
if (res.code === 200) {
arr.forEach((item)=>{
this.deviceInfo[item.infoKey]=res.data
}) })
} else { } else {
throw res throw res

View File

@@ -9,27 +9,13 @@ module.exports = defineConfig({
// 静态资源目录 // 静态资源目录
assetsDir: 'static', assetsDir: 'static',
devServer: { devServer: {
hot: true, proxy: {
compress: true, '/api': {
allowedHosts: 'all', // 代理前缀,可以自定义(如 '/api'
headers: { target: 'http://192.168.0.187:19801', // 目标服务器地址
// 1. 允许开发环境跨域 changeOrigin: true, // 是否改变请求源(跨域必备)
'Access-Control-Allow-Origin': '*' pathRewrite: {
}, '^/api': '' // 重写路径,去掉 '/api' 前缀
historyApiFallback: true,
open: false,
port: 8080,
client: {
overlay: {
runtimeErrors: (error) => {
const ignoreErrors = [
'ResizeObserver loop limit exceeded',
'ResizeObserver loop completed with undelivered notifications.'
]
if (ignoreErrors.includes(error.message)) {
return false
}
return true
} }
} }
} }