14 Commits

Author SHA1 Message Date
a7340c744e APP客户设备绑定-绑定时间 2025-07-19 14:22:36 +08:00
3feafc2cd9 删除设备类型 2025-07-19 10:20:07 +08:00
f2921ff12f 分页查询设备-设备类型 2025-07-19 09:17:14 +08:00
ec89dd8c1e 新增设备 校验 2025-07-18 18:12:36 +08:00
57322c9c87 蓝牙名称 2025-07-18 17:57:58 +08:00
7d91426414 Merge branch 'dyf-device' 2025-07-18 15:17:18 +08:00
ad06811747 撤回设备 2025-07-18 15:06:39 +08:00
dyf
aeaa906bc9 Merge pull request 'feat(fys-demo): 添加视频上传和处理功能' (#5) from liwenlong/fys-Multi-tenant:jingquan into main
Reviewed-on: #5
2025-07-18 14:03:18 +08:00
36092932bf feat(fys-demo): 添加视频上传和处理功能
- 新增 VideoUploadController 控制器处理视频上传
- 添加视频帧提取和转换为 RGB565 格式功能
- 实现视频文件大小和格式校验
- 优化临时文件创建和清理逻辑
- 引入 javacv-platform依赖进行视频处理
2025-07-18 13:27:26 +08:00
34188f20dd 帐号状态(0正常 1停用) 2025-07-18 11:18:30 +08:00
78e2538f71 Merge branch 'dyf-device' 2025-07-17 16:41:08 +08:00
171eeabea1 Merge branch 'dyf-device' 2025-07-17 09:24:10 +08:00
7be94fe1d2 产品参数bug修改 2025-07-15 15:59:32 +08:00
530ee83488 新增绑定时间字段 2025-07-14 14:23:17 +08:00
14 changed files with 377 additions and 95 deletions

View File

@ -6,15 +6,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="queryAppFileList" resultType="com.fuyuanshen.app.domain.vo.AppFileVo"> <select id="queryAppFileList" resultType="com.fuyuanshen.app.domain.vo.AppFileVo">
select a.id,a.business_id,a.file_id,b.file_name,b.url fileUrl from app_business_file a left join sys_oss b on a.file_id = b.oss_id select a.id,a.business_id,a.file_id,b.file_name,b.url fileUrl from app_business_file a left join sys_oss b on a.file_id = b.oss_id
where where 1=1
<if test="businessId != null"> <if test="businessId != null">
and a.business_id = #{businessId} and a.business_id = #{businessId}
</if> </if>
<if test="fileId != null"> <if test="fileId != null">
and a.file_id = #{fileId} and a.file_id = #{fileId}
</if> </if>
<if test="fileType != null">
and a.file_type = #{fileType}
</if>
<if test="createBy != null"> <if test="createBy != null">
a.create_by = #{createBy} and a.create_by = #{createBy}
</if> </if>
order by a.create_time desc order by a.create_time desc
</select> </select>

View File

@ -50,6 +50,12 @@ public class UserQueryCriteria extends BaseEntity {
@Schema(name = "是否启用") @Schema(name = "是否启用")
private Boolean enabled; private Boolean enabled;
/**
* 帐号状态0正常 1停用
*/
@Schema(name = "帐号状态0正常 1停用")
private String status;
@Schema(name = "部门ID") @Schema(name = "部门ID")
private Long deptId; private Long deptId;

View File

@ -68,8 +68,8 @@
<if test="criteria.id != null"> <if test="criteria.id != null">
and u1.user_id = #{criteria.id} and u1.user_id = #{criteria.id}
</if> </if>
<if test="criteria.enabled != null"> <if test="criteria.status != null">
and u1.enabled = #{criteria.enabled} and u.status = #{criteria.status}
</if> </if>
<if test="criteria.deptIds != null and criteria.deptIds.size() != 0"> <if test="criteria.deptIds != null and criteria.deptIds.size() != 0">
and u1.dept_id in and u1.dept_id in
@ -109,8 +109,8 @@
<if test="criteria.blurry != null and criteria.blurry.trim() != ''"> <if test="criteria.blurry != null and criteria.blurry.trim() != ''">
and u.nick_name like concat('%', TRIM(#{criteria.blurry}), '%') and u.nick_name like concat('%', TRIM(#{criteria.blurry}), '%')
</if> </if>
<if test="criteria.enabled != null"> <if test="criteria.status != null">
and u.enabled = #{criteria.enabled} and u.status = #{criteria.status}
</if> </if>
<if test="criteria.params.beginTime != null and criteria.params.endTime != null"> <if test="criteria.params.beginTime != null and criteria.params.endTime != null">
and u.create_time between #{criteria.params.beginTime} and #{criteria.params.endTime} and u.create_time between #{criteria.params.beginTime} and #{criteria.params.endTime}
@ -139,8 +139,8 @@
<if test="criteria.blurry != null and criteria.blurry.trim() != ''"> <if test="criteria.blurry != null and criteria.blurry.trim() != ''">
and u.nick_name like concat('%', TRIM(#{criteria.blurry}), '%') and u.nick_name like concat('%', TRIM(#{criteria.blurry}), '%')
</if> </if>
<if test="criteria.enabled != null"> <if test="criteria.status != null">
and u.enabled = #{criteria.enabled} and u.status = #{criteria.status}
</if> </if>
<if test="criteria.params.beginTime != null and criteria.params.endTime != null"> <if test="criteria.params.beginTime != null and criteria.params.endTime != null">
and u.create_time between #{criteria.params.beginTime} and #{criteria.params.endTime} and u.create_time between #{criteria.params.beginTime} and #{criteria.params.endTime}

View File

@ -103,6 +103,11 @@
<artifactId>fys-common-websocket</artifactId> <artifactId>fys-common-websocket</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,244 @@
package com.fuyuanshen.demo.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.fuyuanshen.common.core.domain.R;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.file.Files;
import java.util.Base64;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameUtils;
import org.springframework.http.ResponseEntity;
@RestController
@RequestMapping("/video")
public class VideoUploadController {
// 可配置项:建议从 application.yml 中读取
private static final int MAX_VIDEO_SIZE = 10 * 1024 * 1024; // 10 MB
private static final int FRAME_RATE = 15; // 每秒抽15帧
private static final int DURATION = 2; // 抽2秒
private static final int TOTAL_FRAMES = FRAME_RATE * DURATION;
private static final int WIDTH = 160;
private static final int HEIGHT = 80;
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@SaIgnore
public R<List<String>> upload(@RequestParam("file") MultipartFile file) {
if (file == null || file.isEmpty()) {
return R.fail("上传文件不能为空");
}
if (!isVideo(file.getOriginalFilename())) {
return R.fail("只允许上传视频文件");
}
if (file.getSize() > MAX_VIDEO_SIZE) {
return R.fail("视频大小不能超过10MB");
}
File tempFile = null;
try {
// 创建临时文件保存上传的视频
tempFile = createTempVideoFile(file);
List<BufferedImage> frames = extractFramesFromVideo(tempFile);
if (frames.isEmpty()) {
return R.fail("无法提取任何帧");
}
// ✅ 新增:保存帧为图片
//saveFramesToLocal(frames, "extracted_frame");
byte[] binaryData = convertFramesToRGB565(frames);
// String base64Data = Base64.getEncoder().encodeToString(binaryData);
//
// return R.ok(base64Data);
// 构造响应头
// 将二进制数据转为 Hex 字符串
// 转换为 Hex 字符串列表
List<String> hexList = bytesToHexList(binaryData);
return R.ok(hexList);
} catch (Exception e) {
return R.fail("视频处理失败:" + e.getMessage());
} finally {
deleteTempFile(tempFile);
}
}
/**
* rgb565 转 hex
*/
private List<String> bytesToHexList(byte[] bytes) {
List<String> hexList = new ArrayList<>();
for (byte b : bytes) {
int value = b & 0xFF;
char high = HEX_ARRAY[value >>> 4];
char low = HEX_ARRAY[value & 0x0F];
hexList.add(String.valueOf(high) + low);
}
return hexList;
}
/**
* 创建临时文件并保存上传的视频
*/
private File createTempVideoFile(MultipartFile file) throws Exception {
File tempFile = Files.createTempFile("upload-", ".mp4").toFile();
file.transferTo(tempFile);
return tempFile;
}
/**
* 从视频中按时间均匀提取指定数量的帧
*/
private List<BufferedImage> extractFramesFromVideo(File videoFile) throws Exception {
List<BufferedImage> frames = new ArrayList<>();
try (FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(videoFile)) {
grabber.start();
// 获取视频总帧数和帧率
long totalFramesInVideo = grabber.getLengthInFrames();
int fps = (int) Math.round(grabber.getFrameRate());
if (fps <= 0) fps = 30;
double durationSeconds = (double) totalFramesInVideo / fps;
if (durationSeconds < DURATION) {
throw new IllegalArgumentException("视频太短,至少需要 " + DURATION + "");
}
// 计算每帧之间的间隔(浮点以实现更精确跳转)
double frameInterval = (double) totalFramesInVideo / TOTAL_FRAMES;
for (int i = 0; i < TOTAL_FRAMES; i++) {
int targetFrameNumber = (int) Math.round(i * frameInterval);
// 避免设置无效帧号
if (targetFrameNumber >= totalFramesInVideo) {
throw new IllegalArgumentException("目标帧超出范围: " + targetFrameNumber + " ");
}
grabber.setFrameNumber(targetFrameNumber);
Frame frame = grabber.grab();
if (frame != null && frame.image != null) {
BufferedImage bufferedImage = Java2DFrameUtils.toBufferedImage(frame);
frames.add(cropImage(bufferedImage, WIDTH, HEIGHT));
} else {
throw new IllegalArgumentException("无法获取第 " + targetFrameNumber + "");
}
}
grabber.stop();
}
return frames;
}
/**
* 将抽取的帧保存到本地,用于调试
*/
private void saveFramesToLocal(List<BufferedImage> frames, String prefix) {
// 指定输出目录
File outputDir = new File("output_frames");
if (!outputDir.exists()) {
outputDir.mkdirs();
}
int index = 0;
for (BufferedImage frame : frames) {
try {
File outputImage = new File(outputDir, prefix + "_" + (index++) + ".png");
ImageIO.write(frame, "png", outputImage);
System.out.println("保存帧图片成功: " + outputImage.getAbsolutePath());
} catch (Exception e) {
throw new IllegalArgumentException("保存帧图片失败 " + e);
}
}
}
/**
* 将所有帧转换为 RGB565 格式字节数组
*/
private byte[] convertFramesToRGB565(List<BufferedImage> frames) throws Exception {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
for (BufferedImage image : frames) {
byte[] rgb565Bytes = convertToRGB565(image);
byteArrayOutputStream.write(rgb565Bytes);
}
return byteArrayOutputStream.toByteArray();
}
/**
* 判断是否是支持的视频格式
*/
private boolean isVideo(String filename) {
String ext = filename.substring(filename.lastIndexOf('.')).toLowerCase();
return Arrays.asList(".mp4", ".avi", ".mov", ".mkv").contains(ext);
}
/**
* 裁剪图像到目标尺寸
*/
private BufferedImage cropImage(BufferedImage img, int targetWidth, int targetHeight) {
int w = Math.min(img.getWidth(), targetWidth);
int h = Math.min(img.getHeight(), targetHeight);
return img.getSubimage(0, 0, w, h);
}
/**
* 将 BufferedImage 转换为 RGB565 格式的字节数组
*/
private byte[] convertToRGB565(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
byte[] result = new byte[width * height * 2]; // RGB565: 2 bytes per pixel
int index = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int rgb = image.getRGB(x, y);
int r = ((rgb >> 16) & 0xFF) >> 3;
int g = ((rgb >> 8) & 0xFF) >> 2;
int b = (rgb & 0xFF) >> 3;
short pixel = (short) ((r << 11) | (g << 5) | b);
result[index++] = (byte) (pixel >> 8); // High byte first
result[index++] = (byte) pixel;
}
}
return result;
}
/**
* 删除临时文件
*/
private void deleteTempFile(File file) {
if (file != null && file.exists()) {
if (!file.delete()) {
throw new IllegalArgumentException("无法删除临时文件: " + file.getAbsolutePath());
}
}
}
}

View File

@ -9,6 +9,8 @@ import com.fuyuanshen.common.tenant.core.TenantEntity;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.util.Date;
/** /**
* @Description: 设备表 * @Description: 设备表
* @Author: WY * @Author: WY
@ -19,6 +21,9 @@ import lombok.Data;
@JsonInclude(JsonInclude.Include.ALWAYS) // 关键注解 @JsonInclude(JsonInclude.Include.ALWAYS) // 关键注解
public class Device extends TenantEntity { public class Device extends TenantEntity {
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
@Schema(name = "ID") @Schema(name = "ID")
private Long id; private Long id;
@ -27,6 +32,9 @@ public class Device extends TenantEntity {
@TableField(exist = false) @TableField(exist = false)
private Long assignId; private Long assignId;
/**
* device_type
*/
@Schema(name = "设备类型") @Schema(name = "设备类型")
private Long deviceType; private Long deviceType;
@ -98,8 +106,6 @@ public class Device extends TenantEntity {
private Integer deviceStatus; private Integer deviceStatus;
/** /**
* 绑定状态 * 绑定状态
* 0 未绑定 * 0 未绑定
@ -114,4 +120,9 @@ public class Device extends TenantEntity {
private String createByName; private String createByName;
private Long bindingUserId; private Long bindingUserId;
/**
* 绑定时间
*/
private Date bindingTime;
} }

View File

@ -25,6 +25,7 @@ public class DeviceAssignments extends TenantEntity {
/** /**
* 设备id * 设备id
* device_id
*/ */
private Long deviceId; private Long deviceId;
@ -34,7 +35,7 @@ public class DeviceAssignments extends TenantEntity {
private Long fromCustomerId; private Long fromCustomerId;
/** /**
* 接收方 * 接收方(当前设备所处位置)
*/ */
private Long toCustomerId; private Long toCustomerId;

View File

@ -58,7 +58,9 @@ public class DeviceExcelImportDTO {
private String remark; private String remark;
@ExcelProperty("设备类型名称") @ExcelProperty("设备类型名称")
@ColumnWidth(20)
private String typeName; private String typeName;
@ExcelProperty("蓝牙名称")
private String bluetoothName;
} }

View File

@ -1,10 +1,12 @@
package com.fuyuanshen.equipment.domain.vo; package com.fuyuanshen.equipment.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data @Data
public class AppDeviceVo { public class AppDeviceVo implements Serializable {
private Long id; private Long id;
@ -49,4 +51,10 @@ public class AppDeviceVo {
* 1 正常 * 1 正常
*/ */
private Integer deviceStatus; private Integer deviceStatus;
/**
* 绑定时间
*/
private Date bindingTime;
} }

View File

@ -85,6 +85,14 @@ public interface DeviceService extends IService<Device> {
*/ */
void unbindDevice(DeviceForm deviceForm); void unbindDevice(DeviceForm deviceForm);
/**
* WEB端查看APP客户设备绑定
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<AppDeviceVo> queryAppDeviceList(DeviceQueryCriteria bo, PageQuery pageQuery); TableDataInfo<AppDeviceVo> queryAppDeviceList(DeviceQueryCriteria bo, PageQuery pageQuery);
int bindDevice(AppDeviceBo bo); int bindDevice(AppDeviceBo bo);

View File

@ -100,6 +100,12 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
public TableDataInfo<Device> queryAll(DeviceQueryCriteria criteria, Page<Device> page) throws IOException { public TableDataInfo<Device> queryAll(DeviceQueryCriteria criteria, Page<Device> page) throws IOException {
criteria.setCurrentOwnerId(LoginHelper.getUserId()); criteria.setCurrentOwnerId(LoginHelper.getUserId());
if (criteria.getDeviceType() != null) {
DeviceTypeGrants deviceTypeGrant = deviceTypeGrantsMapper.selectById(criteria.getDeviceType());
if (deviceTypeGrant != null) {
criteria.setDeviceType(deviceTypeGrant.getDeviceTypeId());
}
}
IPage<Device> devices = deviceMapper.findAll(criteria, page); IPage<Device> devices = deviceMapper.findAll(criteria, page);
List<Device> records = devices.getRecords(); List<Device> records = devices.getRecords();
@ -141,6 +147,16 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void addDevice(DeviceForm deviceForm) throws Exception { public void addDevice(DeviceForm deviceForm) throws Exception {
Device device1 = deviceMapper.selectOne(new QueryWrapper<Device>().eq("device_mac", deviceForm.getDeviceMac()));
if (device1 != null) {
throw new BadRequestException("设备MAC已存在");
}
Device device2 = deviceMapper.selectOne(new QueryWrapper<Device>().eq("device_imei", deviceForm.getDeviceImei()));
if (device2 != null) {
throw new BadRequestException("设备IMEI已存在");
}
DeviceTypeQueryCriteria queryCriteria = new DeviceTypeQueryCriteria(); DeviceTypeQueryCriteria queryCriteria = new DeviceTypeQueryCriteria();
queryCriteria.setDeviceTypeId(deviceForm.getDeviceType()); queryCriteria.setDeviceTypeId(deviceForm.getDeviceType());
queryCriteria.setCustomerId(LoginHelper.getUserId()); queryCriteria.setCustomerId(LoginHelper.getUserId());
@ -319,9 +335,9 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
List<DeviceTypeGrants> deviceTypeGrants = new ArrayList<>(); List<DeviceTypeGrants> deviceTypeGrants = new ArrayList<>();
for (DeviceAssignments assignment : assignments) { for (DeviceAssignments assignment : assignments) {
if (assignment.getToCustomerId() != null) { if (assignment.getToCustomerId() != null && assignment.getToCustomerId() != 0L) {
log.info("设备已经分配客户!!!"); log.info("设备已经分配客户!!!");
continue; throw new RuntimeException("设备已经分配客户!!!");
} }
Device device = deviceMapper.selectById(assignment.getDeviceId()); Device device = deviceMapper.selectById(assignment.getDeviceId());
@ -412,54 +428,6 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
} }
/**
* 撤回设备
*
* @param ids
*/
// @Override
// public void withdrawDevice(List<Long> ids) {
// ids.forEach((id) -> {
// List<Device> deviceChain = getDeviceChain(id);
// deviceChain.forEach((device) -> {
// device.setDeviceStatus(DeviceStatusEnum.INVALID.getCode());
// deviceMapper.updateById(device);
// });
// });
//
// ids.forEach((id) -> {
// Device device = new Device();
// device.setId(id);
// device.setCustomerId(null);
// device.setCustomerName("");
// deviceMapper.updateById(device);
// });
//
// }
//
//
// public List<Device> getDeviceChain(Long originalDeviceId) {
// List<Device> chain = new ArrayList<>();
// Set<Long> visited = new HashSet<>(); // 防止循环引用
// findNext(chain, visited, originalDeviceId);
// return chain;
// }
//
// private void findNext(List<Device> chain, Set<Long> visited, Long currentOriginalDeviceId) {
// if (visited.contains(currentOriginalDeviceId)) {
// log.info("检测到循环引用,终止递归");
// return;
// }
// visited.add(currentOriginalDeviceId);
//
// List<Device> devices = deviceMapper.findByOriginalDeviceId(currentOriginalDeviceId);
// for (Device device : devices) {
// chain.add(device);
// findNext(chain, visited, device.getId());
// }
// }
/** /**
* 撤回设备 * 撤回设备
* *
@ -474,7 +442,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
Device device = deviceMapper.selectById(assignment.getDeviceId()); Device device = deviceMapper.selectById(assignment.getDeviceId());
// 接收者 // 接收者
assignment.setAssigneeName(""); assignment.setAssigneeName("");
assignment.setToCustomerId(null); assignment.setToCustomerId(0L);
deviceAssignmentsMapper.updateById(assignment); deviceAssignmentsMapper.updateById(assignment);
// 获取所有已分配的设备 // 获取所有已分配的设备
@ -502,7 +470,13 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
} }
/**
* WEB端查看APP客户设备绑定
*
* @param bo
* @param pageQuery
* @return
*/
@Override @Override
public TableDataInfo<AppDeviceVo> queryAppDeviceList(DeviceQueryCriteria bo, PageQuery pageQuery) { public TableDataInfo<AppDeviceVo> queryAppDeviceList(DeviceQueryCriteria bo, PageQuery pageQuery) {
if (bo.getBindingUserId() == null) { if (bo.getBindingUserId() == null) {
@ -533,8 +507,9 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>(); UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("id", device.getId()) deviceUpdateWrapper.eq("id", device.getId())
.set("binding_status", BindingStatusEnum.BOUND.getCode()) .set("binding_status", BindingStatusEnum.BOUND.getCode())
.set("binding_user_id", userId); .set("binding_user_id", userId)
; .set("binding_time", new Date());
return baseMapper.update(null, deviceUpdateWrapper); return baseMapper.update(null, deviceUpdateWrapper);
} else if (mode == CommunicationModeEnum.BLUETOOTH.getValue()) { } else if (mode == CommunicationModeEnum.BLUETOOTH.getValue()) {
@ -552,7 +527,8 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>(); UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("id", device.getId()) deviceUpdateWrapper.eq("id", device.getId())
.set("binding_status", BindingStatusEnum.BOUND.getCode()) .set("binding_status", BindingStatusEnum.BOUND.getCode())
.set("binding_user_id", userId); .set("binding_user_id", userId)
.set("binding_time", new Date());
return baseMapper.update(null, deviceUpdateWrapper); return baseMapper.update(null, deviceUpdateWrapper);
} else { } else {
throw new RuntimeException("通讯方式错误"); throw new RuntimeException("通讯方式错误");
@ -571,7 +547,8 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>(); UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("id", device.getId()) deviceUpdateWrapper.eq("id", device.getId())
.set("binding_status", BindingStatusEnum.UNBOUND.getCode()) .set("binding_status", BindingStatusEnum.UNBOUND.getCode())
.set("binding_user_id", null); .set("binding_user_id", null)
.set("binding_time", null);
return baseMapper.update(null, deviceUpdateWrapper); return baseMapper.update(null, deviceUpdateWrapper);
} }

View File

@ -1,6 +1,8 @@
package com.fuyuanshen.equipment.service.impl; package com.fuyuanshen.equipment.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -10,11 +12,13 @@ import com.fuyuanshen.common.core.utils.PageUtil;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.satoken.utils.LoginHelper; import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceAssignments;
import com.fuyuanshen.equipment.domain.DeviceType; import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.DeviceTypeGrants; import com.fuyuanshen.equipment.domain.DeviceTypeGrants;
import com.fuyuanshen.equipment.domain.form.DeviceTypeForm; import com.fuyuanshen.equipment.domain.form.DeviceTypeForm;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import com.fuyuanshen.equipment.domain.query.DeviceTypeQueryCriteria; import com.fuyuanshen.equipment.domain.query.DeviceTypeQueryCriteria;
import com.fuyuanshen.equipment.mapper.DeviceAssignmentsMapper;
import com.fuyuanshen.equipment.mapper.DeviceMapper; import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeGrantsMapper; import com.fuyuanshen.equipment.mapper.DeviceTypeGrantsMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper; import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
@ -41,6 +45,7 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
private final DeviceMapper deviceMapper; private final DeviceMapper deviceMapper;
private final DeviceTypeGrantsMapper deviceTypeGrantsMapper; private final DeviceTypeGrantsMapper deviceTypeGrantsMapper;
private final DeviceAssignmentsMapper deviceAssignmentsMapper;
/** /**
@ -155,30 +160,33 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteAll(List<Long> ids) { public void deleteAll(List<Long> ids) {
List<Long> deviceTypeId = new ArrayList<>();
for (Long id : ids) {
DeviceTypeGrants deviceTypeGrant = deviceTypeGrantsMapper.selectById(id);
// List<DeviceTypeGrants> deviceTypeGrants = deviceTypeGrantsMapper.selectList(new QueryWrapper<DeviceTypeGrants>()
// .eq("device_type_id", deviceTypeGrant.getDeviceTypeId()));
// List<DeviceTypeGrants> deviceAssignments = deviceTypeGrantsMapper.selectList(new QueryWrapper<DeviceTypeGrants>()
// .eq("device_id", deviceTypeGrant.getDeviceTypeId()));
// if (CollectionUtil.isNotEmpty(deviceAssignments)) {
// throw new RuntimeException("该设备类型已绑定设备,无法删除");
// }
// Device device = deviceMapper.selectById(deviceTypeGrant.getDeviceTypeId());
List<Device> devices = deviceMapper.selectList(new QueryWrapper<Device>()
.eq("device_type", deviceTypeGrant.getDeviceTypeId()));
if (CollectionUtil.isNotEmpty(devices)) {
throw new RuntimeException("该设备类型已绑定设备,无法删除!!!");
}
deviceTypeId.add(deviceTypeGrant.getDeviceTypeId());
}
deviceTypeGrantsMapper.deleteByIds(ids); deviceTypeGrantsMapper.deleteByIds(ids);
// deviceTypeMapper.deleteByIds(deviceTypeId);
// List<Long> invalidIds = new ArrayList<>();
// List<Long> invalidId2 = new ArrayList<>();
// for (Long id : ids) {
// DeviceType deviceType = deviceTypeMapper.selectById(id);
// if (deviceType == null || !Objects.equals(deviceType.getOwnerCustomerId(), LoginHelper.getUserId())) {
// invalidIds.add(id);
// }
// DeviceQueryCriteria deviceQueryCriteria = new DeviceQueryCriteria();
// deviceQueryCriteria.setDeviceType(id);
// List<Device> devices = deviceMapper.findAll(deviceQueryCriteria);
// if (!devices.isEmpty()) {
// invalidId2.add(id);
// }
// }
// if (!invalidIds.isEmpty()) {
// throw new RuntimeException("以下设备类型无法删除ID 不存在或无权限): " + invalidIds);
// }
// if (!invalidId2.isEmpty()) {
// throw new RuntimeException("以下设备类型无法删除(已绑定设备): " + invalidId2);
// }
//
// deviceTypeMapper.deleteByIds(ids);
} }

View File

@ -138,7 +138,8 @@
d.device_pic, d.device_pic,
dt.type_name, dt.type_name,
dt.communication_mode, dt.communication_mode,
d.bluetooth_name d.bluetooth_name,
d.binding_time
from device d from device d
inner join device_type dt on d.device_type = dt.id inner join device_type dt on d.device_type = dt.id
where d.binding_user_id = #{criteria.bindingUserId} where d.binding_user_id = #{criteria.bindingUserId}

View File

@ -37,6 +37,8 @@
<lombok.version>1.18.36</lombok.version> <lombok.version>1.18.36</lombok.version>
<bouncycastle.version>1.80</bouncycastle.version> <bouncycastle.version>1.80</bouncycastle.version>
<justauth.version>1.16.7</justauth.version> <justauth.version>1.16.7</justauth.version>
<javacv-platform.version>1.5.7</javacv-platform.version>
<!-- 离线IP地址定位库 --> <!-- 离线IP地址定位库 -->
<ip2region.version>2.7.0</ip2region.version> <ip2region.version>2.7.0</ip2region.version>
@ -142,6 +144,12 @@
<version>${justauth.version}</version> <version>${justauth.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>${javacv-platform.version}</version> <!-- 使用合适的版本号 -->
</dependency>
<!-- common 的依赖配置--> <!-- common 的依赖配置-->
<dependency> <dependency>
<groupId>com.fuyuanshen</groupId> <groupId>com.fuyuanshen</groupId>