diff --git a/maibu-common/src/main/java/com/maibu/core/business/DeviceAction.java b/maibu-common/src/main/java/com/maibu/core/business/DeviceAction.java index 2cb34dc..eb7d12c 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/DeviceAction.java +++ b/maibu-common/src/main/java/com/maibu/core/business/DeviceAction.java @@ -13,9 +13,10 @@ import lombok.EqualsAndHashCode; import java.util.Map; @EqualsAndHashCode(callSuper = true) -@JsonInclude(JsonInclude.Include.NON_NULL) +//@JsonInclude(JsonInclude.Include.NON_NULL) @Data -@TableName("iot_device_action") +@TableName(value = "iot_device_action", autoResultMap = true) +@JsonInclude(JsonInclude.Include.ALWAYS) // 加这一行 public class DeviceAction extends BaseDO { @TableId(type = IdType.AUTO) diff --git a/maibu-common/src/main/java/com/maibu/core/enums/ConnectType.java b/maibu-common/src/main/java/com/maibu/core/enums/ConnectType.java index dd9d6a2..8634493 100644 --- a/maibu-common/src/main/java/com/maibu/core/enums/ConnectType.java +++ b/maibu-common/src/main/java/com/maibu/core/enums/ConnectType.java @@ -11,6 +11,10 @@ public enum ConnectType { MQTT, + ONVIF, + + RTSP, + HTTP; } diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/DeviceProductInterfaceMapper.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/DeviceProductInterfaceMapper.java new file mode 100644 index 0000000..f741621 --- /dev/null +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/DeviceProductInterfaceMapper.java @@ -0,0 +1,17 @@ +package com.maibu.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.maibu.core.business.ProductInterface; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author jsmbz + * @description 针对表【device_product_interface(产品接口表)】的数据库操作Mapper + * @createDate 2026-05-08 15:37:53 + * @Entity abbc.domain.DeviceProductInterface + */ +@Mapper +public interface DeviceProductInterfaceMapper extends BaseMapper { + + +} diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/DeviceProductInterfaceService.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/DeviceProductInterfaceService.java new file mode 100644 index 0000000..cca3b39 --- /dev/null +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/DeviceProductInterfaceService.java @@ -0,0 +1,13 @@ +package com.maibu.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.maibu.core.business.ProductInterface; + +/** + * @author jsmbz + * @description 针对表【device_product_interface(产品接口表)】的数据库操作Service + * @createDate 2026-05-08 15:37:53 + */ +public interface DeviceProductInterfaceService extends IService { + +} diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/DeviceProductService.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/DeviceProductService.java index 48b1f9e..027ae38 100644 --- a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/DeviceProductService.java +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/DeviceProductService.java @@ -21,4 +21,6 @@ public interface DeviceProductService extends IService { * 根据编码查询产品 */ Product selectByCode(String code); + + } diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/DeviceProductInterfaceServiceImpl.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/DeviceProductInterfaceServiceImpl.java new file mode 100644 index 0000000..9e87286 --- /dev/null +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/DeviceProductInterfaceServiceImpl.java @@ -0,0 +1,18 @@ +package com.maibu.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.maibu.core.business.ProductInterface; +import com.maibu.mapper.DeviceProductInterfaceMapper; +import com.maibu.service.DeviceProductInterfaceService; +import org.springframework.stereotype.Service; + +/** + * @author jsmbz + * @description 针对表【device_product_interface(产品接口表)】的数据库操作Service实现 + * @createDate 2026-05-08 15:37:53 + */ +@Service +public class DeviceProductInterfaceServiceImpl extends ServiceImpl + implements DeviceProductInterfaceService { + +} diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/DeviceProductServiceImpl.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/DeviceProductServiceImpl.java index 8b4ccd4..3be5b1a 100644 --- a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/DeviceProductServiceImpl.java +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/DeviceProductServiceImpl.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.Product; import com.maibu.mapper.DeviceProductMapper; import com.maibu.service.DeviceProductService; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; /** * @author jsmbz * @description 针对表【device_product(产品表)】的数据库操作Service实现 * @createDate 2026-05-08 13:45:57 */ @Service public class DeviceProductServiceImpl extends ServiceImpl implements DeviceProductService { @Override public Page selectProductPage(Page page, Product product) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); // 模糊查询产品名称 if (StringUtils.hasText(product.getName())) { wrapper.like(Product::getName, product.getName()); } // 精确查询厂商 if (StringUtils.hasText(product.getManufacturer())) { wrapper.eq(Product::getManufacturer, product.getManufacturer()); } // 精确查询协议 if (StringUtils.hasText(product.getProtocolCode())) { wrapper.eq(Product::getProtocolCode, product.getProtocolCode()); } // 只查询未删除的 wrapper.eq(Product::getDelFlag, 0); // 按创建时间倒序 wrapper.orderByDesc(Product::getCreateTime); return this.page(page, wrapper); } @Override public Product selectByCode(String code) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Product::getCode, code) .eq(Product::getDelFlag, 0); return this.getOne(wrapper); } } \ 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.Product; import com.maibu.mapper.DeviceProductMapper; import com.maibu.service.DeviceProductService; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; /** * @author jsmbz * @description 针对表【device_product(产品表)】的数据库操作Service实现 * @createDate 2026-05-08 13:45:57 */ @Service public class DeviceProductServiceImpl extends ServiceImpl implements DeviceProductService { @Override public Page selectProductPage(Page page, Product product) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); // 模糊查询产品名称 if (StringUtils.hasText(product.getName())) { wrapper.like(Product::getName, product.getName()); } // 精确查询厂商 if (StringUtils.hasText(product.getManufacturer())) { wrapper.eq(Product::getManufacturer, product.getManufacturer()); } // 精确查询协议 if (StringUtils.hasText(product.getProtocolCode())) { wrapper.eq(Product::getProtocolCode, product.getProtocolCode()); } // 只查询未删除的 wrapper.eq(Product::getDelFlag, 0); // 按创建时间倒序 wrapper.orderByDesc(Product::getCreateTime); return this.page(page, wrapper); } @Override public Product selectByCode(String code) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Product::getCode, code) .eq(Product::getDelFlag, 0); return this.getOne(wrapper); } } \ No newline at end of file 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 734310b..83e8e93 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. 处理属性列表(智能更新) if (deviceModel.getSupportProperties() != null) { // 2.1 遍历前端传来的列表:有 ID 则更新,无 ID 则新增 for (DeviceModelProperty prop : deviceModel.getSupportProperties()) { if (prop.getId() != null && prop.getId() > 0) { // 已有记录 → 执行 UPDATE prop.setUpdateTime(LocalDateTime.now()); propertyMapper.updateById(prop); } else { // 新记录 → 执行 INSERT prop.setModelId(modelId); prop.setCreateTime(LocalDateTime.now()); prop.setUpdateTime(LocalDateTime.now()); prop.setDelFlag(false); propertyMapper.insert(prop); } } // 2.2 删除前端没传的属性(通过 NOT IN) List receivedIds = deviceModel.getSupportProperties().stream() .map(DeviceModelProperty::getId) .filter(id -> id != null && id > 0) .collect(Collectors.toList()); if (!receivedIds.isEmpty()) { propertyMapper.delete( new LambdaQueryWrapper() .eq(DeviceModelProperty::getModelId, modelId) .notIn(DeviceModelProperty::getId, receivedIds) ); } else { // 如果传了空列表,删除所有属性 propertyMapper.delete( new LambdaQueryWrapper() .eq(DeviceModelProperty::getModelId, modelId) ); } } // 3. 处理动作列表(同理) if (deviceModel.getSupportActions() != null) { for (DeviceAction action : deviceModel.getSupportActions()) { if (action.getId() != null && action.getId() > 0) { action.setUpdateTime(LocalDateTime.now()); actionMapper.updateById(action); } else { action.setModelId(modelId); action.setCreateTime(LocalDateTime.now()); action.setUpdateTime(LocalDateTime.now()); action.setDelFlag(false); actionMapper.insert(action); } } List receivedActionIds = deviceModel.getSupportActions().stream() .map(DeviceAction::getId) .filter(id -> id != null && id > 0) .collect(Collectors.toList()); if (!receivedActionIds.isEmpty()) { actionMapper.delete( new LambdaQueryWrapper() .eq(DeviceAction::getModelId, modelId) .notIn(DeviceAction::getId, receivedActionIds) ); } else { actionMapper.delete( new LambdaQueryWrapper() .eq(DeviceAction::getModelId, modelId) ); } } 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; } } \ No newline at end of file diff --git a/maibu-service/maibu-system-service/src/main/resources/system/DeviceProductInterfaceMapper.xml b/maibu-service/maibu-system-service/src/main/resources/system/DeviceProductInterfaceMapper.xml new file mode 100644 index 0000000..646c0ec --- /dev/null +++ b/maibu-service/maibu-system-service/src/main/resources/system/DeviceProductInterfaceMapper.xml @@ -0,0 +1 @@ + \ No newline at end of file