Browse Source

1、保利能管系统项目新增项目管理以及优化设备台账管理

dev_bl_eems
3067418132@qq.com 2 weeks ago
parent
commit
d1b905573f
  1. 85
      mh-admin/src/main/java/com/mh/web/controller/project/ProjectInfoController.java
  2. 40
      mh-admin/src/test/java/com/mh/web/controller/ai/AiFileControllerTest.java
  3. 52
      mh-admin/src/test/java/com/mh/web/controller/ai/FileNameEncodingTest.java
  4. 274
      mh-common/src/main/java/com/mh/common/core/domain/entity/ProjectInfo.java
  5. 17
      mh-system/src/main/java/com/mh/system/mapper/project/ProjectInfoMapper.java
  6. 55
      mh-system/src/main/java/com/mh/system/service/project/IProjectInfoService.java
  7. 120
      mh-system/src/main/java/com/mh/system/service/project/impl/ProjectInfoServiceImpl.java

85
mh-admin/src/main/java/com/mh/web/controller/project/ProjectInfoController.java

@ -0,0 +1,85 @@
package com.mh.web.controller.project;
import com.mh.common.annotation.Log;
import com.mh.common.core.controller.BaseController;
import com.mh.common.core.domain.AjaxResult;
import com.mh.common.core.domain.entity.ProjectInfo;
import com.mh.common.core.page.TableDataInfo;
import com.mh.common.enums.BusinessType;
import com.mh.system.service.project.IProjectInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
/**
* @author EEMCS
* @version 1.0
* @project EEMCS
* @description 项目信息管理
* @date 2026-06-11
*/
@RestController
@RequestMapping("/project/info")
public class ProjectInfoController extends BaseController {
@Autowired
private IProjectInfoService projectInfoService;
/**
* 获取项目信息列表
*/
@PreAuthorize("@ss.hasPermi('project:info:list')")
@GetMapping("/list")
public TableDataInfo list(ProjectInfo projectInfo) {
startPage();
List<ProjectInfo> list = projectInfoService.selectProjectInfoList(projectInfo);
return getDataTable(list);
}
/**
* 根据项目ID获取详细信息
*/
@PreAuthorize("@ss.hasPermi('project:info:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable String id) {
return success(projectInfoService.selectProjectInfoById(id));
}
/**
* 新增项目信息
*/
@PreAuthorize("@ss.hasPermi('project:info:add')")
@Log(title = "项目信息管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody ProjectInfo projectInfo) {
projectInfo.setCreateBy(getUsername());
projectInfo.setCreateTime(new Date());
return toAjax(projectInfoService.insertProjectInfo(projectInfo));
}
/**
* 修改项目信息
*/
@PreAuthorize("@ss.hasPermi('project:info:edit')")
@Log(title = "项目信息管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody ProjectInfo projectInfo) {
projectInfo.setUpdateBy(getUsername());
projectInfo.setUpdateTime(new Date());
return toAjax(projectInfoService.updateProjectInfo(projectInfo));
}
/**
* 删除项目信息
*/
@PreAuthorize("@ss.hasPermi('project:info:remove')")
@Log(title = "项目信息管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids) {
return toAjax(projectInfoService.deleteProjectInfoByIds(ids));
}
}

40
mh-admin/src/test/java/com/mh/web/controller/ai/AiFileControllerTest.java

@ -0,0 +1,40 @@
package com.mh.web.controller.ai;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
public class AiFileControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testGetFileDownload() throws Exception {
// 测试GET请求下载文件
mockMvc.perform(get("/ai/files/测试文件.txt"))
.andExpect(status().isNotFound()); // 文件不存在返回404
}
@Test
public void testPostDeviceAnalyzeExport() throws Exception {
// 测试POST请求设备分析导出
mockMvc.perform(post("/ai/files/设备分析报表.xlsx"))
.andExpect(status().isNotFound()); // 文件不存在返回404
}
@Test
public void testChineseFileNameHandling() throws Exception {
// 测试中文文件名处理
mockMvc.perform(get("/ai/files/能耗报表_2026-02-27.docx"))
.andExpect(status().isNotFound()); // 文件不存在返回404,但不应出现映射冲突
}
}

52
mh-admin/src/test/java/com/mh/web/controller/ai/FileNameEncodingTest.java

@ -0,0 +1,52 @@
package com.mh.web.controller.ai;
import org.junit.jupiter.api.Test;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class FileNameEncodingTest {
@Test
public void testChineseFileNameEncoding() throws Exception {
String chineseFileName = "能耗报表_2026-02-27.docx";
// 测试RFC 5987格式编码
String encodedFileName = URLEncoder.encode(chineseFileName, StandardCharsets.UTF_8.toString());
String disposition = String.format("attachment; filename*=UTF-8''%s", encodedFileName);
System.out.println("原始文件名: " + chineseFileName);
System.out.println("编码后文件名: " + encodedFileName);
System.out.println("完整Content-Disposition头: " + disposition);
// 验证编码后的字符串不包含中文字符
assertTrue(encodedFileName.matches("[A-Za-z0-9%_-]+"));
// 验证包含预期的编码字符
assertTrue(encodedFileName.contains("%"));
}
@Test
public void testDifferentChineseFileNames() throws Exception {
String[] testFiles = {
"系统报表.xlsx",
"数据分析报告.pdf",
"能耗统计_2026年2月.docx",
"设备运行状态.csv"
};
for (String fileName : testFiles) {
String encoded = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
String disposition = String.format("attachment; filename*=UTF-8''%s", encoded);
System.out.println("文件名: " + fileName);
System.out.println("编码: " + encoded);
System.out.println("Disposition: " + disposition);
System.out.println("---");
// 验证编码正确
assertTrue(encoded.matches("[A-Za-z0-9%_-]+"));
}
}
}

274
mh-common/src/main/java/com/mh/common/core/domain/entity/ProjectInfo.java

@ -0,0 +1,274 @@
package com.mh.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.mh.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
/**
* @author EEMCS
* @version 1.0
* @project EEMCS
* @description 项目信息管理
* @date 2026-06-11
*/
@TableName("project_info")
public class ProjectInfo extends BaseEntity {
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
/**
* 用户项目编码
*/
private String projectCode;
/**
* 项目名称
*/
private String projectName;
/**
* 项目地址
*/
private String projectAddress;
/**
* 安装日期
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date installDate;
/**
* 验收日期
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date acceptanceDate;
/**
* 上线日期
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date onlineDate;
/**
* 设备数量
*/
private Integer deviceCount;
/**
* 在线设备数量
*/
private Integer onlineDeviceCount;
/**
* 离线设备数量
*/
private Integer offlineDeviceCount;
/**
* 网关数量
*/
private Integer gatewayCount;
/**
* 在线网关数量
*/
private Integer onlineGatewayCount;
/**
* 离线网关数量
*/
private Integer offlineGatewayCount;
/**
* 项目负责人
*/
private String projectManager;
/**
* 电单价
*/
private BigDecimal electricityPrice;
@JsonIgnore
@TableField(exist = false)
private String searchValue;
/** 请求参数 */
@TableField(exist = false)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Map<String, Object> params;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProjectCode() {
return projectCode;
}
public void setProjectCode(String projectCode) {
this.projectCode = projectCode;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getProjectAddress() {
return projectAddress;
}
public void setProjectAddress(String projectAddress) {
this.projectAddress = projectAddress;
}
public Date getInstallDate() {
return installDate;
}
public void setInstallDate(Date installDate) {
this.installDate = installDate;
}
public Date getAcceptanceDate() {
return acceptanceDate;
}
public void setAcceptanceDate(Date acceptanceDate) {
this.acceptanceDate = acceptanceDate;
}
public Date getOnlineDate() {
return onlineDate;
}
public void setOnlineDate(Date onlineDate) {
this.onlineDate = onlineDate;
}
public Integer getDeviceCount() {
return deviceCount;
}
public void setDeviceCount(Integer deviceCount) {
this.deviceCount = deviceCount;
}
public Integer getOnlineDeviceCount() {
return onlineDeviceCount;
}
public void setOnlineDeviceCount(Integer onlineDeviceCount) {
this.onlineDeviceCount = onlineDeviceCount;
}
public Integer getOfflineDeviceCount() {
return offlineDeviceCount;
}
public void setOfflineDeviceCount(Integer offlineDeviceCount) {
this.offlineDeviceCount = offlineDeviceCount;
}
public Integer getGatewayCount() {
return gatewayCount;
}
public void setGatewayCount(Integer gatewayCount) {
this.gatewayCount = gatewayCount;
}
public Integer getOnlineGatewayCount() {
return onlineGatewayCount;
}
public void setOnlineGatewayCount(Integer onlineGatewayCount) {
this.onlineGatewayCount = onlineGatewayCount;
}
public Integer getOfflineGatewayCount() {
return offlineGatewayCount;
}
public void setOfflineGatewayCount(Integer offlineGatewayCount) {
this.offlineGatewayCount = offlineGatewayCount;
}
public String getProjectManager() {
return projectManager;
}
public void setProjectManager(String projectManager) {
this.projectManager = projectManager;
}
public BigDecimal getElectricityPrice() {
return electricityPrice;
}
public void setElectricityPrice(BigDecimal electricityPrice) {
this.electricityPrice = electricityPrice;
}
@Override
public String getSearchValue() {
return searchValue;
}
@Override
public void setSearchValue(String searchValue) {
this.searchValue = searchValue;
}
@Override
public Map<String, Object> getParams() {
return params;
}
@Override
public void setParams(Map<String, Object> params) {
this.params = params;
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("projectCode", projectCode)
.append("projectName", projectName)
.append("projectAddress", projectAddress)
.append("installDate", installDate)
.append("acceptanceDate", acceptanceDate)
.append("onlineDate", onlineDate)
.append("deviceCount", deviceCount)
.append("onlineDeviceCount", onlineDeviceCount)
.append("offlineDeviceCount", offlineDeviceCount)
.append("gatewayCount", gatewayCount)
.append("onlineGatewayCount", onlineGatewayCount)
.append("offlineGatewayCount", offlineGatewayCount)
.append("projectManager", projectManager)
.append("electricityPrice", electricityPrice)
.append("searchValue", searchValue)
.append("params", params)
.toString();
}
}

17
mh-system/src/main/java/com/mh/system/mapper/project/ProjectInfoMapper.java

@ -0,0 +1,17 @@
package com.mh.system.mapper.project;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mh.common.core.domain.entity.ProjectInfo;
import org.apache.ibatis.annotations.Mapper;
/**
* @author EEMCS
* @version 1.0
* @project EEMCS
* @description 项目信息管理
* @date 2026-06-11
*/
@Mapper
public interface ProjectInfoMapper extends BaseMapper<ProjectInfo> {
}

55
mh-system/src/main/java/com/mh/system/service/project/IProjectInfoService.java

@ -0,0 +1,55 @@
package com.mh.system.service.project;
import com.mh.common.core.domain.entity.ProjectInfo;
import java.util.List;
/**
* @author EEMCS
* @version 1.0
* @project EEMCS
* @description 项目信息管理
* @date 2026-06-11
*/
public interface IProjectInfoService {
/**
* 查询项目信息列表
*
* @param projectInfo 项目信息
* @return 项目信息集合
*/
List<ProjectInfo> selectProjectInfoList(ProjectInfo projectInfo);
/**
* 根据ID查询项目信息
*
* @param id 项目ID
* @return 项目信息
*/
ProjectInfo selectProjectInfoById(String id);
/**
* 新增项目信息
*
* @param projectInfo 项目信息
* @return 结果
*/
int insertProjectInfo(ProjectInfo projectInfo);
/**
* 修改项目信息
*
* @param projectInfo 项目信息
* @return 结果
*/
int updateProjectInfo(ProjectInfo projectInfo);
/**
* 批量删除项目信息
*
* @param ids 需要删除的项目ID数组
* @return 结果
*/
int deleteProjectInfoByIds(String[] ids);
}

120
mh-system/src/main/java/com/mh/system/service/project/impl/ProjectInfoServiceImpl.java

@ -0,0 +1,120 @@
package com.mh.system.service.project.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mh.common.core.domain.entity.ProjectInfo;
import com.mh.common.utils.StringUtils;
import com.mh.system.mapper.project.ProjectInfoMapper;
import com.mh.system.service.project.IProjectInfoService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* @author EEMCS
* @version 1.0
* @project EEMCS
* @description 项目信息管理
* @date 2026-06-11
*/
@Service
public class ProjectInfoServiceImpl implements IProjectInfoService {
@Resource
private ProjectInfoMapper projectInfoMapper;
/**
* 查询项目信息列表
*
* @param projectInfo 项目信息
* @return 项目信息集合
*/
@Override
public List<ProjectInfo> selectProjectInfoList(ProjectInfo projectInfo) {
if (projectInfo == null) {
return List.of();
}
QueryWrapper<ProjectInfo> queryWrapper = new QueryWrapper<>();
// 项目名称(模糊查询)
if (!StringUtils.isEmpty(projectInfo.getProjectName())) {
queryWrapper.like("project_name", projectInfo.getProjectName());
}
// 项目负责人(模糊查询)
if (!StringUtils.isEmpty(projectInfo.getProjectManager())) {
queryWrapper.like("project_manager", projectInfo.getProjectManager());
}
// 安装日期范围查询
if (projectInfo.getParams() != null && !projectInfo.getParams().isEmpty()) {
String beginTimeStr = (String) projectInfo.getParams().get("beginTime");
String endTimeStr = (String) projectInfo.getParams().get("endTime");
if (StringUtils.isNotEmpty(beginTimeStr) && StringUtils.isNotEmpty(endTimeStr)) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate beginTime = LocalDate.parse(beginTimeStr, formatter);
LocalDate endTime = LocalDate.parse(endTimeStr, formatter);
queryWrapper.between("install_date", java.sql.Date.valueOf(beginTime), java.sql.Date.valueOf(endTime));
}
}
// 按创建时间倒序排列
queryWrapper.orderByDesc("create_time");
return projectInfoMapper.selectList(queryWrapper);
}
/**
* 根据ID查询项目信息
*
* @param id 项目ID
* @return 项目信息
*/
@Override
public ProjectInfo selectProjectInfoById(String id) {
return projectInfoMapper.selectById(id);
}
/**
* 新增项目信息
*
* @param projectInfo 项目信息
* @return 结果
*/
@Override
public int insertProjectInfo(ProjectInfo projectInfo) {
return projectInfoMapper.insert(projectInfo);
}
/**
* 修改项目信息
*
* @param projectInfo 项目信息
* @return 结果
*/
@Override
public int updateProjectInfo(ProjectInfo projectInfo) {
return projectInfoMapper.updateById(projectInfo);
}
/**
* 批量删除项目信息
*
* @param ids 需要删除的项目ID数组
* @return 结果
*/
@Override
public int deleteProjectInfoByIds(String[] ids) {
if (ids != null && ids.length > 0) {
for (String id : ids) {
projectInfoMapper.deleteById(id);
}
return ids.length;
}
return 0;
}
}
Loading…
Cancel
Save