JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/controller/EnergyConsumptionController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/entity/EnergyConsumption.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/mapper/EnergyConsumptionMapper.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/EnergyConsumptionService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/impl/EnergyConsumptionServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
UI-Project/src/views/Energy/energyConsumption.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
UI-Project/src/views/KanbanDisplay/kanbanDisplay.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/controller/EnergyConsumptionController.java
New file @@ -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); } } JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/entity/EnergyConsumption.java
New file @@ -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; } JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/mapper/EnergyConsumptionMapper.java
New file @@ -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> { } JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/EnergyConsumptionService.java
New file @@ -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); } JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/impl/EnergyConsumptionServiceImpl.java
New file @@ -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()); } } } } UI-Project/src/views/Energy/energyConsumption.vue
New file @@ -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> UI-Project/src/views/KanbanDisplay/kanbanDisplay.vue
@@ -2,8 +2,110 @@ <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 { @@ -93,7 +195,6 @@ //this.drawBarchart('drawBarchart', 1); }, methods: { //方法 draw(name, Option,data) { var myChart = echarts.init(document.getElementById(name)); myChart.setOption(Option);