change - add能源预览

boardTest
yinq 1 year ago
parent 7d03b5a25b
commit b739cca197

@ -17,3 +17,12 @@ export function peaksValleysConsumptionReportList(query) {
params: query
})
}
// 查询能源预览接口
export function energyPreviewReportList(query) {
return request({
url: '/ems/report/energyPreviewReportList',
method: 'get',
params: query
})
}

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="114px" height="87px" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1 0 0 1 -135 -174 )">
<path d="M 8 79 L 114 79 L 114 87 L 0 87 L 0 0 L 8 0 L 8 79 Z M 106.3740234375 7.759765625 C 106.7080078125 8.099609375 106.875 8.53385416666666 106 9.0625 L 106 33.701171875 C 106.875 34.494140625 106.51318359375 35.0511067708333 105.78955078125 35.3720703125 C 105.06591796875 35.6930338541667 104.4072265625 35.5514322916667 103.8134765625 34.947265625 L 97.078125 28.09375 L 61.8427734375 63.947265625 C 61.4716796875 64.3248697916667 61.044921875 64.513671875 60.5625 64.513671875 C 60.080078125 64.513671875 59.6533203125 64.3248697916667 59.2822265625 63.947265625 L 46.3125 50.75 L 23.15625 74.3125 L 12.46875 63.4375 L 45.0322265625 30.302734375 C 45.4033203125 29.9251302083333 45.830078125 29.736328125 46.3125 29.736328125 C 46.794921875 29.736328125 47.2216796875 29.9251302083333 47.5927734375 30.302734375 L 60.5625 43.5 L 86.390625 17.21875 L 79.6552734375 10.365234375 C 79.0615234375 9.76106770833333 78.92236328125 9.0908203125 79.23779296875 8.3544921875 C 79.55322265625 7.6181640625 80.1005859375 7.25 80.8798828125 8 L 105.09375 8 C 105.61328125 7.25 106.0400390625 7.419921875 106.3740234375 7.759765625 Z " fill-rule="nonzero" fill="#000000" stroke="none" transform="matrix(1 0 0 1 135 174 )" />
</g>
</svg>

@ -0,0 +1,63 @@
export function getHoursBetween(startHourStr, endHourStr) {
const startHour = new Date(startHourStr)
let endHour = new Date(endHourStr)
let nowDate = new Date()
nowDate.setHours(nowDate.getHours() - 1);
if (endHour.getTime() > nowDate.getTime()) {
endHour = nowDate
}
const hours = []
while (startHour <= endHour) {
const hourString = `${startHour.getFullYear()}-${String(startHour.getMonth() + 1).padStart(2, '0')}-${String(startHour.getDate()).padStart(2, '0')} ${String(startHour.getHours()).padStart(2, '0')}:00:00`
hours.push(hourString)
startHour.setTime(startHour.getTime() + 60 * 60 * 1000)
}
// return hours;
return hours.sort((a, b) => new Date(b) - new Date(a))
}
export function getDatesBetween(startDateStr, endDateStr) {
const startDate = new Date(startDateStr)
let endDate = new Date(endDateStr)
let nowDate = new Date()
nowDate.setHours(nowDate.getHours() - 1);
if (endDate.getTime() > nowDate.getTime()) {
endDate = nowDate
}
const dates = []
while (startDate <= endDate) {
dates.push(`${startDate.getFullYear()}-${String(startDate.getMonth() + 1).padStart(2, '0')}-${String(startDate.getDate()).padStart(2, '0')}`)
startDate.setDate(startDate.getDate() + 1)
}
// return dates;
return dates.sort((a, b) => new Date(b) - new Date(a))
}
export function getMonthsBetween(startMonthStr, endMonthStr) {
const result = []
const startDate = new Date(startMonthStr + '-01')
let endDate = new Date(endMonthStr + '-01')
const currentDate = new Date(startDate)
let nowDate = new Date()
nowDate.setHours(nowDate.getHours() - 1);
if (endDate.getTime() > nowDate.getTime()) {
endDate = nowDate
}
while (currentDate <= endDate) {
const year = currentDate.getFullYear()
const month = String(currentDate.getMonth() + 1).padStart(2, '0')
result.push(`${year}-${month}`)
currentDate.setMonth(currentDate.getMonth() + 1)
}
return result.sort((a, b) => new Date(b) - new Date(a))
}
export function getYearsBetween(startYearStr, endYearStr) {
const result = []
const startYear = Number(startYearStr.substring(0, 4))
const endYear = Number(endYearStr.substring(0, 4))
for (let i = startYear; i <= endYear; i++) {
result.push(`${i}`)
}
return result.sort((a, b) => new Date(b) - new Date(a))
}

@ -0,0 +1,36 @@
import FileSaver from "file-saver";
import XLSX from "xlsx";
/**
* 字符权限校验
* @param {Array} value 校验值
* @returns {Boolean}
* id:表ID
* name:导出表名字
*xlsxParamtrue/false:如果表格里有数字日期这些需要加上raw: true
*/
export function handleExport(id,name,xlsxParam) {
var wb = XLSX.utils.table_to_book(
document.querySelector('#'+id),
{raw: xlsxParam}
);
var wbout = XLSX.write(wb, {
bookType: "xlsx",
bookSST: true,
type: "array",
});
try {
FileSaver.saveAs(
new Blob([wbout], { type: "application/octet-stream" }),
name+".xlsx"
);
} catch (e) {
if (typeof console !== "undefined") {
console.log(e, wbout);
}
}
return wbout;
}

@ -72,7 +72,7 @@
<el-table-column label="能源类型名称" align="center" prop="energyName" v-if="columns[2].visible"/>
<el-table-column label="单位" align="center" prop="measureUnit" v-if="columns[3].visible"/>
<el-table-column label="单价" align="center" prop="price" v-if="columns[4].visible"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100">
<template slot-scope="scope">
<el-button
size="mini"
@ -82,14 +82,14 @@
v-hasPermi="['ems/base:baseEnergyType:edit']"
>修改
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['ems/base:baseEnergyType:remove']"
>删除
</el-button>
<!-- <el-button-->
<!-- size="mini"-->
<!-- type="text"-->
<!-- icon="el-icon-delete"-->
<!-- @click="handleDelete(scope.row)"-->
<!-- v-hasPermi="['ems/base:baseEnergyType:remove']"-->
<!-- >删除-->
<!-- </el-button>-->
</template>
</el-table-column>
</el-table>

@ -253,16 +253,16 @@
<!-- <el-form-item label="备注" prop="remark">-->
<!-- <el-input v-model="form.remark" placeholder="请输入备注"/>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="启用标识" prop="isFlag">-->
<!-- <el-radio-group v-model="form.isFlag">-->
<!-- <el-radio-->
<!-- v-for="dict in dict.type.is_flag"-->
<!-- :key="dict.value"-->
<!-- :label="dict.value"-->
<!-- >{{ dict.label }}-->
<!-- </el-radio>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<el-form-item label="启用标识" prop="isFlag">
<el-radio-group v-model="form.isFlag">
<el-radio
v-for="dict in dict.type.is_flag"
:key="dict.value"
:label="dict.value"
>{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
@ -351,12 +351,12 @@ export default {
{ key: 0, label: `主键标识`, visible: false },
{ key: 1, label: `计量设备编号`, visible: true },
{ key: 2, label: `统计单元编号`, visible: true },
{ key: 3, label: `计量设备状态`, visible: true },
{ key: 3, label: `计量设备状态`, visible: false },
{ key: 4, label: `计量设备类型`, visible: true },
{ key: 5, label: `计算方式`, visible: true },
{ key: 6, label: `比率`, visible: true },
{ key: 7, label: `备注`, visible: false },
{ key: 8, label: `启用标识`, visible: false },
{ key: 8, label: `启用标识`, visible: true },
{ key: 9, label: `创建人`, visible: false },
{ key: 10, label: `创建时间`, visible: false },
{ key: 11, label: `修改人`, visible: false },
@ -403,7 +403,7 @@ export default {
monitorCode: null,
workUnitCode: null,
monitorStatus: null,
monitorType: null,
monitorType: this.queryParams.monitorType,
formulaMode: 0,
proportion: 1,
remark: null,

@ -0,0 +1,635 @@
<template>
<div class="app-container">
<el-card class="box-card" style="margin-bottom: 10px">
<el-row :gutter="20">
<el-col :span="24" :xs="24">
<el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="能源类型" prop="energyType">
<el-select v-model="queryParams.energyType" style="width: 100px" placeholder="请选择能源类型">
<el-option
v-for="item in energyTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="日期类型" prop="dateType">
<el-select v-model="queryParams.dateType" style="width: 100px" placeholder="请选择日期类型">
<el-option
v-for="dict in dateTypeList"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="采集时间">
<el-date-picker
v-model="queryParams.startTime"
style="width: 200px"
type="datetime"
placeholder="选择日期时间"
value-format="yyyy-MM-dd HH:mm:ss"
></el-date-picker>
</el-form-item>
<el-form-item label-width="auto">-</el-form-item>
<el-form-item>
<el-date-picker
v-model="queryParams.endTime"
value-format="yyyy-MM-dd HH:mm:ss"
style="width: 200px"
type="datetime"
placeholder="选择日期时间"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索
</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置
</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</el-card>
<el-row :gutter="20">
<el-col :span="5" :xs="24">
<el-card class="box-card" style="height: 350px; position: relative">
<img
class="centered-image"
src="@/assets/images/electricityIcon.svg"
/>
<div class="centered-text total-consumption-label">
总耗量
</div>
<div class="centered-text total-consumption-value">
{{ totalConsumption != null ? totalConsumption.toFixed(2) : '' }}{{ measurementUnit }}
</div>
</el-card>
</el-col>
<el-col :span="19" :xs="24">
<el-card class="box-card" style="height: 350px; margin-bottom: 10px">
<div id="card" class="card-container"></div>
</el-card>
</el-col>
</el-row>
<el-card class="box-card" style="margin-bottom: 30px">
<el-row :gutter="20">
<el-col :span="24" :xs="24">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出
</el-button>
</el-col>
<right-toolbar
:showSearch.sync="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
header-cell-class-name="columnClassName"
id="bootstrap-table"
v-loading="loading"
:data="dataList"
@selection-change="handleSelectionChange"
>
<template v-for="time in timeList">
<el-table-column
v-if="time.title && time.rowspan == 2"
:key="time.title"
:label="time.title"
:prop="time.field"
min-width="120"
/>
<el-table-column
v-if="time.title && time.colspan == 1"
:key="time.title"
:label="time.title"
>
<el-table-column
min-width="140"
:key="time.title + '_' + time.field"
:label="'耗量(' + measurementUnit + ')'"
:prop="time.field"
/>
</el-table-column>
</template>
</el-table>
</el-col>
</el-row>
</el-card>
</div>
</template>
<script>
import {
energyPreviewReportList
} from '@/api/ems/report/reportPort.js'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import * as echarts from 'echarts'
import {
getHoursBetween,
getDatesBetween,
getMonthsBetween,
getYearsBetween
} from '@/utils/dateReportUtils.js'
import { handleExport } from '@/utils/export.js'
import { parseTime } from '@/utils/ruoyi'
let data = {}
let optionData = {}
export default {
name: 'EnergyPreview',
dicts: ['statistical_unit'],
components: { Treeselect },
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
dataList: null,
// List
timeList: null,
energyList: null,
//
title: '',
//
open: false,
//
form: {},
//
queryParams: {
energyType: '2',
dateType: '10',
startTime: '',
endTime: ''
},
//
totalConsumption: 0,
//
measurementUnit: 'kW·h',
//
dateTypeList: [
{ label: '时', value: '13' },
{ label: '日', value: '10' },
{ label: '月', value: '7' },
{ label: '年', value: '4' }
],
//
energyTypeList: [
{ value: '2', label: '电' },
{ value: '3', label: '水' },
{ value: '4', label: '蒸汽' }
],
option: {
grid: {
containLabel: true,
left: '2%',
right: '2%',
bottom: '5%',
top: 20
},
tooltip: {
trigger: 'axis',
formatter: function(params) {
return params.data + 'kW·h'
},
textStyle: {
align: 'left'
}
},
xAxis: [
{
axisLabel: {
color: '#333',
fontSize: 14
// interval: 0,
},
axisTick: {
lineStyle: {
color: '#384267'
},
show: true
},
splitLine: {
show: false
},
axisLine: {
lineStyle: {
color: 'rgba(255,255,255,0.1)',
width: 1
},
show: true
},
data: data.x,
type: 'category'
}
],
yAxis: {
axisLabel: {
color: '#333',
fontSize: 14
},
axisTick: {
lineStyle: {
color: '#384267',
width: 1
},
show: true
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(255,255,255,0.1)'
}
},
axisLine: {
lineStyle: {
color: 'rgba(255,255,255,0.1)',
width: 1
},
show: true
},
name: ''
},
dataZoom: [],
series: [
{
data: data.y,
type: 'bar',
barMaxWidth: 20,
barWidth: '75%',
itemStyle: {
color: {
x: 0,
y: 0,
x2: 0,
y2: 1,
type: 'linear',
global: false,
colorStops: [
{
offset: 0,
color: optionData?.bgColor ? optionData.bgColor : '#0a8ff6'
},
{
offset: 1,
color: '#06f8f7'
}
]
}
}
},
{
type: 'line',
stack: '总量',
symbol: 'circle',
symbolSize: 8,
itemStyle: {
normal: {
borderWidth: 2,
borderColor: '#3aa1ff',
color: '#3aa1ff',
lineStyle: {
color: '#3aa1ff',
width: 1
}
}
},
tooltip: {
show: false
},
data: data.y
}
]
}
}
},
created() {
const nowDate = parseTime(new Date(), '{y}-{m}-{d}')
this.queryParams.startTime = nowDate + ' 00:00:00'
this.queryParams.endTime = nowDate + ' 23:59:59'
},
mounted() {
this.handleQuery()
},
methods: {
getDateList(startTime, endTime) {
if (this.queryParams.dateType === '13') {
return getHoursBetween(startTime, endTime)
} else if (this.queryParams.dateType === '10') {
return getDatesBetween(startTime, endTime)
} else if (this.queryParams.dateType === '7') {
return getMonthsBetween(startTime, endTime)
} else if (this.queryParams.dateType === '4') {
return getYearsBetween(startTime, endTime)
}
},
barChart() {
var chartDom = document.getElementById('card')
var myChart = echarts.init(chartDom)
let data = []
const createLinearGradient = (startColor, endColor) => ({
x: 0,
y: 0,
x2: 0,
y2: 1,
type: 'linear',
global: false,
colorStops: [
{ offset: 0, color: startColor },
{ offset: 1, color: endColor }
]
})
const axisStyle = {
axisLabel: { color: '#333', fontSize: 14 },
axisTick: { lineStyle: { color: '#384267', width: 1 }, show: true },
axisLine: { lineStyle: { color: 'rgba(255,255,255,0.1)', width: 1 }, show: true }
}
const option = {
grid: {
containLabel: true,
left: '2%',
right: '2%',
bottom: '5%',
top: 20
},
tooltip: {
trigger: 'axis',
formatter: (params) => `${params[0].name}<br>${params[0].marker} ${params[0].data}kW·h`
},
xAxis: [
{
...axisStyle,
data: [],
type: 'category',
splitLine: { show: false }
}
],
yAxis: {
...axisStyle,
splitLine: { show: true, lineStyle: { color: 'rgba(255,255,255,0.1)' } },
name: ''
},
dataZoom: [],
series: [
{
data: data,
type: 'bar',
barMaxWidth: 20,
barWidth: '75%',
itemStyle: {
color: createLinearGradient(optionData?.bgColor || '#0a8ff6', '#06f8f7')
}
},
{
data: data,
type: 'line',
stack: '总量',
symbol: 'circle',
symbolSize: 8,
itemStyle: {
normal: {
borderWidth: 2,
borderColor: '#3aa1ff',
color: '#3aa1ff',
lineStyle: { color: '#3aa1ff', width: 1 }
}
},
tooltip: { show: false }
}
]
}
myChart.setOption(option)
energyPreviewReportList(this.queryParams).then((response) => {
this.dataList = response.data
this.loading = false
const data = response.data || []
if (data.length === 0) return
this.totalConsumption = data.reduce((sum, item) => {
return sum + parseFloat(item.expendSum || 0);
}, 0);
const keys = Object.keys(data[0])
const filteredKeys = keys.filter(key => key && !['unitName', 'state', 'expendSum', 'type'].includes(key))
const yData = filteredKeys.map(key => {
return data.reduce((sum, item) => sum + parseFloat(item[key] || 0), 0).toFixed(2)
})
const timeData = filteredKeys.map(key => key.split('expend')[1] + ':00:00')
const sortedData = timeData.map((time, index) => ({
name: time,
value: parseFloat(yData[index]),
time: new Date(time).getTime()
})).sort((a, b) => a.time - b.time)
const xAxisData = sortedData.map(item => item.name.split(':')[0])
const seriesData = sortedData.map(item => item.value)
myChart.setOption({
dataZoom: [{
show: true,
type: 'slider',
bottom: '3%',
xAxisIndex: 0,
height: 12,
start: 0,
brushSelect: false,
end: (1 / (seriesData.length / 20)) * 100,
textStyle: {
fontSize: 0,
color: 'rgba(0,0,0,0)'
}
}],
xAxis: [{
data: xAxisData
}],
series: [{
data: seriesData
}, {
data: seriesData
}]
})
})
},
/** 查询用户列表 */
getList(dateList) {
this.loading = true
this.initTable(dateList)
this.barChart()
},
initTable(columns) {
this.timeList = []
this.energyList = []
this.timeList.push(
{
title: '用电类型名称',
field: 'unitName',
align: 'center',
rowspan: 2
},
{
field: 'expendSum',
title: '耗量合计(' + this.measurementUnit + ')',
align: 'center',
rowspan: 2
}
)
for (let i in columns) {
this.timeList.push({
title: columns[i],
align: 'center',
colspan: 1,
field: 'expend' + columns[i].substring(0, 13)
})
this.energyList.push({
field: 'expend' + columns[i].substring(0, 13),
title: '耗量(' + this.measurementUnit + ')',
align: 'center',
rowspan: 1
})
}
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
userId: undefined
}
this.resetForm('form')
},
/** 搜索按钮操作 */
handleQuery() {
let dateList = this.getDateList(
this.queryParams.startTime,
this.queryParams.endTime
)
this.getList(dateList)
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams.dateType = '10'
this.queryParams.startTime = ''
this.queryParams.endTime = ''
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.userId)
this.single = selection.length != 1
this.multiple = !selection.length
},
/** 导出按钮操作 */
handleExport() {
handleExport('bootstrap-table', `能源预览_${new Date().getTime()}`, true)
}
}
}
</script>
<style lang="scss" scoped>
.app-container {
::v-deep.columnClassName {
font-size: 10px;
font-weight: normal;
}
.tree {
width: 220px;
::v-deep .el-tree-node {
white-space: normal; //!!!!!!!!!
.el-tree-node__content {
height: 100%;
align-items: start;
}
}
}
}
.app-container {
padding: 20px;
}
.centered-image {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -100%);
}
.centered-text {
position: absolute;
left: 50%;
transform: translate(-50%, 0%);
font-weight: 600;
text-align: center;
}
.total-consumption-label {
top: 45%;
font-size: 1.9vw;
}
.total-consumption-value {
top: 55%;
width: 100%;
padding: 3px 10px;
font-size: 1.7vw;
}
.card-container {
width: 100%;
height: 350px;
margin-left: 50px;
user-select: none;
margin-top: -30px;
}
.mb8 {
margin-bottom: 8px;
}
</style>

@ -148,7 +148,6 @@ export default {
label: "label"
},
dateTypeList: [
{dateTypeCode: 19, dateTypeName: '时'},
{dateTypeCode: 10, dateTypeName: '日'},
{dateTypeCode: 7, dateTypeName: '月'},
{dateTypeCode: 4, dateTypeName: '年'},

Loading…
Cancel
Save