From 038006a212901b0b644b007d337c5d352ea47431 Mon Sep 17 00:00:00 2001 From: rqian <1206436827@qq.com> Date: Sat, 9 May 2026 14:47:10 +0800 Subject: [PATCH] =?UTF-8?q?#=E4=BF=AE=E5=A4=8D=E6=A8=A1=E5=9E=8B=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=8E=A5=E5=8F=A3-=E9=80=BB=E8=BE=91=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E4=B8=8D=E7=94=9F=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/SysDeviceModelController.java | 88 +++++++++++++++---- .../system/SysIotCommDeviceController.java | 30 +++++++ .../maibu/service/SysDeviceModelService.java | 7 ++ .../impl/SysDeviceModelServiceImpl.java | 2 +- 4 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 maibu-admin/src/main/java/com/maibu/web/controller/system/SysIotCommDeviceController.java diff --git a/maibu-admin/src/main/java/com/maibu/web/controller/system/SysDeviceModelController.java b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysDeviceModelController.java index bb548bf..e9796eb 100644 --- a/maibu-admin/src/main/java/com/maibu/web/controller/system/SysDeviceModelController.java +++ b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysDeviceModelController.java @@ -7,6 +7,7 @@ import com.maibu.core.business.Device; import com.maibu.core.business.DeviceModel;import com.maibu.core.business.DeviceRunStatistics; import com.maibu.core.controller.BaseController; import com.maibu.core.domain.AjaxResult; +import com.maibu.core.enums.ConnectType; import com.maibu.core.page.TableDataInfo; import com.maibu.enums.BusinessType; import com.maibu.mapper.DeviceRunStatisticsMapper; @@ -33,9 +34,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -107,27 +106,82 @@ public class SysDeviceModelController extends BaseController { } + /** + * 查询支持的协议类型 + */ + @GetMapping("/connectTypes") + @ApiOperation("查询协议类型列表") + public AjaxResult getConnectTypes() { + List> types = Arrays.stream(ConnectType.values()) + .map(type -> { + Map map = new HashMap<>(); + map.put("code", type.name()); + map.put("name", type.name()); + return map; + }) + .collect(Collectors.toList()); + return AjaxResult.success(types); + } + + + + /** + * 查询支持的协议类型 + */ + @GetMapping("/DataTypes") + @ApiOperation("查询数据类型列表") + public AjaxResult getDataTypes() { + List> types = new ArrayList<>(); + + // 1. Java 8大基本数据类型 + types.add(createTypeMap("byte", "byte(字节型)")); + types.add(createTypeMap("short", "short(短整型)")); + types.add(createTypeMap("int", "int(整型)")); + types.add(createTypeMap("long", "long(长整型)")); + types.add(createTypeMap("float", "float(单精度浮点型)")); + types.add(createTypeMap("double", "double(双精度浮点型)")); + types.add(createTypeMap("char", "char(字符型)")); + types.add(createTypeMap("boolean", "boolean(布尔型)")); + + return AjaxResult.success(types); + } + + + + /** + * 构造数据类型Map(抽成工具方法,代码更简洁) + */ + private Map createTypeMap(String code, String name) { + Map map = new HashMap<>(); + map.put("code", code); + map.put("name", name); + return map; + } + /** + * 删除设备模型 + */ + //@PreAuthorize("@ss.hasPermi('iot:deviceModel:remove')") + @DeleteMapping("/delete/{id}") + @ApiOperation("删除设备模型") + @Log(title = "设备模型", businessType = BusinessType.DELETE) + public AjaxResult remove(@PathVariable Long id) { + if (id == null) { + return AjaxResult.error("模型ID不能为空"); + } - - - - - - - - - - - - - - + try { + int rows = deviceModelService.deleteDeviceModelById(id); + return toAjax(rows); + } catch (Exception e) { + return AjaxResult.error(e.getMessage()); + } + } diff --git a/maibu-admin/src/main/java/com/maibu/web/controller/system/SysIotCommDeviceController.java b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysIotCommDeviceController.java new file mode 100644 index 0000000..1562c06 --- /dev/null +++ b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysIotCommDeviceController.java @@ -0,0 +1,30 @@ +package com.maibu.web.controller.system; + +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.maibu.core.business.Product; +import com.maibu.core.business.dto.ProductDTO; +import com.maibu.core.controller.BaseController; +import com.maibu.core.domain.AjaxResult; +import com.maibu.core.page.TableDataInfo; +import com.maibu.service.DeviceProductService; +import com.maibu.utils.ServletUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; + +/** + * 厂家模块 + */ +@Api(tags = "物联网设备模块") +@RestController +@RequestMapping("/system/iotDevice") +public class SysIotCommDeviceController extends BaseController { + + + +} diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SysDeviceModelService.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SysDeviceModelService.java index 9cb6383..c7e3b33 100644 --- a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SysDeviceModelService.java +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SysDeviceModelService.java @@ -39,4 +39,11 @@ public interface SysDeviceModelService { * @return */ int updateDeviceModel(DeviceModel deviceModel); + + /** + * 删除(逻辑删除模型) + * @param id + * @return + */ + int deleteDeviceModelById(Long id); } diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/SysDeviceModelServiceImpl.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/SysDeviceModelServiceImpl.java index 83e8e93..801fa9a 100644 --- a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/SysDeviceModelServiceImpl.java +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/SysDeviceModelServiceImpl.java @@ -1 +1 @@ -package com.maibu.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.maibu.core.business.DeviceAction; import com.maibu.core.business.DeviceModel; import com.maibu.core.business.DeviceModelProperty; import com.maibu.exception.ServiceException; import com.maibu.mapper.SysDeviceActionMapper; import com.maibu.mapper.SysDeviceModelMapper; import com.maibu.mapper.SysDevicePropertyMapper; import com.maibu.service.SysDeviceModelService; import com.maibu.service.SysDevicePropertyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.time.LocalDateTime; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; /** * @author jsmbz * @description 针对表【iot_device_model(设备模型表)】的数据库操作Service实现 * @createDate 2026-05-07 11:36:11 */ @Service public class SysDeviceModelServiceImpl extends ServiceImpl implements SysDeviceModelService { @Autowired private SysDeviceModelMapper deviceModelMapper; @Autowired private SysDeviceActionMapper actionMapper; @Autowired private SysDevicePropertyMapper propertyMapper; @Override @Transactional(rollbackFor = Exception.class) // ⭐ 关键 public int insertDeviceModel(DeviceModel deviceModel) { // 1. 插入模型主表 deviceModel.setCreateTime(LocalDateTime.now()); deviceModel.setDelFlag(false); int rows = deviceModelMapper.insert(deviceModel); if (rows <= 0) { throw new ServiceException("模型创建失败"); } Long modelId = deviceModel.getId(); // 2. 插入属性列表 if (!CollectionUtils.isEmpty(deviceModel.getSupportProperties())) { LocalDateTime now = LocalDateTime.now(); for (DeviceModelProperty prop : deviceModel.getSupportProperties()) { prop.setModelId(modelId); prop.setCreateTime(now); prop.setDelFlag(false); propertyMapper.insert(prop); } } // 3. 插入动作列表 if (!CollectionUtils.isEmpty(deviceModel.getSupportActions())) { LocalDateTime now = LocalDateTime.now(); for (DeviceAction action : deviceModel.getSupportActions()) { action.setModelId(modelId); action.setCreateTime(now); action.setDelFlag(false); actionMapper.insert(action); } } return 1; } @Override public Page selectDeviceModelPage(Page page, DeviceModel deviceModel) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); if (deviceModel.getName() != null && !deviceModel.getName().isEmpty()) { wrapper.like(DeviceModel::getName, deviceModel.getName()); } if (deviceModel.getConnectType() != null) { wrapper.eq(DeviceModel::getConnectType, deviceModel.getConnectType()); } if (deviceModel.getDeviceType() != null) { wrapper.eq(DeviceModel::getDeviceType, deviceModel.getDeviceType()); } wrapper.eq(DeviceModel::getDelFlag, false); wrapper.orderByDesc(DeviceModel::getCreateTime); Page resultPage = deviceModelMapper.selectPage(page, wrapper); if (!CollectionUtils.isEmpty(resultPage.getRecords())) { resultPage.getRecords().forEach(model -> { List properties = propertyMapper.selectList( new LambdaQueryWrapper() .eq(DeviceModelProperty::getModelId, model.getId()) .eq(DeviceModelProperty::getDelFlag, false) .orderByAsc(DeviceModelProperty::getId) ); model.setSupportProperties(properties); List actions = actionMapper.selectList( new LambdaQueryWrapper() .eq(DeviceAction::getModelId, model.getId()) .eq(DeviceAction::getDelFlag, false) .orderByAsc(DeviceAction::getId) ); model.setSupportActions(actions); }); } return resultPage; } @Override public DeviceModel selectDeviceModelById(Long id) { // 1. 查主表 DeviceModel model = deviceModelMapper.selectById(id); if (model == null) return null; // 2. 查属性 List properties = propertyMapper.selectList( new LambdaQueryWrapper() .eq(DeviceModelProperty::getModelId, id) .eq(DeviceModelProperty::getDelFlag, false) ); model.setSupportProperties(properties); // 3. 查动作 List actions = actionMapper.selectList( new LambdaQueryWrapper() .eq(DeviceAction::getModelId, id) .eq(DeviceAction::getDelFlag, false) ); model.setSupportActions(actions); return model; } @Override @Transactional(rollbackFor = Exception.class) public int updateDeviceModel(DeviceModel deviceModel) { // 1. 更新模型主表 deviceModel.setUpdateTime(LocalDateTime.now()); deviceModelMapper.updateById(deviceModel); Long modelId = deviceModel.getId(); // 2. 处理属性列表(按 property_key 精准更新) if (deviceModel.getSupportProperties() != null) { // 2.1 查询数据库已有的所有属性 List existingProperties = propertyMapper.selectList( new LambdaQueryWrapper() .eq(DeviceModelProperty::getModelId, modelId) ); // 2.2 构建已有属性的 property_key → ID 映射 java.util.Map existingKeyMap = existingProperties.stream() .collect(Collectors.toMap(DeviceModelProperty::getPropertyKey, DeviceModelProperty::getId)); // 2.3 收集前端传来的所有 property_key java.util.Set receivedKeys = deviceModel.getSupportProperties().stream() .map(DeviceModelProperty::getPropertyKey) .collect(Collectors.toSet()); LocalDateTime now = LocalDateTime.now(); // 2.4 处理前端传来的属性:有 ID 则更新,无 ID 则新增 for (DeviceModelProperty prop : deviceModel.getSupportProperties()) { Long existingId = existingKeyMap.get(prop.getPropertyKey()); if (prop.getId() != null && prop.getId() > 0) { // 前端传了 ID → 执行 UPDATE prop.setUpdateTime(now); propertyMapper.updateById(prop); } else if (existingId != null) { // 前端没传 ID,但数据库有该 property_key → 用已有 ID 执行 UPDATE prop.setId(existingId); prop.setUpdateTime(now); propertyMapper.updateById(prop); } else { // 全新的 property_key → 执行 INSERT prop.setModelId(modelId); prop.setCreateTime(now); prop.setUpdateTime(now); prop.setDelFlag(false); propertyMapper.insert(prop); } } // 2.5 删除前端没传的属性(数据库有,但前端没传的) List toDeleteIds = existingProperties.stream() .filter(prop -> !receivedKeys.contains(prop.getPropertyKey())) .map(DeviceModelProperty::getId) .collect(Collectors.toList()); if (!toDeleteIds.isEmpty()) { propertyMapper.deleteBatchIds(toDeleteIds); } } // 3. 处理动作列表(同理,按 action_id 精准更新) if (deviceModel.getSupportActions() != null) { List existingActions = actionMapper.selectList( new LambdaQueryWrapper() .eq(DeviceAction::getModelId, modelId) ); java.util.Map existingActionMap = existingActions.stream() .collect(Collectors.toMap(DeviceAction::getActionId, DeviceAction::getId)); java.util.Set receivedActionIds = deviceModel.getSupportActions().stream() .map(DeviceAction::getActionId) .collect(Collectors.toSet()); LocalDateTime now = LocalDateTime.now(); for (DeviceAction action : deviceModel.getSupportActions()) { Long existingId = existingActionMap.get(action.getActionId()); if (action.getId() != null && action.getId() > 0) { action.setUpdateTime(now); actionMapper.updateById(action); } else if (existingId != null) { action.setId(existingId); action.setUpdateTime(now); actionMapper.updateById(action); } else { action.setModelId(modelId); action.setCreateTime(now); action.setUpdateTime(now); action.setDelFlag(false); actionMapper.insert(action); } } List toDeleteActionIds = existingActions.stream() .filter(action -> !receivedActionIds.contains(action.getActionId())) .map(DeviceAction::getId) .collect(Collectors.toList()); if (!toDeleteActionIds.isEmpty()) { actionMapper.deleteBatchIds(toDeleteActionIds); } } return 1; } } \ No newline at end of file +package com.maibu.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.maibu.core.business.DeviceAction; import com.maibu.core.business.DeviceModel; import com.maibu.core.business.DeviceModelProperty; import com.maibu.exception.ServiceException; import com.maibu.mapper.SysDeviceActionMapper; import com.maibu.mapper.SysDeviceModelMapper; import com.maibu.mapper.SysDevicePropertyMapper; import com.maibu.service.SysDeviceModelService; import com.maibu.service.SysDevicePropertyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.time.LocalDateTime; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; /** * @author jsmbz * @description 针对表【iot_device_model(设备模型表)】的数据库操作Service实现 * @createDate 2026-05-07 11:36:11 */ @Service public class SysDeviceModelServiceImpl extends ServiceImpl implements SysDeviceModelService { @Autowired private SysDeviceModelMapper deviceModelMapper; @Autowired private SysDeviceActionMapper actionMapper; @Autowired private SysDevicePropertyMapper propertyMapper; @Override @Transactional(rollbackFor = Exception.class) // ⭐ 关键 public int insertDeviceModel(DeviceModel deviceModel) { // 1. 插入模型主表 deviceModel.setCreateTime(LocalDateTime.now()); deviceModel.setDelFlag(false); int rows = deviceModelMapper.insert(deviceModel); if (rows <= 0) { throw new ServiceException("模型创建失败"); } Long modelId = deviceModel.getId(); // 2. 插入属性列表 if (!CollectionUtils.isEmpty(deviceModel.getSupportProperties())) { LocalDateTime now = LocalDateTime.now(); for (DeviceModelProperty prop : deviceModel.getSupportProperties()) { prop.setModelId(modelId); prop.setCreateTime(now); prop.setDelFlag(false); propertyMapper.insert(prop); } } // 3. 插入动作列表 if (!CollectionUtils.isEmpty(deviceModel.getSupportActions())) { LocalDateTime now = LocalDateTime.now(); for (DeviceAction action : deviceModel.getSupportActions()) { action.setModelId(modelId); action.setCreateTime(now); action.setDelFlag(false); actionMapper.insert(action); } } return 1; } @Override public Page selectDeviceModelPage(Page page, DeviceModel deviceModel) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); if (deviceModel.getName() != null && !deviceModel.getName().isEmpty()) { wrapper.like(DeviceModel::getName, deviceModel.getName()); } if (deviceModel.getConnectType() != null) { wrapper.eq(DeviceModel::getConnectType, deviceModel.getConnectType()); } if (deviceModel.getDeviceType() != null) { wrapper.eq(DeviceModel::getDeviceType, deviceModel.getDeviceType()); } wrapper.eq(DeviceModel::getDelFlag, false); wrapper.orderByDesc(DeviceModel::getCreateTime); Page resultPage = deviceModelMapper.selectPage(page, wrapper); if (!CollectionUtils.isEmpty(resultPage.getRecords())) { resultPage.getRecords().forEach(model -> { List properties = propertyMapper.selectList( new LambdaQueryWrapper() .eq(DeviceModelProperty::getModelId, model.getId()) .eq(DeviceModelProperty::getDelFlag, false) .orderByAsc(DeviceModelProperty::getId) ); model.setSupportProperties(properties); List actions = actionMapper.selectList( new LambdaQueryWrapper() .eq(DeviceAction::getModelId, model.getId()) .eq(DeviceAction::getDelFlag, false) .orderByAsc(DeviceAction::getId) ); model.setSupportActions(actions); }); } return resultPage; } @Override public DeviceModel selectDeviceModelById(Long id) { // 1. 查主表 DeviceModel model = deviceModelMapper.selectById(id); if (model == null) return null; // 2. 查属性 List properties = propertyMapper.selectList( new LambdaQueryWrapper() .eq(DeviceModelProperty::getModelId, id) .eq(DeviceModelProperty::getDelFlag, false) ); model.setSupportProperties(properties); // 3. 查动作 List actions = actionMapper.selectList( new LambdaQueryWrapper() .eq(DeviceAction::getModelId, id) .eq(DeviceAction::getDelFlag, false) ); model.setSupportActions(actions); return model; } @Override @Transactional(rollbackFor = Exception.class) public int updateDeviceModel(DeviceModel deviceModel) { // 1. 更新模型主表 deviceModel.setUpdateTime(LocalDateTime.now()); deviceModelMapper.updateById(deviceModel); Long modelId = deviceModel.getId(); // 2. 处理属性列表(按 property_key 精准更新) if (deviceModel.getSupportProperties() != null) { // 2.1 查询数据库已有的所有属性 List existingProperties = propertyMapper.selectList( new LambdaQueryWrapper() .eq(DeviceModelProperty::getModelId, modelId) ); // 2.2 构建已有属性的 property_key → ID 映射 java.util.Map existingKeyMap = existingProperties.stream() .collect(Collectors.toMap(DeviceModelProperty::getPropertyKey, DeviceModelProperty::getId)); // 2.3 收集前端传来的所有 property_key java.util.Set receivedKeys = deviceModel.getSupportProperties().stream() .map(DeviceModelProperty::getPropertyKey) .collect(Collectors.toSet()); LocalDateTime now = LocalDateTime.now(); // 2.4 处理前端传来的属性:有 ID 则更新,无 ID 则新增 for (DeviceModelProperty prop : deviceModel.getSupportProperties()) { Long existingId = existingKeyMap.get(prop.getPropertyKey()); if (prop.getId() != null && prop.getId() > 0) { // 前端传了 ID → 执行 UPDATE prop.setUpdateTime(now); propertyMapper.updateById(prop); } else if (existingId != null) { // 前端没传 ID,但数据库有该 property_key → 用已有 ID 执行 UPDATE prop.setId(existingId); prop.setUpdateTime(now); propertyMapper.updateById(prop); } else { // 全新的 property_key → 执行 INSERT prop.setModelId(modelId); prop.setCreateTime(now); prop.setUpdateTime(now); prop.setDelFlag(false); propertyMapper.insert(prop); } } // 2.5 删除前端没传的属性(数据库有,但前端没传的) List toDeleteIds = existingProperties.stream() .filter(prop -> !receivedKeys.contains(prop.getPropertyKey())) .map(DeviceModelProperty::getId) .collect(Collectors.toList()); if (!toDeleteIds.isEmpty()) { propertyMapper.deleteBatchIds(toDeleteIds); } } // 3. 处理动作列表(同理,按 action_id 精准更新) if (deviceModel.getSupportActions() != null) { List existingActions = actionMapper.selectList( new LambdaQueryWrapper() .eq(DeviceAction::getModelId, modelId) ); java.util.Map existingActionMap = existingActions.stream() .collect(Collectors.toMap(DeviceAction::getActionId, DeviceAction::getId)); java.util.Set receivedActionIds = deviceModel.getSupportActions().stream() .map(DeviceAction::getActionId) .collect(Collectors.toSet()); LocalDateTime now = LocalDateTime.now(); for (DeviceAction action : deviceModel.getSupportActions()) { Long existingId = existingActionMap.get(action.getActionId()); if (action.getId() != null && action.getId() > 0) { action.setUpdateTime(now); actionMapper.updateById(action); } else if (existingId != null) { action.setId(existingId); action.setUpdateTime(now); actionMapper.updateById(action); } else { action.setModelId(modelId); action.setCreateTime(now); action.setUpdateTime(now); action.setDelFlag(false); actionMapper.insert(action); } } List toDeleteActionIds = existingActions.stream() .filter(action -> !receivedActionIds.contains(action.getActionId())) .map(DeviceAction::getId) .collect(Collectors.toList()); if (!toDeleteActionIds.isEmpty()) { actionMapper.deleteBatchIds(toDeleteActionIds); } } return 1; } @Override @Transactional(rollbackFor = Exception.class) public int deleteDeviceModelById(Long id) { // 1. 检查模型是否存在 DeviceModel model = deviceModelMapper.selectById(id); if (model == null) { throw new ServiceException("模型不存在"); } // 2. 逻辑删除模型主表(使用 MyBatis-Plus 内置方法自动处理逻辑删除) boolean success = this.removeById(id); if (!success) { throw new ServiceException("模型删除失败"); } // 3. 逻辑删除关联的属性(使用 deleteById 自动处理逻辑删除) List properties = propertyMapper.selectList( new LambdaQueryWrapper() .eq(DeviceModelProperty::getModelId, id) ); if (!CollectionUtils.isEmpty(properties)) { for (DeviceModelProperty prop : properties) { propertyMapper.deleteById(prop.getId()); } } // 4. 逻辑删除关联的动作(使用 deleteById 自动处理逻辑删除) List actions = actionMapper.selectList( new LambdaQueryWrapper() .eq(DeviceAction::getModelId, id) ); if (!CollectionUtils.isEmpty(actions)) { for (DeviceAction action : actions) { actionMapper.deleteById(action.getId()); } } return 1; } } \ No newline at end of file