diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index 4535cba..d657830 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.framework.excel.core.util; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; +import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.converters.longconverter.LongStringConverter; import com.alibaba.excel.support.ExcelTypeEnum; @@ -9,7 +11,10 @@ import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.List; /** @@ -68,7 +73,7 @@ public class ExcelUtils { * @throws IOException 写入失败的情况 */ public static void writeCSV(HttpServletResponse response, String filename, String sheetName, - Class head, List data) throws IOException { + Class head, List data) throws IOException { response.setHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename)); // response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.setContentType("application/vnd.opencmlformats-officedocument.spreadsheetml.sheet"); @@ -89,11 +94,4 @@ public class ExcelUtils { } - public static List readCSV(MultipartFile file, Class head) throws IOException { - return EasyExcel.read(file.getInputStream(), head, null) - .excelType(ExcelTypeEnum.CSV) - .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 - .doReadAllSync(); - } - } diff --git a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/EXAController.java b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/EXAController.java index dd82886..eee1249 100644 --- a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/EXAController.java +++ b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/EXAController.java @@ -89,8 +89,8 @@ public class EXAController { @GetMapping("/group") @Operation(summary = "获取EXA所有组名") @PreAuthorize("@ss.hasPermission('alert:exa:query')") - public CommonResult> getEXAGroupInfo() throws URISyntaxException, IOException { - List groupList=exaService.getEXAGroupInfo(); + public CommonResult>> getEXAGroupInfo() throws URISyntaxException, IOException { + List> groupList=exaService.getEXAGroupInfo(); return success(groupList); } @@ -132,8 +132,8 @@ public class EXAController { @PreAuthorize("@ss.hasPermission('system:user:import')") public CommonResult importExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { - System.out.println(file); - List list = ExcelUtils.readCSV(file, Point.class); + System.out.println(file.getInputStream()); + List list = ExcelUtils.read(file, Point.class); return success(exaService.importPointList(list, updateSupport)); } diff --git a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/EXAGroupRespVO.java b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/EXAGroupRespVO.java new file mode 100644 index 0000000..f5fc81f --- /dev/null +++ b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/EXAGroupRespVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.alert.controller.admin.exa.vo; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "EXA - 获取组名 Response VO") +@Data +@NoArgsConstructor // 添加无参构造器 +@AllArgsConstructor // 添加全参构造器,与@Builder兼容 +public class EXAGroupRespVO { + /** + * 组名 + */ + @JSONField(name="GroupsJson") + private String GroupsJson; + + /** + * 返回值 + */ + @JSONField(name="ReturnValue") + private Long ReturnValue; +} diff --git a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/EXAResult.java b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/EXAResult.java index 4f05aac..6b85368 100644 --- a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/EXAResult.java +++ b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/EXAResult.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.alert.controller.admin.exa.vo; import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; +@Data public class EXAResult { @JSONField(name="ReturnValue") public Long ReturnValue; diff --git a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/Point.java b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/Point.java index cb0df87..88a9c9c 100644 --- a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/Point.java +++ b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/exa/vo/Point.java @@ -15,8 +15,8 @@ import lombok.experimental.Accessors; @NoArgsConstructor @Accessors(chain = false) // 设置 chain = false,避免用户导入有问题 public class Point { - @Schema(description = "", example = "芋道") - public String AssetCode; +// @Schema(description = "", example = "芋道") +// public String AssetCode; @ExcelProperty("点号名称") @Schema(description = "点号", example = "芋道") @@ -42,12 +42,12 @@ public class Point { @ExcelProperty("自动保存") public Boolean AutoSave=true; - public Double UpperBound=9999999.0; - public Double LowerBound=-9999999.0; - public Double UpperLimit=9999999.0; - public Double LowerLimit=-9999999.0; - public Double UpperUpperLimit=9999999.0; - public Double LowerLowerLimit=-9999999.0; +// public Double UpperBound=9999999.0; +// public Double LowerBound=-9999999.0; +// public Double UpperLimit=9999999.0; +// public Double LowerLimit=-9999999.0; +// public Double UpperUpperLimit=9999999.0; +// public Double LowerLowerLimit=-9999999.0; public String Comment=""; public String Note=""; diff --git a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/exa/EXAService.java b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/exa/EXAService.java index 8cb9a76..0aec5c0 100644 --- a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/exa/EXAService.java +++ b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/exa/EXAService.java @@ -34,7 +34,7 @@ public interface EXAService { String createPoint(Point pointVo) throws IOException; - public List getEXAGroupInfo() throws URISyntaxException, IOException; + public List> getEXAGroupInfo() throws URISyntaxException, IOException; public String deletePoint(String ItemName); EXAPointImportRespVO importPointList(List importPoints, boolean isUpdateSupport); diff --git a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/exa/EXAServiceImpl.java b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/exa/EXAServiceImpl.java index 29926b6..aa2e74b 100644 --- a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/exa/EXAServiceImpl.java +++ b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/exa/EXAServiceImpl.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.alert.controller.admin.exa.vo.*; import cn.iocoder.yudao.module.alert.controller.admin.system.vo.PointOptionItemVO; import cn.iocoder.yudao.module.alert.utils.EXAUtils; +import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -38,6 +39,7 @@ public class EXAServiceImpl implements EXAService { private String EXA_IP; //根据测点名称测点描述模糊查询 + /** * 根据测点名称测点描述模糊查询 * @@ -46,7 +48,7 @@ public class EXAServiceImpl implements EXAService { */ @Override public PageResult getEXAPage(EXAPageReqVO reqVO) throws IOException, URISyntaxException { - List exaListAll = exaUtils.getPointInfo(EXA_IP,reqVO); + List exaListAll = exaUtils.getPointInfo(EXA_IP, reqVO); Long total = Long.valueOf(exaListAll.size()); List exaList = getPartList(exaListAll, reqVO.getPageNo(), reqVO.getPageSize()); @@ -66,7 +68,7 @@ public class EXAServiceImpl implements EXAService { list.forEach(entity -> { try { - entity.setValue(exaUtils.getNowData(EXA_IP,entity.getItemName()).get(0)); + entity.setValue(exaUtils.getNowData(EXA_IP, entity.getItemName()).get(0)); } catch (URISyntaxException e) { throw new RuntimeException(e); } catch (IOException e) { @@ -85,8 +87,9 @@ public class EXAServiceImpl implements EXAService { */ @Override public EXAResult getEXAListNowReal(EXANowListReqVO list) throws URISyntaxException, IOException { - return exaUtils.getNowDataList(EXA_IP,list); + return exaUtils.getNowDataList(EXA_IP, list); } + /** * 根据点号查询实时值 * @@ -95,9 +98,10 @@ public class EXAServiceImpl implements EXAService { */ @Override public String getEXANow(String itemName) throws URISyntaxException, IOException { - return exaUtils.getNowData(EXA_IP,itemName).get(0); + return exaUtils.getNowData(EXA_IP, itemName).get(0); } + /** * 根据点号查询历史值 * @@ -105,9 +109,10 @@ public class EXAServiceImpl implements EXAService { * @return 分页结果 */ @Override - public List> getEXAHistory(EXAHistoryReqVO exaHistoryReqVo) { - return exaUtils.getHistory(EXA_IP,exaHistoryReqVo); + public List> getEXAHistory(EXAHistoryReqVO exaHistoryReqVo) { + return exaUtils.getHistory(EXA_IP, exaHistoryReqVo); } + /** * 根据多个点号查询历史值 * @@ -115,23 +120,25 @@ public class EXAServiceImpl implements EXAService { * @return 分页结果 */ @Override - public List>> getEXAHistorys(EXAHistoryReqVO exaHistoryReqVo) { - return exaUtils.getHistorys(EXA_IP,exaHistoryReqVo); + public List>> getEXAHistorys(EXAHistoryReqVO exaHistoryReqVo) { + return exaUtils.getHistorys(EXA_IP, exaHistoryReqVo); } @Override - public String createPoint(Point pointVo) throws IOException { - return exaUtils.setPoint(EXA_IP,pointVo); + public String createPoint(Point pointVo) throws IOException { + return exaUtils.setPoint(EXA_IP, pointVo); } + /** * 查询EXA所有分组信息 * * @return 分页结果 */ @Override - public List getEXAGroupInfo() throws URISyntaxException, IOException { + public List> getEXAGroupInfo() throws URISyntaxException, IOException { return exaUtils.getGroup(EXA_IP); } + /** * 删除EXA点号 * @@ -139,14 +146,15 @@ public class EXAServiceImpl implements EXAService { * @return 分页结果 */ @Override - public String deletePoint(String ItemName){ - return exaUtils.deletePoint(EXA_IP,ItemName); + public String deletePoint(String ItemName) { + return exaUtils.deletePoint(EXA_IP, ItemName); } + /** * 导入EXA点号 * - * @param importPoints 导入点号列表 + * @param importPoints 导入点号列表 * @param isUpdateSupport 是否支持更新 * @return 分页结果 */ @@ -163,13 +171,17 @@ public class EXAServiceImpl implements EXAService { .updateNames(new ArrayList<>()).failureNames(new LinkedHashMap<>()).build(); importPoints.forEach(importUser -> { try { - String createResult=createPoint(importUser); - if(createResult.equals("1")){ + String createResult = createPoint(importUser); + EXAResult vo = JSON.parseObject(createResult, EXAResult.class); + if (vo.ReturnValue.equals(1L)) { respVO.getCreateNames().add(importUser.getItemName()); + } else if (vo.ReturnValue.equals(-19L)) { + respVO.getFailureNames().put(importUser.getItemName(), "该点号已存在"); + } else { + respVO.getFailureNames().put(importUser.getItemName(), "未知错误"); } - } catch (IOException e) { - throw new RuntimeException(e); + throw exception(EXA_POINT_IMPORT_FAILED, importUser.getItemName(), e); } }); return respVO; diff --git a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/utils/EXAUtils.java b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/utils/EXAUtils.java index 439dd2e..ee71aa7 100644 --- a/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/utils/EXAUtils.java +++ b/yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/utils/EXAUtils.java @@ -276,53 +276,85 @@ public class EXAUtils { return result; } - public List getGroup(String EXA_IP) throws URISyntaxException, IOException { - List result = new ArrayList<>(); - try { - // 目标 RPC 服务的 URL - String url = "http://" + EXA_IP + ":9000/exawebapi/exagroup/getgroups"; - //创建HttpClient对象 - CloseableHttpClient httpClient = HttpClients.createDefault(); - /* - * 由于GET请求的参数都是拼装在URL地址后方,所以我们要构建一个URL,带参数 - */ - URIBuilder uriBuilder = new URIBuilder(url); - - /** 添加参数 */ -// uriBuilder.addParameter("ItemNames", itemNames); - //创建请求对象 - HttpGet httpGet = new HttpGet(uriBuilder.build()); + public List> getGroup(String EXA_IP) throws IOException { + String requestPathAddItem = "http://" + EXA_IP + ":9000/exawebapi/EXAItem/GetAllGroups"; + String result = Request.Post(requestPathAddItem) + .addHeader("Content-type", "application/json") + .execute().returnContent().asString(Charset.forName("utf-8")); + // Add validation for empty or null response + if (result == null || result.isEmpty()) { + return new ArrayList<>(); + } - // 传输的类型 - httpGet.addHeader("Content-Type", "application/json"); - //发送请求,请求响应结果 - CloseableHttpResponse response = httpClient.execute(httpGet); - //获取服务器返回的状态码 - int statusCode = response.getStatusLine().getStatusCode(); - System.out.println("服务端返回成功的状态码为:" + statusCode); - HttpEntity entity = response.getEntity(); - String body = EntityUtils.toString(entity).replaceAll("\\\\", ""); - System.out.println("服务端返回的数据为:" + body); - if (body.startsWith("\"") && body.endsWith("\"")) { - // 步骤3:去掉双引号 - body = body.substring(1, body.length() - 1); // 去掉首尾的双引号 + try { + // Handle potential escaped quotes in response + if (result.startsWith("\"") && result.endsWith("\"")) { + result = result.substring(1, result.length() - 1).replace("\\\"", "\"").replace("\\\\", "\\"); } - Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create(); - Type listType = new TypeToken>() { - }.getType(); - result = gson.fromJson(body, listType); - - //关闭资源 - response.close(); - httpClient.close(); + EXAGroupRespVO vo = JSON.parseObject(result, EXAGroupRespVO.class); + List> jsonResult = new ArrayList<>(); + if(vo.getReturnValue().equals(1L)){ + jsonResult = JSON.parseObject(vo.getGroupsJson(), new com.alibaba.fastjson.TypeReference>>() {}); + } + return jsonResult; } catch (Exception e) { - + System.err.println("Failed to parse group data: " + e.getMessage()); + System.err.println("Response was: " + result); + // Return empty list instead of null to prevent NullPointerException + return new ArrayList<>(); } - return result; + } +// public List getGroup(String EXA_IP) throws URISyntaxException, IOException { +// List result = new ArrayList<>(); +// try { +// // 目标 RPC 服务的 URL +// String url = "http://" + EXA_IP + ":9000/exawebapi/EXAItem/GetAllGroups"; +// //创建HttpClient对象 +// CloseableHttpClient httpClient = HttpClients.createDefault(); +// /* +// * 由于GET请求的参数都是拼装在URL地址后方,所以我们要构建一个URL,带参数 +// */ +// URIBuilder uriBuilder = new URIBuilder(url); +// +// /** 添加参数 */ +//// uriBuilder.addParameter("ItemNames", itemNames); +// +// //创建请求对象 +// HttpGet httpGet = new HttpGet(uriBuilder.build()); +// +// // 传输的类型 +// httpGet.addHeader("Content-Type", "application/json"); +// //发送请求,请求响应结果 +// CloseableHttpResponse response = httpClient.execute(httpGet); +// //获取服务器返回的状态码 +// int statusCode = response.getStatusLine().getStatusCode(); +// System.out.println("服务端返回成功的状态码为:" + statusCode); +// HttpEntity entity = response.getEntity(); +// String body = EntityUtils.toString(entity).replaceAll("\\\\", ""); +// System.out.println("服务端返回的数据为:" + body); +// if (body.startsWith("\"") && body.endsWith("\"")) { +// // 步骤3:去掉双引号 +// body = body.substring(1, body.length() - 1); // 去掉首尾的双引号 +// } +// +// Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create(); +// Type listType = new TypeToken>() { +// }.getType(); +// result = gson.fromJson(body, listType); +// +// //关闭资源 +// response.close(); +// httpClient.close(); +// } catch (Exception e) { +// +// } +// return result; +// } + public String deletePoint(String EXA_IP, String ItemName) { String requestPathDeleteItem = "http://" + EXA_IP + ":9000/exawebapi/exaitem/DeleteItem?ItemName=" + ItemName; // 创建HttpClient diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 76cf672..c59a7ee 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -167,7 +167,6 @@ public interface ErrorCodeConstants { ErrorCode NOTIFY_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_028_000, "模板参数({})缺失"); - ErrorCode EXA_POINT_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_002_029_000, "导入EXA测点数据不能为空!"); // ========== 模型实例模块 3-001========== @@ -190,4 +189,10 @@ public interface ErrorCodeConstants { ErrorCode SYSTEM_CONFIG_NOT_EXISTS = new ErrorCode(1_002_033_000, "系统配置不存在"); ErrorCode SYSTEM_CONFIG_NAME_DUPLICATE = new ErrorCode(1_002_033_001, "已经存在该名字的系统配置"); + // ========== Excel 导入导出 1-002-034-000 ========== + ErrorCode EXCEL_FILE_EMPTY = new ErrorCode(1_002_034_000, "Excel 文件为空"); + // ========== EXA模块 1-002-034-000 ========== + ErrorCode EXA_POINT_IMPORT_LIST_IS_EMPTY = new ErrorCode(6_001_000, "导入EXA测点数据不能为空!"); + ErrorCode EXA_POINT_IMPORT_FAILED = new ErrorCode(6_001_001, "导入EXA测点数据失败!失败测点:({})"); + }