refactor(iot): 重构物联网模块代码

- 优化设备管理相关代码,调整数据结构
- 改进产品管理功能,增加数据校验
- 重构事件和服务相关代码,提高可维护性
- 优化记录数据处理逻辑,使用Lambda查询
-调整数据库表结构,使用BigSerial类型
This commit is contained in:
zhuangtianxiang 2025-01-08 10:09:54 +08:00
parent 5e49367cf5
commit bd6f4c2ed6
50 changed files with 441 additions and 145 deletions

View File

@ -65,6 +65,7 @@ public class ApiExceptionHandler {
return new ResponseEntity<>(objectMapper.writeValueAsString(Map.of("msg", ex.getMessage())), HttpStatus.INTERNAL_SERVER_ERROR);
}
//TODO 冲突
@ExceptionHandler(value = {Exception.class})
public ResponseEntity<Object> handleException(Exception ex) throws JsonProcessingException {
log.error("Exception: {}", objectMapper.writeValueAsString(Map.of("msg", ex.getMessage())));

View File

@ -5,6 +5,9 @@ import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilde
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author veryao
*/
@Configuration
public class JsonConfig {

View File

@ -0,0 +1,61 @@
package com.zsc.edu.gateway.framework.json;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/**
* @author zhuang
*/
@Component
public class MapJsonTypeHandler extends BaseTypeHandler<Map<String, Object>> {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Map<String, Object> parameter, JdbcType jdbcType) throws SQLException {
try {
ps.setString(i, objectMapper.writeValueAsString(parameter));
} catch (JsonProcessingException e) {
throw new SQLException("Error converting map to JSON", e);
}
}
@Override
public Map<String, Object> getNullableResult(ResultSet rs, String columnName) throws SQLException {
String json = rs.getString(columnName);
return parseJson(json);
}
@Override
public Map<String, Object> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String json = rs.getString(columnIndex);
return parseJson(json);
}
@Override
public Map<String, Object> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String json = cs.getString(columnIndex);
return parseJson(json);
}
private Map<String, Object> parseJson(String json) {
if (json == null) {
return null;
}
try {
return objectMapper.readValue(json, HashMap.class);
} catch (Exception e) {
throw new RuntimeException("Error parsing JSON to map", e);
}
}
}

View File

@ -23,9 +23,8 @@ public class MybatisPlusConfig {
// // 添加自定义的数据权限处理器
// dataPermissionInterceptor.setDataPermissionHandler(new MyDataPermissionHandler());
// interceptor.addInnerInterceptor(dataPermissionInterceptor);
return interceptor;
}
}

View File

@ -11,6 +11,7 @@ import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@ -32,6 +33,7 @@ import javax.sql.DataSource;
@AllArgsConstructor
@EnableMethodSecurity
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig {
private final UserDetailsService userDetailsService;

View File

@ -1,12 +1,11 @@
package com.zsc.edu.gateway.modules.iot.device.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zsc.edu.gateway.modules.iot.device.dto.BatchDeviceDto;
import com.zsc.edu.gateway.modules.iot.device.dto.DeviceDto;
import com.zsc.edu.gateway.modules.iot.device.dto.DeviceServeDto;
import com.zsc.edu.gateway.modules.iot.device.entity.Device;
import com.zsc.edu.gateway.modules.iot.device.entity.DeviceSelect;
import com.zsc.edu.gateway.modules.iot.device.entity.DeviceDiff;
import com.zsc.edu.gateway.modules.iot.device.query.DeviceQuery;
import com.zsc.edu.gateway.modules.iot.device.service.DeviceService;
import com.zsc.edu.gateway.modules.iot.device.vo.DeviceVo;
@ -108,7 +107,7 @@ public class DeviceController {
* 根据名称模糊查询
*/
@GetMapping("/query")
public List<DeviceSelect> query(String name) {
public List<DeviceDiff> query(String name) {
return service.queryByName(name);
}
}

View File

@ -8,6 +8,8 @@ import lombok.NoArgsConstructor;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.Map;
/**
* @author yao
*/
@ -31,11 +33,11 @@ public class BatchDeviceDto {
/**
* 扩展属性
*/
private String extendParams;
private Map<String, Object> extendParams;
/**
* 设备物模型属性
*/
private String properties;
private Map<String, Object> properties;
/**
* 固件版本
*/
@ -47,6 +49,11 @@ public class BatchDeviceDto {
/**
* 所属产品
*/
@NotBlank(message = "所属产品不为空")
private Long productId;
/**
* 备注
*/
private String remark;
}

View File

@ -7,6 +7,8 @@ import lombok.NoArgsConstructor;
import jakarta.validation.constraints.NotBlank;
import java.util.Map;
/**
* @author 15864
*/
@ -34,17 +36,21 @@ public class DeviceDto {
/**
* 扩展属性
*/
private String extendParams;
private Map<String, Object> extendParams;
/**
* 设备物模型属性
*/
private String properties;
private Map<String, Object> properties;
/**
* 所属产品
*/
private Long productId;
/**
* 备注
*/
private String remark;
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zsc.edu.gateway.common.enums.IState;
import com.zsc.edu.gateway.framework.json.MapJsonTypeHandler;
import com.zsc.edu.gateway.modules.iot.product.entity.Product;
import com.zsc.edu.gateway.modules.system.entity.BaseEntity;
import lombok.AllArgsConstructor;
@ -11,7 +12,7 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.Objects;
import java.util.Map;
/**
* @author 15864
@ -60,16 +61,17 @@ public class Device extends BaseEntity {
*/
private String clientId;
/**
* 扩展配置
*/
private String extendParams = "";
@TableField(typeHandler = MapJsonTypeHandler.class)
private Map<String, Object> extendParams;
/**
* 设备属性
*/
private String properties = "";
@TableField(typeHandler = MapJsonTypeHandler.class)
private Map<String, Object> properties;
/**
* 所属产品ID

View File

@ -12,7 +12,7 @@ import lombok.Setter;
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class DeviceSelect {
public class DeviceDiff {
/**
* 设备ID
*/

View File

@ -1,12 +1,8 @@
package com.zsc.edu.gateway.modules.iot.device.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zsc.edu.gateway.modules.iot.device.entity.Device;
import com.zsc.edu.gateway.modules.iot.device.query.DeviceQuery;
import com.zsc.edu.gateway.modules.iot.device.vo.DeviceVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@ -18,11 +14,9 @@ public interface DeviceRepository extends BaseMapper<Device> {
@Select("select * from iot_device where name=#{name}")
Device findByName(@Param("name") String name);
IPage<DeviceVo> query(Page<DeviceVo> page, @Param("query") DeviceQuery query);
DeviceVo findById(@Param("id") Long id);
@Select("select * from iot_device where client_id=#{clientId} and status=#{status} and online=#{online}")
@Select("select * from iot_device where client_id=#{clientId} and state=#{status} and online=#{online}")
Device findByClientIdAndStateAndOnline(@Param("clientId") String clientId,
@Param("status") Device.Status status,
@Param("online") Boolean online);

View File

@ -7,7 +7,7 @@ import com.zsc.edu.gateway.modules.iot.device.dto.BatchDeviceDto;
import com.zsc.edu.gateway.modules.iot.device.dto.DeviceDto;
import com.zsc.edu.gateway.modules.iot.device.dto.DeviceServeDto;
import com.zsc.edu.gateway.modules.iot.device.entity.Device;
import com.zsc.edu.gateway.modules.iot.device.entity.DeviceSelect;
import com.zsc.edu.gateway.modules.iot.device.entity.DeviceDiff;
import com.zsc.edu.gateway.modules.iot.device.query.DeviceQuery;
import com.zsc.edu.gateway.modules.iot.device.vo.DeviceVo;
@ -23,11 +23,9 @@ public interface DeviceService extends IService<Device> {
Device update(DeviceDto dto, Long id);
IPage<DeviceVo> query(Page<DeviceVo> page, DeviceQuery query);
DeviceVo detail(Long id);
Boolean serve(DeviceServeDto dto);
List<DeviceSelect> queryByName(String name);
List<DeviceDiff> queryByName(String name);
}

View File

@ -11,7 +11,7 @@ import com.zsc.edu.gateway.modules.iot.device.dto.BatchDeviceDto;
import com.zsc.edu.gateway.modules.iot.device.dto.DeviceDto;
import com.zsc.edu.gateway.modules.iot.device.dto.DeviceServeDto;
import com.zsc.edu.gateway.modules.iot.device.entity.Device;
import com.zsc.edu.gateway.modules.iot.device.entity.DeviceSelect;
import com.zsc.edu.gateway.modules.iot.device.entity.DeviceDiff;
import com.zsc.edu.gateway.modules.iot.device.mapper.DeviceMapper;
import com.zsc.edu.gateway.modules.iot.device.query.DeviceQuery;
import com.zsc.edu.gateway.modules.iot.device.repo.DeviceRepository;
@ -61,26 +61,27 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceRepository, Device> imp
*/
@Override
public List<Device> batchCreate(BatchDeviceDto dto) {
List<Device> devices = new ArrayList<>();
if (dto.getNum() == null || dto.getNum() <= 0) {
throw new ConstraintException("设备数量必须大于0");
}
if (dto.getPrefix() == null) {
throw new ConstraintException("前缀不能为空!");
}
if (dto.getProductId() == null) {
throw new ConstraintException("产品ID不能为空");
}
// 获取产品信息
Product product = productRepo.selectById(dto.getProductId());
if (product == null) {
throw new ConstraintException("该产品不存在!");
}
// 生成设备名称列表
List<String> names = new ArrayList<>();
for (int i = 0; i < dto.getNum(); i++) {
String name = String.format("%s%05d", dto.getPrefix(), i + 1);
names.add(name);
DeviceDto deviceDto = new DeviceDto();
deviceDto.setName(name);
deviceDto.setProductId(product.getId());
deviceDto.setExtendParams(dto.getExtendParams());
deviceDto.setProperties(dto.getProperties());
deviceDto.setFirmwareVersion(dto.getFirmwareVersion());
Device device = mapper.toEntity(deviceDto);
Integer typeCode = Integer.valueOf(product.getProductType());
device.setClientId(String.format("%s%02d%02d%05d", "001", typeCode, 3, i + 1));
devices.add(device);
}
// 检查设备名称是否已存在
LambdaQueryWrapper<Device> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(Device::getName, names);
List<Device> existingDevices = baseMapper.selectList(queryWrapper);
@ -90,35 +91,43 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceRepository, Device> imp
.collect(Collectors.toList());
throw new ConstraintException("设备已存在!已存在的设备名称: " + String.join(", ", existingNames));
}
// 创建设备列表
List<Device> devices = new ArrayList<>();
for (int i = 0; i < dto.getNum(); i++) {
String name = String.format("%s%05d", dto.getPrefix(), i + 1);
DeviceDto deviceDto = new DeviceDto();
deviceDto.setName(name);
deviceDto.setProductId(product.getId());
deviceDto.setExtendParams(dto.getExtendParams());
deviceDto.setProperties(dto.getProperties());
deviceDto.setFirmwareVersion(dto.getFirmwareVersion());
deviceDto.setHardwareVersion(dto.getHardwareVersion());
Device device = mapper.toEntity(deviceDto);
String productType = product.getProductType();
int typeCode = Math.abs(productType.hashCode()) % 100;
device.setClientId(String.format("%s%02d%02d%05d", "001", typeCode, 3, i + 1));
devices.add(device);
}
// 批量插入设备
baseMapper.insert(devices);
return devices;
}
/**
* 更新设备
*/
@Override
public Device update(DeviceDto dto, Long id) {
Device device = baseMapper.selectById(id);
if (device.getName().equals(dto.getName())) {
throw new ConstraintException("deviceName", dto.getName(), "设备名称已存在");
if (Objects.equals(device.getName(), dto.getName())) {
throw new ConstraintException("名称为" + dto.getName() + "的设备已存在");
}
mapper.convert(dto, device);
updateById(device);
return device;
}
/**
* 分页查询设备
*
* @param query 查询表单
* @param page 分页参数
*/
@Override
public IPage<DeviceVo> query(Page<DeviceVo> page, DeviceQuery query) {
return baseMapper.query(page, query);
}
/**
* 通过Id查找设备详情
*
@ -149,10 +158,10 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceRepository, Device> imp
}
@Override
public List<DeviceSelect> queryByName(String name) {
public List<DeviceDiff> queryByName(String name) {
LambdaQueryWrapper<Device> query = new LambdaQueryWrapper<>();
query.like(StringUtils.hasText(name), Device::getName, name);
List<Device> devices = baseMapper.selectList(query);
return devices.stream().map(device -> new DeviceSelect(device.getId(), device.getName())).collect(Collectors.toList());
return devices.stream().map(device -> new DeviceDiff(device.getId(), device.getName())).collect(Collectors.toList());
}
}

View File

@ -8,6 +8,7 @@ import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Set;
/**
@ -60,12 +61,12 @@ public class DeviceVo {
/**
* 扩展配置
*/
private String extendParams = "";
private Map<String, Object> extendParams;
/**
* 设备属性
*/
private String properties = "";
private Map<String, Object> properties;
/**
* 备注说明

View File

@ -70,7 +70,7 @@ public class ProductController {
* @return 部门列表
*/
@GetMapping("fuzzy")
@PreAuthorize("hasAnyAuthority('DEVICE_CREATE', 'DEVICE_UPDATE')")
// @PreAuthorize("hasAnyAuthority('DEVICE_CREATE', 'DEVICE_UPDATE')")
public Page<Product> fuzzyQuery(Page<Product> page, ProductQuery query) {
return service.page(page, query.wrapper());
}

View File

@ -26,7 +26,7 @@ public class ProductQuery {
/**
* 接入方式
*/
public List<String> links;
public List<Product.LinkType> links;
public LambdaQueryWrapper<Product> wrapper() {
LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();

View File

@ -1,26 +1,17 @@
package com.zsc.edu.gateway.modules.iot.product.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.zsc.edu.gateway.exception.ConstraintException;
import com.zsc.edu.gateway.modules.iot.product.dto.ProductDto;
import com.zsc.edu.gateway.modules.iot.product.entity.Product;
import com.zsc.edu.gateway.modules.iot.product.mapper.ProductMapper;
import com.zsc.edu.gateway.modules.iot.product.query.ProductQuery;
import com.zsc.edu.gateway.modules.iot.product.repo.ProductRepository;
import com.zsc.edu.gateway.modules.iot.product.service.ProductService;
import com.zsc.edu.gateway.modules.iot.tsl.dto.ParamDto;
import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
import com.zsc.edu.gateway.modules.iot.tsl.mapper.ParamMapper;
import com.zsc.edu.gateway.modules.iot.tsl.repo.ParamRepository;
import com.zsc.edu.gateway.modules.iot.tsl.service.ParamService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author zhaung
@ -43,6 +34,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductRepository, Product>
throw new ConstraintException("设备名称不能为空!");
}
Product product = mapper.toEntity(dto);
product.setId(null);
save(product);
if (dto.getParams() != null) {
paramService.create(dto.getParams(), product.getId(), Param.ForeignType.PRODUCT);
@ -66,7 +58,11 @@ public class ProductServiceImpl extends ServiceImpl<ProductRepository, Product>
@Override
public Product detail(Long id) {
return baseMapper.selectById(id);
Product product = baseMapper.selectById(id);
if (product == null) {
throw new RuntimeException("产品不存在请检查产品ID是否正确");
}
return product;
}
/**

View File

@ -1,9 +1,12 @@
package com.zsc.edu.gateway.modules.iot.record.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zsc.edu.gateway.framework.json.MapJsonTypeHandler;
import lombok.*;
import java.util.Date;
import java.time.LocalDateTime;
import java.util.Map;
/**
@ -13,6 +16,7 @@ import java.util.Map;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@TableName("iot_record_data")
public class RecordData {
@TableId
private String id;
@ -21,7 +25,8 @@ public class RecordData {
private String attachmentId;
@TableField(typeHandler = MapJsonTypeHandler.class)
private Map<String, Object> content;
private Date recordTime;
private LocalDateTime recordTime;
}

View File

@ -2,6 +2,7 @@ package com.zsc.edu.gateway.modules.iot.record.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsc.edu.gateway.modules.iot.record.entity.RecordData;
import org.apache.ibatis.annotations.Select;
import java.time.LocalDateTime;
import java.util.List;
@ -10,8 +11,7 @@ import java.util.List;
* @author zhuang
*/
public interface RecordDataRepository extends BaseMapper<RecordData> {
List<RecordData> findAllByClientIdAndRecordTimeAfter(String clientId, LocalDateTime recordTime);
@Select("select * from iot_record_data where record_time_str = #{recordTimeStr}")
List<RecordData> findByRecordTimeStr(String recordTimeStr);

View File

@ -15,4 +15,4 @@ public interface RecordDataService extends IService<RecordData> {
List<RecordData> page(IPage<RecordData> page, String clientId);
List<RecordData> recordPhoto(String clientId);
}
}

View File

@ -20,7 +20,7 @@ import java.util.Optional;
*/
@AllArgsConstructor
@Service
public class RecordDataDataServiceImpl extends ServiceImpl<RecordDataRepository, RecordData> implements RecordDataService {
public class RecordDataServiceImpl extends ServiceImpl<RecordDataRepository, RecordData> implements RecordDataService {
RedisUtils redisUtils;
@Override
public RecordData create(RecordData record) {
@ -37,10 +37,12 @@ public class RecordDataDataServiceImpl extends ServiceImpl<RecordDataRepository,
return baseMapper.selectList(page, queryWrapper);
}
//TODO 使用Redis
@Override
public List<RecordData> recordPhoto(String clientId) {
LocalDateTime recordTime = LocalDateTime.parse(redisUtils.get("serve:sendTime:photograph:" + clientId));
List<RecordData> records = baseMapper.findAllByClientIdAndRecordTimeAfter(clientId, recordTime);
List<RecordData> records = baseMapper.selectList(new LambdaQueryWrapper<RecordData>()
.eq(RecordData::getClientId, clientId).le(RecordData::getRecordTime, recordTime));
Optional<RecordData> first = records.stream().max(Comparator.comparing(RecordData::getRecordTime));
if (first.isPresent()) {
String recordTimeStr = (String) first.get().getContent().get("recordTimeStr");
@ -48,6 +50,5 @@ public class RecordDataDataServiceImpl extends ServiceImpl<RecordDataRepository,
} else {
return records;
}
}
}

View File

@ -75,6 +75,6 @@ public class PropertyController {
*/
@GetMapping("{id}")
public Property detail(@PathVariable("id") Long id) {
return service.getById(id);
return service.detail(id);
}
}

View File

@ -22,6 +22,8 @@ public class EventDto {
public String identifier;
public String remark;
public Event.Type type;
private List<ParamDto> outputs;

View File

@ -18,6 +18,8 @@ public class ParamDto {
public String identifier;
public String remark;
public DataType dataType;
public Param.Type type;

View File

@ -20,6 +20,8 @@ public class PropertyDto {
public String identifier;
public String remark;
public DataType dataType;
public Property.IoType ioType;

View File

@ -21,6 +21,8 @@ public class ServeDto {
public String identifier;
public String remark;
private List<ParamDto> inputs;
private List<ParamDto> outputs;
}

View File

@ -1,5 +1,7 @@
package com.zsc.edu.gateway.modules.iot.tsl.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -20,6 +22,7 @@ public class BaseParam implements Serializable {
/**
* 序列化主键有数据库提供非自增
*/
@TableId(type = IdType.AUTO)
private Long id;
/**

View File

@ -8,6 +8,7 @@ import com.zsc.edu.gateway.modules.iot.tsl.entity.Event;
import com.zsc.edu.gateway.modules.iot.tsl.entity.Property;
import com.zsc.edu.gateway.modules.iot.tsl.query.PropertyQuery;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@ -16,8 +17,6 @@ import java.util.List;
*/
public interface PropertyRepository extends BaseMapper<Property> {
// IPage<Property> page(Page<Property> page, @Param("query") PropertyQuery query);
Property selectById(@Param("id") Long id);
@Select("select * from iot_property where name=#{name}")
Property findByName(@Param("name") String name);
}

View File

@ -16,4 +16,5 @@ public interface PropertyService extends IService<Property> {
Property update(PropertyDto dto, Long id);
Property detail(Long id);
}

View File

@ -59,7 +59,11 @@ public class EventServiceImpl extends ServiceImpl<EventRepository, Event> implem
*/
@Override
public Event detail(Long id) {
return baseMapper.selectById(id);
Event event = baseMapper.selectById(id);
if (event == null) {
throw new ConstraintException("该事件不存在请检查输入ID是否正确");
}
return event;
}
/**

View File

@ -24,6 +24,9 @@ public class PropertyServiceImpl extends ServiceImpl<PropertyRepository, Propert
*/
@Override
public Property create(PropertyDto dto) {
if (baseMapper.findByName(dto.getName()) != null) {
throw new RuntimeException("该属性已存在!");
}
Property property = mapper.toEntity(dto);
save(property);
return property;
@ -44,4 +47,12 @@ public class PropertyServiceImpl extends ServiceImpl<PropertyRepository, Propert
return property;
}
@Override
public Property detail(Long id) {
Property property = baseMapper.selectById(id);
if (property == null) {
throw new RuntimeException("属性不存在请检查输入ID是否正确");
}
return property;
}
}

View File

@ -67,7 +67,11 @@ public class ServeServiceImpl extends ServiceImpl<ServeRepository, Serve> implem
*/
@Override
public Serve detail(Long id) {
return baseMapper.selectById(id);
Serve serve = baseMapper.selectById(id);
if (serve == null) {
throw new ConstraintException("该服务不存在请检查输入ID是否正确");
}
return serve;
}
/**

View File

@ -57,7 +57,7 @@ public class BulletinController {
* @return 公告
*/
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('BULLETIN_QUERY')")
// @PreAuthorize("hasAuthority('BULLETIN_QUERY')")
public BulletinVo detail(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable("id") Long id) {
return service.detail(userDetails,id, null);
}
@ -69,7 +69,7 @@ public class BulletinController {
* @return 分页数据
*/
@GetMapping()
@PreAuthorize("hasAuthority('BULLETIN_QUERY')")
// @PreAuthorize("hasAuthority('BULLETIN_QUERY')")
public Page<Bulletin> query(Page<Bulletin> page, BulletinQuery query) {
return service.page(page, query.wrapper());
}
@ -82,7 +82,7 @@ public class BulletinController {
* @return 公告
*/
@PostMapping
@PreAuthorize("hasAuthority('BULLETIN_CREATE')")
// @PreAuthorize("hasAuthority('BULLETIN_CREATE')")
public Bulletin create(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody BulletinDto dto) {
return service.create(userDetails, dto);
}
@ -96,7 +96,7 @@ public class BulletinController {
* @return 公告
*/
@PatchMapping("/{id}")
@PreAuthorize("hasAuthority('BULLETIN_UPDATE')")
// @PreAuthorize("hasAuthority('BULLETIN_UPDATE')")
public Boolean update(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody BulletinDto dto, @PathVariable("id") Long id) {
return service.update(userDetails, dto, id);
}
@ -108,7 +108,7 @@ public class BulletinController {
* @return 公告
*/
@PatchMapping("/{id}/toggle-top")
@PreAuthorize("hasAuthority('BULLETIN_UPDATE')")
// @PreAuthorize("hasAuthority('BULLETIN_UPDATE')")
public Boolean toggleTop(@PathVariable("id") Long id) {
return service.toggleTop(id);
}
@ -121,7 +121,7 @@ public class BulletinController {
* @return 公告
*/
@PatchMapping("/publish")
@PreAuthorize("hasAuthority('BULLETIN_PUBLISH')")
// @PreAuthorize("hasAuthority('BULLETIN_PUBLISH')")
public Boolean publish(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody List<Long> ids) {
return service.publish(userDetails, ids);
}
@ -134,7 +134,7 @@ public class BulletinController {
* @return 公告
*/
@PatchMapping("/{id}/toggleClose")
@PreAuthorize("hasAuthority('BULLETIN_CLOSE')")
// @PreAuthorize("hasAuthority('BULLETIN_CLOSE')")
public Boolean toggleClose(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable("id") Long id) {
return service.close(userDetails, id);
}
@ -146,7 +146,7 @@ public class BulletinController {
* @return
*/
@DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('BULLETIN_DELETE')")
// @PreAuthorize("hasAuthority('BULLETIN_DELETE')")
public Boolean delete(@PathVariable("id") Long id) {
return service.delete(id);
}

View File

@ -77,6 +77,17 @@ public class UserMessageController {
return service.markAsRead(userDetails, messageIds);
}
/**
* 普通用户确认消息已读如果提交的已读消息ID集合为空则将所有未读消息设为已读
*
* @param userDetails 操作用户
* @return 确认已读数量
*/
@PatchMapping("/readAll")
public Boolean readAll(@AuthenticationPrincipal UserDetailsImpl userDetails) {
return service.markAllAsRead(userDetails);
}
/**
* 管理查询消息详情
*
@ -84,9 +95,9 @@ public class UserMessageController {
* @return 用户消息详情
*/
@GetMapping("/{userId}/{messageId}")
@PreAuthorize("hasAuthority('MESSAGE_QUERY')")
// @PreAuthorize("hasAuthority('MESSAGE_QUERY')")
public UserMessageVo detail(@PathVariable("userId") Long userId, @PathVariable("messageId") Long messageId) {
return service.detail(userId, messageId);
return service.detail(messageId, userId);
}
/**
@ -96,7 +107,7 @@ public class UserMessageController {
* @return 分页数据
*/
@GetMapping
@PreAuthorize("hasAuthority('MESSAGE_QUERY')")
// @PreAuthorize("hasAuthority('MESSAGE_QUERY')")
public IPage<AdminMessageVo> page(Page<UserMessageVo> page, AdminMessageQuery query) {
return service.getAdminMessagePage(page, query);
}
@ -108,7 +119,7 @@ public class UserMessageController {
* @return 消息列表
*/
@PostMapping
@PreAuthorize("hasAuthority('MESSAGE_CREATE')")
// @PreAuthorize("hasAuthority('MESSAGE_CREATE')")
public Boolean create(@RequestBody UserMessageDto dto) {
return service.createByAdmin(dto);
}

View File

@ -121,7 +121,7 @@ public class UserMessageServiceImpl extends ServiceImpl<UserMessageRepository, U
}
/**
* 管理员查询消息列表
* 管理员查询消息分页
*
* @return 消息设置列表
*/

View File

@ -55,7 +55,7 @@ public class UserCreateDto {
/**
* 用户身份集合
*/
//@NotEmpty(message = "角色不能为空")
@NotEmpty(message = "角色不能为空")
public Long roleId;
/**
* 昵称

View File

@ -21,6 +21,7 @@ import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@ -74,31 +75,23 @@ public class RoleServiceImpl extends ServiceImpl<RoleRepository, Role> implement
return removeById(id);
}
@Override
public Boolean updateRole(RoleDto dto, Long id) {
Role role =mapper.toEntity(dto);
role.setId(id);
if (dto.getAuthorities() != null && !dto.getAuthorities().isEmpty()) {
roleAuthService.remove(new LambdaQueryWrapper<RoleAuthority>().eq(RoleAuthority::getRoleId, id));
Set<Authority> authorities = new HashSet<>(dto.getAuthorities());
// roleAuthService.saveBatch(authorities.stream().map(authority -> new RoleAuthority(id, authority.getId())).collect(Collectors.toList()));
}
return updateById(role);
}
@Override
public Boolean edit(RoleDto dto, Long id) {
boolean existsByName = count(new LambdaQueryWrapper<Role>().ne(Role::getId, id).eq(Role::getName, dto.getName())) > 0;
if (existsByName) {
throw new ConstraintException("name", dto.name, "同名角色已存在");
Role existingRole = getById(id);
if (existingRole == null) {
throw new ConstraintException("id", id.toString(), "角色不存在");
}
if (!Objects.equals(existingRole.getName(), dto.getName()) &&
count(new LambdaQueryWrapper<Role>().eq(Role::getName, dto.getName())) > 0) {
throw new ConstraintException("name", dto.getName(), "同名角色已存在");
}
mapper.convert(dto, existingRole);
roleAuthService.remove(new LambdaQueryWrapper<RoleAuthority>().eq(RoleAuthority::getRoleId, id));
// saveRoleAuths(id, dto.getAuthorities());
return update(dto.updateWrapper(id));
saveRoleAuths(id, dto.getAuthorities());
return updateById(existingRole);
}
@Override
public RoleVo detail(Long id) {
// Role role = getById(id);
@ -110,7 +103,10 @@ public class RoleServiceImpl extends ServiceImpl<RoleRepository, Role> implement
@Override
public Boolean saveRoleAuths(Long roleId, Set<AuthorityCreateDto> authorities) {
// 保存角色关联权限
List<RoleAuthority> roleAuthorities = authorities.stream().map(authority -> new RoleAuthority(roleId, authorityRepository.getAuthorityIdByName(authority.getName()))).collect(Collectors.toList());
List<RoleAuthority> roleAuthorities = authorities.stream()
.map(authority ->
new RoleAuthority(roleId, authorityRepository.getAuthorityIdByName(authority.getName())))
.collect(Collectors.toList());
return roleAuthService.saveBatch(roleAuthorities);
}
}

View File

@ -62,7 +62,7 @@ public class UserServiceImpl extends ServiceImpl<UserRepository, User> implement
public Boolean updatePassword(String password, Long id) {
User user = getById(id);
user.setPassword(passwordEncoder.encode(password));
return save(user);
return updateById(user);
}
@Override

View File

@ -544,7 +544,7 @@ VALUES (1, 1, 1, 'prop1', 'Property 1', 'This is property 1'),
(9, 1, 1, 'prop9', 'Property 9', 'This is property 9'),
(10, 2, 2, 'prop10', 'Property 10', 'This is property 10');
INSERT INTO iot_serve (product_id, identifier, name, remark)
INSERT INTO iot_serve (id, product_id, identifier, name, remark)
VALUES (1, 'serve1', 'Service 1', 'This is service 1'),
(2, 'serve2', 'Service 2', 'This is service 2'),
(3, 'serve3', 'Service 3', 'This is service 3'),
@ -640,4 +640,77 @@ VALUES (1, TRUE, TRUE, FALSE, TRUE, '测试消息1', '这是第一条测试消
9),
(2, FALSE, FALSE, FALSE, TRUE, '测试消息10', '这是第十条测试消息的内容。', '备注10', NOW(), 'user5', NOW(),
'user5', 10);
-- V2__Alter_sys_user_id_to_bigserial.sql
-- 备份现有数据
CREATE TABLE sys_user_backup AS
SELECT *
FROM sys_user;
-- 删除现有表
DROP TABLE IF EXISTS sys_user;
-- 重新创建表
CREATE TABLE sys_user
(
id bigserial not null
constraint _copy_3
primary key,
dept_id bigint,
role_id bigint,
username varchar(20) not null,
password varchar not null,
phone varchar(11),
email varchar(40),
name varchar(255),
avatar varchar(255),
address varchar(255),
create_by varchar(255),
update_by varchar(255),
create_time timestamp(6),
update_time timestamp(6),
remark varchar(255),
enable_state varchar(5)
);
comment on column sys_user.dept_id is '部门id';
comment on column sys_user.role_id is '角色id';
comment on column sys_user.username is '用户名';
comment on column sys_user.password is '密码';
comment on column sys_user.phone is '手机号码';
comment on column sys_user.email is '电子邮箱';
comment on column sys_user.name is '昵称';
comment on column sys_user.avatar is '头像';
comment on column sys_user.address is '地址';
comment on column sys_user.create_by is '创建者';
comment on column sys_user.update_by is '更新者';
comment on column sys_user.enable_state is '状态';
alter table sys_user
owner to gitea;
-- 插入备份的数据
INSERT INTO sys_user (dept_id, role_id, username, password, phone, email, name, avatar, address, create_by, update_by,
create_time, update_time, remark, enable_state)
SELECT dept_id,
role_id,
username,
password,
phone,
email,
name,
avatar,
address,
create_by,
update_by,
create_time,
update_time,
remark,
enable_state
FROM sys_user_backup;
-- 删除备份表
DROP TABLE sys_user_backup;
ALTER TABLE iot_property
ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY;

View File

@ -1,6 +1,6 @@
create table iot_device
(
id serial not null
id bigserial not null
constraint _name_pk
primary key,
name varchar,

View File

@ -7,7 +7,8 @@ create table iot_event
type integer,
identifier varchar,
name varchar,
remark varchar
remark varchar,
dept_id bigint
);
comment on table iot_event is '物模型服务';
@ -24,6 +25,8 @@ comment on column iot_event.name is '名称';
comment on column iot_event.remark is '备注';
comment on column iot_event.dept_id is '部门权限id';
alter table iot_event
owner to gitea;

View File

@ -1,18 +1,18 @@
create table iot_product
(
id bigserial not null
id bigserial not null
constraint iot_product_pk
primary key,
name varchar,
type_string varchar,
model varchar,
link integer,
create_by varchar,
create_time timestamp,
update_by varchar,
update_time timestamp,
remark varchar,
dept_id bigint
name varchar,
product_type varchar,
model varchar,
link integer,
create_by varchar,
create_time timestamp,
update_by varchar,
update_time timestamp,
remark varchar,
dept_id bigint
);
comment on table iot_product is '产品表';
@ -21,7 +21,7 @@ comment on column iot_product.id is '主键';
comment on column iot_product.name is '产品名称';
comment on column iot_product.type_string is '产品类型';
comment on column iot_product.product_type is '产品类型';
comment on column iot_product.model is '产品型号';

View File

@ -1,6 +1,6 @@
create table iot_property
(
id bigserial not null
id bigint not null
constraint iot_property_pk
primary key,
product_id bigint,

View File

@ -0,0 +1,26 @@
create table iot_record_data
(
id serial not null
constraint iot_record_data_pk
primary key,
client_id varchar,
attachment_id varchar,
content varchar,
record_time timestamp
);
comment on table iot_record_data is '上报数据表';
comment on column iot_record_data.id is '主键';
comment on column iot_record_data.client_id is '委托人ID';
comment on column iot_record_data.attachment_id is '附件ID ';
comment on column iot_record_data.content is '内容';
comment on column iot_record_data.record_time is '记录时间';
alter table iot_record_data
owner to gitea;

View File

@ -6,7 +6,8 @@ create table iot_serve
product_id bigint,
identifier varchar,
name varchar,
remark varchar
remark varchar,
dept_id bigint
);
comment on table iot_serve is '物模型服务';
@ -21,6 +22,8 @@ comment on column iot_serve.name is '名称';
comment on column iot_serve.remark is '备注';
comment on column iot_serve.dept_id is '部门权限id';
alter table iot_serve
owner to gitea;

View File

@ -1,11 +1,12 @@
create table sys_message
(
id serial primary key,
id bigserial not null
primary key,
type integer not null,
system boolean not null,
email boolean not null,
sms boolean not null,
html boolean not null,
email boolean,
sms boolean,
html boolean,
title varchar,
content varchar,
remark varchar,

View File

@ -0,0 +1,68 @@
create table sys_user
(
dept_id bigint,
role_id bigint,
username varchar(20) not null,
password varchar not null,
phone varchar(11),
email varchar(40),
name varchar(255),
avatar varchar(255),
address varchar(255),
create_by varchar(255),
update_by varchar(255),
create_time timestamp(6),
update_time timestamp(6),
remark varchar(255),
enable_state varchar(5),
id bigint not null
primary key
);
comment
on column sys_user.dept_id is '部门id';
comment
on column sys_user.role_id is '角色id';
comment
on column sys_user.username is '用户名';
comment
on column sys_user.password is '密码';
comment
on column sys_user.phone is '手机号码';
comment
on column sys_user.email is '电子邮箱';
comment
on column sys_user.name is '昵称';
comment
on column sys_user.avatar is '头像';
comment
on column sys_user.address is '地址';
comment
on column sys_user.create_by is '创建者';
comment
on column sys_user.update_by is '更新者';
comment
on column sys_user.enable_state is '状态';
alter table sys_user
owner to gitea;
_user
.
enable_state
is '状态';
alter table sys_user
owner to gitea;

View File

@ -13,8 +13,10 @@
<result column="factory_id" property="factoryId"/>
<result column="client_id" property="clientId"/>
<result column="product_id" property="productId"/>
<result column="extend_params" property="extendParams"/>
<result column="properties" property="properties"/>
<result column="extend_params" property="extendParams"
typeHandler="com.zsc.edu.gateway.framework.json.MapJsonTypeHandler"/>
<result column="properties" property="properties"
typeHandler="com.zsc.edu.gateway.framework.json.MapJsonTypeHandler"/>
<result column="create_by" jdbcType="VARCHAR" property="deviceCreateBy"/>
<result column="update_by" jdbcType="VARCHAR" property="deviceUpdateBy"/>
<result column="create_time" jdbcType="DATE" property="deviceCreateTime"/>
@ -53,8 +55,7 @@
ip.remark as param_remark
from iot_device d
left join iot_product p on d.product_id = p.id
left join iot_product_param pp on pp.product_id = p.id
left join iot_param ip on pp.param_id = ip.id
left join iot_param ip on p.id = ip.foreign_id and ip.foreign_type = 3
where d.id = #{id}
</select>

View File

@ -7,7 +7,7 @@
<id column="id" property="id"/>
<result column="dept_id" property="deptId"/>
<result column="name" property="name"/>
<result column="type_string" property="productType"/>
<result column="product_type" property="productType"/>
<result column="model" property="model"/>
<result column="link" property="link"/>
<result column="create_by" jdbcType="VARCHAR" property="createBy"/>

View File

@ -42,8 +42,8 @@
left join sys_user su on sum.user_id = su.id
left join sys_message sm on sm.id = sum.message_id
<where>
sm.id=#{messageId}
and su.id=#{userId}
sum.message_id=#{messageId}
and sum.user_id=#{userId}
</where>
</select>