Compare commits

...

2 Commits

Author SHA1 Message Date
bc0419e2c3 设备列表 2025-06-19 18:09:14 +08:00
d421ca5499 设备列表 2025-06-19 18:09:03 +08:00
16 changed files with 339 additions and 43 deletions

View File

@ -29,12 +29,14 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
/**
* 获取当前登录的用户
*
* @author Zheng Jie
* @date 2019-01-17
*/
@ -59,6 +61,7 @@ public class SecurityUtils {
/**
* 获取当前登录的用户
*
* @return UserDetails
*/
public static UserDetails getCurrentUser() {
@ -68,9 +71,10 @@ public class SecurityUtils {
/**
* 获取当前用户的数据权限
*
* @return /
*/
public static List<Long> getCurrentUserDataScope(){
public static List<Long> getCurrentUserDataScope() {
UserDetails userDetails = getCurrentUser();
// 将 Java 对象转换为 JSONObject 对象
JSONObject jsonObject = (JSONObject) JSON.toJSON(userDetails);
@ -80,11 +84,12 @@ public class SecurityUtils {
/**
* 获取数据权限级别
*
* @return 级别
*/
public static String getDataScopeType() {
List<Long> dataScopes = getCurrentUserDataScope();
if(CollUtil.isEmpty(dataScopes)){
if (CollUtil.isEmpty(dataScopes)) {
return "";
}
return DataScopeEnum.ALL.getValue();
@ -92,6 +97,7 @@ public class SecurityUtils {
/**
* 获取用户ID
*
* @return 系统用户ID
*/
public static Long getCurrentUserId() {
@ -100,6 +106,7 @@ public class SecurityUtils {
/**
* 获取用户ID
*
* @return 系统用户ID
*/
public static Long getCurrentUserId(String token) {
@ -128,11 +135,11 @@ public class SecurityUtils {
/**
* 获取Token
*
* @return /
*/
public static String getToken() {
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder
.getRequestAttributes())).getRequest();
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
String bearerToken = request.getHeader(header);
if (bearerToken != null && bearerToken.startsWith(tokenStartWith)) {
// 去掉令牌前缀

View File

@ -10,6 +10,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.fuyuanshen.base.BaseEntity;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
@ -28,9 +29,18 @@ public class Device extends BaseEntity implements Serializable {
@ApiModelProperty(value = "设备类型")
private Long deviceType;
@ApiModelProperty(value = "设备类型名称")
private String typeName;
@ApiModelProperty(value = "客户号")
private Long customerId;
@ApiModelProperty(value = "当前所有者")
private Long currentOwnerId;
@ApiModelProperty(value = "原始所有者(创建者)")
private Long originalOwnerId;
@ApiModelProperty(value = "所属客户")
private String customerName;
@ -46,6 +56,9 @@ public class Device extends BaseEntity implements Serializable {
@ApiModelProperty(value = "设备MAC")
private String deviceMac;
@ApiModelProperty(value = "设备IMEI")
private String deviceImei;
@ApiModelProperty(value = "设备SN")
private String deviceSn;
@ -58,10 +71,6 @@ public class Device extends BaseEntity implements Serializable {
@ApiModelProperty(value = "备注")
private String remark;
@TableField(exist = false)
@ApiModelProperty(value = "设备类型名称")
private String typeName;
/**
* 租户ID
*/

View File

@ -28,9 +28,11 @@ public class DeviceType extends BaseEntity implements Serializable {
@ApiModelProperty(value = "ID", hidden = true)
private Long id;
@ExcelProperty("客户号")
@ApiModelProperty(value = "客户号")
private Long customerId;
@ApiModelProperty(value = "创建该类型的客户")
private String ownerCustomerId;
/**
* 租户ID
*/
@ -54,6 +56,7 @@ public class DeviceType extends BaseEntity implements Serializable {
@ApiModelProperty(value = "通讯方式", example = "0:4G;1:蓝牙")
private String communicationMode;
public void copy(DeviceType source) {
BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
}

View File

@ -0,0 +1,94 @@
package com.fuyuanshen.modules.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fuyuanshen.base.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* 设备分配权限表 (解决跨客户共享)
*
* @TableName device_type_grants
*/
@TableName(value = "device_type_grants")
@Data
public class DeviceTypeGrants {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 设备类型
*/
private Long deviceTypeId;
/**
* 被授权的客户
*/
private Long customerId;
/**
* 授权方客户
*/
private Long grantorCustomerId;
/**
* 生成日期
*/
private Date grantedAt;
/**
* 关联分配记录
*/
private Integer assignmentId;
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
DeviceTypeGrants other = (DeviceTypeGrants) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) && (this.getDeviceTypeId() == null ? other.getDeviceTypeId() == null : this.getDeviceTypeId().equals(other.getDeviceTypeId())) && (this.getCustomerId() == null ? other.getCustomerId() == null : this.getCustomerId().equals(other.getCustomerId())) && (this.getGrantorCustomerId() == null ? other.getGrantorCustomerId() == null : this.getGrantorCustomerId().equals(other.getGrantorCustomerId())) && (this.getGrantedAt() == null ? other.getGrantedAt() == null : this.getGrantedAt().equals(other.getGrantedAt())) && (this.getAssignmentId() == null ? other.getAssignmentId() == null : this.getAssignmentId().equals(other.getAssignmentId()));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getDeviceTypeId() == null) ? 0 : getDeviceTypeId().hashCode());
result = prime * result + ((getCustomerId() == null) ? 0 : getCustomerId().hashCode());
result = prime * result + ((getGrantorCustomerId() == null) ? 0 : getGrantorCustomerId().hashCode());
result = prime * result + ((getGrantedAt() == null) ? 0 : getGrantedAt().hashCode());
result = prime * result + ((getAssignmentId() == null) ? 0 : getAssignmentId().hashCode());
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", deviceTypeId=").append(deviceTypeId);
sb.append(", customerId=").append(customerId);
sb.append(", grantorCustomerId=").append(grantorCustomerId);
sb.append(", grantedAt=").append(grantedAt);
sb.append(", assignmentId=").append(assignmentId);
sb.append("]");
return sb.toString();
}
}

View File

@ -33,11 +33,14 @@ public class DeviceForm {
@ApiModelProperty(value = "设备图片存储路径", hidden = true)
private String devicePic;
@NotBlank(message = "设备MAC不能为空")
@ApiModelProperty(value = "设备MAC", required = true)
// @NotBlank(message = "设备MAC不能为空")
@ApiModelProperty(value = "设备MAC")
private String deviceMac;
@NotBlank(message = "设备SN不能为空")
@ApiModelProperty(value = "设备IMEI")
private String deviceImei;
// @NotBlank(message = "设备SN不能为空")
@ApiModelProperty(value = "设备SN", required = true)
private String deviceSn;

View File

@ -0,0 +1,51 @@
package com.fuyuanshen.modules.system.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 设备状态枚举
*
* @author: 默苍璃
* @date: 2025-06-1916:02
*/
@Getter
@AllArgsConstructor
public enum DeviceStatusEnum {
/**
* 失效
*/
INVALID(0, "失效"),
/**
* 正常
*/
NORMAL(1, "正常");
/**
* 状态码
*/
private final Integer code;
/**
* 描述
*/
private final String description;
/**
* 根据状态码获取描述
*
* @param code 状态码
* @return 描述
*/
public static String getDescriptionByCode(Integer code) {
for (DeviceStatusEnum status : DeviceStatusEnum.values()) {
if (status.getCode().equals(code)) {
return status.getDescription();
}
}
return null;
}
}

View File

@ -0,0 +1,18 @@
package com.fuyuanshen.modules.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fuyuanshen.modules.system.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

@ -74,4 +74,11 @@ public class DeviceTypeController {
return new ResponseEntity<>(HttpStatus.OK);
}
@GetMapping(value = "/communicationMode")
@ApiOperation("获取设备类型通讯方式")
public ResponseVO<DeviceType> getCommunicationMode(@ApiParam(value = "设备类型ID", required = true) Long id) {
return ResponseVO.success(deviceTypeService.getById(id));
}
}

View File

@ -0,0 +1,14 @@
package com.fuyuanshen.modules.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.fuyuanshen.modules.system.domain.DeviceTypeGrants;
/**
* @author 97433
* @description 针对表【device_type_grants】的数据库操作Service
* @createDate 2025-06-19 13:49:33
*/
public interface DeviceTypeGrantsService extends IService<DeviceTypeGrants> {
}

View File

@ -13,39 +13,50 @@ import java.util.List;
* @Author: WY
* @Date: 2025/5/14
**/
public interface DeviceTypeService extends IService<DeviceType> {
public interface DeviceTypeService extends IService<DeviceType> {
/**
* 查询数据分页
*
* @param criteria 条件
* @param page 分页参数
* @param page 分页参数
* @return PageResult
*/
PageResult<DeviceType> queryAll(DeviceTypeQueryCriteria criteria, Page<Object> page);
/**
* 查询所有数据不分页
*
* @param criteria 条件参数
* @return List<DeviceTypeDto>
*/
List<DeviceType> queryAll(DeviceTypeQueryCriteria criteria);
/**
* 查询所有设备类型
*
* @return
*/
List<DeviceType> queryDeviceTypes();
/**
* 创建
* 新增设备类型
*
* @param resources /
*/
void create(DeviceType resources);
/**
* 编辑
*
* @param resources /
*/
void update(DeviceType resources);
/**
* 多选删除
*
* @param ids /
*/
void deleteAll(List<Long> ids);

View File

@ -14,13 +14,16 @@ import com.fuyuanshen.modules.security.service.UserCacheManager;
import com.fuyuanshen.modules.system.constant.UserConstants;
import com.fuyuanshen.modules.system.domain.Device;
import com.fuyuanshen.modules.system.domain.DeviceType;
import com.fuyuanshen.modules.system.domain.DeviceTypeGrants;
import com.fuyuanshen.modules.system.domain.User;
import com.fuyuanshen.modules.system.domain.app.APPDevice;
import com.fuyuanshen.modules.system.domain.dto.CustomerVo;
import com.fuyuanshen.modules.system.domain.dto.DeviceForm;
import com.fuyuanshen.modules.system.domain.dto.DeviceQueryCriteria;
import com.fuyuanshen.modules.system.enums.BindingStatusEnum;
import com.fuyuanshen.modules.system.enums.DeviceStatusEnum;
import com.fuyuanshen.modules.system.mapper.DeviceMapper;
import com.fuyuanshen.modules.system.mapper.DeviceTypeGrantsMapper;
import com.fuyuanshen.modules.system.mapper.DeviceTypeMapper;
import com.fuyuanshen.modules.system.mapper.UserMapper;
import com.fuyuanshen.modules.system.mapper.app.APPDeviceMapper;
@ -67,6 +70,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
private final UserCacheManager userCacheManager;
private final APPDeviceMapper appDeviceMapper;
private final DeviceTypeGrantsMapper deviceTypeGrantsMapper;
@Autowired
private UserService userService;
@ -137,22 +141,33 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
public void addDevice(DeviceForm deviceForm) throws Exception {
// 获取当前登录用户信息
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username1 = authentication.getName();
// Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// String username1 = authentication.getName();
// 从缓存获取
// UserDetails currentUser = SecurityUtils.getCurrentUser();
// String username = currentUser.getUsername();
// JwtUserDto jwtUserDto = userCacheManager.getUserCache(username);
User currentUser = userMapper.findByUsername(SecurityUtils.getCurrentUsername());
QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("device_mac", deviceForm.getDeviceMac());
// queryWrapper.eq("tenant_id", currentUser.getTenantId());
if ((deviceMapper.selectOne(queryWrapper)) != null) {
throw new BadRequestException("设备 mac地址 有误,请仔细核对!!!");
if (StringUtils.isNotEmpty(deviceForm.getDeviceMac())){
QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("device_mac", deviceForm.getDeviceMac());
// queryWrapper.eq("tenant_id", currentUser.getTenantId());
if ((deviceMapper.selectOne(queryWrapper)) != null) {
throw new BadRequestException("设备 mac地址 有误,请仔细核对!!!");
}
}
QueryWrapper<DeviceTypeGrants> deviceTypeGrantsQueryWrapper = new QueryWrapper<>();
deviceTypeGrantsQueryWrapper.eq("customer_id", currentUser.getId());
deviceTypeGrantsQueryWrapper.eq("device_type_id", deviceForm.getDeviceType());
Long count = deviceTypeGrantsMapper.selectCount(deviceTypeGrantsQueryWrapper);
if (count <= 0) {
throw new BadRequestException("请先授权设备类型!!!");
}
// 保存图片并获取URL
String imageUrl = saveDeviceImage(deviceForm.getFile(), deviceForm.getDeviceMac());
// 设置图片路径
deviceForm.setDevicePic(imageUrl);
@ -163,9 +178,13 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
// 添加租户ID
device.setTenantId(currentUser.getTenantId());
// 默认状态正常
device.setDeviceStatus(1);
device.setDeviceStatus(DeviceStatusEnum.NORMAL.getCode());
// SnowflakeGenerator snowflakeGenerator = new SnowflakeGenerator();
// device.setId(snowflakeGenerator.next());
device.setCurrentOwnerId(currentUser.getId());
device.setOriginalOwnerId(currentUser.getId());
deviceMapper.insert(device);
}

View File

@ -0,0 +1,18 @@
package com.fuyuanshen.modules.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyuanshen.modules.system.domain.DeviceTypeGrants;
import com.fuyuanshen.modules.system.mapper.DeviceTypeGrantsMapper;
import com.fuyuanshen.modules.system.service.DeviceTypeGrantsService;
import org.springframework.stereotype.Service;
/**
* @author 97433
* @description 针对表【device_type_grants】的数据库操作Service实现
* @createDate 2025-06-19 13:49:33
*/
@Service
public class DeviceTypeGrantsServiceImpl extends ServiceImpl<DeviceTypeGrantsMapper, DeviceTypeGrants>
implements DeviceTypeGrantsService {
}

View File

@ -3,6 +3,8 @@ package com.fuyuanshen.modules.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyuanshen.modules.system.domain.DeviceTypeGrants;
import com.fuyuanshen.modules.system.mapper.DeviceTypeGrantsMapper;
import com.fuyuanshen.modules.utils.NanoId;
import lombok.RequiredArgsConstructor;
import com.fuyuanshen.modules.security.service.UserCacheManager;
@ -23,6 +25,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@ -39,6 +42,7 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
private final DeviceTypeMapper deviceTypeMapper;
private final UserMapper userMapper;
private final UserCacheManager userCacheManager;
private final DeviceTypeGrantsMapper deviceTypeGrantsMapper;
/**
@ -51,7 +55,7 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
@Override
public PageResult<DeviceType> queryAll(DeviceTypeQueryCriteria criteria, Page<Object> page) {
JwtUserDto userCache = userCacheManager.getUserCache(SecurityUtils.getCurrentUsername());
User currentUser = userMapper.findByUsername(SecurityUtils.getCurrentUsername());
// 非超级管理员增加数据隔离
// if (userCache.getUser().getTenantId() != null && !userCache.getUser().getTenantId().equals(UserConstants.SUPER_ADMIN_ID)) {
// List<User> subUsers = userMapper.findUserTree(userCache.getUser().getId());
@ -64,11 +68,14 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
// List<User> users = userMapper.findByTenantId(userCache.getUser().getTenantId());
// Set<Long> userIds = users.stream().map(User::getId).collect(Collectors.toSet());
// criteria.setCustomerId(userIds);
// }
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username", SecurityUtils.getCurrentUsername());
User user = userMapper.selectOne(wrapper);
criteria.setCustomerId(user.getId());
// 非超级管理员增加数据隔离(只能看到自己创建的设备类型)
if (currentUser.getTenantId() != null && !currentUser.getTenantId().equals(UserConstants.SUPER_ADMIN_ID)) {
//
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username", SecurityUtils.getCurrentUsername());
User user = userMapper.selectOne(wrapper);
criteria.setCustomerId(user.getId());
}
return PageUtil.toPage(deviceTypeMapper.findAll(criteria, page));
}
@ -118,9 +125,19 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
@Override
@Transactional(rollbackFor = Exception.class)
public void create(DeviceType resources) {
resources.setId(NanoId.generate(16));
Long deviceTypeId = NanoId.generate(16);
resources.setId(deviceTypeId);
resources.setCustomerId(SecurityUtils.getCurrentUserId());
deviceTypeMapper.insert(resources);
// 自动授权给自己
DeviceTypeGrants deviceTypeGrants = new DeviceTypeGrants();
deviceTypeGrants.setDeviceTypeId(deviceTypeId);
deviceTypeGrants.setCustomerId(SecurityUtils.getCurrentUserId());
deviceTypeGrants.setGrantorCustomerId(SecurityUtils.getCurrentUserId());
deviceTypeGrants.setGrantedAt(new Date());
deviceTypeGrantsMapper.insert(deviceTypeGrants);
}

View File

@ -24,12 +24,19 @@
, device_type, customer_id, device_name, device_pic, device_mac, device_sn, remark, create_by, update_by, create_time, update_time
</sql>
<sql id="device_Column_List">
d.id,
d.device_type, d.customer_id, d.device_name, d.device_pic, d.device_mac,
d.device_sn, d.remark, d.create_by, d.update_by, d.create_time, d.update_time,
d.binding_status, d.current_owner_id, d.original_owner_id, d.customer_name,
d.device_imei, d.longitude, d.latitude, d.tenant_id
</sql>
<!-- 分页查询设备 -->
<select id="findAll" resultType="com.fuyuanshen.modules.system.domain.Device">
select
d.id, d.customer_id, d.customer_name, d.device_name,
d.device_pic, d.device_mac, d.device_sn, d.create_by, d.update_by,
d.create_time, d.update_time, d.device_type, d.remark, d.device_status, d.binding_status,t.type_name
<include refid="device_Column_List" />,
t.type_name as typeName
from device d
left join device_type t
on d.device_type = t.id

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.modules.system.mapper.DeviceTypeGrantsMapper">
<resultMap id="BaseResultMap" type="com.fuyuanshen.modules.system.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

@ -44,24 +44,23 @@
<!-- 查询所有设备类型 -->
<select id="findAll" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from device_type
SELECT dt.*
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 type_name like concat('%', TRIM(#{criteria.typeName}), '%')
and dt.type_name like concat('%', TRIM(#{criteria.typeName}), '%')
</if>
<if test="criteria.customerId != null">
and customer_id = #{criteria.customerId}
and dt.customer_id = #{criteria.customerId}
</if>
<if test="criteria.tenantId != null">
and tenant_id = #{criteria.tenantId}
and dt.tenant_id = #{criteria.tenantId}
</if>
<if test="criteria.createBy != null">
and create_by = #{criteria.createBy}
and dt.create_by = #{criteria.createBy}
</if>
</where>
order by id desc
order by create_time desc
</select>
</mapper>