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

@ -29,6 +29,9 @@ import com.fuyuanshen.web.service.SysRegisterService;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -157,4 +160,14 @@ public class AppAuthController {
return R.ok(result); return R.ok(result);
} }
@GetMapping("/test")
public void testSend() {
// 在创建完SmsBlend实例后再未手动调用注销的情况下框架会持有该实例可以直接通过指定configId来获取想要的配置如果你想使用
// 负载均衡形式获取实例只要使用getSmsBlend的无参重载方法即可如果你仅有一个配置也可以使用该方法
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
SmsResponse smsResponse = smsBlend.sendMessage("18656573389", "123");
}
} }

View File

@ -174,11 +174,15 @@ sms:
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 # 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: alibaba supplier: alibaba
# 有些称为accessKey有些称之为apiKey也有称为sdkKey或者appId。 # 有些称为accessKey有些称之为apiKey也有称为sdkKey或者appId。
access-key-id: 您的accessKey access-key-id: LTAI5tJdDNpZootsPQ5hdELx
# 称为accessSecret有些称之为apiSecret # 称为accessSecret有些称之为apiSecret
access-key-secret: 您的accessKeySecret access-key-secret: mU4WtffcCXpHPz5tLwQpaGtLsJXONt
signature: 您的短信签名 #模板ID 非必须配置如果使用sendMessage的快速发送需此配置
sdk-app-id: 您的sdkAppId template-id: SMS_322180518
#模板变量 上述模板的变量
templateName: code
signature: 湖北星汉研创科技
# sdk-app-id: 您的sdkAppId
config2: config2:
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 # 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: tencent supplier: tencent

View File

@ -0,0 +1,304 @@
--- # 监控中心配置
spring.boot.admin.client:
# 增加客户端开关
enabled: false
url: http://localhost:9090/admin
instance:
service-host-type: IP
metadata:
username: ${spring.boot.admin.client.username}
userpassword: ${spring.boot.admin.client.password}
username: @monitor.username@
password: @monitor.password@
--- # snail-job 配置
snail-job:
enabled: false
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
group: "fys_group"
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表
token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
server:
host: 127.0.0.1
port: 17888
# 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段
namespace: ${spring.profiles.active}
# 随主应用端口漂移
port: 2${server.port}
# 客户端ip指定
host:
# RPC类型: netty, grpc
rpc-type: grpc
--- # 数据源配置
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
p6spy: true
# 设置默认的数据源或者数据源组,默认值即为 master
primary: master
# 严格模式 匹配不到数据源则报错
strict: true
datasource:
# 主库数据源
master:
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://47.120.79.150:3306/fys-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: Jq_123456#
# # 从库数据源
# slave:
# lazy: true
# type: ${spring.datasource.type}
# driverClassName: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username:
# password:
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
hikari:
# 最大连接池数量
maxPoolSize: 20
# 最小空闲线程数量
minIdle: 10
# 配置获取连接等待超时的时间
connectionTimeout: 30000
# 校验超时时间
validationTimeout: 5000
# 空闲连接存活最大时间默认10分钟
idleTimeout: 600000
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
maxLifetime: 1800000
# 多久检查一次连接的活性
keepaliveTime: 30000
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring.data:
redis:
# 地址
host: 47.120.79.150
# 端口默认为6379
port: 6379
# 数据库索引
database: 2
# redis 密码必须配置
password: xhYc_djkl382^#780!
# 连接超时时间
timeout: 10s
# 是否开启ssl
ssl.enabled: false
# redisson 配置
redisson:
# redis key前缀
keyPrefix:
# 线程池数量
threads: 4
# Netty线程池数量
nettyThreads: 8
# 单节点配置
singleServerConfig:
# 客户端名称 不能用中文
clientName: fys-Vue-Plus
# 最小空闲连接数
connectionMinimumIdleSize: 8
# 连接池大小
connectionPoolSize: 32
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 命令等待超时,单位:毫秒
timeout: 3000
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
--- # mail 邮件发送
mail:
enabled: false
host: smtp.163.com
port: 465
# 是否需要用户名密码验证
auth: true
# 发送方遵循RFC-822标准
from: xxx@163.com
# 用户名注意如果使用foxmail邮箱此处user为qq号
user: xxx@163.com
# 密码注意某些邮箱需要为SMTP服务单独设置密码详情查看相关帮助
pass: xxxxxxxxxx
# 使用 STARTTLS安全连接STARTTLS是对纯文本通信协议的扩展。
starttlsEnable: true
# 使用SSL安全连接
sslEnable: true
# SMTP超时时长单位毫秒缺省值不超时
timeout: 0
# Socket连接超时值单位毫秒缺省值不超时
connectionTimeout: 0
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用
sms:
# 配置源类型用于标定配置来源(interface,yaml)
config-type: yaml
# 用于标定yml中的配置是否开启短信拦截接口配置不受此限制
restricted: true
# 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
minute-max: 1
# 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
account-max: 30
# 以下配置来自于 com.fuyuanshen.sms4j.provider.config.BaseConfig类中
blends:
# 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可
# 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户
config1:
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: alibaba
# 有些称为accessKey有些称之为apiKey也有称为sdkKey或者appId。
access-key-id: 您的accessKey
# 称为accessSecret有些称之为apiSecret
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
config2:
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: tencent
access-key-id: 您的accessKey
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
--- # 三方授权
justauth:
# 前端外网访问地址
address: http://localhost:80
type:
maxkey:
# maxkey 服务器地址
# 注意 如下均配置均不需要修改 maxkey 已经内置好了数据
server-url: http://sso.maxkey.top
client-id: 876892492581044224
client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8
redirect-uri: ${justauth.address}/social-callback?source=maxkey
topiam:
# topiam 服务器地址
server-url: http://127.0.0.1:1898/api/v1/authorize/y0q************spq***********8ol
client-id: 449c4*********937************759
client-secret: ac7***********1e0************28d
redirect-uri: ${justauth.address}/social-callback?source=topiam
scopes: [openid, email, phone, profile]
qq:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=qq
union-id: false
weibo:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=weibo
gitee:
client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98
client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac
redirect-uri: ${justauth.address}/social-callback?source=gitee
dingtalk:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=dingtalk
baidu:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=baidu
csdn:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=csdn
coding:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=coding
coding-group-name: xx
oschina:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=oschina
alipay_wallet:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet
alipay-public-key: MIIB**************DAQAB
wechat_open:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_open
wechat_mp:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_mp
wechat_enterprise:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise
agent-id: 1000002
gitlab:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=gitlab
gitea:
# 前端改动 https://gitee.com/JavaLionLi/plus-ui/pulls/204
# gitea 服务器地址
server-url: https://demo.gitea.com
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=gitea
# 文件存储路径
file:
mac:
path: ~/file/
avatar: ~/avatar/
linux:
path: /home/eladmin/file/
avatar: /home/eladmin/avatar/
windows:
path: C:\eladmin\file\
avatar: C:\eladmin\avatar\
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5
device:
pic: C:\eladmin\file\ #设备图片存储路径
ip: http://fuyuanshen.com:81/ #服务器地址
app_avatar:
pic: C:\eladmin\file\ #设备图片存储路径
#ip: http://fuyuanshen.com:81/ #服务器地址
ip: https://fuyuanshen.com/ #服务器地址
# MQTT配置
mqtt:
username: admin
password: fys123456
url: tcp://47.107.152.87:1883
subClientId: fys_subClient_01
subTopic: worker/alert/#,worker/location/#
pubTopic: worker/location
pubClientId: fys_pubClient_01

View File

@ -216,6 +216,8 @@ springdoc:
packages-to-scan: com.fuyuanshen.equipment packages-to-scan: com.fuyuanshen.equipment
- group: 客户管理模块 - group: 客户管理模块
packages-to-scan: com.fuyuanshen.customer packages-to-scan: com.fuyuanshen.customer
- group: APP模块
packages-to-scan: com.fuyuanshen.app
# 防止XSS攻击 # 防止XSS攻击
xss: xss:

View File

@ -0,0 +1,24 @@
package com.fuyuanshen.common.sms.controller;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author: 默苍璃
* @date: 2025-07-0714:02
*/
@RestController
public class TestSMSController {
@GetMapping("/test")
public void testSend() {
// 在创建完SmsBlend实例后再未手动调用注销的情况下框架会持有该实例可以直接通过指定configId来获取想要的配置如果你想使用
// 负载均衡形式获取实例只要使用getSmsBlend的无参重载方法即可如果你仅有一个配置也可以使用该方法
SmsBlend smsBlend = SmsFactory.getSmsBlend("alibaba");
SmsResponse smsResponse = smsBlend.sendMessage("18656573389", "123");
}
}

View File

@ -58,4 +58,5 @@ public class ResourcesConfig implements WebMvcConfigurer {
public GlobalExceptionHandler globalExceptionHandler() { public GlobalExceptionHandler globalExceptionHandler() {
return new GlobalExceptionHandler(); return new GlobalExceptionHandler();
} }
} }

View File

@ -15,6 +15,11 @@
<dependencies> <dependencies>
<dependency>
<groupId>com.fuyuanshen</groupId>
<artifactId>fys-equipment</artifactId>
</dependency>
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.fuyuanshen</groupId> <groupId>com.fuyuanshen</groupId>

View File

@ -6,8 +6,8 @@ import com.fuyuanshen.app.domain.APPDeviceType;
import com.fuyuanshen.app.domain.dto.APPUnbindDTO; import com.fuyuanshen.app.domain.dto.APPUnbindDTO;
import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria; import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria;
import com.fuyuanshen.app.service.equipment.APPDeviceService; import com.fuyuanshen.app.service.equipment.APPDeviceService;
import com.fuyuanshen.common.core.domain.PageResult;
import com.fuyuanshen.common.core.domain.ResponseVO; import com.fuyuanshen.common.core.domain.ResponseVO;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -34,16 +34,11 @@ public class APPDeviceController {
@PostMapping(value = "/list") @PostMapping(value = "/list")
@Operation(summary = "APP客户设备列表") @Operation(summary = "APP客户设备列表")
public ResponseVO<PageResult<APPDevice>> appDeviceList(@RequestBody APPDeviceQueryCriteria criteria) { public TableDataInfo<APPDevice> appDeviceList(@RequestBody APPDeviceQueryCriteria criteria) {
Page<APPDevice> page = new Page<>(criteria.getPage(), criteria.getSize()); Page<APPDevice> page = new Page<>(criteria.getPage(), criteria.getSize());
PageResult<APPDevice> devices = null;
try { TableDataInfo<APPDevice> devices = appDeviceService.appDeviceList(page, criteria);
devices = appDeviceService.appDeviceList(page, criteria); return devices;
} catch (Exception e) {
log.error("queryDevice error: " + e.getMessage());
return ResponseVO.fail("");
}
return ResponseVO.success(devices);
} }
@ -65,16 +60,11 @@ public class APPDeviceController {
@GetMapping @GetMapping
@Operation(summary = "WEB端查看APP客户设备绑定") @Operation(summary = "WEB端查看APP客户设备绑定")
public ResponseVO<PageResult<APPDevice>> queryAPPDevice(APPDeviceQueryCriteria criteria) { public TableDataInfo<APPDevice> queryAPPDevice(APPDeviceQueryCriteria criteria) {
Page<APPDevice> page = new Page<>(criteria.getPage(), criteria.getSize()); Page<APPDevice> page = new Page<>(criteria.getPage(), criteria.getSize());
PageResult<APPDevice> devices = null; TableDataInfo<APPDevice> devices = null;
try { devices = appDeviceService.queryAll(page, criteria);
devices = appDeviceService.queryAll(page, criteria); return devices;
} catch (Exception e) {
log.error("queryDevice error: " + e.getMessage());
return ResponseVO.fail("");
}
return ResponseVO.success(devices);
} }

View File

@ -0,0 +1,48 @@
package com.fuyuanshen.app.enums;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* 用户类型枚举
*
* @author: 默苍璃
* @date: 2025-06-1811:14
*/
public enum UserType {
APP(0, "APP"), MINI_PROGRAM(1, "小程序");
private final int value;
private final String description;
UserType(int value, String description) {
this.value = value;
this.description = description;
}
@JsonValue
public int getValue() {
return value;
}
public String getDescription() {
return description;
}
/**
* 根据值获取对应的枚举
*
* @param value 枚举值
* @return 对应的枚举对象
*/
public static UserType fromValue(int value) {
for (UserType userType : values()) {
if (userType.getValue() == value) {
return userType;
}
}
throw new IllegalArgumentException("Invalid user type value: " + value);
}
}

View File

@ -0,0 +1,29 @@
package com.fuyuanshen.app.mapper.equipment;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fuyuanshen.app.domain.APPDeviceType;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author 97433
* @description 针对表【app_device_type(设备类型表)】的数据库操作Mapper
* @createDate 2025-06-24 11:16:18
* @Entity system.domain.AppDeviceType
*/
@Mapper
public interface AppDeviceTypeMapper extends BaseMapper<APPDeviceType> {
/**
* 查询设备类型列表
*
* @param criteria 查询条件
* @return 设备类型列表
*/
List<APPDeviceType> appTypeList(@Param("criteria") DeviceQueryCriteria criteria);
}

View File

@ -7,6 +7,7 @@ import com.fuyuanshen.app.domain.APPDeviceType;
import com.fuyuanshen.app.domain.dto.APPUnbindDTO; import com.fuyuanshen.app.domain.dto.APPUnbindDTO;
import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria; import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria;
import com.fuyuanshen.common.core.domain.PageResult; import com.fuyuanshen.common.core.domain.PageResult;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import java.util.List; import java.util.List;
@ -22,7 +23,7 @@ public interface APPDeviceService extends IService<APPDevice> {
* *
* @param criteria * @param criteria
*/ */
PageResult<APPDevice> appDeviceList(Page<APPDevice> page, APPDeviceQueryCriteria criteria); TableDataInfo<APPDevice> appDeviceList(Page<APPDevice> page, APPDeviceQueryCriteria criteria);
/** /**
@ -47,7 +48,7 @@ public interface APPDeviceService extends IService<APPDevice> {
* @param page * @param page
* @return * @return
*/ */
PageResult<APPDevice> queryAll(Page<APPDevice> page, APPDeviceQueryCriteria criteria); TableDataInfo<APPDevice> queryAll(Page<APPDevice> page, APPDeviceQueryCriteria criteria);
/** /**
* APP/小程序用户设备解绑 * APP/小程序用户设备解绑

View File

@ -10,9 +10,20 @@ import com.fuyuanshen.app.domain.APPDevice;
import com.fuyuanshen.app.domain.APPDeviceType; import com.fuyuanshen.app.domain.APPDeviceType;
import com.fuyuanshen.app.domain.dto.APPUnbindDTO; import com.fuyuanshen.app.domain.dto.APPUnbindDTO;
import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria; import com.fuyuanshen.app.domain.query.APPDeviceQueryCriteria;
import com.fuyuanshen.app.enums.UserType;
import com.fuyuanshen.app.mapper.equipment.APPDeviceMapper; import com.fuyuanshen.app.mapper.equipment.APPDeviceMapper;
import com.fuyuanshen.app.mapper.equipment.AppDeviceTypeMapper;
import com.fuyuanshen.app.service.equipment.APPDeviceService; import com.fuyuanshen.app.service.equipment.APPDeviceService;
import com.fuyuanshen.common.core.domain.PageResult; import com.fuyuanshen.common.core.domain.PageResult;
import com.fuyuanshen.common.core.exception.BadRequestException;
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.enums.BindingStatusEnum;
import com.fuyuanshen.equipment.enums.CommunicationModeEnum;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -34,6 +45,9 @@ import java.util.stream.Collectors;
public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice> implements APPDeviceService { public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice> implements APPDeviceService {
private final APPDeviceMapper appDeviceMapper; private final APPDeviceMapper appDeviceMapper;
private final DeviceMapper deviceMapper;
private final AppDeviceTypeMapper appDeviceTypeMapper;
private final DeviceTypeMapper deviceTypeMapper;
/** /**
@ -42,7 +56,7 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
* @param criteria * @param criteria
*/ */
@Override @Override
public PageResult<APPDevice> appDeviceList(Page<APPDevice> page, APPDeviceQueryCriteria criteria) { public TableDataInfo<APPDevice> appDeviceList(Page<APPDevice> page, APPDeviceQueryCriteria criteria) {
// criteria.setCustomerId(SecurityUtils.getCurrentUserId()); // criteria.setCustomerId(SecurityUtils.getCurrentUserId());
// IPage<APPDevice> devices = appDeviceMapper.appDeviceList(page, criteria); // IPage<APPDevice> devices = appDeviceMapper.appDeviceList(page, criteria);
// return new PageResult<>(devices.getRecords(), devices.getTotal()); // return new PageResult<>(devices.getRecords(), devices.getTotal());
@ -72,56 +86,58 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
@Override @Override
@Transactional @Transactional
public void appBindDevice(APPDeviceQueryCriteria criteria) { public void appBindDevice(APPDeviceQueryCriteria criteria) {
// List<Device> devices = new ArrayList<>();
// List<Device> devices = new ArrayList<>(); if (criteria.getCommunicationMode().equals(CommunicationModeEnum.BLUETOOTH.getValue())) {
// devices = deviceMapper.selectList(new QueryWrapper<Device>()
// if (criteria.getCommunicationMode().equals(CommunicationModeEnum.BLUETOOTH.getValue())) { .eq("original_device_id", null)
// devices = deviceMapper.selectList(new QueryWrapper<Device>().eq("device_mac", criteria.getDeviceMac())); .eq("device_mac", criteria.getDeviceMac()));
// if (CollectionUtil.isEmpty(devices)) { if (CollectionUtil.isEmpty(devices)) {
// throw new BadRequestException("请先将设备入库!!!"); throw new BadRequestException("请先将设备入库!!!");
// } }
// List<APPDevice> appDevices = appDeviceMapper.selectList(new QueryWrapper<APPDevice>() List<APPDevice> appDevices = appDeviceMapper.selectList(new QueryWrapper<APPDevice>()
// .eq("device_mac", criteria.getDeviceMac()).eq("binding_type", UserType.APP.getValue())); .eq("device_mac", criteria.getDeviceMac()).eq("binding_type", UserType.APP.getValue()));
// if (CollectionUtil.isNotEmpty(appDevices)) { if (CollectionUtil.isNotEmpty(appDevices)) {
// throw new BadRequestException("该设备已绑定!!!"); throw new BadRequestException("该设备已绑定!!!");
// } }
// } }
//
// if (criteria.getCommunicationMode().equals(CommunicationModeEnum.FOUR_G.getValue())) { if (criteria.getCommunicationMode().equals(CommunicationModeEnum.FOUR_G.getValue())) {
// devices = deviceMapper.selectList(new QueryWrapper<Device>().eq("device_imei", criteria.getDeviceImei())); devices = deviceMapper.selectList(new QueryWrapper<Device>()
// if (CollectionUtil.isEmpty(devices)) { .eq("original_device_id", null)
// throw new BadRequestException("请先将设备入库!!!"); .eq("device_imei", criteria.getDeviceImei()));
// } if (CollectionUtil.isEmpty(devices)) {
// List<APPDevice> appDevices = appDeviceMapper.selectList(new QueryWrapper<APPDevice>() throw new BadRequestException("请先将设备入库!!!");
// .eq("device_imei", criteria.getDeviceImei()).eq("binding_type", UserType.APP.getValue())); }
// if (CollectionUtil.isNotEmpty(appDevices)) { List<APPDevice> appDevices = appDeviceMapper.selectList(new QueryWrapper<APPDevice>()
// throw new BadRequestException("该设备已绑定!!!"); .eq("device_imei", criteria.getDeviceImei()).eq("binding_type", UserType.APP.getValue()));
// } if (CollectionUtil.isNotEmpty(appDevices)) {
// } throw new BadRequestException("该设备已绑定!!!");
// }
// Device device = devices.get(0); }
// device.setBindingStatus(BindingStatusEnum.BOUND.getCode());
// deviceMapper.updateById(device); Device device = devices.get(0);
// device.setBindingStatus(BindingStatusEnum.BOUND.getCode());
// APPDevice appDevice = new APPDevice(); deviceMapper.updateById(device);
// BeanUtil.copyProperties(device, appDevice);
// appDevice.setBindingType(UserType.APP.getValue()); APPDevice appDevice = new APPDevice();
// appDevice.setBindingStatus(BindingStatusEnum.BOUND.getCode()); BeanUtil.copyProperties(device, appDevice);
// Long currentUserId = SecurityUtils.getCurrentUserId(); appDevice.setBindingType(UserType.APP.getValue());
// appDevice.setCustomerId(currentUserId); appDevice.setBindingStatus(BindingStatusEnum.BOUND.getCode());
// appDevice.setCreateTime(new Timestamp(System.currentTimeMillis())); Long userId = LoginHelper.getUserId();
// // 设备类型名称 appDevice.setCustomerId(userId);
// appDevice.setDeviceTypeName(device.getTypeName()); appDevice.setCreateTime(new Timestamp(System.currentTimeMillis()));
// appDeviceMapper.insert(appDevice); // 设备类型名称
// appDevice.setDeviceTypeName(device.getTypeName());
// APPDeviceType appDeviceType = appDeviceTypeMapper.selectById(device.getDeviceType()); appDeviceMapper.insert(appDevice);
// if (appDeviceType == null) {
// DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType()); APPDeviceType appDeviceType = appDeviceTypeMapper.selectById(device.getDeviceType());
// APPDeviceType type = new APPDeviceType(); if (appDeviceType == null) {
// BeanUtil.copyProperties(deviceType, type); DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
// type.setCustomerId(currentUserId); APPDeviceType type = new APPDeviceType();
// appDeviceTypeMapper.insert(type); BeanUtil.copyProperties(deviceType, type);
// } type.setCustomerId(userId);
appDeviceTypeMapper.insert(type);
}
} }
@ -134,11 +150,9 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
* @return * @return
*/ */
@Override @Override
public PageResult<APPDevice> queryAll(Page<APPDevice> page, APPDeviceQueryCriteria criteria) { public TableDataInfo<APPDevice> queryAll(Page<APPDevice> page, APPDeviceQueryCriteria criteria) {
// IPage<APPDevice> devices = appDeviceMapper.queryAll(page, criteria); IPage<APPDevice> devices = appDeviceMapper.queryAll(page, criteria);
// return new PageResult<>(devices.getRecords(), devices.getTotal()); return new TableDataInfo<>(devices.getRecords(), devices.getTotal());
return null;
} }

View File

@ -0,0 +1,35 @@
<?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.app.mapper.equipment.AppDeviceTypeMapper">
<resultMap id="BaseResultMap" type="com.fuyuanshen.app.domain.APPDeviceType">
<id property="id" column="id"/>
<result property="typeName" column="type_name"/>
<result property="isSupportBle" column="is_support_ble"/>
<result property="locateMode" column="locate_mode"/>
<result property="networkWay" column="network_way"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="customerId" column="customer_id"/>
<result property="communicationMode" column="communication_mode"/>
</resultMap>
<sql id="Base_Column_List">
id
,type_name,is_support_ble,locate_mode,network_way,create_by,
update_by,create_time,update_time,customer_id,communication_mode
</sql>
<!-- 查询设备类型列表 -->
<select id="appTypeList" resultType="com.fuyuanshen.app.domain.APPDeviceType">
select d.* from app_device_type as d
<where>
and d.customer_id = #{criteria.customerId}
</where>
order by d.create_time desc
</select>
</mapper>

View File

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

View File

@ -0,0 +1,34 @@
package com.fuyuanshen.customer.constant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 数组相关常量
*
* @author: 默苍璃
* @date: 2025-07-0710:10
*/
public class ArrayConstants {
/**
* 默认长整型数组
*/
public static final Long[] DEFAULT_LONG_ARRAY = {666L};
public static final Long DEFAULT_LONG = 666L;
/**
* 空字符串数组
*/
public static final String[] EMPTY_STRING_ARRAY = new String[0];
/**
* 获取只读的默认长整型列表
*/
public static List<Long> getDefaultLongList() {
return Collections.unmodifiableList(new ArrayList<>(List.of(DEFAULT_LONG_ARRAY)));
}
}

View File

@ -6,11 +6,18 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyuanshen.common.core.domain.model.LoginUser; import com.fuyuanshen.common.core.domain.model.LoginUser;
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.customer.constant.ArrayConstants;
import com.fuyuanshen.customer.domain.Customer; import com.fuyuanshen.customer.domain.Customer;
import com.fuyuanshen.customer.domain.query.UserQueryCriteria; import com.fuyuanshen.customer.domain.query.UserQueryCriteria;
import com.fuyuanshen.customer.domain.vo.ConsumerVo; import com.fuyuanshen.customer.domain.vo.ConsumerVo;
import com.fuyuanshen.customer.mapper.CustomerMapper; import com.fuyuanshen.customer.mapper.CustomerMapper;
import com.fuyuanshen.customer.service.CustomerService; import com.fuyuanshen.customer.service.CustomerService;
import com.fuyuanshen.system.domain.SysUserRole;
import com.fuyuanshen.system.domain.bo.SysUserBo;
import com.fuyuanshen.system.mapper.SysRoleMapper;
import com.fuyuanshen.system.mapper.SysUserRoleMapper;
import com.fuyuanshen.system.service.ISysUserService;
import com.fuyuanshen.system.service.impl.SysUserServiceImpl;
import io.undertow.util.BadRequestException; import io.undertow.util.BadRequestException;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -28,6 +35,9 @@ import java.util.Set;
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements CustomerService { public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements CustomerService {
private final CustomerMapper customerMapper; private final CustomerMapper customerMapper;
private final SysUserServiceImpl userService;
private final SysRoleMapper roleMapper;
private final SysUserRoleMapper userRoleMapper;
/** /**
@ -57,6 +67,7 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
*/ */
@Override @Override
public List<Customer> queryAllCustomers(UserQueryCriteria criteria) { public List<Customer> queryAllCustomers(UserQueryCriteria criteria) {
criteria.setPid(LoginHelper.getUserId());
List<Customer> users = customerMapper.queryAllCustomers(criteria); List<Customer> users = customerMapper.queryAllCustomers(criteria);
return users; return users;
} }
@ -83,6 +94,13 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
customer.setPid(loginUser.getUserId()); customer.setPid(loginUser.getUserId());
save(customer); save(customer);
// 新增用户与角色管理
SysUserRole sysUserRole = new SysUserRole();
sysUserRole.setUserId(customer.getCustomerId());
sysUserRole.setRoleId(ArrayConstants.DEFAULT_LONG);
userRoleMapper.insert(sysUserRole);
} }

View File

@ -148,7 +148,6 @@
</where> </where>
</select> </select>
<!-- 查询所有客户 --> <!-- 查询所有客户 -->
<select id="queryAllCustomers" resultType="com.fuyuanshen.customer.domain.Customer"> <select id="queryAllCustomers" resultType="com.fuyuanshen.customer.domain.Customer">
select u.user_id as customerId, select u.user_id as customerId,
@ -165,6 +164,9 @@
#{item} #{item}
</foreach> </foreach>
</if> </if>
<if test="criteria.pid != null">
and u.pid = #{criteria.pid}
</if>
</where> </where>
</select> </select>
@ -187,16 +189,15 @@
<!-- 根据id查询客户 --> <!-- 根据id查询客户 -->
<select id="queryCustomerById" resultType="com.fuyuanshen.customer.domain.Customer"> <select id="queryCustomerById" resultType="com.fuyuanshen.customer.domain.Customer">
select u.* select u.*,u.user_id as customerId
from sys_user u from sys_user u
<where> <where>
<if test="customerId!= null"> <if test="customerId!= null">
and u.user_id = customerId) and u.user_id = #{customerId}
</if> </if>
<if test="pid != null"> <if test="pid != null">
and u.pid = pid) and u.pid = #{pid}
</if> </if>
</where> </where>
</select> </select>

View File

@ -17,6 +17,12 @@
</description> </description>
<dependencies> <dependencies>
<!-- <dependency> -->
<!-- <groupId>com.fuyuanshen</groupId> -->
<!-- <artifactId>fys-app</artifactId> -->
<!-- </dependency> -->
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.fuyuanshen</groupId> <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")}) @Operation(summary = "分页查询设备列表", security = {@SecurityRequirement(name = "bearer-key")})
@GetMapping @GetMapping
public TableDataInfo<Device> queryDevice(DeviceQueryCriteria criteria) throws IOException { 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); return deviceService.queryAll(criteria, page);
} }
@ -133,9 +133,9 @@ public class DeviceController {
// @Log("撤回设备") // @Log("撤回设备")
@Operation(summary = "撤回分配设备") @Operation(summary = "撤回分配设备")
@PostMapping(value = "/withdraw") @PostMapping(value = "/withdraw")
public ResponseVO<Object> withdrawDevice(@Validated @ModelAttribute DeviceForm deviceForm) { public ResponseVO<Object> withdrawDevice(@RequestBody List<Long> ids) {
try { try {
deviceService.withdrawDevice(deviceForm); deviceService.withdrawDevice(ids);
} catch (Exception e) { } catch (Exception e) {
log.error("updateDevice error: " + e.getMessage()); log.error("updateDevice error: " + e.getMessage());
return ResponseVO.fail("出错了"); return ResponseVO.fail("出错了");

View File

@ -33,7 +33,7 @@ public class DeviceTypeController {
@GetMapping @GetMapping
@Operation(summary = "分页查询设备类型") @Operation(summary = "分页查询设备类型")
public TableDataInfo<DeviceType> queryDeviceType(DeviceTypeQueryCriteria criteria) { 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); return deviceTypeService.queryAll(criteria, page);
} }

View File

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

View File

@ -27,6 +27,19 @@ public class DeviceType extends TenantEntity {
@Schema(name = "创建该类型的客户") @Schema(name = "创建该类型的客户")
private Long ownerCustomerId; private Long ownerCustomerId;
/**
* 原始所有者(创建者)
* original_owner_id
*/
@Schema(name = "原始所有者(创建者)")
private Long originalOwnerId;
/**
* 原始设备
*/
@Schema(name = "原始设备类型")
private Long originalDeviceId;
@NotBlank(message = "设备类型名称不能为空") @NotBlank(message = "设备类型名称不能为空")
@Schema(name = "类型名称", required = true) @Schema(name = "类型名称", required = true)
private String typeName; 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) @ColumnWidth(20)
private String deviceName; private String deviceName;
@ExcelProperty(value = "设备图片", converter = ByteArrayImageConverter.class) @ExcelProperty(value = "设备图片", converter = ByteArrayImageConverter.class)
@ColumnWidth(15) @ColumnWidth(15)
private byte[] devicePic; private byte[] devicePic;

View File

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

View File

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

View File

@ -31,9 +31,8 @@ public class DeviceTypeQueryCriteria extends BaseEntity implements Serializable
private Long tenantId; private Long tenantId;
@Schema(name = "页码", example = "1") @Schema(name = "页码", example = "1")
private Integer page = 1; private Integer pageNum = 1;
@Schema(name = "每页数据量", example = "10") @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 @Slf4j
public class UploadDeviceDataListener implements ReadListener<DeviceExcelImportDTO> { public class UploadDeviceDataListener implements ReadListener<DeviceExcelImportDTO> {
// 存储图片数据的映射 // 存储图片数据的映射
private final Map<Integer, byte[]> rowImageMap = new HashMap<>(); private final Map<Integer, byte[]> rowImageMap = new HashMap<>();
@ -48,6 +47,7 @@ public class UploadDeviceDataListener implements ReadListener<DeviceExcelImportD
this.params = params; this.params = params;
} }
public ImportResult getImportResult() { public ImportResult getImportResult() {
ImportResult result = new ImportResult(); ImportResult result = new ImportResult();
result.setSuccessCount(successCount); result.setSuccessCount(successCount);
@ -151,23 +151,26 @@ public class UploadDeviceDataListener implements ReadListener<DeviceExcelImportD
Device device = rowDeviceMap.get(rowIndex); Device device = rowDeviceMap.get(rowIndex);
DeviceExcelImportDTO originalDto = rowDtoMap.get(rowIndex); DeviceExcelImportDTO originalDto = rowDtoMap.get(rowIndex);
try { try {
DeviceQueryCriteria criteria = new DeviceQueryCriteria(); // DeviceQueryCriteria criteria = new DeviceQueryCriteria();
criteria.setDeviceMac(device.getDeviceMac()); // criteria.setDeviceMac(device.getDeviceMac());
criteria.setTenantId(params.getTenantId()); // criteria.setTenantId(params.getTenantId());
List<Device> deviceList = params.getDeviceMapper().findAll(criteria); // List<Device> deviceList = params.getDeviceMapper().findAll(criteria);
if (!deviceList.isEmpty()) { // if (!deviceList.isEmpty()) {
throw new RuntimeException("设备MAC重复"); // throw new RuntimeException("设备MAC重复");
} // }
device.setTenantId(params.getTenantId()); // device.setTenantId(params.getTenantId());
// 设备类型 // 设备类型
QueryWrapper<DeviceType> wrapper = new QueryWrapper<>(); QueryWrapper<DeviceType> wrapper = new QueryWrapper<>();
wrapper.eq("type_name", device.getTypeName()); 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); List<DeviceType> deviceTypes = params.getDeviceTypeMapper().selectList(wrapper);
if (CollectionUtil.isNotEmpty(deviceTypes)) { if (CollectionUtil.isNotEmpty(deviceTypes)) {
device.setDeviceType(deviceTypes.get(0).getId()); device.setDeviceType(deviceTypes.get(0).getId());
} }
device.setCurrentOwnerId(loginUser.getUserId());
device.setOriginalOwnerId(loginUser.getUserId());
device.setCreateByName(loginUser.getNickname());
params.getDeviceService().save(device); params.getDeviceService().save(device);
successCount++; successCount++;
log.info("行 {} 数据插入成功", rowIndex); log.info("行 {} 数据插入成功", rowIndex);

View File

@ -33,4 +33,19 @@ public interface DeviceMapper extends BaseMapper<Device> {
List<Device> findAllDevices(@Param("criteria") DeviceQueryCriteria criteria); List<Device> findAllDevices(@Param("criteria") DeviceQueryCriteria criteria);
Page<AppDeviceVo> queryAppDeviceList(Page<AppDeviceVo> page,@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); 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; package com.fuyuanshen.equipment.service.impl;
import cn.hutool.core.bean.BeanUtil; 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.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; 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.domain.vo.CustomerVo;
import com.fuyuanshen.equipment.enums.BindingStatusEnum; import com.fuyuanshen.equipment.enums.BindingStatusEnum;
import com.fuyuanshen.equipment.enums.CommunicationModeEnum; import com.fuyuanshen.equipment.enums.CommunicationModeEnum;
import com.fuyuanshen.equipment.enums.DeviceStatusEnum;
import com.fuyuanshen.equipment.mapper.DeviceMapper; import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper; import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import com.fuyuanshen.equipment.service.DeviceService; import com.fuyuanshen.equipment.service.DeviceService;
@ -40,9 +42,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Objects;
/** /**
* @Description: * @Description:
@ -122,7 +122,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void addDevice(DeviceForm deviceForm) throws Exception { public void addDevice(DeviceForm deviceForm) throws Exception {
DeviceTypeQueryCriteria queryCriteria = new DeviceTypeQueryCriteria(); DeviceTypeQueryCriteria queryCriteria = new DeviceTypeQueryCriteria();
queryCriteria.setDeviceTypeId(deviceForm.getId()); queryCriteria.setDeviceTypeId(deviceForm.getDeviceType());
queryCriteria.setCustomerId(LoginHelper.getUserId()); queryCriteria.setCustomerId(LoginHelper.getUserId());
List<DeviceType> deviceTypes = deviceTypeMapper.findAll(queryCriteria); List<DeviceType> deviceTypes = deviceTypeMapper.findAll(queryCriteria);
if (deviceTypes.isEmpty()) { if (deviceTypes.isEmpty()) {
@ -141,6 +141,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
Device device = new Device(); Device device = new Device();
LoginUser loginUser = LoginHelper.getLoginUser(); LoginUser loginUser = LoginHelper.getLoginUser();
device.setCurrentOwnerId(loginUser.getUserId()); device.setCurrentOwnerId(loginUser.getUserId());
device.setOriginalOwnerId(loginUser.getUserId());
device.setCreateByName(loginUser.getNickname()); device.setCreateByName(loginUser.getNickname());
device.setTypeName(deviceTypes.get(0).getTypeName()); device.setTypeName(deviceTypes.get(0).getTypeName());
BeanUtil.copyProperties(deviceForm, device, true); BeanUtil.copyProperties(deviceForm, device, true);
@ -161,7 +162,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
public void update(DeviceForm deviceForm) throws Exception { public void update(DeviceForm deviceForm) throws Exception {
DeviceTypeQueryCriteria deviceTypeQueryCriteria = new DeviceTypeQueryCriteria(); DeviceTypeQueryCriteria deviceTypeQueryCriteria = new DeviceTypeQueryCriteria();
deviceTypeQueryCriteria.setDeviceTypeId(deviceForm.getId()); deviceTypeQueryCriteria.setDeviceTypeId(deviceForm.getDeviceType());
deviceTypeQueryCriteria.setCustomerId(LoginHelper.getUserId()); deviceTypeQueryCriteria.setCustomerId(LoginHelper.getUserId());
List<DeviceType> deviceTypes = deviceTypeMapper.findAll(deviceTypeQueryCriteria); List<DeviceType> deviceTypes = deviceTypeMapper.findAll(deviceTypeQueryCriteria);
if (deviceTypes.isEmpty()) { if (deviceTypes.isEmpty()) {
@ -179,9 +180,11 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
// 处理上传的图片 // 处理上传的图片
// String imageUrl = saveDeviceImage(deviceForm.getFile(), device.getDeviceName()); // String imageUrl = saveDeviceImage(deviceForm.getFile(), device.getDeviceName());
SysOssVo upload = ossService.upload(deviceForm.getFile()); if (deviceForm.getFile() != null) {
// 设置图片路径 SysOssVo upload = ossService.upload(deviceForm.getFile());
deviceForm.setDevicePic(upload.getUrl()); // 设置图片路径
deviceForm.setDevicePic(upload.getUrl());
}
// 更新字段 // 更新字段
BeanUtil.copyProperties(deviceForm, device, true); BeanUtil.copyProperties(deviceForm, device, true);
@ -248,8 +251,65 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
* *
* @param customerVo * @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 @Override
@Transactional(rollbackFor = Exception.class)
public void assignCustomer(CustomerVo customerVo) { public void assignCustomer(CustomerVo customerVo) {
List<Long> deviceIds = customerVo.getDeviceIds(); List<Long> deviceIds = customerVo.getDeviceIds();
Long customerId = customerVo.getCustomerId(); Long customerId = customerVo.getCustomerId();
@ -259,51 +319,117 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
throw new RuntimeException("待分配的客户不存在!!!"); throw new RuntimeException("待分配的客户不存在!!!");
} }
List<Device> devicesToAssign = new ArrayList<>();
List<Long> invalidIds = new ArrayList<>(); List<Long> invalidIds = new ArrayList<>();
List<Device> devices = new ArrayList<>();
for (Long id : deviceIds) { for (Long id : deviceIds) {
Device device = deviceMapper.selectById(id); Device device = deviceMapper.selectById(id);
if (device == null || !Objects.equals(device.getCurrentOwnerId(), LoginHelper.getUserId())) { if (device == null || !Objects.equals(device.getCurrentOwnerId(), LoginHelper.getUserId())) {
invalidIds.add(id); invalidIds.add(id);
continue; continue;
} }
Device assignCustomer = deviceMapper.getAssignCustomer(device.getId());
if (assignCustomer != null) {
invalidIds.add(id);
continue;
}
device.setCustomerId(customerId); device.setCustomerId(customerId);
device.setCustomerName(customer.getNickName()); device.setCustomerName(customer.getNickName());
devices.add(device); devicesToAssign.add(device);
} }
if (!invalidIds.isEmpty()) { if (!invalidIds.isEmpty()) {
throw new RuntimeException("以下设备无法分配ID 不存在或无权限): " + invalidIds); throw new RuntimeException("以下设备无法分配ID 不存在或无权限): " + invalidIds);
} }
devices.forEach((device) -> { // 批量处理设备分配
deviceMapper.updateById(device); batchAssignDevices(devicesToAssign, customer);
device.setId(null);
device.setCurrentOwnerId(customerId);
deviceMapper.insert(device);
DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
deviceType.setId(null);
device.setCurrentOwnerId(customerId);
deviceTypeMapper.insert(deviceType);
});
} }
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 @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.common.satoken.utils.LoginHelper;
import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType; import com.fuyuanshen.equipment.domain.DeviceType;
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.DeviceMapper; import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeGrantsMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper; import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import com.fuyuanshen.equipment.service.DeviceTypeService; import com.fuyuanshen.equipment.service.DeviceTypeService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -22,6 +24,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -37,6 +40,8 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
private final DeviceTypeMapper deviceTypeMapper; private final DeviceTypeMapper deviceTypeMapper;
private final DeviceMapper deviceMapper; private final DeviceMapper deviceMapper;
private final DeviceTypeGrantsMapper deviceTypeGrantsMapper;
/** /**
* 分页查询设备类型 * 分页查询设备类型
@ -85,8 +90,17 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
LoginUser loginUser = LoginHelper.getLoginUser(); LoginUser loginUser = LoginHelper.getLoginUser();
resources.setCustomerId(loginUser.getUserId()); resources.setCustomerId(loginUser.getUserId());
resources.setOwnerCustomerId(loginUser.getUserId()); resources.setOwnerCustomerId(loginUser.getUserId());
resources.setOriginalOwnerId(loginUser.getUserId());
resources.setCreateByName(loginUser.getNickname()); resources.setCreateByName(loginUser.getNickname());
deviceTypeMapper.insert(resources); 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 @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void update(DeviceTypeForm resources) { 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()); DeviceType deviceType = deviceTypeMapper.selectById(resources.getId());
if (deviceType == null) { if (deviceType == null) {
throw new RuntimeException("设备类型不存在"); throw new RuntimeException("设备类型不存在");
@ -121,28 +140,30 @@ 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> invalidIds = new ArrayList<>(); deviceTypeGrantsMapper.deleteByIds(ids);
List<Long> invalidId2 = new ArrayList<>(); //
for (Long id : ids) { // List<Long> invalidIds = new ArrayList<>();
DeviceType deviceType = deviceTypeMapper.selectById(id); // List<Long> invalidId2 = new ArrayList<>();
if (deviceType == null || !Objects.equals(deviceType.getCustomerId(), LoginHelper.getUserId())) { // for (Long id : ids) {
invalidIds.add(id); // DeviceType deviceType = deviceTypeMapper.selectById(id);
} // if (deviceType == null || !Objects.equals(deviceType.getOwnerCustomerId(), LoginHelper.getUserId())) {
DeviceQueryCriteria deviceQueryCriteria = new DeviceQueryCriteria(); // invalidIds.add(id);
deviceQueryCriteria.setDeviceTypeId(id); // }
List<Device> devices = deviceMapper.findAll(deviceQueryCriteria); // DeviceQueryCriteria deviceQueryCriteria = new DeviceQueryCriteria();
if (!devices.isEmpty()) { // deviceQueryCriteria.setDeviceType(id);
invalidId2.add(id); // List<Device> devices = deviceMapper.findAll(deviceQueryCriteria);
} // if (!devices.isEmpty()) {
} // invalidId2.add(id);
if (!invalidIds.isEmpty()) { // }
throw new RuntimeException("以下设备类型无法删除ID 不存在或无权限): " + invalidIds); // }
} // if (!invalidIds.isEmpty()) {
if (!invalidId2.isEmpty()) { // throw new RuntimeException("以下设备类型无法删除ID 不存在或无权限): " + invalidIds);
throw new RuntimeException("以下设备类型无法删除(已绑定设备): " + invalidId2); // }
} // if (!invalidId2.isEmpty()) {
// throw new RuntimeException("以下设备类型无法删除(已绑定设备): " + invalidId2);
deviceTypeMapper.deleteByIds(ids); // }
//
// 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 id="findAll" resultType="com.fuyuanshen.equipment.domain.Device">
select d.* ,t.type_name select d.* , t.type_name
FROM device d FROM device d
LEFT JOIN device_type t ON d.device_type = t.id LEFT JOIN device_type t ON d.device_type = t.id
<where> <where>
@ -52,22 +52,23 @@
<if test="criteria.deviceImei != null"> <if test="criteria.deviceImei != null">
and d.device_imei = #{criteria.deviceImei} and d.device_imei = #{criteria.deviceImei}
</if> </if>
<if test="criteria.deviceTypeId != null"> <if test="criteria.deviceType != null">
and d.device_type = #{criteria.deviceTypeId} and d.device_type = #{criteria.deviceType}
</if> </if>
<if test="criteria.deviceStatus != null"> <if test="criteria.deviceStatus != null">
-- and da.active = #{criteria.deviceStatus} and d.device_status = #{criteria.deviceStatus}
</if> </if>
<if test="criteria.currentOwnerId != null"> <if test="criteria.currentOwnerId != null">
d.current_owner_id = #{criteria.currentOwnerId} and d.current_owner_id = #{criteria.currentOwnerId}
</if> </if>
<if test="criteria.createTime != null and criteria.createTime.size() != 0"> <if test="criteria.params.beginTime != null and criteria.params.endTime != null">
and d.create_time between #{criteria.createTime[0]} and #{criteria.createTime[1]} and d.create_time between #{criteria.params.beginTime} and #{criteria.params.endTime}
</if> </if>
<if test="criteria.tenantId != null"> <if test="criteria.tenantId != null">
AND tenant_id = #{criteria.tenantId} AND tenant_id = #{criteria.tenantId}
</if> </if>
</where> </where>
order by d.create_time desc
</select> </select>
<select id="findAllDevices" resultType="com.fuyuanshen.equipment.domain.Device"> <select id="findAllDevices" resultType="com.fuyuanshen.equipment.domain.Device">
@ -100,4 +101,20 @@
where d.binding_user_id = #{criteria.bindingUserId} where d.binding_user_id = #{criteria.bindingUserId}
</select> </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> </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" > <!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"> <mapper namespace="com.fuyuanshen.equipment.mapper.DeviceTypeMapper">
<resultMap id="BaseResultMap" type="com.fuyuanshen.equipment.domain.DeviceType"> <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="type_name" property="typeName"/>
<result column="is_support_ble" property="isSupportBle"/> <result column="is_support_ble" property="isSupportBle"/>
<result column="locate_mode" property="locateMode"/> <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 , type_name, is_support_ble, locate_mode, network_way, create_by, update_by, create_time, update_time,communication_mode
</sql> </sql>
<!-- 查询所有设备类型 --> <!-- 查询所有设备类型 -->
<select id="findAll" resultMap="BaseResultMap"> <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 FROM device_type dt
JOIN device_type_grants dg ON dt.id = dg.device_type_id
<where> <where>
<if test="criteria.typeName != null and criteria.typeName.trim() != ''"> <if test="criteria.typeName != null and criteria.typeName.trim() != ''">
and dt.type_name like concat('%', TRIM(#{criteria.typeName}), '%') and dt.type_name like concat('%', TRIM(#{criteria.typeName}), '%')
</if> </if>
<if test="criteria.deviceTypeId != null">
and dt.id = #{criteria.deviceTypeId}
</if>
<if test="criteria.customerId != null"> <if test="criteria.customerId != null">
and dt.owner_customer_id = #{criteria.customerId} and dg.customer_id = #{criteria.customerId}
</if> </if>
</where> </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> </select>
</mapper> </mapper>

View File

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

View File

@ -428,7 +428,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
* @param user 用户对象 * @param user 用户对象
* @param clear 清除已存在的关联数据 * @param clear 清除已存在的关联数据
*/ */
private void insertUserRole(SysUserBo user, boolean clear) { public void insertUserRole(SysUserBo user, boolean clear) {
this.insertUserRole(user.getUserId(), user.getRoleIds(), clear); this.insertUserRole(user.getUserId(), user.getRoleIds(), clear);
} }