7 changed files with 643 additions and 0 deletions
@ -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)); |
||||
} |
||||
} |
||||
@ -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,但不应出现映射冲突
|
||||
} |
||||
} |
||||
@ -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%_-]+")); |
||||
} |
||||
} |
||||
} |
||||
@ -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(); |
||||
} |
||||
} |
||||
@ -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> { |
||||
|
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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…
Reference in new issue