From 7d1c41d7d38e527a81b17b3dd5c50916fb53864e Mon Sep 17 00:00:00 2001 From: rqian <1206436827@qq.com> Date: Sat, 9 May 2026 14:46:08 +0800 Subject: [PATCH] =?UTF-8?q?#=E5=8E=82=E5=AE=B6=E6=A8=A1=E5=9D=97=E7=9A=84?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=BF=94=E5=9B=9E=E5=80=BC=E7=9A=84=E8=A1=A5?= =?UTF-8?q?=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/SysProductController.java | 47 +++++++++++------ .../java/com/maibu/core/business/Product.java | 4 +- .../maibu/core/business/ProductInterface.java | 2 +- .../maibu/core/business/dto/ProductDTO.java | 51 +++++++++++++++++++ .../maibu/service/DeviceProductService.java | 11 ++++ .../impl/DeviceProductServiceImpl.java | 2 +- 6 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 maibu-common/src/main/java/com/maibu/core/business/dto/ProductDTO.java diff --git a/maibu-admin/src/main/java/com/maibu/web/controller/system/SysProductController.java b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysProductController.java index d388d43..4340d27 100644 --- a/maibu-admin/src/main/java/com/maibu/web/controller/system/SysProductController.java +++ b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysProductController.java @@ -3,6 +3,7 @@ package com.maibu.web.controller.system; import cn.hutool.core.convert.Convert; import com.maibu.core.business.DeviceModel; 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; @@ -13,10 +14,12 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; +import java.time.LocalDateTime; import java.util.List; /** @@ -32,16 +35,20 @@ public class SysProductController extends BaseController { /** * 分页查询产品列表 */ - // @PreAuthorize("@ss.hasPermi('iot:product:list')") + // @PreAuthorize("@ss.hasPermi('iot:product:list')") @GetMapping("/list") @ApiOperation("查询产品列表") - public TableDataInfo list(Product product) { + public TableDataInfo list(ProductDTO productDTO) { Integer pageNum = Convert.toInt(ServletUtils.getParameter("pageNum"), 1); Integer pageSize = Convert.toInt(ServletUtils.getParameter("pageSize"), 10); Page page = new Page<>(pageNum, pageSize); - Page resultPage = productService.selectProductPage(page, product); + // DTO 转 Entity 用于查询筛选 + Product product = new Product(); + BeanUtils.copyProperties(productDTO, product); + + Page resultPage = productService.selectProductPage(page, product); return getDataTable(resultPage.getRecords(), resultPage.getTotal()); } @@ -51,21 +58,26 @@ public class SysProductController extends BaseController { //@PreAuthorize("@ss.hasPermi('iot:product:add')") @PostMapping("/add") @ApiOperation("新增产品") - public AjaxResult add(@RequestBody Product product) { - // 参数校验 - if (product.getName() == null || product.getName().isEmpty()) { + public AjaxResult add(@RequestBody ProductDTO productDTO) { + if (productDTO.getName() == null || productDTO.getName().isEmpty()) { return AjaxResult.error("产品名称不能为空"); } - if (product.getCode() == null || product.getCode().isEmpty()) { + if (productDTO.getCode() == null || productDTO.getCode().isEmpty()) { return AjaxResult.error("产品编码不能为空"); } // 检查编码是否重复 - Product existProduct = productService.selectByCode(product.getCode()); + Product existProduct = productService.selectByCode(productDTO.getCode()); if (existProduct != null) { return AjaxResult.error("产品编码已存在"); } + // DTO 转 Entity + Product product = new Product(); + BeanUtils.copyProperties(productDTO, product); + product.setCreateTime(LocalDateTime.now()); + product.setDelFlag(false); + boolean success = productService.save(product); return toAjax(success ? 1 : 0); } @@ -73,28 +85,31 @@ public class SysProductController extends BaseController { /** * 修改产品 */ - //@PreAuthorize("@ss.hasPermi('iot:product:edit')") @PostMapping("/update") @ApiOperation("修改产品") - public AjaxResult edit(@RequestBody Product product) { - if (product.getId() == null) { - return AjaxResult.error("产品ID不能为空"); + public AjaxResult edit(@RequestBody ProductDTO productDTO) { + if (productDTO.getId() == null) { + return AjaxResult.error("产品 ID 不能为空"); } - // 检查产品是否存在 - Product existProduct = productService.getById(product.getId()); + Product existProduct = productService.getById(productDTO.getId()); if (existProduct == null) { return AjaxResult.error("产品不存在"); } // 如果修改了编码,检查是否重复 - if (product.getCode() != null && !product.getCode().equals(existProduct.getCode())) { - Product duplicate = productService.selectByCode(product.getCode()); + if (productDTO.getCode() != null && !productDTO.getCode().equals(existProduct.getCode())) { + Product duplicate = productService.selectByCode(productDTO.getCode()); if (duplicate != null) { return AjaxResult.error("产品编码已存在"); } } + // DTO 转 Entity + Product product = new Product(); + BeanUtils.copyProperties(productDTO, product); + product.setUpdateTime(LocalDateTime.now()); + boolean success = productService.updateById(product); return toAjax(success ? 1 : 0); } diff --git a/maibu-common/src/main/java/com/maibu/core/business/Product.java b/maibu-common/src/main/java/com/maibu/core/business/Product.java index 4cf2a67..748efea 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/Product.java +++ b/maibu-common/src/main/java/com/maibu/core/business/Product.java @@ -18,7 +18,7 @@ import java.util.Map; @EqualsAndHashCode(callSuper = true) @JsonInclude(JsonInclude.Include.NON_NULL) @Data -@TableName("iot_device_product") +@TableName(value = "device_product", autoResultMap = true) public class Product extends BaseDO { private static final long serialVersionUID = 1L; @@ -52,4 +52,6 @@ public class Product extends BaseDO { private Integer status; + @TableField(exist = false) + private List interfaces; // 产品接口列表 } diff --git a/maibu-common/src/main/java/com/maibu/core/business/ProductInterface.java b/maibu-common/src/main/java/com/maibu/core/business/ProductInterface.java index d34162e..09c67cb 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/ProductInterface.java +++ b/maibu-common/src/main/java/com/maibu/core/business/ProductInterface.java @@ -17,7 +17,7 @@ import java.util.Map; @EqualsAndHashCode(callSuper = true) @JsonInclude(JsonInclude.Include.NON_NULL) @Data -@TableName("iot_device_product_inter") +@TableName("device_product_inter") public class ProductInterface extends BaseDO { private static final long serialVersionUID = 1L; diff --git a/maibu-common/src/main/java/com/maibu/core/business/dto/ProductDTO.java b/maibu-common/src/main/java/com/maibu/core/business/dto/ProductDTO.java new file mode 100644 index 0000000..6ebab07 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/business/dto/ProductDTO.java @@ -0,0 +1,51 @@ +package com.maibu.core.business.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.maibu.core.business.ProductInterface; +import com.maibu.core.domain.BaseDO; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; +import java.util.Map; + + + +@Data +public class ProductDTO extends BaseDO { + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.AUTO) + private Long id; + + private String code; + + private String name; + + private String manufacturer; + + private Long categoryId; + + private String protocolCode; + + private String transport; + + private String uploadTopic; + + private String subscribeTopic; + + private Integer status; + + @TableField(typeHandler = JacksonTypeHandler.class) + private Map thingsModels; + + + + + +} 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 027ae38..2861047 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 @@ -23,4 +23,15 @@ public interface DeviceProductService extends IService { Product selectByCode(String code); + + /** + * 新增产品(含接口表入库) + */ + boolean insertProduct(Product product); + /** + * 修改产品(含接口表入库) + */ + boolean updateProduct(Product product); + + } 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 3be5b1a..a1eadc9 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.core.business.ProductInterface; import com.maibu.exception.ServiceException; import com.maibu.mapper.DeviceProductInterfaceMapper; import com.maibu.mapper.DeviceProductMapper; import com.maibu.service.DeviceProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** * @author jsmbz * @description 针对表【device_product(产品表)】的数据库操作Service实现 * @createDate 2026-05-08 13:45:57 */ @Service public class DeviceProductServiceImpl extends ServiceImpl implements DeviceProductService { @Autowired private DeviceProductInterfaceMapper deviceProductInterfaceMapper; @Autowired private DeviceProductMapper productMapper; @Override public Page selectProductPage(Page page, Product product) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); // 精确查询产品编码 if (StringUtils.hasText(product.getCode())) { wrapper.eq(Product::getCode, product.getCode()); } // 模糊查询产品名称 if (StringUtils.hasText(product.getName())) { wrapper.like(Product::getName, product.getName()); } // 精确查询厂商 if (StringUtils.hasText(product.getManufacturer())) { wrapper.eq(Product::getManufacturer, product.getManufacturer()); } // 精确查询分类ID if (product.getCategoryId() != null) { wrapper.eq(Product::getCategoryId, product.getCategoryId()); } // 精确查询协议 if (StringUtils.hasText(product.getProtocolCode())) { wrapper.eq(Product::getProtocolCode, product.getProtocolCode()); } // 精确查询传输方式 if (StringUtils.hasText(product.getTransport())) { wrapper.eq(Product::getTransport, product.getTransport()); } // 精确查询状态 if (product.getStatus() != null) { wrapper.eq(Product::getStatus, product.getStatus()); } // 只查询未删除的 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); } @Override @Transactional(rollbackFor = Exception.class) public boolean insertProduct(Product product) { // 1. 插入产品主表 product.setCreateTime(LocalDateTime.now()); product.setUpdateTime(LocalDateTime.now()); product.setDelFlag(false); product.setStatus(1); // 默认启用 int rows = this.baseMapper.insert(product); if (rows <= 0) { throw new ServiceException("产品创建失败"); } Long productId = product.getId(); // 获取自增 ID // 2. 插入产品接口列表(如果前端传了) if (!CollectionUtils.isEmpty(product.getInterfaces())) { LocalDateTime now = LocalDateTime.now(); for (ProductInterface interfaceItem : product.getInterfaces()) { interfaceItem.setProductId(productId); interfaceItem.setCreateTime(now); interfaceItem.setUpdateTime(now); interfaceItem.setDelFlag(false); deviceProductInterfaceMapper.insert(interfaceItem); } } return true; } @Override @Transactional(rollbackFor = Exception.class) public boolean updateProduct(Product product) { // 1. 更新产品主表 product.setUpdateTime(LocalDateTime.now()); boolean success = productMapper.updateById(product) > 0; if (!success) { throw new ServiceException("产品更新失败"); } Long productId = product.getId(); // 2. 处理产品接口列表(按 interface_name 精准更新) if (product.getInterfaces() != null) { // 2.1 查询数据库已有的所有接口 List existingInterfaces = deviceProductInterfaceMapper.selectList( new LambdaQueryWrapper() .eq(ProductInterface::getProductId, productId) ); // 2.2 构建已有接口的 interface_name → ID 映射 Map existingNameMap = existingInterfaces.stream() .collect(Collectors.toMap(ProductInterface::getInterfaceName, ProductInterface::getId)); // 2.3 收集前端传来的所有 interface_name Set receivedNames = product.getInterfaces().stream() .map(ProductInterface::getInterfaceName) .collect(Collectors.toSet()); LocalDateTime now = LocalDateTime.now(); // 2.4 处理前端传来的接口:有 ID 则更新,无 ID 则新增 for (ProductInterface interfaceItem : product.getInterfaces()) { Long existingId = existingNameMap.get(interfaceItem.getInterfaceName()); if (interfaceItem.getId() != null && interfaceItem.getId() > 0) { // 前端传了 ID → 执行 UPDATE interfaceItem.setUpdateTime(now); deviceProductInterfaceMapper.updateById(interfaceItem); } else if (existingId != null) { // 前端没传 ID,但数据库有该 interface_name → 用已有 ID 执行 UPDATE interfaceItem.setId(existingId); interfaceItem.setUpdateTime(now); deviceProductInterfaceMapper.updateById(interfaceItem); } else { // 全新的 interface_name → 执行 INSERT interfaceItem.setProductId(productId); interfaceItem.setCreateTime(now); interfaceItem.setUpdateTime(now); interfaceItem.setDelFlag(false); deviceProductInterfaceMapper.insert(interfaceItem); } } // 2.5 删除前端没传的接口(数据库有,但前端没传的) List toDeleteIds = existingInterfaces.stream() .filter(item -> !receivedNames.contains(item.getInterfaceName())) .map(ProductInterface::getId) .collect(Collectors.toList()); if (!toDeleteIds.isEmpty()) { deviceProductInterfaceMapper.deleteBatchIds(toDeleteIds); } } return true; } } \ No newline at end of file