From b0f6c6fcd1febb5f74f0af08be5d9a71f297351a Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Mon, 5 Jan 2026 17:58:42 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=8E=86=E5=8F=B2=E8=AE=B0=E5=BD=95=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/scheduler/SchedulerManager.java | 19 +- .../infra/service/job/JobServiceImpl.java | 4 +- .../admin/device/DeviceController.java | 15 +- .../admin/device/vo/LineDeviceRequestVO.java | 6 + .../admin/device/vo/SingleDeviceRespVO.java | 19 ++ .../iot/service/device/DeviceService.java | 5 +- .../iot/service/device/DeviceServiceImpl.java | 175 +++++++----- .../iot/service/device/TDengineService.java | 258 ++++++++++++++++-- 8 files changed, 408 insertions(+), 93 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/SingleDeviceRespVO.java diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/scheduler/SchedulerManager.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/scheduler/SchedulerManager.java index d56682e0cd..14e376905e 100644 --- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/scheduler/SchedulerManager.java +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/scheduler/SchedulerManager.java @@ -6,6 +6,7 @@ import org.quartz.*; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0; +import static org.quartz.Scheduler.DEFAULT_GROUP; /** * {@link org.quartz.Scheduler} 的管理器,负责创建任务 @@ -41,13 +42,15 @@ public class SchedulerManager { Integer retryCount, Integer retryInterval) throws SchedulerException { validateScheduler(); + String jobKeyName = jobHandlerName+ "_"+ jobId; + JobKey jobKey = JobKey.jobKey(jobKeyName, DEFAULT_GROUP); // 创建 JobDetail 对象 JobDetail jobDetail = JobBuilder.newJob(JobHandlerInvoker.class) .usingJobData(JobDataKeyEnum.JOB_ID.name(), jobId) .usingJobData(JobDataKeyEnum.JOB_HANDLER_NAME.name(), jobHandlerName) - .withIdentity(jobHandlerName).build(); + .withIdentity(jobKey).build(); // 创建 Trigger 对象 - Trigger trigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval); + Trigger trigger = this.buildTrigger(jobKey, jobHandlerParam, cronExpression, retryCount, retryInterval); // 新增 Job 调度 scheduler.scheduleJob(jobDetail, trigger); } @@ -140,6 +143,18 @@ public class SchedulerManager { .build(); } + private Trigger buildTrigger(JobKey jobKey, String jobHandlerParam, String cronExpression, + Integer retryCount, Integer retryInterval) { + return TriggerBuilder.newTrigger() + .withIdentity(jobKey.getName()) + .forJob(jobKey) + .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)) + .usingJobData(JobDataKeyEnum.JOB_HANDLER_PARAM.name(), jobHandlerParam) + .usingJobData(JobDataKeyEnum.JOB_RETRY_COUNT.name(), retryCount) + .usingJobData(JobDataKeyEnum.JOB_RETRY_INTERVAL.name(), retryInterval) + .build(); + } + private void validateScheduler() { if (scheduler == null) { throw exception0(NOT_IMPLEMENTED.getCode(), diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java index c0490dc111..87a2158466 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java @@ -61,7 +61,7 @@ public class JobServiceImpl implements JobService { jobMapper.insert(job); // 3.1 添加 Job 到 Quartz 中 - schedulerManager.addJob(job.getId(), job.getName(), job.getHandlerParam(), job.getCronExpression(), + schedulerManager.addJob(job.getId(), job.getHandlerName(), job.getHandlerParam(), job.getCronExpression(), createReqVO.getRetryCount(), createReqVO.getRetryInterval()); // 3.2 更新 JobDO JobDO updateObj = JobDO.builder().id(job.getId()).status(JobStatusEnum.STOP.getStatus()).build(); @@ -135,7 +135,7 @@ public class JobServiceImpl implements JobService { JobDO job = validateJobExists(id); // 触发 Quartz 中的 Job - schedulerManager.triggerJob(job.getId(), job.getName(), job.getHandlerParam()); + schedulerManager.triggerJob(job.getId(), job.getHandlerName(), job.getHandlerParam()); } @Override diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java index d02f465134..e91aab8955 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java @@ -176,13 +176,22 @@ public class DeviceController { @GetMapping("/singleDevice") @Operation(summary = "单设备查看") // @PreAuthorize("@ss.hasPermission('iot:device:query')") - public CommonResult> > singleDevice(@RequestParam("deviceId") Long deviceId) throws JsonProcessingException { - Map> deviceContactModelDO=deviceService.singleDevice(deviceId); + public CommonResult>>> singleDevice(@RequestParam("deviceId") Long deviceId) throws JsonProcessingException { + Map>> deviceContactModelDO=deviceService.singleDevice(deviceId); return success(deviceContactModelDO); } - + @GetMapping("/historyRecord") + @Operation(summary = "历史记录查询") +// @PreAuthorize("@ss.hasPermission('iot:device:query')") + public CommonResult>> historyRecord(@RequestParam("deviceId") Long deviceId, + @RequestParam(name = "collectionStartTime", required = false) String collectionStartTime, + @RequestParam(name = "collectionEndTime", required = false) String collectionEndTime + ) throws JsonProcessingException { + List> deviceContactModelDO=deviceService.historyRecord(deviceId,collectionStartTime,collectionEndTime); + return success(deviceContactModelDO); + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/LineDeviceRequestVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/LineDeviceRequestVO.java index e2967298ed..54771ab05d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/LineDeviceRequestVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/LineDeviceRequestVO.java @@ -31,4 +31,10 @@ public class LineDeviceRequestVO extends PageParam { @Schema(description = "采集时间") private LocalDateTime collectionTime; + @Schema(description = "开始采集时间") + private String collectionStartTime; + + @Schema(description = "结束采集时间") + private String collectionEndTime; + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/SingleDeviceRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/SingleDeviceRespVO.java new file mode 100644 index 0000000000..92c36f8051 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/SingleDeviceRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.iot.controller.admin.device.vo; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 单设备监控 Resp VO") +@Data +public class SingleDeviceRespVO { + + @Schema(description = "点位名称", example = "26404") + private String pointName; + + @Schema(description = "点位值", example = "26404") + private String pointValue; + + @Schema(description = "采集时间") + private String collectTime; +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java index 2b4fec8108..6769e217cc 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceAttributeDO; import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelattribute.DeviceModelAttributeDO; import cn.iocoder.yudao.module.iot.dal.devicecontactmodel.DeviceContactModelDO; import com.fasterxml.jackson.core.JsonProcessingException; +import org.springframework.web.bind.annotation.RequestParam; import javax.validation.Valid; import java.util.Collection; @@ -124,5 +125,7 @@ public interface DeviceService { PageResult lineDevicePage(LineDeviceRequestVO pageReqVO); - Map> singleDevice(Long deviceId) throws JsonProcessingException; + Map>> singleDevice(Long deviceId) throws JsonProcessingException; + + List> historyRecord(Long deviceId,String collectionStartTime, String collectionEndTime); } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java index 81a61da753..c7194e7df3 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java @@ -393,11 +393,6 @@ public class DeviceServiceImpl implements DeviceService { } - - - - - }else { throw exception(OPC_CONNECT_FAILURE_DOES_NOT_EXIST); } @@ -502,93 +497,139 @@ public class DeviceServiceImpl implements DeviceService { return lineDeviceRespVOPageResult; - } @Override - public Map> singleDevice(Long deviceId) throws JsonProcessingException { + public Map>> singleDevice(Long deviceId) throws JsonProcessingException { - List resultList = new ArrayList<>(); + Map>> resultMap = new LinkedHashMap<>(); try { - // 获取设备数据列表 - List> deviceDataList = tdengineService.getAllDeviceDataOrderByTimeDesc(deviceId); - + // 1. 获取设备数据列表 + List> deviceDataList = tdengineService.getNewestDeviceDataOrderByTimeDesc(deviceId); + + // 2. 获取属性类型映射 + Map idToNameMap = deviceAttributeTypeMapper.selectList() + .stream() + .collect(Collectors.toMap( + DeviceAttributeTypeDO::getId, + DeviceAttributeTypeDO::getName + )); + + // 3. 遍历并处理 for (Map deviceData : deviceDataList) { String queryDataJson = (String) deviceData.get("queryData"); - Timestamp timestamp = (Timestamp) deviceData.get("timestamp"); - - - if (queryDataJson != null && !queryDataJson.isEmpty()) { - ObjectMapper objectMapper = new ObjectMapper(); - - // 简化配置,只注册基础模块 - objectMapper.registerModule(new JavaTimeModule()); - objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - // 忽略未知属性,避免因缺少字段而报错 - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - - // 解析JSON数组为对象列表 - List models = objectMapper.readValue( + if (StringUtils.isNotBlank(queryDataJson)) { + // 使用TypeReference解析为List而不是具体的DO对象 + List> dataList = new ObjectMapper().readValue( queryDataJson, - new TypeReference>() {} + new TypeReference>>() {} ); - // 可以为每个对象设置时间戳(如果需要) - for (DeviceContactModelDO model : models) { - // 设置查询时间戳 - model.setLatestCollectionTime(String.valueOf(timestamp)); - resultList.add(model); + for (Map data : dataList) { + // 获取属性类型名称 + String attributeTypeName = "其他"; + String typeStr = (String) data.get("attributeType"); + if (typeStr != null) { + try { + attributeTypeName = typeStr; + } catch (Exception e) { + attributeTypeName = "未知"; + } + } + + // 提取需要的字段 + Map simplifiedData = new HashMap<>(); + simplifiedData.put("addressValue", data.get("addressValue")); + simplifiedData.put("attributeName", data.get("attributeName")); + + resultMap + .computeIfAbsent(attributeTypeName, k -> new ArrayList<>()) + .add(simplifiedData); } } } + } catch (Exception e) { System.out.println("处理设备数据时发生异常: " + e.getMessage()); } + return resultMap; + } + @Override + public List> historyRecord(Long deviceId,String collectionStartTime, String collectionEndTime) { - List deviceAttributeTypeDOS = deviceAttributeTypeMapper.selectList(); - // 最基本的转换方式 - Map idToNameMap = deviceAttributeTypeDOS.stream() - .collect(Collectors.toMap(DeviceAttributeTypeDO::getId, DeviceAttributeTypeDO::getName)); + List> resultList = new ArrayList<>(); + try { + // 1. 获取设备数据列表 + List> deviceDataList = tdengineService.getstDeviceDataOrderByTimeDesc(deviceId,collectionStartTime,collectionEndTime); + + // 2. 获取属性类型映射 + Map idToNameMap = deviceAttributeTypeMapper.selectList() + .stream() + .collect(Collectors.toMap( + DeviceAttributeTypeDO::getId, + DeviceAttributeTypeDO::getName + )); + + // 3. 遍历每个时间点的数据 + for (Map deviceData : deviceDataList) { + String queryDataJson = (String) deviceData.get("queryData"); + Timestamp timestamp = (Timestamp) deviceData.get("timestamp"); - // 分组并排序 - Map> groupedAndSorted = resultList.stream() - .collect(Collectors.groupingBy( - // 处理attributeType为null的情况,设为"其他" - item -> { - String typeStr = item.getAttributeType(); - if (typeStr == null) { - return "其他"; - } + if (StringUtils.isNotBlank(queryDataJson) && timestamp != null) { + List> dataList = new ObjectMapper().readValue( + queryDataJson, + new TypeReference>>() {} + ); + + // 按属性类型分组 + Map>> groupedData = new LinkedHashMap<>(); + + for (Map data : dataList) { + String attributeTypeName = "其他"; + String typeStr = (String) data.get("attributeType"); + if (typeStr != null) { try { - // 关键步骤:将 String 转换为 Long - Long typeLong = Long.valueOf(typeStr); - String name = idToNameMap.get(typeLong); - return (name == null) ? "未知" : name; - } catch (NumberFormatException e) { - // 如果字符串不能转换为Long,则归类为"未知" - return "未知"; + attributeTypeName = typeStr; + } catch (Exception e) { + attributeTypeName = "未知"; } - }, // 使用LinkedHashMap保持分组顺序(可选) - LinkedHashMap::new, - // 对每个分组内的元素按latestCollectionTime倒序排序 - Collectors.collectingAndThen( - Collectors.toList(), - list -> list.stream() - .sorted(Comparator.comparing( - DeviceContactModelDO::getLatestCollectionTime, - Comparator.nullsLast(Comparator.reverseOrder()) // 处理latestCollectionTime为null的情况 - )) - .collect(Collectors.toList()) - ) - )); - - - return groupedAndSorted; + } + + Map simplifiedData = new HashMap<>(); + simplifiedData.put("addressValue", data.get("addressValue")); + simplifiedData.put("attributeName", data.get("attributeName")); + + groupedData + .computeIfAbsent(attributeTypeName, k -> new ArrayList<>()) + .add(simplifiedData); + } + + // 创建当前时间点的Map + Map timePointData = new LinkedHashMap<>(); + + // 添加属性分组 + for (Map.Entry>> entry : groupedData.entrySet()) { + timePointData.put(entry.getKey(), entry.getValue()); + } + + // 添加收集时间 + timePointData.put("collectTime", timestamp.toString()); + + resultList.add(timePointData); + } + } + + } catch (Exception e) { + System.out.println("处理设备数据时发生异常: " + e.getMessage()); + } + + return resultList; + } private void validateDeviceAttributeExists(Long id) { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java index 6ef8a3551b..7b3cbc7387 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java @@ -1,19 +1,25 @@ package cn.iocoder.yudao.module.iot.service.device; import com.baomidou.dynamic.datasource.annotation.DS; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.taosdata.jdbc.utils.BlobUtil; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.nio.charset.StandardCharsets; +import java.sql.Blob; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @Service public class TDengineService { @@ -40,7 +46,7 @@ public class TDengineService { // 3. 创建超级表 String createSuperTableSQL = "CREATE STABLE IF NOT EXISTS device_data (" + "ts TIMESTAMP, " + - "query_data NCHAR(2048)" + + "query_data BLOB" + ") TAGS (device_id BIGINT)"; jdbcTemplate.execute(createSuperTableSQL); @@ -82,8 +88,44 @@ public class TDengineService { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String timestampStr = sdf.format(ts); result.put("timestamp", timestampStr); - String queryData = rs.getString("query_data"); - result.put("queryData", queryData); + + byte[] blob = rs.getBytes("query_data"); + if (blob != null) { + String jsonStr = new String(blob, StandardCharsets.UTF_8); + + try { + // 1. 先去除外层的双引号(如果存在) + String trimmed = jsonStr.trim(); + if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) { + trimmed = trimmed.substring(1, trimmed.length() - 1); + } + + // 2. 检查是否是十六进制字符串 + if (isHexString(trimmed)) { + // 3. 十六进制解码 + String decodedJson = hexToString(trimmed); + result.put("queryData", decodedJson); + } else { + // 如果不是十六进制,尝试直接解析 + ObjectMapper objectMapper = new ObjectMapper(); + List> queryData = objectMapper.readValue( + trimmed, + new TypeReference>>() {} + ); + result.put("queryData", queryData); + } + + } catch (Exception e) { + System.err.println("解析JSON失败: " + e.getMessage()); + result.put("queryData", new ArrayList<>()); + result.put("rawData", jsonStr); + } + + } else { + result.put("queryData", new ArrayList<>()); + } + + result.put("deviceId", id); result.put("tableName", tableName); return result; @@ -112,12 +154,11 @@ public class TDengineService { /** * 向指定设备插入带时间戳的数据 * @param id 设备ID - * @param queryData 查询数据 * @param timestamp 时间戳 * @return 插入是否成功 */ @DS("tdengine") - public boolean insertDeviceData(Long id, String queryData, Timestamp timestamp) { + public boolean insertDeviceData(Long id, String jsonString, Timestamp timestamp) { try { // 确保使用正确的数据库 jdbcTemplate.execute("USE besure"); @@ -125,9 +166,12 @@ public class TDengineService { String tableName = "d_" + id; String sql = "INSERT INTO " + tableName + " (ts, query_data) VALUES (?, ?)"; - int affectedRows = jdbcTemplate.update(sql, timestamp, queryData); - System.out.println("向设备" + id + "插入数据成功,时间戳: " + timestamp); - return affectedRows > 0; + return jdbcTemplate.update(sql, ps -> { + ps.setTimestamp(1, timestamp); + // JSON字符串转byte数组 + byte[] blobData = jsonString.getBytes(StandardCharsets.UTF_8); + ps.setBytes(2, blobData); + }) > 0; } catch (Exception e) { System.out.println("向设备" + id + "插入数据时发生异常: " + e.getMessage()); return false; @@ -140,24 +184,202 @@ public class TDengineService { * @return 设备数据列表,按时间戳倒序排列 */ @DS("tdengine") - public List> getAllDeviceDataOrderByTimeDesc(Long id) { + public List> getNewestDeviceDataOrderByTimeDesc(Long id) { String tableName = "d_" + id; - String sql = "SELECT ts, query_data FROM besure." + tableName + " ORDER BY ts DESC"; + String sql = "SELECT ts, query_data FROM besure." + tableName + " ORDER BY ts DESC LIMIT 1"; try { - return jdbcTemplate.query(sql, new RowMapper>() { + return Collections.singletonList(jdbcTemplate.queryForObject(sql, new RowMapper>() { @Override public Map mapRow(ResultSet rs, int rowNum) throws SQLException { Map result = new HashMap<>(); result.put("timestamp", rs.getTimestamp("ts")); - result.put("queryData", rs.getString("query_data")); result.put("deviceId", id); + + byte[] blob = rs.getBytes("query_data"); + if (blob != null) { + String jsonStr = new String(blob, StandardCharsets.UTF_8); + + try { + // 1. 先去除外层的双引号(如果存在) + String trimmed = jsonStr.trim(); + if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) { + trimmed = trimmed.substring(1, trimmed.length() - 1); + } + + // 2. 检查是否是十六进制字符串 + if (isHexString(trimmed)) { + // 3. 十六进制解码 + String decodedJson = hexToString(trimmed); + + result.put("queryData", decodedJson); + } else { + // 如果不是十六进制,尝试直接解析 + ObjectMapper objectMapper = new ObjectMapper(); + List> queryData = objectMapper.readValue( + trimmed, + new TypeReference>>() {} + ); + result.put("queryData", queryData); + } + + } catch (Exception e) { + System.err.println("解析JSON失败: " + e.getMessage()); + result.put("queryData", new ArrayList<>()); + result.put("rawData", jsonStr); + } + + } else { + result.put("queryData", new ArrayList<>()); + } + return result; } - }); + })); + } catch (EmptyResultDataAccessException e) { + return Collections.singletonList(createEmptyResult(id)); } catch (Exception e) { - System.out.println("查询设备" + id + "的全部数据时发生异常: " + e.getMessage()); + System.err.println("查询设备" + id + "的最新数据时发生异常: " + e.getMessage()); + e.printStackTrace(); + return Collections.singletonList(createEmptyResult(id)); + } + } + + + // 检查是否是十六进制字符串 + private boolean isHexString(String str) { + if (str == null || str.trim().isEmpty()) { + return false; + } + String s = str.trim(); + // 检查是否只包含十六进制字符(0-9, a-f, A-F) + return s.matches("^[0-9a-fA-F]+$"); + } + + // 十六进制解码 + private String hexToString(String hex) { + try { + // 使用 Apache Commons Codec + byte[] bytes = Hex.decodeHex(hex); + return new String(bytes, StandardCharsets.UTF_8); + } catch (DecoderException e) { + throw new RuntimeException("十六进制解码失败: " + e.getMessage(), e); + } + } + private List> parseJsonData(byte[] blob) { + if (blob == null || blob.length == 0) { return new ArrayList<>(); } + + try { + String jsonStr = new String(blob, StandardCharsets.UTF_8); + + // 检查是否是有效的JSON + if (jsonStr.trim().startsWith("[") && jsonStr.trim().endsWith("]")) { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(jsonStr, + new TypeReference>>() {}); + } else { + // 可能是字符串化的JSON,尝试去除引号 + jsonStr = jsonStr.trim(); + if (jsonStr.startsWith("\"") && jsonStr.endsWith("\"")) { + jsonStr = jsonStr.substring(1, jsonStr.length() - 1); + return new ObjectMapper().readValue(jsonStr, + new TypeReference>>() {}); + } + } + } catch (Exception e) { + System.err.println("解析JSON数据失败: " + e.getMessage()); + } + + return new ArrayList<>(); + } + + private Map createEmptyResult(Long deviceId) { + Map result = new HashMap<>(); + result.put("deviceId", deviceId); + result.put("queryData", new ArrayList<>()); + result.put("timestamp", null); + return result; + } + /** + * 查询指定设备表的全部数据并按时间倒序排序 + * @param id 设备ID + * @return 设备数据列表,按时间戳倒序排列 + */ + @DS("tdengine") + public List> getstDeviceDataOrderByTimeDesc(Long id,String collectionStartTime, String collectionEndTime) { + String tableName = "d_" + id; + StringBuilder sqlBuilder = new StringBuilder(); + List params = new ArrayList<>(); + + sqlBuilder.append("SELECT ts, query_data FROM besure.").append(tableName).append(" WHERE 1=1"); + + if (collectionStartTime != null) { + // 直接将时间字符串拼接到SQL中 + sqlBuilder.append(" AND ts >= '").append(collectionStartTime).append("'"); + } + + if (collectionEndTime != null) { + sqlBuilder.append(" AND ts <= '").append(collectionEndTime).append("'"); + } + + sqlBuilder.append(" ORDER BY ts DESC"); + + try { + return jdbcTemplate.query(sqlBuilder.toString(), new RowMapper>() { + @Override + public Map mapRow(ResultSet rs, int rowNum) throws SQLException { + Map result = new HashMap<>(); + result.put("timestamp", rs.getTimestamp("ts")); + result.put("deviceId", id); + + byte[] blob = rs.getBytes("query_data"); + if (blob != null) { + String jsonStr = new String(blob, StandardCharsets.UTF_8); + + try { + // 1. 先去除外层的双引号(如果存在) + String trimmed = jsonStr.trim(); + if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) { + trimmed = trimmed.substring(1, trimmed.length() - 1); + } + + // 2. 检查是否是十六进制字符串 + if (isHexString(trimmed)) { + // 3. 十六进制解码 + String decodedJson = hexToString(trimmed); + + result.put("queryData", decodedJson); + } else { + // 如果不是十六进制,尝试直接解析 + ObjectMapper objectMapper = new ObjectMapper(); + List> queryData = objectMapper.readValue( + trimmed, + new TypeReference>>() {} + ); + result.put("queryData", queryData); + } + + } catch (Exception e) { + System.err.println("解析JSON失败: " + e.getMessage()); + result.put("queryData", new ArrayList<>()); + result.put("rawData", jsonStr); + } + + } else { + result.put("queryData", new ArrayList<>()); + } + + return result; + } + }); + } catch (EmptyResultDataAccessException e) { + return Collections.singletonList(createEmptyResult(id)); + } catch (Exception e) { + System.err.println("查询设备" + id + "的最新数据时发生异常: " + e.getMessage()); + e.printStackTrace(); + return Collections.singletonList(createEmptyResult(id)); + } } } \ No newline at end of file From 870cb78385be9dcd4c1af0761fd4a6881043c259 Mon Sep 17 00:00:00 2001 From: 86158 <461356067@qq.com> Date: Mon, 5 Jan 2026 18:07:47 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 3 + .../admin/recipe/RecipeController.java | 95 +++++++++++++++++++ .../admin/recipe/vo/RecipePageReqVO.java | 52 ++++++++++ .../admin/recipe/vo/RecipeRespVO.java | 63 ++++++++++++ .../admin/recipe/vo/RecipeSaveReqVO.java | 46 +++++++++ .../recipepoint/RecipePointController.java | 95 +++++++++++++++++++ .../recipepoint/vo/RecipePointPageReqVO.java | 46 +++++++++ .../recipepoint/vo/RecipePointRespVO.java | 55 +++++++++++ .../recipepoint/vo/RecipePointSaveReqVO.java | 39 ++++++++ .../recipetype/RecipeTypeController.java | 95 +++++++++++++++++++ .../recipetype/vo/RecipeTypePageReqVO.java | 37 ++++++++ .../admin/recipetype/vo/RecipeTypeRespVO.java | 43 +++++++++ .../recipetype/vo/RecipeTypeSaveReqVO.java | 31 ++++++ .../iot/dal/dataobject/recipe/RecipeDO.java | 71 ++++++++++++++ .../dataobject/recipepoint/RecipePointDO.java | 63 ++++++++++++ .../dataobject/recipetype/RecipeTypeDO.java | 51 ++++++++++ .../iot/dal/mysql/recipe/RecipeMapper.java | 36 +++++++ .../mysql/recipepoint/RecipePointMapper.java | 34 +++++++ .../mysql/recipetype/RecipeTypeMapper.java | 31 ++++++ .../iot/service/recipe/RecipeService.java | 55 +++++++++++ .../iot/service/recipe/RecipeServiceImpl.java | 74 +++++++++++++++ .../recipepoint/RecipePointService.java | 55 +++++++++++ .../recipepoint/RecipePointServiceImpl.java | 74 +++++++++++++++ .../service/recipetype/RecipeTypeService.java | 55 +++++++++++ .../recipetype/RecipeTypeServiceImpl.java | 74 +++++++++++++++ .../resources/mapper/recipe/RecipeMapper.xml | 12 +++ .../mapper/recipepoint/RecipePointMapper.xml | 12 +++ .../mapper/recipetype/RecipeTypeMapper.xml | 12 +++ .../service/device/DeviceServiceImplTest.java | 12 +-- .../EnergyDeviceServiceImplTest.java | 6 +- 30 files changed, 1418 insertions(+), 9 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/RecipeController.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipePageReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipeRespVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipeSaveReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/RecipePointController.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointPageReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointRespVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointSaveReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/RecipeTypeController.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypePageReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypeRespVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypeSaveReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipe/RecipeDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipepoint/RecipePointDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipetype/RecipeTypeDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipe/RecipeMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipepoint/RecipePointMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipetype/RecipeTypeMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipe/RecipeService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipe/RecipeServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipepoint/RecipePointService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipepoint/RecipePointServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipetype/RecipeTypeService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipetype/RecipeTypeServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipe/RecipeMapper.xml create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipepoint/RecipePointMapper.xml create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipetype/RecipeTypeMapper.xml diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java index 15f3d6296f..9635d6bb73 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java @@ -49,5 +49,8 @@ public interface ErrorCodeConstants { ErrorCode OPC_CLOSE_CONNECT_FAILURE= new ErrorCode(1_003_000_000, "OPC断开连接失败"); ErrorCode OPC_PARAMETER_DOES_NOT_EXIST= new ErrorCode(1_003_000_000, "连接关闭参数不存在"); ErrorCode CREATE_TDENGINE_FAILURE= new ErrorCode(1_003_000_000, "创建Tdengine子表失败"); + ErrorCode RECIPE_NOT_EXISTS = new ErrorCode(1_003_000_000, "配方主不存在"); + ErrorCode RECIPE_POINT_NOT_EXISTS = new ErrorCode(1_003_000_000, "配方点位配置表(配方与设备点位关联)不存在"); + ErrorCode RECIPE_TYPE_NOT_EXISTS = new ErrorCode(1_003_000_000, "配方类型表(基础字典)不存在"); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/RecipeController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/RecipeController.java new file mode 100644 index 0000000000..be84fbb309 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/RecipeController.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipe; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.iot.controller.admin.recipe.vo.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipe.RecipeDO; +import cn.iocoder.yudao.module.iot.service.recipe.RecipeService; + +@Tag(name = "管理后台 - 配方管理主") +@RestController +@RequestMapping("/iot/recipe") +@Validated +public class RecipeController { + + @Resource + private RecipeService recipeService; + + @PostMapping("/create") + @Operation(summary = "创建配方管理主") + @PreAuthorize("@ss.hasPermission('iot:recipe:create')") + public CommonResult createRecipe(@Valid @RequestBody RecipeSaveReqVO createReqVO) { + return success(recipeService.createRecipe(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新配方管理主") + @PreAuthorize("@ss.hasPermission('iot:recipe:update')") + public CommonResult updateRecipe(@Valid @RequestBody RecipeSaveReqVO updateReqVO) { + recipeService.updateRecipe(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除配方管理主") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('iot:recipe:delete')") + public CommonResult deleteRecipe(@RequestParam("id") Long id) { + recipeService.deleteRecipe(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得配方管理主") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('iot:recipe:query')") + public CommonResult getRecipe(@RequestParam("id") Long id) { + RecipeDO recipe = recipeService.getRecipe(id); + return success(BeanUtils.toBean(recipe, RecipeRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得配方管理主分页") + @PreAuthorize("@ss.hasPermission('iot:recipe:query')") + public CommonResult> getRecipePage(@Valid RecipePageReqVO pageReqVO) { + PageResult pageResult = recipeService.getRecipePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, RecipeRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出配方管理主 Excel") + @PreAuthorize("@ss.hasPermission('iot:recipe:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportRecipeExcel(@Valid RecipePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = recipeService.getRecipePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "配方管理主.xls", "数据", RecipeRespVO.class, + BeanUtils.toBean(list, RecipeRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipePageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipePageReqVO.java new file mode 100644 index 0000000000..ddeabd2d35 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipePageReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipe.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 配方管理主分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class RecipePageReqVO extends PageParam { + + @Schema(description = "配方名称", example = "赵六") + private String name; + + @Schema(description = "配方编码") + private String recipeCode; + + @Schema(description = "配方类型(关联配方类型表code)", example = "2") + private String recipeType; + + @Schema(description = "关联产品名称", example = "李四") + private String productName; + + @Schema(description = "关联设备ID(关联iot_device.id)", example = "14725") + private Long machineId; + + @Schema(description = "关联设备编码(冗余字段)") + private String machineCode; + + @Schema(description = "关联设备名称(冗余字段)", example = "芋艿") + private String machineName; + + @Schema(description = "配方描述") + private String recipeDesc; + + @Schema(description = "是否启用(0-禁用,1-启用)") + private Boolean isEnable; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "数据单位") + private String dataUnit; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipeRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipeRespVO.java new file mode 100644 index 0000000000..82beec1173 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipeRespVO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipe.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 配方管理主 Response VO") +@Data +@ExcelIgnoreUnannotated +public class RecipeRespVO { + + @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "6587") + @ExcelProperty("主键ID") + private Long id; + + @Schema(description = "配方名称", example = "赵六") + @ExcelProperty("配方名称") + private String name; + + @Schema(description = "配方编码") + @ExcelProperty("配方编码") + private String recipeCode; + + @Schema(description = "配方类型(关联配方类型表code)", example = "2") + @ExcelProperty("配方类型(关联配方类型表code)") + private String recipeType; + + @Schema(description = "关联产品名称", example = "李四") + @ExcelProperty("关联产品名称") + private String productName; + + @Schema(description = "关联设备ID(关联iot_device.id)", example = "14725") + @ExcelProperty("关联设备ID(关联iot_device.id)") + private Long machineId; + + @Schema(description = "关联设备编码(冗余字段)") + @ExcelProperty("关联设备编码(冗余字段)") + private String machineCode; + + @Schema(description = "关联设备名称(冗余字段)", example = "芋艿") + @ExcelProperty("关联设备名称(冗余字段)") + private String machineName; + + @Schema(description = "配方描述") + @ExcelProperty("配方描述") + private String recipeDesc; + + @Schema(description = "是否启用(0-禁用,1-启用)", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("是否启用(0-禁用,1-启用)") + private Boolean isEnable; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "数据单位") + @ExcelProperty("数据单位") + private String dataUnit; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipeSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipeSaveReqVO.java new file mode 100644 index 0000000000..5fe2cb1a87 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipe/vo/RecipeSaveReqVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipe.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - 配方管理主新增/修改 Request VO") +@Data +public class RecipeSaveReqVO { + + @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "6587") + private Long id; + + @Schema(description = "配方名称", example = "赵六") + private String name; + + @Schema(description = "配方编码") + private String recipeCode; + + @Schema(description = "配方类型(关联配方类型表code)", example = "2") + private String recipeType; + + @Schema(description = "关联产品名称", example = "李四") + private String productName; + + @Schema(description = "关联设备ID(关联iot_device.id)", example = "14725") + private Long machineId; + + @Schema(description = "关联设备编码(冗余字段)") + private String machineCode; + + @Schema(description = "关联设备名称(冗余字段)", example = "芋艿") + private String machineName; + + @Schema(description = "配方描述") + private String recipeDesc; + + @Schema(description = "是否启用(0-禁用,1-启用)", requiredMode = Schema.RequiredMode.REQUIRED) +// @NotNull(message = "是否启用(0-禁用,1-启用)不能为空") + private Boolean isEnable; + + @Schema(description = "数据单位") + private String dataUnit; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/RecipePointController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/RecipePointController.java new file mode 100644 index 0000000000..9e316d5075 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/RecipePointController.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipepoint; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.iot.controller.admin.recipepoint.vo.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipepoint.RecipePointDO; +import cn.iocoder.yudao.module.iot.service.recipepoint.RecipePointService; + +@Tag(name = "管理后台 - 配方点位配置表(配方与设备点位关联)") +@RestController +@RequestMapping("/iot/recipe-point") +@Validated +public class RecipePointController { + + @Resource + private RecipePointService recipePointService; + + @PostMapping("/create") + @Operation(summary = "创建配方点位配置表(配方与设备点位关联)") + @PreAuthorize("@ss.hasPermission('iot:recipe-point:create')") + public CommonResult createRecipePoint(@Valid @RequestBody RecipePointSaveReqVO createReqVO) { + return success(recipePointService.createRecipePoint(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新配方点位配置表(配方与设备点位关联)") + @PreAuthorize("@ss.hasPermission('iot:recipe-point:update')") + public CommonResult updateRecipePoint(@Valid @RequestBody RecipePointSaveReqVO updateReqVO) { + recipePointService.updateRecipePoint(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除配方点位配置表(配方与设备点位关联)") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('iot:recipe-point:delete')") + public CommonResult deleteRecipePoint(@RequestParam("id") Long id) { + recipePointService.deleteRecipePoint(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得配方点位配置表(配方与设备点位关联)") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('iot:recipe-point:query')") + public CommonResult getRecipePoint(@RequestParam("id") Long id) { + RecipePointDO recipePoint = recipePointService.getRecipePoint(id); + return success(BeanUtils.toBean(recipePoint, RecipePointRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得配方点位配置表(配方与设备点位关联)分页") + @PreAuthorize("@ss.hasPermission('iot:recipe-point:query')") + public CommonResult> getRecipePointPage(@Valid RecipePointPageReqVO pageReqVO) { + PageResult pageResult = recipePointService.getRecipePointPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, RecipePointRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出配方点位配置表(配方与设备点位关联) Excel") + @PreAuthorize("@ss.hasPermission('iot:recipe-point:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportRecipePointExcel(@Valid RecipePointPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = recipePointService.getRecipePointPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "配方点位配置表(配方与设备点位关联).xls", "数据", RecipePointRespVO.class, + BeanUtils.toBean(list, RecipePointRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointPageReqVO.java new file mode 100644 index 0000000000..0b567382c1 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointPageReqVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipepoint.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 配方点位配置表(配方与设备点位关联)分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class RecipePointPageReqVO extends PageParam { + + @Schema(description = "关联配方ID(关联iot_recipe.id)", example = "8760") + private Long recipeId; + + @Schema(description = "点位编码(关联iot_device_attribute_type.code)") + private String pointCode; + + @Schema(description = "点位名称", example = "李四") + private String pointName; + + @Schema(description = "点位类型", example = "1") + private String pointType; + + @Schema(description = "数据类型(如:Time、Number等)", example = "1") + private String dataType; + + @Schema(description = "单位(如:s、min等)") + private String unit; + + @Schema(description = "设定值") + private String setValue; + + @Schema(description = "实际值(从设备上载同步)") + private String actualValue; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointRespVO.java new file mode 100644 index 0000000000..d7ac9e423a --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointRespVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipepoint.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 配方点位配置表(配方与设备点位关联) Response VO") +@Data +@ExcelIgnoreUnannotated +public class RecipePointRespVO { + + @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "27323") + @ExcelProperty("主键ID") + private Long id; + + @Schema(description = "关联配方ID(关联iot_recipe.id)", example = "8760") + @ExcelProperty("关联配方ID(关联iot_recipe.id)") + private Long recipeId; + + @Schema(description = "点位编码(关联iot_device_attribute_type.code)") + @ExcelProperty("点位编码(关联iot_device_attribute_type.code)") + private String pointCode; + + @Schema(description = "点位名称", example = "李四") + @ExcelProperty("点位名称") + private String pointName; + + @Schema(description = "点位类型", example = "1") + @ExcelProperty("点位类型") + private String pointType; + + @Schema(description = "数据类型(如:Time、Number等)", example = "1") + @ExcelProperty("数据类型(如:Time、Number等)") + private String dataType; + + @Schema(description = "单位(如:s、min等)") + @ExcelProperty("单位(如:s、min等)") + private String unit; + + @Schema(description = "设定值") + @ExcelProperty("设定值") + private String setValue; + + @Schema(description = "实际值(从设备上载同步)") + @ExcelProperty("实际值(从设备上载同步)") + private String actualValue; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointSaveReqVO.java new file mode 100644 index 0000000000..911e2d49fc --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipepoint/vo/RecipePointSaveReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipepoint.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - 配方点位配置表(配方与设备点位关联)新增/修改 Request VO") +@Data +public class RecipePointSaveReqVO { + + @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "27323") + private Long id; + + @Schema(description = "关联配方ID(关联iot_recipe.id)", example = "8760") + private Long recipeId; + + @Schema(description = "点位编码(关联iot_device_attribute_type.code)") + private String pointCode; + + @Schema(description = "点位名称", example = "李四") + private String pointName; + + @Schema(description = "点位类型", example = "1") + private String pointType; + + @Schema(description = "数据类型(如:Time、Number等)", example = "1") + private String dataType; + + @Schema(description = "单位(如:s、min等)") + private String unit; + + @Schema(description = "设定值") + private String setValue; + + @Schema(description = "实际值(从设备上载同步)") + private String actualValue; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/RecipeTypeController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/RecipeTypeController.java new file mode 100644 index 0000000000..cb6f49e07e --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/RecipeTypeController.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipetype; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.iot.controller.admin.recipetype.vo.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipetype.RecipeTypeDO; +import cn.iocoder.yudao.module.iot.service.recipetype.RecipeTypeService; + +@Tag(name = "管理后台 - 配方类型表(基础字典)") +@RestController +@RequestMapping("/iot/recipe-type") +@Validated +public class RecipeTypeController { + + @Resource + private RecipeTypeService recipeTypeService; + + @PostMapping("/create") + @Operation(summary = "创建配方类型表(基础字典)") + @PreAuthorize("@ss.hasPermission('iot:recipe-type:create')") + public CommonResult createRecipeType(@Valid @RequestBody RecipeTypeSaveReqVO createReqVO) { + return success(recipeTypeService.createRecipeType(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新配方类型表(基础字典)") + @PreAuthorize("@ss.hasPermission('iot:recipe-type:update')") + public CommonResult updateRecipeType(@Valid @RequestBody RecipeTypeSaveReqVO updateReqVO) { + recipeTypeService.updateRecipeType(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除配方类型表(基础字典)") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('iot:recipe-type:delete')") + public CommonResult deleteRecipeType(@RequestParam("id") Long id) { + recipeTypeService.deleteRecipeType(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得配方类型表(基础字典)") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('iot:recipe-type:query')") + public CommonResult getRecipeType(@RequestParam("id") Long id) { + RecipeTypeDO recipeType = recipeTypeService.getRecipeType(id); + return success(BeanUtils.toBean(recipeType, RecipeTypeRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得配方类型表(基础字典)分页") + @PreAuthorize("@ss.hasPermission('iot:recipe-type:query')") + public CommonResult> getRecipeTypePage(@Valid RecipeTypePageReqVO pageReqVO) { + PageResult pageResult = recipeTypeService.getRecipeTypePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, RecipeTypeRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出配方类型表(基础字典) Excel") + @PreAuthorize("@ss.hasPermission('iot:recipe-type:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportRecipeTypeExcel(@Valid RecipeTypePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = recipeTypeService.getRecipeTypePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "配方类型表(基础字典).xls", "数据", RecipeTypeRespVO.class, + BeanUtils.toBean(list, RecipeTypeRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypePageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypePageReqVO.java new file mode 100644 index 0000000000..2555e5be37 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypePageReqVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipetype.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 配方类型表(基础字典)分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class RecipeTypePageReqVO extends PageParam { + + @Schema(description = "类型编码(唯一标识)") + private String code; + + @Schema(description = "类型名称", example = "张三") + private String name; + + @Schema(description = "关联工序") + private String process; + + @Schema(description = "配方类型描述", example = "你说的对") + private String remark; + + @Schema(description = "排序字段") + private Integer sort; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypeRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypeRespVO.java new file mode 100644 index 0000000000..bdbc2442fb --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypeRespVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipetype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 配方类型表(基础字典) Response VO") +@Data +@ExcelIgnoreUnannotated +public class RecipeTypeRespVO { + + @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "21350") + @ExcelProperty("主键ID") + private Long id; + + @Schema(description = "类型编码(唯一标识)") + @ExcelProperty("类型编码(唯一标识)") + private String code; + + @Schema(description = "类型名称", example = "张三") + @ExcelProperty("类型名称") + private String name; + + @Schema(description = "关联工序") + @ExcelProperty("关联工序") + private String process; + + @Schema(description = "配方类型描述", example = "你说的对") + @ExcelProperty("配方类型描述") + private String remark; + + @Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("排序字段") + private Integer sort; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypeSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypeSaveReqVO.java new file mode 100644 index 0000000000..7c911aade7 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/recipetype/vo/RecipeTypeSaveReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.iot.controller.admin.recipetype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - 配方类型表(基础字典)新增/修改 Request VO") +@Data +public class RecipeTypeSaveReqVO { + + @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "21350") + private Long id; + + @Schema(description = "类型编码(唯一标识)") + private String code; + + @Schema(description = "类型名称", example = "张三") + private String name; + + @Schema(description = "关联工序") + private String process; + + @Schema(description = "配方类型描述", example = "你说的对") + private String remark; + + @Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "排序字段不能为空") + private Integer sort; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipe/RecipeDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipe/RecipeDO.java new file mode 100644 index 0000000000..d911170425 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipe/RecipeDO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.recipe; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 配方管理主 DO + * + * @author 内蒙必硕 + */ +@TableName("iot_recipe") +@KeySequence("iot_recipe_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RecipeDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + /** + * 配方名称 + */ + private String name; + /** + * 配方编码 + */ + private String recipeCode; + /** + * 配方类型(关联配方类型表code) + */ + private String recipeType; + /** + * 关联产品名称 + */ + private String productName; + /** + * 关联设备ID(关联iot_device.id) + */ + private Long machineId; + /** + * 关联设备编码(冗余字段) + */ + private String machineCode; + /** + * 关联设备名称(冗余字段) + */ + private String machineName; + /** + * 配方描述 + */ + private String recipeDesc; + /** + * 是否启用(0-禁用,1-启用) + */ + private Boolean isEnable; + /** + * 数据单位 + */ + private String dataUnit; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipepoint/RecipePointDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipepoint/RecipePointDO.java new file mode 100644 index 0000000000..a4ac7766a3 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipepoint/RecipePointDO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.recipepoint; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 配方点位配置表(配方与设备点位关联) DO + * + * @author 内蒙必硕 + */ +@TableName("iot_recipe_point") +@KeySequence("iot_recipe_point_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RecipePointDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + /** + * 关联配方ID(关联iot_recipe.id) + */ + private Long recipeId; + /** + * 点位编码(关联iot_device_attribute_type.code) + */ + private String pointCode; + /** + * 点位名称 + */ + private String pointName; + /** + * 点位类型 + */ + private String pointType; + /** + * 数据类型(如:Time、Number等) + */ + private String dataType; + /** + * 单位(如:s、min等) + */ + private String unit; + /** + * 设定值 + */ + private String setValue; + /** + * 实际值(从设备上载同步) + */ + private String actualValue; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipetype/RecipeTypeDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipetype/RecipeTypeDO.java new file mode 100644 index 0000000000..8037af779b --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/recipetype/RecipeTypeDO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.recipetype; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 配方类型表(基础字典) DO + * + * @author 内蒙必硕 + */ +@TableName("iot_recipe_type") +@KeySequence("iot_recipe_type_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RecipeTypeDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + /** + * 类型编码(唯一标识) + */ + private String code; + /** + * 类型名称 + */ + private String name; + /** + * 关联工序 + */ + private String process; + /** + * 配方类型描述 + */ + private String remark; + /** + * 排序字段 + */ + private Integer sort; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipe/RecipeMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipe/RecipeMapper.java new file mode 100644 index 0000000000..7bdca08e36 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipe/RecipeMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.iot.dal.mysql.recipe; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipe.RecipeDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.iot.controller.admin.recipe.vo.*; + +/** + * 配方管理主 Mapper + * + * @author 内蒙必硕 + */ +@Mapper +public interface RecipeMapper extends BaseMapperX { + + default PageResult selectPage(RecipePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(RecipeDO::getName, reqVO.getName()) + .eqIfPresent(RecipeDO::getRecipeCode, reqVO.getRecipeCode()) + .eqIfPresent(RecipeDO::getRecipeType, reqVO.getRecipeType()) + .likeIfPresent(RecipeDO::getProductName, reqVO.getProductName()) + .eqIfPresent(RecipeDO::getMachineId, reqVO.getMachineId()) + .eqIfPresent(RecipeDO::getMachineCode, reqVO.getMachineCode()) + .likeIfPresent(RecipeDO::getMachineName, reqVO.getMachineName()) + .eqIfPresent(RecipeDO::getRecipeDesc, reqVO.getRecipeDesc()) + .eqIfPresent(RecipeDO::getIsEnable, reqVO.getIsEnable()) + .betweenIfPresent(RecipeDO::getCreateTime, reqVO.getCreateTime()) + .eqIfPresent(RecipeDO::getDataUnit, reqVO.getDataUnit()) + .orderByDesc(RecipeDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipepoint/RecipePointMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipepoint/RecipePointMapper.java new file mode 100644 index 0000000000..2e131522bd --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipepoint/RecipePointMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.iot.dal.mysql.recipepoint; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipepoint.RecipePointDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.iot.controller.admin.recipepoint.vo.*; + +/** + * 配方点位配置表(配方与设备点位关联) Mapper + * + * @author 内蒙必硕 + */ +@Mapper +public interface RecipePointMapper extends BaseMapperX { + + default PageResult selectPage(RecipePointPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(RecipePointDO::getRecipeId, reqVO.getRecipeId()) + .eqIfPresent(RecipePointDO::getPointCode, reqVO.getPointCode()) + .likeIfPresent(RecipePointDO::getPointName, reqVO.getPointName()) + .eqIfPresent(RecipePointDO::getPointType, reqVO.getPointType()) + .eqIfPresent(RecipePointDO::getDataType, reqVO.getDataType()) + .eqIfPresent(RecipePointDO::getUnit, reqVO.getUnit()) + .eqIfPresent(RecipePointDO::getSetValue, reqVO.getSetValue()) + .eqIfPresent(RecipePointDO::getActualValue, reqVO.getActualValue()) + .betweenIfPresent(RecipePointDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(RecipePointDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipetype/RecipeTypeMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipetype/RecipeTypeMapper.java new file mode 100644 index 0000000000..ae4d3bc64e --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/recipetype/RecipeTypeMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.iot.dal.mysql.recipetype; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipetype.RecipeTypeDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.iot.controller.admin.recipetype.vo.*; + +/** + * 配方类型表(基础字典) Mapper + * + * @author 内蒙必硕 + */ +@Mapper +public interface RecipeTypeMapper extends BaseMapperX { + + default PageResult selectPage(RecipeTypePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(RecipeTypeDO::getCode, reqVO.getCode()) + .likeIfPresent(RecipeTypeDO::getName, reqVO.getName()) + .eqIfPresent(RecipeTypeDO::getProcess, reqVO.getProcess()) + .eqIfPresent(RecipeTypeDO::getRemark, reqVO.getRemark()) + .eqIfPresent(RecipeTypeDO::getSort, reqVO.getSort()) + .betweenIfPresent(RecipeTypeDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(RecipeTypeDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipe/RecipeService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipe/RecipeService.java new file mode 100644 index 0000000000..892f1fc80a --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipe/RecipeService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.iot.service.recipe; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.iot.controller.admin.recipe.vo.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipe.RecipeDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 配方管理主 Service 接口 + * + * @author 内蒙必硕 + */ +public interface RecipeService { + + /** + * 创建配方管理主 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createRecipe(@Valid RecipeSaveReqVO createReqVO); + + /** + * 更新配方管理主 + * + * @param updateReqVO 更新信息 + */ + void updateRecipe(@Valid RecipeSaveReqVO updateReqVO); + + /** + * 删除配方管理主 + * + * @param id 编号 + */ + void deleteRecipe(Long id); + + /** + * 获得配方管理主 + * + * @param id 编号 + * @return 配方管理主 + */ + RecipeDO getRecipe(Long id); + + /** + * 获得配方管理主分页 + * + * @param pageReqVO 分页查询 + * @return 配方管理主分页 + */ + PageResult getRecipePage(RecipePageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipe/RecipeServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipe/RecipeServiceImpl.java new file mode 100644 index 0000000000..6a4733a301 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipe/RecipeServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.iot.service.recipe; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.iot.controller.admin.recipe.vo.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipe.RecipeDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.iot.dal.mysql.recipe.RecipeMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; + +/** + * 配方管理主 Service 实现类 + * + * @author 内蒙必硕 + */ +@Service +@Validated +public class RecipeServiceImpl implements RecipeService { + + @Resource + private RecipeMapper recipeMapper; + + @Override + public Long createRecipe(RecipeSaveReqVO createReqVO) { + // 插入 + RecipeDO recipe = BeanUtils.toBean(createReqVO, RecipeDO.class); + recipeMapper.insert(recipe); + // 返回 + return recipe.getId(); + } + + @Override + public void updateRecipe(RecipeSaveReqVO updateReqVO) { + // 校验存在 + validateRecipeExists(updateReqVO.getId()); + // 更新 + RecipeDO updateObj = BeanUtils.toBean(updateReqVO, RecipeDO.class); + recipeMapper.updateById(updateObj); + } + + @Override + public void deleteRecipe(Long id) { + // 校验存在 + validateRecipeExists(id); + // 删除 + recipeMapper.deleteById(id); + } + + private void validateRecipeExists(Long id) { + if (recipeMapper.selectById(id) == null) { + throw exception(RECIPE_NOT_EXISTS); + } + } + + @Override + public RecipeDO getRecipe(Long id) { + return recipeMapper.selectById(id); + } + + @Override + public PageResult getRecipePage(RecipePageReqVO pageReqVO) { + return recipeMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipepoint/RecipePointService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipepoint/RecipePointService.java new file mode 100644 index 0000000000..a50071eb14 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipepoint/RecipePointService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.iot.service.recipepoint; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.iot.controller.admin.recipepoint.vo.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipepoint.RecipePointDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 配方点位配置表(配方与设备点位关联) Service 接口 + * + * @author 内蒙必硕 + */ +public interface RecipePointService { + + /** + * 创建配方点位配置表(配方与设备点位关联) + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createRecipePoint(@Valid RecipePointSaveReqVO createReqVO); + + /** + * 更新配方点位配置表(配方与设备点位关联) + * + * @param updateReqVO 更新信息 + */ + void updateRecipePoint(@Valid RecipePointSaveReqVO updateReqVO); + + /** + * 删除配方点位配置表(配方与设备点位关联) + * + * @param id 编号 + */ + void deleteRecipePoint(Long id); + + /** + * 获得配方点位配置表(配方与设备点位关联) + * + * @param id 编号 + * @return 配方点位配置表(配方与设备点位关联) + */ + RecipePointDO getRecipePoint(Long id); + + /** + * 获得配方点位配置表(配方与设备点位关联)分页 + * + * @param pageReqVO 分页查询 + * @return 配方点位配置表(配方与设备点位关联)分页 + */ + PageResult getRecipePointPage(RecipePointPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipepoint/RecipePointServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipepoint/RecipePointServiceImpl.java new file mode 100644 index 0000000000..b3b1de02f8 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipepoint/RecipePointServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.iot.service.recipepoint; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.iot.controller.admin.recipepoint.vo.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipepoint.RecipePointDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.iot.dal.mysql.recipepoint.RecipePointMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; + +/** + * 配方点位配置表(配方与设备点位关联) Service 实现类 + * + * @author 内蒙必硕 + */ +@Service +@Validated +public class RecipePointServiceImpl implements RecipePointService { + + @Resource + private RecipePointMapper recipePointMapper; + + @Override + public Long createRecipePoint(RecipePointSaveReqVO createReqVO) { + // 插入 + RecipePointDO recipePoint = BeanUtils.toBean(createReqVO, RecipePointDO.class); + recipePointMapper.insert(recipePoint); + // 返回 + return recipePoint.getId(); + } + + @Override + public void updateRecipePoint(RecipePointSaveReqVO updateReqVO) { + // 校验存在 + validateRecipePointExists(updateReqVO.getId()); + // 更新 + RecipePointDO updateObj = BeanUtils.toBean(updateReqVO, RecipePointDO.class); + recipePointMapper.updateById(updateObj); + } + + @Override + public void deleteRecipePoint(Long id) { + // 校验存在 + validateRecipePointExists(id); + // 删除 + recipePointMapper.deleteById(id); + } + + private void validateRecipePointExists(Long id) { + if (recipePointMapper.selectById(id) == null) { + throw exception(RECIPE_POINT_NOT_EXISTS); + } + } + + @Override + public RecipePointDO getRecipePoint(Long id) { + return recipePointMapper.selectById(id); + } + + @Override + public PageResult getRecipePointPage(RecipePointPageReqVO pageReqVO) { + return recipePointMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipetype/RecipeTypeService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipetype/RecipeTypeService.java new file mode 100644 index 0000000000..1962a4c033 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipetype/RecipeTypeService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.iot.service.recipetype; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.iot.controller.admin.recipetype.vo.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipetype.RecipeTypeDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 配方类型表(基础字典) Service 接口 + * + * @author 内蒙必硕 + */ +public interface RecipeTypeService { + + /** + * 创建配方类型表(基础字典) + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createRecipeType(@Valid RecipeTypeSaveReqVO createReqVO); + + /** + * 更新配方类型表(基础字典) + * + * @param updateReqVO 更新信息 + */ + void updateRecipeType(@Valid RecipeTypeSaveReqVO updateReqVO); + + /** + * 删除配方类型表(基础字典) + * + * @param id 编号 + */ + void deleteRecipeType(Long id); + + /** + * 获得配方类型表(基础字典) + * + * @param id 编号 + * @return 配方类型表(基础字典) + */ + RecipeTypeDO getRecipeType(Long id); + + /** + * 获得配方类型表(基础字典)分页 + * + * @param pageReqVO 分页查询 + * @return 配方类型表(基础字典)分页 + */ + PageResult getRecipeTypePage(RecipeTypePageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipetype/RecipeTypeServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipetype/RecipeTypeServiceImpl.java new file mode 100644 index 0000000000..7bd061cdd4 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/recipetype/RecipeTypeServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.iot.service.recipetype; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.iot.controller.admin.recipetype.vo.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.recipetype.RecipeTypeDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.iot.dal.mysql.recipetype.RecipeTypeMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; + +/** + * 配方类型表(基础字典) Service 实现类 + * + * @author 内蒙必硕 + */ +@Service +@Validated +public class RecipeTypeServiceImpl implements RecipeTypeService { + + @Resource + private RecipeTypeMapper recipeTypeMapper; + + @Override + public Long createRecipeType(RecipeTypeSaveReqVO createReqVO) { + // 插入 + RecipeTypeDO recipeType = BeanUtils.toBean(createReqVO, RecipeTypeDO.class); + recipeTypeMapper.insert(recipeType); + // 返回 + return recipeType.getId(); + } + + @Override + public void updateRecipeType(RecipeTypeSaveReqVO updateReqVO) { + // 校验存在 + validateRecipeTypeExists(updateReqVO.getId()); + // 更新 + RecipeTypeDO updateObj = BeanUtils.toBean(updateReqVO, RecipeTypeDO.class); + recipeTypeMapper.updateById(updateObj); + } + + @Override + public void deleteRecipeType(Long id) { + // 校验存在 + validateRecipeTypeExists(id); + // 删除 + recipeTypeMapper.deleteById(id); + } + + private void validateRecipeTypeExists(Long id) { + if (recipeTypeMapper.selectById(id) == null) { + throw exception(RECIPE_TYPE_NOT_EXISTS); + } + } + + @Override + public RecipeTypeDO getRecipeType(Long id) { + return recipeTypeMapper.selectById(id); + } + + @Override + public PageResult getRecipeTypePage(RecipeTypePageReqVO pageReqVO) { + return recipeTypeMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipe/RecipeMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipe/RecipeMapper.xml new file mode 100644 index 0000000000..5fa73872cd --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipe/RecipeMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipepoint/RecipePointMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipepoint/RecipePointMapper.xml new file mode 100644 index 0000000000..be08e742fd --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipepoint/RecipePointMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipetype/RecipeTypeMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipetype/RecipeTypeMapper.xml new file mode 100644 index 0000000000..546fffde81 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/recipetype/RecipeTypeMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImplTest.java index 4fc34608b2..c5261b0af1 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImplTest.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImplTest.java @@ -106,12 +106,12 @@ public class DeviceServiceImplTest extends BaseDbUnitTest { } - @Test - public void testCreateTDengine() { - // 准备参数 - Long id = 12313L; - deviceService.createTDengine(id); - } +// @Test +// public void testCreateTDengine() { +// // 准备参数 +// Long id = 12313L; +// deviceService.createTDengine(id); +// } diff --git a/yudao-module-mes/yudao-module-mes-biz/src/test/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImplTest.java b/yudao-module-mes/yudao-module-mes-biz/src/test/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImplTest.java index bfc56f0e90..c9a162775e 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/test/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImplTest.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/test/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImplTest.java @@ -112,7 +112,7 @@ public class EnergyDeviceServiceImplTest extends BaseDbUnitTest { EnergyDeviceDO dbEnergyDevice = randomPojo(EnergyDeviceDO.class, o -> { // 等会查询到 o.setName(null); o.setCode(null); - o.setDeviceType(null); +// o.setDeviceType(null); o.setInfo(null); o.setCheckCron(null); o.setLastCheckTime(null); @@ -127,7 +127,7 @@ public class EnergyDeviceServiceImplTest extends BaseDbUnitTest { // 测试 code 不匹配 energyDeviceMapper.insert(cloneIgnoreId(dbEnergyDevice, o -> o.setCode(null))); // 测试 deviceType 不匹配 - energyDeviceMapper.insert(cloneIgnoreId(dbEnergyDevice, o -> o.setDeviceType(null))); +// energyDeviceMapper.insert(cloneIgnoreId(dbEnergyDevice, o -> o.setDeviceType(null))); // 测试 info 不匹配 energyDeviceMapper.insert(cloneIgnoreId(dbEnergyDevice, o -> o.setInfo(null))); // 测试 checkCron 不匹配 @@ -146,7 +146,7 @@ public class EnergyDeviceServiceImplTest extends BaseDbUnitTest { EnergyDevicePageReqVO reqVO = new EnergyDevicePageReqVO(); reqVO.setName(null); reqVO.setCode(null); - reqVO.setDeviceType(null); +// reqVO.setDeviceType(null); reqVO.setInfo(null); reqVO.setCheckCron(null); reqVO.setLastCheckTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));