feat(iot): 优化设备管理功能
- 添加附件预览功能 - 修复设备列表查询条件 - 优化产品和设备控制器 - 调整 WebSocket连接逻辑
This commit is contained in:
parent
182d4c7961
commit
790aed76ea
1
pom.xml
1
pom.xml
@ -145,7 +145,6 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
<version>3.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
@ -26,16 +26,14 @@ public class WebSocketInterceptor implements HandshakeInterceptor {
|
||||
private ProductService productService;
|
||||
|
||||
@Override
|
||||
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
|
||||
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {
|
||||
if (request instanceof ServletServerHttpRequest) {
|
||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||
// 获取路径变量
|
||||
// 获取完整路径
|
||||
String path = servletRequest.getRequestURI();
|
||||
String[] pathParts = path.split("/");
|
||||
String pathVariable = pathParts[pathParts.length - 1];
|
||||
|
||||
// 根据路径变量设置不同的业务逻辑 Supplier
|
||||
switch (pathVariable) {
|
||||
// 根据路径设置不同的业务逻辑 Supplier
|
||||
switch (path) {
|
||||
case "/api/rest/device/ws/device/status":
|
||||
attributes.put("dataSupplier", (Supplier<String>) () -> String.valueOf(deviceService.status()));
|
||||
break;
|
||||
@ -46,7 +44,7 @@ public class WebSocketInterceptor implements HandshakeInterceptor {
|
||||
attributes.put("dataSupplier", (Supplier<String>) () -> String.valueOf(productService.status()));
|
||||
break;
|
||||
default:
|
||||
attributes.put("dataSupplier", (Supplier<String>) () -> "Unknown path: " + pathVariable);
|
||||
attributes.put("dataSupplier", (Supplier<String>) () -> "Unknown path: " + path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.zsc.edu.gateway.modules.attachment.controller;
|
||||
|
||||
import com.zsc.edu.gateway.exception.StorageException;
|
||||
import com.zsc.edu.gateway.framework.storage.exception.StorageFileNotFoundException;
|
||||
import com.zsc.edu.gateway.modules.attachment.entity.Attachment;
|
||||
import com.zsc.edu.gateway.modules.attachment.service.AttachmentService;
|
||||
import com.zsc.edu.gateway.modules.operationLog.entity.OperationLogAnnotation;
|
||||
@ -8,6 +9,7 @@ import lombok.AllArgsConstructor;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.ContentDisposition;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.parameters.P;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -73,6 +75,43 @@ public class AttachmentController {
|
||||
}
|
||||
return ResponseEntity.ok(wrapper.resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览附件
|
||||
*
|
||||
* @param id 附件ID
|
||||
* @return 附件文件内容(直接预览)
|
||||
*/
|
||||
@GetMapping("/preview/{id}")
|
||||
public ResponseEntity<?> preview(
|
||||
@PathVariable("id") String id
|
||||
) {
|
||||
try {
|
||||
Attachment.Wrapper wrapper = service.loadAsWrapper(id);
|
||||
String mimeType = wrapper.attachment.mimeType;
|
||||
|
||||
// 如果是图片或 PDF,直接返回文件流
|
||||
if (mimeType.startsWith("image/") || mimeType.equals("application/pdf")) {
|
||||
ContentDisposition contentDisposition = ContentDisposition.builder("inline")
|
||||
.filename(wrapper.attachment.fileName, StandardCharsets.UTF_8)
|
||||
.build();
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString())
|
||||
.header(HttpHeaders.CONTENT_TYPE, mimeType)
|
||||
.body(wrapper.resource);
|
||||
} else {
|
||||
// 如果是文本文件,直接返回文本内容
|
||||
String content = new String(wrapper.resource.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
|
||||
return ResponseEntity.ok(content);
|
||||
}
|
||||
} catch (StorageFileNotFoundException e) {
|
||||
return ResponseEntity.notFound().build();
|
||||
} catch (IOException e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件读取失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据附件ID获取附件信息
|
||||
* */
|
||||
|
@ -4,7 +4,6 @@ import com.alibaba.fastjson2.JSONException;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.zsc.edu.gateway.framework.message.sse.SseConfig;
|
||||
import com.zsc.edu.gateway.framework.mybatisplus.DataPermission;
|
||||
import com.zsc.edu.gateway.modules.iot.device.dto.BatchDeviceDto;
|
||||
import com.zsc.edu.gateway.modules.iot.device.dto.DeviceDto;
|
||||
@ -38,8 +37,6 @@ public class DeviceController {
|
||||
DeviceService service;
|
||||
|
||||
RecordDataService recordService;
|
||||
@Resource
|
||||
private SseConfig sseConfig;
|
||||
|
||||
/**
|
||||
* 创建设备
|
||||
|
@ -64,4 +64,5 @@ public class DeviceDto {
|
||||
*/
|
||||
public String previewId;
|
||||
|
||||
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ public class Device extends BaseEntity {
|
||||
* 设备预览图附件ID
|
||||
*/
|
||||
public String previewId;
|
||||
|
||||
//TODO 设备运行状态
|
||||
|
||||
public enum Status implements IEnum<Integer>, IState<Status> {
|
||||
UNACTIVATED(0, "未激活"),
|
||||
|
@ -43,10 +43,7 @@ public class DeviceQuery {
|
||||
* 设态是否在线
|
||||
*/
|
||||
public Boolean isOnline;
|
||||
/**
|
||||
* 产品名称
|
||||
*/
|
||||
public String productName;
|
||||
|
||||
|
||||
public LambdaQueryWrapper<Device> wrapper() {
|
||||
LambdaQueryWrapper<Device> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
@ -32,4 +32,6 @@ public interface DeviceRepository extends BaseMapper<Device> {
|
||||
Device findByClientId(@Param("clientId") String clientId);
|
||||
|
||||
List<Device> selectListByName(@Param("name") String name);
|
||||
|
||||
IPage<Device> selectPageByConditions(Page<Device> page, @Param("query") DeviceQuery query);
|
||||
}
|
||||
|
@ -172,9 +172,10 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceRepository, Device> imp
|
||||
/**
|
||||
* 查询设备列表
|
||||
*/
|
||||
//TODO 解决分页条件问题
|
||||
@Override
|
||||
public IPage<Device> query(Page<Device> page, DeviceQuery query) {
|
||||
return deviceRepo.selectPage(page, query.wrapper());
|
||||
return baseMapper.selectPageByConditions(page, query);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,7 +126,6 @@ public class DeviceVo {
|
||||
*/
|
||||
public Attachment preview;
|
||||
|
||||
|
||||
/**
|
||||
* 所属产品ID
|
||||
*/
|
||||
|
@ -1,14 +1,12 @@
|
||||
package com.zsc.edu.gateway.modules.iot.product.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.zsc.edu.gateway.framework.message.sse.SseConfig;
|
||||
import com.zsc.edu.gateway.framework.mybatisplus.DataPermission;
|
||||
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.query.ProductQuery;
|
||||
import com.zsc.edu.gateway.modules.iot.product.service.ProductService;
|
||||
import com.zsc.edu.gateway.modules.operationLog.entity.OperationLogAnnotation;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -25,8 +23,6 @@ public class ProductController {
|
||||
|
||||
private final ProductService service;
|
||||
|
||||
@Resource
|
||||
SseConfig sseConfig;
|
||||
|
||||
/**
|
||||
* 创建产品
|
||||
|
@ -82,10 +82,27 @@
|
||||
where d.id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectList" resultType="com.zsc.edu.gateway.modules.iot.device.entity.Device">
|
||||
SELECT d.*, p.name AS productName
|
||||
<select id="selectPageByConditions" resultType="com.zsc.edu.gateway.modules.iot.device.entity.Device">
|
||||
SELECT d.*, p.*
|
||||
FROM iot_device d
|
||||
LEFT JOIN iot_product p ON d.product_id = p.id
|
||||
<where>
|
||||
<if test="query.name != null and query.name != ''">
|
||||
AND d.name LIKE concat('%', #{query.name}, '%')
|
||||
</if>
|
||||
<if test="query.clientId != null and query.clientId != ''">
|
||||
AND d.client_id = #{query.clientId}
|
||||
</if>
|
||||
<if test="query.state != null and query.state != ''">
|
||||
AND d.state = #{query.state}
|
||||
</if>
|
||||
<if test="query.isOnline != null and query.isOnline != ''">
|
||||
AND d.online = #{query.isOnline}
|
||||
</if>
|
||||
<if test="query.productId != null and query.productId != ''">
|
||||
AND d.product_id = #{query.productId}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectListByName" resultMap="BaseResultMap">
|
||||
@ -105,6 +122,8 @@
|
||||
left join iot_param ip on p.id = ip.foreign_id and ip.foreign_type = 3
|
||||
left join attachment ai on d.icon_id = ai.id
|
||||
left join attachment ap on d.preview_id = ap.id
|
||||
<if test="name != null">
|
||||
WHERE d.name LIKE concat('%', #{name}, '%')
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
Loading…
Reference in New Issue
Block a user