From 67c9118cffb7d7407668bbbad4c64f9aaf21ba0d Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期二, 18 三月 2025 10:06:37 +0800
Subject: [PATCH] 看板能耗管理
---
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/EnergyConsumptionService.java | 8
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/impl/EnergyConsumptionServiceImpl.java | 29 ++
UI-Project/src/views/KanbanDisplay/kanbanDisplay.vue | 129 +++++++++++-
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/controller/EnergyConsumptionController.java | 89 ++++++++
UI-Project/src/views/Energy/energyConsumption.vue | 254 +++++++++++++++++++++++++
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/entity/EnergyConsumption.java | 32 +++
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/mapper/EnergyConsumptionMapper.java | 9
7 files changed, 536 insertions(+), 14 deletions(-)
diff --git a/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/controller/EnergyConsumptionController.java b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/controller/EnergyConsumptionController.java
new file mode 100644
index 0000000..a72a062
--- /dev/null
+++ b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/controller/EnergyConsumptionController.java
@@ -0,0 +1,89 @@
+package com.mes.energy.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.mes.energy.entity.EnergyConsumption;
+import com.mes.energy.service.EnergyConsumptionService;
+import com.mes.utils.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Api(tags = "鑳芥簮绠$悊")
+@RestController
+@RequestMapping("/energy/consumption")
+public class EnergyConsumptionController {
+
+ @Autowired
+ private EnergyConsumptionService energyService;
+
+ @ApiOperation("鑾峰彇鑳借�楁暟鎹垪琛�")
+ @PostMapping("/listEnergy")
+ @ResponseBody
+ public Result list(@RequestBody Map<String, Object> params) {
+ Integer page = params.get("page") == null ? 1 : (Integer) params.get("page");
+ Integer pageSize = params.get("pageSize") == null ? 10 : (Integer) params.get("pageSize");
+
+ Page<EnergyConsumption> pageData = energyService.page(
+ new Page<>(page, pageSize),
+ new QueryWrapper<EnergyConsumption>().orderByDesc("record_date")
+ );
+
+ return Result.build(200, "鏌ヨ鎴愬姛", pageData);
+ }
+
+ @ApiOperation("娣诲姞鑳借�楁暟鎹�")
+ @PostMapping("/addEnergy")
+ @ResponseBody
+ public Result add(@RequestBody EnergyConsumption consumption) {
+ consumption.setCreatedAt(new Date());
+ consumption.setUpdatedAt(new Date());
+ int count = energyService.save(consumption) ? 1 : 0;
+ String message = count > 0 ? "娣诲姞鎴愬姛锛�" + count : "娣诲姞澶辫触!";
+ return Result.build(200, message, count);
+ }
+
+ @ApiOperation("淇敼鑳借�楁暟鎹�")
+ @PostMapping("/updateEnergy")
+ @ResponseBody
+ public Result update(@RequestBody EnergyConsumption consumption) {
+ consumption.setUpdatedAt(new Date());
+ int count = energyService.updateById(consumption) ? 1 : 0;
+ String message = count > 0 ? "淇敼鎴愬姛锛�" + count : "淇敼澶辫触!";
+ energyService.notifyEnergyUpdate(consumption);
+ return Result.build(200, message, count);
+ }
+
+ @ApiOperation("鍒犻櫎鑳借�楁暟鎹�")
+ @PostMapping("/deleteEnergy")
+ @ResponseBody
+ public Result delete(@RequestBody EnergyConsumption consumption) {
+ int count = energyService.removeById(consumption.getId()) ? 1 : 0;
+ String message = count > 0 ? "鍒犻櫎鎴愬姛锛�" + count : "鍒犻櫎澶辫触!";
+ return Result.build(200, message, count);
+ }
+
+ @ApiOperation("鑾峰彇鍥捐〃鏁版嵁")
+ @PostMapping("/chartEnergy")
+ @ResponseBody
+ public Result getChartData() {
+ List<EnergyConsumption> data = energyService.list(
+ new QueryWrapper<EnergyConsumption>()
+ .orderByAsc("record_date")
+ .last("limit 30")
+ );
+
+ Map<String, Object> result = new HashMap<>();
+ result.put("actual", data);
+ result.put("planned", null);
+
+ return Result.build(200, "鏌ヨ鎴愬姛", result);
+ }
+}
\ No newline at end of file
diff --git a/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/entity/EnergyConsumption.java b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/entity/EnergyConsumption.java
new file mode 100644
index 0000000..8568b56
--- /dev/null
+++ b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/entity/EnergyConsumption.java
@@ -0,0 +1,32 @@
+package com.mes.energy.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Data
+@TableName("energy_consumption")
+public class EnergyConsumption {
+
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+ private Date recordDate;
+
+ private Double energyValue;
+
+ private Integer userId;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date createdAt;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date updatedAt;
+}
\ No newline at end of file
diff --git a/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/mapper/EnergyConsumptionMapper.java b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/mapper/EnergyConsumptionMapper.java
new file mode 100644
index 0000000..1477162
--- /dev/null
+++ b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/mapper/EnergyConsumptionMapper.java
@@ -0,0 +1,9 @@
+package com.mes.energy.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.mes.energy.entity.EnergyConsumption;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface EnergyConsumptionMapper extends BaseMapper<EnergyConsumption> {
+}
\ No newline at end of file
diff --git a/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/EnergyConsumptionService.java b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/EnergyConsumptionService.java
new file mode 100644
index 0000000..862ce7c
--- /dev/null
+++ b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/EnergyConsumptionService.java
@@ -0,0 +1,8 @@
+package com.mes.energy.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.mes.energy.entity.EnergyConsumption;
+
+public interface EnergyConsumptionService extends IService<EnergyConsumption> {
+ void notifyEnergyUpdate(EnergyConsumption consumption);
+}
\ No newline at end of file
diff --git a/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/impl/EnergyConsumptionServiceImpl.java b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/impl/EnergyConsumptionServiceImpl.java
new file mode 100644
index 0000000..a76bc5f
--- /dev/null
+++ b/JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/impl/EnergyConsumptionServiceImpl.java
@@ -0,0 +1,29 @@
+package com.mes.energy.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.mes.energy.entity.EnergyConsumption;
+import com.mes.energy.mapper.EnergyConsumptionMapper;
+import com.mes.energy.service.EnergyConsumptionService;
+import com.mes.tools.WebSocketServer;
+import cn.hutool.json.JSONObject;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+
+@Service
+public class EnergyConsumptionServiceImpl extends ServiceImpl<EnergyConsumptionMapper, EnergyConsumption> implements EnergyConsumptionService {
+
+ @Override
+ public void notifyEnergyUpdate(EnergyConsumption consumption) {
+ JSONObject message = new JSONObject();
+ message.set("type", "energy_update");
+ message.set("data", consumption);
+
+ ArrayList<WebSocketServer> servers = WebSocketServer.sessionMap.get("energy");
+ if (servers != null) {
+ for (WebSocketServer server : servers) {
+ server.sendMessage(message.toString());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/UI-Project/src/views/Energy/energyConsumption.vue b/UI-Project/src/views/Energy/energyConsumption.vue
new file mode 100644
index 0000000..f1fa606
--- /dev/null
+++ b/UI-Project/src/views/Energy/energyConsumption.vue
@@ -0,0 +1,254 @@
+<script setup>
+import { ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import request from '@/utils/request'
+
+// 鏁版嵁瀹氫箟
+const formData = ref({
+ recordDate: new Date().toISOString().slice(0, 10),
+ energyValue: null
+})
+const loading = ref(false)
+const energyData = ref([])
+
+// 鏃ユ湡鏍煎紡鍖�
+const formatDate = (dateStr) => {
+ const date = new Date(dateStr)
+ return date.toISOString().slice(0, 10)
+}
+
+// 妫�鏌ユ棩鏈熸槸鍚﹂噸澶�
+const checkDateExists = (date, excludeId = null) => {
+ return energyData.value.some(item =>
+ item.recordDate === date && (!excludeId || item.id !== excludeId)
+ )
+}
+
+// API 璇锋眰
+const loadDataFromApi = async () => {
+ loading.value = true
+ try {
+ const { data } = await request({
+ url: '/deviceInteraction/energy/consumption/listEnergy',
+ method: 'post',
+ data: { page: 1, pageSize: 10 }
+ })
+ if (data?.records) {
+ energyData.value = data.records.map(item => ({
+ ...item,
+ editing: false,
+ originalData: { ...item }
+ }))
+ }
+ } catch (error) {
+ ElMessage.error('鏁版嵁鍔犺浇澶辫触')
+ console.error(error)
+ } finally {
+ loading.value = false
+ }
+}
+
+// 琛ㄥ崟鎿嶄綔
+const handleSubmit = async () => {
+ if (!formData.value.recordDate || formData.value.energyValue === null) {
+ ElMessage.error('璇峰~鍐欏畬鏁翠俊鎭�')
+ return
+ }
+
+ if (checkDateExists(formData.value.recordDate)) {
+ ElMessage.error('璇ユ棩鏈熷凡瀛樺湪鑳借�楄褰�')
+ return
+ }
+
+ try {
+ await request({
+ url: '/deviceInteraction/energy/consumption/addEnergy',
+ method: 'post',
+ data: formData.value
+ })
+ ElMessage.success('娣诲姞鎴愬姛')
+ await loadDataFromApi()
+ resetForm()
+ } catch (error) {
+ ElMessage.error('娣诲姞澶辫触')
+ console.error(error)
+ }
+}
+
+const resetForm = () => {
+ formData.value = {
+ recordDate: new Date().toISOString().slice(0, 10),
+ energyValue: null
+ }
+}
+
+// 琛ㄦ牸鎿嶄綔
+const handleRowEdit = async (index, row) => {
+ if (!row.editing) {
+ row.editing = true
+ return
+ }
+
+ if (!row.recordDate || row.energyValue === null) {
+ ElMessage.error('璇峰~鍐欏畬鏁翠俊鎭�')
+ return
+ }
+
+ if (checkDateExists(row.recordDate, row.id)) {
+ ElMessage.error('璇ユ棩鏈熷凡瀛樺湪鑳借�楄褰�')
+ return
+ }
+
+ try {
+ await request({
+ url: '/deviceInteraction/energy/consumption/updateEnergy',
+ method: 'post',
+ data: {
+ id: row.id,
+ recordDate: row.recordDate,
+ energyValue: row.energyValue
+ }
+ })
+ row.editing = false
+ row.originalData = { ...row }
+ ElMessage.success('淇敼鎴愬姛')
+ } catch (error) {
+ ElMessage.error('淇敼澶辫触')
+ console.error(error)
+ }
+}
+
+const cancelEdit = (index, row) => {
+ Object.assign(row, row.originalData)
+ row.editing = false
+}
+
+const handleDelete = async (index) => {
+ try {
+ await ElMessageBox.confirm('纭鍒犻櫎璇ヨ褰曪紵', '璀﹀憡', {
+ type: 'warning'
+ })
+ const id = energyData.value[index].id
+ await request({
+ url: '/deviceInteraction/energy/consumption/deleteEnergy',
+ method: 'post',
+ data: { id }
+ })
+ energyData.value.splice(index, 1)
+ ElMessage.success('鍒犻櫎鎴愬姛')
+ } catch (error) {
+ if (error !== 'cancel') {
+ ElMessage.error('鍒犻櫎澶辫触')
+ console.error(error)
+ }
+ }
+}
+
+// 鍒濆鍖�
+loadDataFromApi()
+</script>
+
+<template>
+ <el-container>
+ <el-header class="header" style="height: auto; margin:20px 0 -10px ; ">
+ <el-form :inline="true" :model="formData" label-width="80px" class="form-container">
+ <el-form-item label="鏃ユ湡" prop="recordDate">
+ <el-date-picker
+ v-model="formData.recordDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="閫夋嫨鏃ユ湡"
+ :default-value="new Date()"
+ style="width: 200px"
+ />
+ </el-form-item>
+ <el-form-item label="鑳借�楀��" prop="energyValue">
+ <el-input-number
+ v-model="formData.energyValue"
+ :precision="2"
+ :step="0.1"
+ :min="0"
+ controls-position="right"
+ style="width: 200px"
+ />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleSubmit">鎻愪氦</el-button>
+ <el-button @click="resetForm">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ </el-header>
+
+ <el-main class="main">
+ <div class="table-container">
+ <el-table
+ :data="energyData"
+ border
+ style="width: 100%"
+ height="500"
+ v-loading="loading"
+ >
+ <el-table-column prop="recordDate" label="鏃ユ湡" width="180">
+ <template #default="scope">
+ <el-date-picker
+ v-if="scope.row.editing"
+ v-model="scope.row.recordDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="閫夋嫨鏃ユ湡"
+ style="width: 140px"
+ />
+ <span v-else>{{ formatDate(scope.row.recordDate) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="energyValue" label="鑳借�楀��" width="180">
+ <template #default="scope">
+ <el-input-number
+ v-if="scope.row.editing"
+ v-model="scope.row.energyValue"
+ :precision="2"
+ :step="0.1"
+ :min="0"
+ controls-position="right"
+ style="width: 140px"
+ />
+ <span v-else>{{ scope.row.energyValue }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="200" fixed="right">
+ <template #default="scope">
+ <el-button-group>
+ <el-button
+ size="small"
+ :type="scope.row.editing ? 'success' : 'primary'"
+ @click="handleRowEdit(scope.$index, scope.row)"
+ >
+ {{ scope.row.editing ? '淇濆瓨' : '缂栬緫' }}
+ </el-button>
+ <el-button
+ v-if="scope.row.editing"
+ size="small"
+ @click="cancelEdit(scope.$index, scope.row)"
+ >
+ 鍙栨秷
+ </el-button>
+ <el-button
+ v-else
+ size="small"
+ type="danger"
+ @click="handleDelete(scope.$index)"
+ >
+ 鍒犻櫎
+ </el-button>
+ </el-button-group>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </el-main>
+ </el-container>
+</template>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/UI-Project/src/views/KanbanDisplay/kanbanDisplay.vue b/UI-Project/src/views/KanbanDisplay/kanbanDisplay.vue
index 2f445e8..be17efd 100644
--- a/UI-Project/src/views/KanbanDisplay/kanbanDisplay.vue
+++ b/UI-Project/src/views/KanbanDisplay/kanbanDisplay.vue
@@ -1,9 +1,111 @@
<!-- 绌虹櫧椤� -->
-
-
+
+
<script setup>
-import { ref, computed } from 'vue'
-import * as echarts from 'echarts';
+import { ref, onMounted } from 'vue'
+import * as echarts from 'echarts'
+import request from '@/utils/request'
+
+const energyData = ref([])
+
+// 鑾峰彇鑳借�楁暟鎹�
+const loadEnergyData = async () => {
+ try {
+ const res = await request({
+ url: '/deviceInteraction/energy/consumption/chartEnergy',
+ method: 'post'
+ })
+ if (res.code === 200) {
+ energyData.value = res.data.actual || [];
+ updateEnergyChart()
+ }
+ } catch (error) {
+ console.error('鑾峰彇鑳借�楁暟鎹け璐�:', error)
+ }
+}
+
+const draw = (name, Option) => {
+ var myChart = echarts.init(document.getElementById(name));
+ myChart.setOption(Option);
+}
+
+const drawDay = (name, Option) => {
+ Option.title.text = "鑳借�楃鐞�";
+ draw(name, Option);
+}
+
+// 鏇存柊鑳借�楀浘琛�
+const updateEnergyChart = () => {
+ // 鎸夋棩鏈熸帓搴忓苟鏍煎紡鍖栨棩鏈�
+ const sortedData = [...energyData.value].sort((a, b) =>
+ new Date(a.recordDate) - new Date(b.recordDate)
+ ).map(item => {
+ const date = new Date(item.recordDate);
+ return {
+ ...item,
+ recordDate: `${date.getMonth() + 1}-${date.getDate().toString().padStart(2, '0')}`
+ };
+ });
+
+ const energyoption = {
+ title: {
+ text: '鑳借�楃鐞�'
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ label: {
+ backgroundColor: '#6a7985'
+ }
+ }
+ },
+ legend: {
+ data: ['鑳借�楀��']
+ },
+ toolbox: {
+ feature: {
+ saveAsImage: {}
+ }
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: [
+ {
+ type: 'category',
+ boundaryGap: false,
+ data: sortedData.map(item => item.recordDate)
+ }
+ ],
+ yAxis: [
+ {
+ type: 'value'
+ }
+ ],
+ series: [
+ {
+ name: '鑳借�楀��',
+ type: 'line',
+ areaStyle: {},
+ label: {
+ show: true,
+ position: 'top'
+ },
+ data: sortedData.map(item => item.energyValue)
+ }
+ ]
+ }
+
+ drawDay('drawLineChart_day71', energyoption);
+}
+
+onMounted(() => {
+ loadEnergyData()
+})
</script>
<script>
export default {
@@ -81,7 +183,7 @@
100, 122, 101]
}
]
-
+
}
this.drawDay('drawLineChart_day11',OptionDay, 1);
// this.drawLineChart('drawLineChart_day11', 1);
@@ -93,17 +195,16 @@
//this.drawBarchart('drawBarchart', 1);
},
methods: {
- //鏂规硶
- draw(name, Option,data) {
+ draw(name, Option, data) {
var myChart = echarts.init(document.getElementById(name));
myChart.setOption(Option);
},
- drawDay(name, Option,data) {
+ drawDay(name, Option, data) {
Option.title.text="鏃ョ湅鏉�";
console.log(Option);
- this.draw(name, Option,data);
+ this.draw(name, Option, data);
},
- drawLineChart(name, Option,data) {
+ drawLineChart(name, Option, data) {
console.log(name);
console.log(data);
var myChart = echarts.init(document.getElementById(name));
@@ -152,14 +253,14 @@
}
}
]
-
-
+
+
});
}
}
}
</script>
-
+
<template>
<div>
<div style="font-size: 30px;height: 70px;line-height: 70px;border: 1px solid #ccc;text-align: center;">
@@ -184,7 +285,7 @@
<div id="drawLineChart_day71" style="height: 33.3%;width: 100%;border: 1px solid #ccc;">鑳借�楃鐞�-鎸夊ぉ鏄剧ず锛堟墜杈擄級</div>
</div>
</div>
-
+
<!-- <div style="width:33% ;height: 880px;border: 1px solid #ccc;">
<div id="drawLineChart_day1" style="height: 300px;width: 25%;border: 1px solid #ccc;float: left;"></div>
<div id="drawLineChart_day2" style="height: 300px;width: 25%;border: 1px solid #ccc;float: left;"></div>
--
Gitblit v1.8.0