Merge remote-tracking branch 'origin/dyf-device'

This commit is contained in:
2025-07-08 11:35:03 +08:00
46 changed files with 1419 additions and 181 deletions

View File

@ -17,6 +17,12 @@
</description>
<dependencies>
<!-- <dependency> -->
<!-- <groupId>com.fuyuanshen</groupId> -->
<!-- <artifactId>fys-app</artifactId> -->
<!-- </dependency> -->
<!-- 通用工具-->
<dependency>
<groupId>com.fuyuanshen</groupId>

View File

@ -0,0 +1,49 @@
package com.fuyuanshen.equipment.controller;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
import com.fuyuanshen.common.log.annotation.Log;
import com.fuyuanshen.common.log.enums.BusinessType;
import com.fuyuanshen.common.web.core.BaseController;
import com.fuyuanshen.equipment.domain.bo.UserAppBo;
import com.fuyuanshen.equipment.service.AppUserService;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description:
* @Author: WY
* @Date: 2025/5/16
**/
@Slf4j
@Tag(name = "设备管理", description = "设备:设备管理")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/app/device")
public class DeviceAPPController extends BaseController {
private final AppUserService appUserService;
/**
* 修改APP用户信息
*/
// @SaCheckPermission("app:user:edit")
@Log(title = "APP用户信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody UserAppBo bo) {
return toAjax(appUserService.updateByBo(bo));
}
}

View File

@ -62,7 +62,7 @@ public class DeviceController {
@Operation(summary = "分页查询设备列表", security = {@SecurityRequirement(name = "bearer-key")})
@GetMapping
public TableDataInfo<Device> queryDevice(DeviceQueryCriteria criteria) throws IOException {
Page<Device> page = new Page<>(criteria.getPage(), criteria.getSize());
Page<Device> page = new Page<>(criteria.getPageNum(), criteria.getPageSize());
return deviceService.queryAll(criteria, page);
}
@ -133,9 +133,9 @@ public class DeviceController {
// @Log("撤回设备")
@Operation(summary = "撤回分配设备")
@PostMapping(value = "/withdraw")
public ResponseVO<Object> withdrawDevice(@Validated @ModelAttribute DeviceForm deviceForm) {
public ResponseVO<Object> withdrawDevice(@RequestBody List<Long> ids) {
try {
deviceService.withdrawDevice(deviceForm);
deviceService.withdrawDevice(ids);
} catch (Exception e) {
log.error("updateDevice error: " + e.getMessage());
return ResponseVO.fail("出错了");

View File

@ -33,7 +33,7 @@ public class DeviceTypeController {
@GetMapping
@Operation(summary = "分页查询设备类型")
public TableDataInfo<DeviceType> queryDeviceType(DeviceTypeQueryCriteria criteria) {
Page<DeviceType> page = new Page<>(criteria.getPage(), criteria.getSize());
Page<DeviceType> page = new Page<>(criteria.getPageNum(), criteria.getPageSize());
return deviceTypeService.queryAll(criteria, page);
}

View File

@ -1,7 +1,5 @@
package com.fuyuanshen.equipment.domain;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
@ -55,6 +53,11 @@ public class Device extends TenantEntity {
@Schema(name = "原始所有者(创建者)")
private Long originalOwnerId;
/**
* 原始设备
*/
@Schema(name = "原始设备")
private Long originalDeviceId;
/*@Schema( name = "设备编号")
private String deviceNo;*/
@ -99,7 +102,6 @@ public class Device extends TenantEntity {
@Schema(name = "绑定状态")
private Integer bindingStatus;
/**
* 创建人名称
*/

View File

@ -27,6 +27,19 @@ public class DeviceType extends TenantEntity {
@Schema(name = "创建该类型的客户")
private Long ownerCustomerId;
/**
* 原始所有者(创建者)
* original_owner_id
*/
@Schema(name = "原始所有者(创建者)")
private Long originalOwnerId;
/**
* 原始设备
*/
@Schema(name = "原始设备类型")
private Long originalDeviceId;
@NotBlank(message = "设备类型名称不能为空")
@Schema(name = "类型名称", required = true)
private String typeName;

View File

@ -0,0 +1,99 @@
package com.fuyuanshen.equipment.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fuyuanshen.common.tenant.core.TenantEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.util.Date;
/**
* APP用户信息对象 app_user
*
* @author Lion Li
* @date 2025-06-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("app_user")
public class UserApp extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
@TableId(value = "user_id")
private Long userId;
/**
* 用户账号
*/
private String userName;
/**
* 用户昵称
*/
private String nickName;
/**
* 用户类型app_user系统用户
*/
private String userType;
/**
* 用户邮箱
*/
private String email;
/**
* 手机号码
*/
private String phonenumber;
/**
* 用户性别0男 1女 2未知
*/
private String sex;
/**
* 头像地址
*/
private Long avatar;
/**
* 密码
*/
private String password;
/**
* 帐号状态0正常 1停用
*/
private String status;
/**
* 删除标志0代表存在 1代表删除
*/
@TableLogic
private String delFlag;
/**
* 最后登录IP
*/
private String loginIp;
/**
* 最后登录时间
*/
private Date loginDate;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,95 @@
package com.fuyuanshen.equipment.domain.bo;
import com.fuyuanshen.common.core.validate.AddGroup;
import com.fuyuanshen.common.core.validate.EditGroup;
import com.fuyuanshen.common.mybatis.core.domain.BaseEntity;
import com.fuyuanshen.equipment.domain.UserApp;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* APP用户信息业务对象 app_user
*
* @author Lion Li
* @date 2025-06-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = UserApp.class, reverseConvertGenerate = false)
public class UserAppBo extends BaseEntity {
/**
* 用户ID
*/
@NotNull(message = "用户ID不能为空", groups = { EditGroup.class })
private Long userId;
/**
* 用户账号
*/
@NotBlank(message = "用户账号不能为空", groups = { AddGroup.class, EditGroup.class })
private String userName;
/**
* 用户昵称
*/
// @NotBlank(message = "用户昵称不能为空", groups = { AddGroup.class, EditGroup.class })
private String nickName;
/**
* 用户类型app_user系统用户
*/
private String userType;
/**
* 用户邮箱
*/
private String email;
/**
* 手机号码
*/
private String phonenumber;
/**
* 用户性别0男 1女 2未知
*/
private String sex;
/**
* 头像地址
*/
private Long avatar;
/**
* 密码
*/
private String password;
/**
* 帐号状态0正常 1停用
*/
private String status;
/**
* 最后登录IP
*/
private String loginIp;
/**
* 最后登录时间
*/
private Date loginDate;
/**
* 备注
*/
private String remark;
}

View File

@ -26,7 +26,6 @@ public class DeviceExcelImportDTO {
@ColumnWidth(20)
private String deviceName;
@ExcelProperty(value = "设备图片", converter = ByteArrayImageConverter.class)
@ColumnWidth(15)
private byte[] devicePic;

View File

@ -21,7 +21,7 @@ public class DeviceForm {
private Long assignId;
@Schema(title = "设备类型")
private Long deviceTypeId;
private Long deviceType;
@Schema(title = "客户号")
private Long customerId;

View File

@ -1,5 +1,6 @@
package com.fuyuanshen.equipment.domain.query;
import com.fuyuanshen.common.mybatis.core.domain.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -15,7 +16,7 @@ import java.util.Set;
* @Date: 2025/5/16
**/
@Data
public class DeviceQueryCriteria {
public class DeviceQueryCriteria extends BaseEntity {
@Schema(name = "设备id")
private Long deviceId;
@ -24,7 +25,7 @@ public class DeviceQueryCriteria {
private String deviceName;
@Schema(name = "设备类型")
private Long deviceTypeId;
private Long deviceType;
@Schema(name = "设备MAC")
private String deviceMac;
@ -43,14 +44,11 @@ public class DeviceQueryCriteria {
@Schema(name = "设备状态 0 失效 1 正常 ")
private Integer deviceStatus;
@Schema(name = "创建时间")
private List<Timestamp> createTime;
@Schema(name = "页码", example = "1")
private Integer page = 1;
private Integer pageNum = 1;
@Schema(name = "每页数据量", example = "10")
private Integer size = 10;
private Integer pageSize = 10;
@Schema(name = "客户id")
private Long customerId;

View File

@ -31,9 +31,8 @@ public class DeviceTypeQueryCriteria extends BaseEntity implements Serializable
private Long tenantId;
@Schema(name = "页码", example = "1")
private Integer page = 1;
private Integer pageNum = 1;
@Schema(name = "每页数据量", example = "10")
private Integer size = 10;
private Integer pageSize = 10;
}

View File

@ -0,0 +1,120 @@
package com.fuyuanshen.equipment.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.fuyuanshen.common.excel.annotation.ExcelDictFormat;
import com.fuyuanshen.common.excel.convert.ExcelDictConvert;
import com.fuyuanshen.equipment.domain.UserApp;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* APP用户信息视图对象 app_user
*
* @author Lion Li
* @date 2025-06-27
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = UserApp.class)
public class UserAppVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
@ExcelProperty(value = "用户ID")
private Long userId;
/**
* 用户账号
*/
@ExcelProperty(value = "用户账号")
private String userName;
/**
* 用户昵称
*/
@ExcelProperty(value = "用户昵称")
private String nickName;
/**
* 用户类型app_user系统用户
*/
@ExcelProperty(value = "用户类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "a=pp_user系统用户")
private String userType;
/**
* 用户邮箱
*/
@ExcelProperty(value = "用户邮箱")
private String email;
/**
* 手机号码
*/
@ExcelProperty(value = "手机号码")
private String phonenumber;
/**
* 用户性别0男 1女 2未知
*/
@ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=男,1=女,2=未知")
private String sex;
/**
* 头像地址
*/
@ExcelProperty(value = "头像地址")
private Long avatar;
/**
* 密码
*/
@ExcelProperty(value = "密码")
private String password;
/**
* 帐号状态0正常 1停用
*/
@ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=正常,1=停用")
private String status;
/**
* 最后登录IP
*/
@ExcelProperty(value = "最后登录IP")
private String loginIp;
/**
* 最后登录时间
*/
@ExcelProperty(value = "最后登录时间")
private Date loginDate;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 租户编号
*/
private String tenantId;
/**
* 部门ID
*/
private Long deptId;
}

View File

@ -29,7 +29,6 @@ import java.util.*;
@Slf4j
public class UploadDeviceDataListener implements ReadListener<DeviceExcelImportDTO> {
// 存储图片数据的映射
private final Map<Integer, byte[]> rowImageMap = new HashMap<>();
@ -48,6 +47,7 @@ public class UploadDeviceDataListener implements ReadListener<DeviceExcelImportD
this.params = params;
}
public ImportResult getImportResult() {
ImportResult result = new ImportResult();
result.setSuccessCount(successCount);
@ -151,23 +151,26 @@ public class UploadDeviceDataListener implements ReadListener<DeviceExcelImportD
Device device = rowDeviceMap.get(rowIndex);
DeviceExcelImportDTO originalDto = rowDtoMap.get(rowIndex);
try {
DeviceQueryCriteria criteria = new DeviceQueryCriteria();
criteria.setDeviceMac(device.getDeviceMac());
criteria.setTenantId(params.getTenantId());
List<Device> deviceList = params.getDeviceMapper().findAll(criteria);
if (!deviceList.isEmpty()) {
throw new RuntimeException("设备MAC重复");
}
device.setTenantId(params.getTenantId());
// DeviceQueryCriteria criteria = new DeviceQueryCriteria();
// criteria.setDeviceMac(device.getDeviceMac());
// criteria.setTenantId(params.getTenantId());
// List<Device> deviceList = params.getDeviceMapper().findAll(criteria);
// if (!deviceList.isEmpty()) {
// throw new RuntimeException("设备MAC重复");
// }
// device.setTenantId(params.getTenantId());
// 设备类型
QueryWrapper<DeviceType> wrapper = new QueryWrapper<>();
wrapper.eq("type_name", device.getTypeName());
wrapper.eq("customer_id", params.getUserId());
// wrapper.eq("customer_id", params.getUserId());
List<DeviceType> deviceTypes = params.getDeviceTypeMapper().selectList(wrapper);
if (CollectionUtil.isNotEmpty(deviceTypes)) {
device.setDeviceType(deviceTypes.get(0).getId());
}
device.setCurrentOwnerId(loginUser.getUserId());
device.setOriginalOwnerId(loginUser.getUserId());
device.setCreateByName(loginUser.getNickname());
params.getDeviceService().save(device);
successCount++;
log.info("行 {} 数据插入成功", rowIndex);

View File

@ -33,4 +33,19 @@ public interface DeviceMapper extends BaseMapper<Device> {
List<Device> findAllDevices(@Param("criteria") DeviceQueryCriteria criteria);
Page<AppDeviceVo> queryAppDeviceList(Page<AppDeviceVo> page,@Param("criteria") DeviceQueryCriteria criteria);
/**
* 获取分配设备的客户
*
* @param customerId
* @return
*/
Device getAssignCustomer(Long customerId);
/**
* 获取设备链
*
* @param originalDeviceId
* @return
*/
List<Device> findByOriginalDeviceId(Long originalDeviceId);
}

View File

@ -0,0 +1,18 @@
package com.fuyuanshen.equipment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fuyuanshen.equipment.domain.DeviceTypeGrants;
import org.apache.ibatis.annotations.Mapper;
/**
* @author 97433
* @description 针对表【device_type_grants】的数据库操作Mapper
* @createDate 2025-06-19 13:49:33
* @Entity generator.domain.DeviceTypeGrants
*/
@Mapper
public interface DeviceTypeGrantsMapper extends BaseMapper<DeviceTypeGrants> {
}

View File

@ -36,4 +36,12 @@ public interface DeviceTypeMapper extends BaseMapper<DeviceType> {
*/
List<DeviceType> findAll(@Param("criteria") DeviceTypeQueryCriteria criteria);
/**
* 获取已经分配的设备类型
*
* @param customerId
* @return
*/
DeviceType getAssignType(@Param("deviceType") Long deviceType, @Param("customerId") Long customerId);
}

View File

@ -0,0 +1,17 @@
package com.fuyuanshen.equipment.mapper;
import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus;
import com.fuyuanshen.equipment.domain.UserApp;
import com.fuyuanshen.equipment.domain.vo.UserAppVo;
import org.apache.ibatis.annotations.Mapper;
/**
* APP用户信息Mapper接口
*
* @author Lion Li
* @date 2025-06-27
*/
@Mapper
public interface UserAppMapper extends BaseMapperPlus<UserApp, UserAppVo> {
}

View File

@ -0,0 +1,27 @@
package com.fuyuanshen.equipment.service;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.equipment.domain.bo.UserAppBo;
import java.util.Collection;
import java.util.List;
/**
* APP用户信息Service接口
*
* @author Lion Li
* @date 2025-06-27
*/
public interface AppUserService {
/**
* 修改APP用户信息
*
* @param bo APP用户信息
* @return 是否修改成功
*/
Boolean updateByBo(UserAppBo bo);
}

View File

@ -76,7 +76,7 @@ public interface DeviceService extends IService<Device> {
/**
* 撤回设备
*/
void withdrawDevice(DeviceForm deviceForm);
void withdrawDevice(List<Long> ids);
/**
* 解绑设备

View File

@ -1,6 +1,7 @@
package com.fuyuanshen.equipment.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.generator.SnowflakeGenerator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@ -25,6 +26,7 @@ import com.fuyuanshen.equipment.domain.vo.AppDeviceVo;
import com.fuyuanshen.equipment.domain.vo.CustomerVo;
import com.fuyuanshen.equipment.enums.BindingStatusEnum;
import com.fuyuanshen.equipment.enums.CommunicationModeEnum;
import com.fuyuanshen.equipment.enums.DeviceStatusEnum;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import com.fuyuanshen.equipment.service.DeviceService;
@ -40,9 +42,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.*;
/**
* @Description:
@ -122,7 +122,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
@Transactional(rollbackFor = Exception.class)
public void addDevice(DeviceForm deviceForm) throws Exception {
DeviceTypeQueryCriteria queryCriteria = new DeviceTypeQueryCriteria();
queryCriteria.setDeviceTypeId(deviceForm.getId());
queryCriteria.setDeviceTypeId(deviceForm.getDeviceType());
queryCriteria.setCustomerId(LoginHelper.getUserId());
List<DeviceType> deviceTypes = deviceTypeMapper.findAll(queryCriteria);
if (deviceTypes.isEmpty()) {
@ -141,6 +141,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
Device device = new Device();
LoginUser loginUser = LoginHelper.getLoginUser();
device.setCurrentOwnerId(loginUser.getUserId());
device.setOriginalOwnerId(loginUser.getUserId());
device.setCreateByName(loginUser.getNickname());
device.setTypeName(deviceTypes.get(0).getTypeName());
BeanUtil.copyProperties(deviceForm, device, true);
@ -161,7 +162,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
public void update(DeviceForm deviceForm) throws Exception {
DeviceTypeQueryCriteria deviceTypeQueryCriteria = new DeviceTypeQueryCriteria();
deviceTypeQueryCriteria.setDeviceTypeId(deviceForm.getId());
deviceTypeQueryCriteria.setDeviceTypeId(deviceForm.getDeviceType());
deviceTypeQueryCriteria.setCustomerId(LoginHelper.getUserId());
List<DeviceType> deviceTypes = deviceTypeMapper.findAll(deviceTypeQueryCriteria);
if (deviceTypes.isEmpty()) {
@ -179,9 +180,11 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
// 处理上传的图片
// String imageUrl = saveDeviceImage(deviceForm.getFile(), device.getDeviceName());
SysOssVo upload = ossService.upload(deviceForm.getFile());
// 设置图片路径
deviceForm.setDevicePic(upload.getUrl());
if (deviceForm.getFile() != null) {
SysOssVo upload = ossService.upload(deviceForm.getFile());
// 设置图片路径
deviceForm.setDevicePic(upload.getUrl());
}
// 更新字段
BeanUtil.copyProperties(deviceForm, device, true);
@ -248,8 +251,65 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
*
* @param customerVo
*/
// @Override
// @Transactional(rollbackFor = Exception.class)
// public void assignCustomer1(CustomerVo customerVo) {
// List<Long> deviceIds = customerVo.getDeviceIds();
// Long customerId = customerVo.getCustomerId();
//
// Customer customer = customerMapper.queryCustomerById(customerId, LoginHelper.getLoginUser().getPid());
// if (customer == null) {
// throw new RuntimeException("待分配的客户不存在!!!");
// }
//
// List<Long> invalidIds = new ArrayList<>();
// List<Device> devices = new ArrayList<>();
// for (Long id : deviceIds) {
// Device device = deviceMapper.selectById(id);
// if (device == null || !Objects.equals(device.getCurrentOwnerId(), LoginHelper.getUserId())) {
// invalidIds.add(id);
// continue;
// }
// Device assignCustomer = deviceMapper.getAssignCustomer(device.getId());
// if (assignCustomer != null) {
// invalidIds.add(id);
// continue;
// }
// device.setCustomerId(customerId);
// device.setCustomerName(customer.getNickName());
// devices.add(device);
// }
// if (!invalidIds.isEmpty()) {
// throw new RuntimeException("以下设备无法分配ID 不存在或无权限): " + invalidIds);
// }
//
// devices.forEach((device) -> {
//
// deviceMapper.updateById(device);
// device.setCurrentOwnerId(customerId);
// if (device.getDeviceType() == null) {
// throw new RuntimeException("设备类型有问题!!! ");
// }
// DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
// SnowflakeGenerator snowflakeGenerator = new SnowflakeGenerator();
// device.setOriginalDeviceId(device.getId());
// Long next = snowflakeGenerator.next();
// device.setId(next);
// device.setDeviceType(next);
//
// DeviceType assignType = deviceTypeMapper.getAssignType(device.getDeviceType(), customerId);
// if (assignType == null) {
// deviceType.setOriginalDeviceId(deviceType.getId());
// deviceType.setId(next);
// deviceType.setOwnerCustomerId(customerId);
// deviceTypeMapper.insert(deviceType);
// }
//
// deviceMapper.insert(device);
//
// });
// }
@Override
@Transactional(rollbackFor = Exception.class)
public void assignCustomer(CustomerVo customerVo) {
List<Long> deviceIds = customerVo.getDeviceIds();
Long customerId = customerVo.getCustomerId();
@ -259,51 +319,117 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
throw new RuntimeException("待分配的客户不存在!!!");
}
List<Device> devicesToAssign = new ArrayList<>();
List<Long> invalidIds = new ArrayList<>();
List<Device> devices = new ArrayList<>();
for (Long id : deviceIds) {
Device device = deviceMapper.selectById(id);
if (device == null || !Objects.equals(device.getCurrentOwnerId(), LoginHelper.getUserId())) {
invalidIds.add(id);
continue;
}
Device assignCustomer = deviceMapper.getAssignCustomer(device.getId());
if (assignCustomer != null) {
invalidIds.add(id);
continue;
}
device.setCustomerId(customerId);
device.setCustomerName(customer.getNickName());
devices.add(device);
devicesToAssign.add(device);
}
if (!invalidIds.isEmpty()) {
throw new RuntimeException("以下设备无法分配ID 不存在或无权限): " + invalidIds);
}
devices.forEach((device) -> {
deviceMapper.updateById(device);
device.setId(null);
device.setCurrentOwnerId(customerId);
deviceMapper.insert(device);
DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
deviceType.setId(null);
device.setCurrentOwnerId(customerId);
deviceTypeMapper.insert(deviceType);
});
// 批量处理设备分配
batchAssignDevices(devicesToAssign, customer);
}
public void assign(List<Long> deviceIds) {
@Transactional(rollbackFor = Exception.class)
public void batchAssignDevices(List<Device> devicesToAssign, Customer customer) {
Long userId = LoginHelper.getUserId();
SnowflakeGenerator snowflakeGenerator = new SnowflakeGenerator();
for (Device device : devicesToAssign) {
if (device.getDeviceType() == null) {
throw new RuntimeException("设备类型有问题!!! ");
}
deviceMapper.updateById(device);
DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
DeviceType assignType = deviceTypeMapper.getAssignType(device.getDeviceType(), customer.getCustomerId());
Long next = snowflakeGenerator.next();
device.setOriginalDeviceId(device.getId());
device.setCurrentOwnerId(customer.getCustomerId());
device.setOriginalOwnerId(device.getCurrentOwnerId());
device.setCustomerId(null);
device.setCustomerName("");
device.setId(next);
if (assignType == null) {
deviceType.setOriginalDeviceId(deviceType.getId());
deviceType.setOriginalOwnerId(deviceType.getOwnerCustomerId());
deviceType.setId(next);
device.setDeviceType(next);
deviceType.setOwnerCustomerId(customer.getCustomerId());
deviceTypeMapper.insert(deviceType);
} else {
device.setDeviceType(assignType.getId());
}
deviceMapper.insert(device);
}
}
/**
* 撤回设备
*
* @param deviceForm
* @param ids
*/
@Override
public void withdrawDevice(DeviceForm deviceForm) {
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());
}
}

View File

@ -11,10 +11,12 @@ import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.DeviceTypeGrants;
import com.fuyuanshen.equipment.domain.form.DeviceTypeForm;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import com.fuyuanshen.equipment.domain.query.DeviceTypeQueryCriteria;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeGrantsMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import com.fuyuanshen.equipment.service.DeviceTypeService;
import lombok.RequiredArgsConstructor;
@ -22,6 +24,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@ -37,6 +40,8 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
private final DeviceTypeMapper deviceTypeMapper;
private final DeviceMapper deviceMapper;
private final DeviceTypeGrantsMapper deviceTypeGrantsMapper;
/**
* 分页查询设备类型
@ -85,8 +90,17 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
LoginUser loginUser = LoginHelper.getLoginUser();
resources.setCustomerId(loginUser.getUserId());
resources.setOwnerCustomerId(loginUser.getUserId());
resources.setOriginalOwnerId(loginUser.getUserId());
resources.setCreateByName(loginUser.getNickname());
deviceTypeMapper.insert(resources);
// 自动授权给自己
DeviceTypeGrants deviceTypeGrants = new DeviceTypeGrants();
deviceTypeGrants.setDeviceTypeId(resources.getId());
deviceTypeGrants.setCustomerId(loginUser.getUserId());
deviceTypeGrants.setGrantorCustomerId(loginUser.getUserId());
deviceTypeGrants.setGrantedAt(new Date());
deviceTypeGrantsMapper.insert(deviceTypeGrants);
}
@ -98,6 +112,11 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
@Override
@Transactional(rollbackFor = Exception.class)
public void update(DeviceTypeForm resources) {
DeviceTypeGrants deviceTypeGrants = deviceTypeGrantsMapper.selectById(resources.getId());
if (deviceTypeGrants == null) {
throw new RuntimeException("设备类型不存在");
}
resources.setId(deviceTypeGrants.getDeviceTypeId());
DeviceType deviceType = deviceTypeMapper.selectById(resources.getId());
if (deviceType == null) {
throw new RuntimeException("设备类型不存在");
@ -121,28 +140,30 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
@Transactional(rollbackFor = Exception.class)
public void deleteAll(List<Long> ids) {
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.getCustomerId(), LoginHelper.getUserId())) {
invalidIds.add(id);
}
DeviceQueryCriteria deviceQueryCriteria = new DeviceQueryCriteria();
deviceQueryCriteria.setDeviceTypeId(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);
deviceTypeGrantsMapper.deleteByIds(ids);
//
// 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

@ -0,0 +1,41 @@
package com.fuyuanshen.equipment.service.impl;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.equipment.domain.UserApp;
import com.fuyuanshen.equipment.domain.bo.UserAppBo;
import com.fuyuanshen.equipment.mapper.UserAppMapper;
import com.fuyuanshen.equipment.service.AppUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Collection;
/**
* Service业务层处理
*
* @author Lion Li
* @date 2025-06-27
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class UserAppServiceImpl implements AppUserService {
private final UserAppMapper baseMapper;
/**
* 修改APP用户信息
*
* @param bo APP用户信息
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(UserAppBo bo) {
UserApp update = MapstructUtils.convert(bo, UserApp.class);
return baseMapper.updateById(update) > 0;
}
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fuyuanshen.equipment.mapper.UserAppMapper">
</mapper>

View File

@ -38,7 +38,7 @@
<!-- 分页查询设备 -->
<select id="findAll" resultType="com.fuyuanshen.equipment.domain.Device">
select d.* ,t.type_name
select d.* , t.type_name
FROM device d
LEFT JOIN device_type t ON d.device_type = t.id
<where>
@ -52,22 +52,23 @@
<if test="criteria.deviceImei != null">
and d.device_imei = #{criteria.deviceImei}
</if>
<if test="criteria.deviceTypeId != null">
and d.device_type = #{criteria.deviceTypeId}
<if test="criteria.deviceType != null">
and d.device_type = #{criteria.deviceType}
</if>
<if test="criteria.deviceStatus != null">
-- and da.active = #{criteria.deviceStatus}
and d.device_status = #{criteria.deviceStatus}
</if>
<if test="criteria.currentOwnerId != null">
d.current_owner_id = #{criteria.currentOwnerId}
and d.current_owner_id = #{criteria.currentOwnerId}
</if>
<if test="criteria.createTime != null and criteria.createTime.size() != 0">
and d.create_time between #{criteria.createTime[0]} and #{criteria.createTime[1]}
<if test="criteria.params.beginTime != null and criteria.params.endTime != null">
and d.create_time between #{criteria.params.beginTime} and #{criteria.params.endTime}
</if>
<if test="criteria.tenantId != null">
AND tenant_id = #{criteria.tenantId}
</if>
</where>
order by d.create_time desc
</select>
<select id="findAllDevices" resultType="com.fuyuanshen.equipment.domain.Device">
@ -100,4 +101,20 @@
where d.binding_user_id = #{criteria.bindingUserId}
</select>
<!-- 获取分配设备的客户 -->
<select id="getAssignCustomer" resultType="com.fuyuanshen.equipment.domain.Device">
SELECT *
FROM device
WHERE original_device_id = #{customerId}
AND device_status = 1
</select>
<!-- 获取设备链 -->
<select id="findByOriginalDeviceId" resultType="com.fuyuanshen.equipment.domain.Device"
parameterType="java.lang.Long">
SELECT id, original_device_id
FROM device
WHERE original_device_id = #{originalDeviceId}
</select>
</mapper>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fuyuanshen.equipment.mapper.DeviceTypeGrantsMapper">
<resultMap id="BaseResultMap" type="com.fuyuanshen.equipment.domain.DeviceTypeGrants">
<id property="id" column="id" />
<result property="deviceTypeId" column="device_type_id" />
<result property="customerId" column="customer_id" />
<result property="grantorCustomerId" column="grantor_customer_id" />
<result property="grantedAt" column="granted_at" />
<result property="assignmentId" column="assignment_id" />
</resultMap>
<sql id="Base_Column_List">
id,device_type_id,customer_id,grantor_customer_id,granted_at,assignment_id
</sql>
</mapper>

View File

@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.fuyuanshen.equipment.mapper.DeviceTypeMapper">
<resultMap id="BaseResultMap" type="com.fuyuanshen.equipment.domain.DeviceType">
<id column="id" property="id"/>
<id column="grant_id" property="id"/>
<result column="type_name" property="typeName"/>
<result column="is_support_ble" property="isSupportBle"/>
<result column="locate_mode" property="locateMode"/>
@ -19,22 +19,27 @@
, type_name, is_support_ble, locate_mode, network_way, create_by, update_by, create_time, update_time,communication_mode
</sql>
<!-- 查询所有设备类型 -->
<select id="findAll" resultMap="BaseResultMap">
SELECT DISTINCT dt.*
SELECT DISTINCT dt.* ,dg.id AS grant_id ,dg.create_time AS Dcreate_time
FROM device_type dt
JOIN device_type_grants dg ON dt.id = dg.device_type_id
<where>
<if test="criteria.typeName != null and criteria.typeName.trim() != ''">
and dt.type_name like concat('%', TRIM(#{criteria.typeName}), '%')
</if>
<if test="criteria.deviceTypeId != null">
and dt.id = #{criteria.deviceTypeId}
</if>
<if test="criteria.customerId != null">
and dt.owner_customer_id = #{criteria.customerId}
and dg.customer_id = #{criteria.customerId}
</if>
</where>
ORDER BY dt.create_time DESC
ORDER BY Dcreate_time DESC
</select>
<!-- 获取已经分配的设备类型 -->
<select id="getAssignType" resultType="com.fuyuanshen.equipment.domain.DeviceType">
SELECT *
FROM device_type
WHERE owner_customer_id = #{customerId}
AND original_device_id = #{deviceType}
</select>
</mapper>