diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..480bdf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..8b08f1d --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..e7dd41c --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,814 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + "associatedIndex": 1 +} + + + + + + + + + + + + + + + + + + + + + + + + + + 1776320869599 + + + + + + + + + + + + file://$PROJECT_DIR$/src/main/java/com/maibu/Main.java + 13 + + + file://$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/Main.java + 13 + + + file://$PROJECT_DIR$/maibu-service/src/main/java/com/maibu/Main.java + 13 + + + + + \ No newline at end of file diff --git a/maibu-framework/pom.xml b/maibu-framework/pom.xml new file mode 100644 index 0000000..6e0ecea --- /dev/null +++ b/maibu-framework/pom.xml @@ -0,0 +1,145 @@ + + + 4.0.0 + + com.maibu + MiddlePlatform + 4.0.0 + + + maibu-framework + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + com.maibu + maibu-system-service + ${maibu.version} + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + org.apache.shardingsphere + shardingsphere-jdbc-core-spring-boot-starter + ${shardingsphere.version} + + + + + org.apache.tomcat + tomcat-dbcp + 10.0.16 + + + + + com.baomidou + dynamic-datasource-spring-boot-starter + ${dynamic-datasource.version} + + + + + pro.fessional + kaptcha + + + javax.servlet-api + javax.servlet + + + + + + + com.github.oshi + oshi-core + + + + + org.redisson + redisson-spring-boot-starter + ${redisson.version} + + + org.redisson + redisson-spring-data-31 + + + + + org.redisson + redisson-spring-data-25 + ${redisson.version} + + + + com.baomidou + lock4j-redisson-spring-boot-starter + ${lock4j.version} + + + redisson-spring-boot-starter + org.redisson + + + + + + + com.github.ben-manes.caffeine + caffeine + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + org.springframework.session + spring-session-data-redis + + + com.google.code.gson + gson + + + + com.aliyun + dysmsapi20170525 + 2.0.24 + + + + + + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/maibu-framework/src/main/java/com/maibu/ali/AliSmsController.java b/maibu-framework/src/main/java/com/maibu/ali/AliSmsController.java new file mode 100644 index 0000000..aff3058 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/ali/AliSmsController.java @@ -0,0 +1,88 @@ +package com.maibu.ali; + +import com.aliyun.dysmsapi20170525.models.SendSmsRequest; +import com.fastbee.framework.web.service.TokenService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("external/sms") +public class AliSmsController { + + + @Autowired + private TokenService tokenService; + + @Autowired + private AliSmsService aliSmsService; + + /** + * 发送短信验证码 + */ + @PostMapping("/sendAliSmsCode") + @Log(title = "短信验证", businessType = BusinessType.OTHER) + public AjaxResult sendSmsCode(@RequestBody SendSmsRequest request) { + String phoneNumber = request.getPhoneNumbers(); + + // 验证手机号格式 + if (!isValidPhoneNumber(phoneNumber)) { + return AjaxResult.error("手机号格式不正确"); + } + // 发送短信验证码 + boolean result = aliSmsService.sendPhoneSms(phoneNumber); + if (result) { + return AjaxResult.success("验证码已发送"); + } else { + return AjaxResult.error("验证码发送失败,请稍后重试"); + } + } + +// /** +// * 短信验证码登录 +// */ +// @PostMapping("/sms-login") +// public AjaxResult smsLogin(@RequestBody SendSmsRequest request) { +// String phoneNumber = request.getPhoneNumbers(); +//// String code = request.getCode(); +// +// // 验证手机号格式 +// if (!isValidPhoneNumber(phoneNumber)) { +// return AjaxResult.error("手机号格式不正确"); +// } +// +// // 验证验证码 +// if (!smsUtil.verifySmsCode(phoneNumber, code)) { +// return AjaxResult.error("验证码错误或已过期"); +// } +// +// // 查询用户信息 +// SysUser user = userService.selectUserByPhoneNumber(phoneNumber); +// if (user == null) { +// // 如果用户不存在,可以选择自动注册 +// user = registerUserByPhone(phoneNumber); +// } +// +// // 生成登录令牌 +// LoginUser loginUser = new LoginUser(); +// loginUser.setUser(user); +// String token = tokenService.createToken(loginUser); +// +// // 返回令牌和用户信息 +// Map result = new HashMap<>(); +// result.put("token", token); +// result.put("user", user); +// return AjaxResult.success(result); +// } + + /** + * 验证手机号格式 + */ + private boolean isValidPhoneNumber(String phoneNumber) { + // 简单的手机号格式验证 + return phoneNumber != null && phoneNumber.matches("^1[3-9]\\d{9}$"); + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/ali/AliSmsService.java b/maibu-framework/src/main/java/com/maibu/ali/AliSmsService.java new file mode 100644 index 0000000..a5809bd --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/ali/AliSmsService.java @@ -0,0 +1,90 @@ +package com.maibu.ali; + +import com.aliyun.dysmsapi20170525.models.SendSmsResponse; +import com.fastbee.common.core.redis.RedisCache; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +@Service +@Slf4j +public class AliSmsService { + + @Value("${ali.sms.access-key-id:LTAI5tFxmTZAeFBNa7sqcHUj}") + private String accessKeyId; + + @Value("${ali.sms.access-key-secret:vtHYhEWrh585jleku55TbHhtYscmGU}") + private String accessKeySecret; + + @Value("${ali.sms.endpoint:dysmsapi.aliyuncs.com}") + private String endpoint; + + @Value("${ali.sms.sign-name:飒沓机器人}") + private String signName; + + @Value("${ali.sms.template-code:SMS_498590140}") + private String templateCode; + + @Value("${ali.sms.expired-time:1}") + private int expiredTime; + + private static final String redisKey = "sms:code:"; + + @Autowired + private RedisCache redisCache; + + + public boolean sendPhoneSms(String phoneNumber) { + String code = String.valueOf(ThreadLocalRandom.current().nextInt(100000, 1000000)); + SendSmsResponse result = AliSmsUtil.sendSmsCode(accessKeyId, accessKeySecret, phoneNumber, + signName, templateCode, endpoint, code, expiredTime); + if (result != null) { + log.info("send phoneNumber:{}", phoneNumber); + log.info("send code:{}", code); + if (result.getBody().getCode().equalsIgnoreCase("OK")) { + String key = redisKey + phoneNumber; + log.info("send put:{}", key); + log.info("send put value :{}", code); + redisCache.setCacheObject(key, code, expiredTime, TimeUnit.MINUTES); + return true; + } + } + return false; + } + + /** + * 验证短信验证码 + */ + public boolean verifySmsCode(String phoneNumber, String code) { + try { + log.info("phoneNumber:{}", phoneNumber); + log.info("code:{}", code); + if (StringUtils.isEmpty(phoneNumber) || StringUtils.isEmpty(code)) { + return false; + } + String key = redisKey + phoneNumber; + String storedCode = redisCache.getCacheObject(key); + log.info("key:{}", key); + log.info("storedCode:{}", storedCode); + if (StringUtils.isEmpty(storedCode)) { + return false; + } else { + if (code.equals(storedCode)) { + // 验证成功后删除验证码 + redisCache.deleteObject(key); + return true; + } + return false; + } + } catch (Exception e) { + log.error("验证短信验证码异常,手机号: {}", phoneNumber, e); + return false; + } + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/ali/AliSmsUtil.java b/maibu-framework/src/main/java/com/maibu/ali/AliSmsUtil.java new file mode 100644 index 0000000..d3689a1 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/ali/AliSmsUtil.java @@ -0,0 +1,64 @@ +package com.maibu.ali; + +import com.aliyun.dysmsapi20170525.Client; +import com.aliyun.dysmsapi20170525.models.SendSmsRequest; +import com.aliyun.dysmsapi20170525.models.SendSmsResponse; +import com.aliyun.teaopenapi.models.Config; +import com.fastbee.common.utils.json.JsonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class AliSmsUtil { + + private static final Logger logger = LoggerFactory.getLogger(AliSmsUtil.class); + + /** + * 发送短信验证码 + */ + public static SendSmsResponse sendSmsCode(String accessKeyId, String accessKeySecret, String phoneNumber, String signName, + String templateCode, String endpoint, String code, int time) { + try { + // 构造请求对象 + SendSmsRequest sendSmsRequest = new SendSmsRequest() + .setPhoneNumbers(phoneNumber) + .setSignName(signName) + .setTemplateCode(templateCode) +// // TemplateParam 为序列化后的 JSON 字符串。其中\"表示转义后的双引号。 + .setTemplateParam("{\"code\":\"" + code + "\",\"time\":\"" + time + "\"}"); + + + Config config = new Config() + // 配置 AccessKey ID,请确保代码运行环境配置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。 + .setAccessKeyId(accessKeyId) + // 配置 AccessKey Secret,请确保代码运行环境配置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。 + .setAccessKeySecret(accessKeySecret); + // System.getenv()方法表示获取系统环境变量,不要直接在getenv()中填入AccessKey信息。 + + // 配置 Endpoint。 + config.endpoint = endpoint; + + Client client = new Client(config); + // 发送 API 请求 + SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest); + logger.info("发送短信反馈信息: {}", JsonUtils.toJsonString(sendSmsResponse)); + if (sendSmsResponse != null) { + logger.info("发送短信反馈信息body: {}", JsonUtils.toJsonString(sendSmsResponse.getBody())); + if (sendSmsResponse.statusCode == 200) { + // submit success + return sendSmsResponse; + } else { + // submit success + return null; + } + } else { + // fail + return null; + } + } catch (Exception e) { + logger.error("发送短信异常,手机号: {}", phoneNumber, e); + return null; + } + } +} \ No newline at end of file diff --git a/maibu-framework/src/main/java/com/maibu/aspect/WebLogAspect.java b/maibu-framework/src/main/java/com/maibu/aspect/WebLogAspect.java new file mode 100644 index 0000000..945c151 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/aspect/WebLogAspect.java @@ -0,0 +1,70 @@ +package com.maibu.aspect; + +import com.google.gson.Gson; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; + +//@Aspect +//@Component +public class WebLogAspect { +// private final static Logger logger = LoggerFactory.getLogger(WebLogAspect.class); +// /** 以 controller 包下定义的所有请求为切入点 */ +// @Pointcut("execution(public * com.fastbee.data.controller..*.*(..))") +// public void webLog() {} +// /** +// * 在切点之前织入 +// * @param joinPoint +// * @throws Throwable +// */ +// @Before("webLog()") +// public void doBefore(JoinPoint joinPoint) throws Throwable { +// // 开始打印请求日志 +// ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); +// HttpServletRequest request = attributes.getRequest(); +// // 打印请求相关参数 +// logger.info("========================================== Start =========================================="); +// // 打印请求 url +// logger.info("\nURL : {} \nHTTP Method : {} \nClass Method : {}.{} \nIP : {} \nRequest Args : {}", request.getRequestURL().toString(), request.getMethod(), joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), request.getRemoteAddr(), new Gson().toJson(joinPoint.getArgs())); +//// // 打印 Http method +//// logger.info("HTTP Method : {}", request.getMethod()); +//// // 打印调用 controller 的全路径以及执行方法 +//// logger.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); +//// // 打印请求的 IP +//// logger.info("IP : {}", request.getRemoteAddr()); +//// // 打印请求入参 +//// logger.info("Request Args : {}", new Gson().toJson(joinPoint.getArgs())); +// } +// /** +// * 在切点之后织入 +// * @throws Throwable +// */ +// @After("webLog()") +// public void doAfter() throws Throwable { +// logger.info("=========================================== End ==========================================="); + // 每个请求之间空一行 +// logger.info(""); +// } +// /** +// * 环绕 +// * @param proceedingJoinPoint +// * @return +// * @throws Throwable +// */ +// @Around("webLog()") +// public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { +// long startTime = System.currentTimeMillis(); +// Object result = proceedingJoinPoint.proceed(); +// // 打印出参 +// logger.info("\nResponse Args : {} \nTime-Consuming : {} ms", new Gson().toJson(result), System.currentTimeMillis() - startTime); +// // 执行耗时 +//// logger.info("\nTime-Consuming : {} ms", System.currentTimeMillis() - startTime); +// return result; +// } +} diff --git a/maibu-framework/src/main/java/com/maibu/aspectj/DataScopeAspect.java b/maibu-framework/src/main/java/com/maibu/aspectj/DataScopeAspect.java new file mode 100644 index 0000000..3171d89 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/aspectj/DataScopeAspect.java @@ -0,0 +1,167 @@ +package com.maibu.aspectj; + +import java.util.ArrayList; +import java.util.List; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; +import com.fastbee.common.annotation.DataScope; +import com.fastbee.common.core.domain.BaseEntity; +import com.fastbee.common.core.domain.entity.SysRole; +import com.fastbee.common.core.domain.entity.SysUser; +import com.fastbee.common.core.domain.model.LoginUser; +import com.fastbee.common.core.text.Convert; +import com.fastbee.common.utils.SecurityUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.framework.security.context.PermissionContextHolder; + +/** + * 数据过滤处理 + * + * @author ruoyi + */ +@Aspect +@Component +public class DataScopeAspect +{ + /** + * 全部数据权限 + */ + public static final String DATA_SCOPE_ALL = "1"; + + /** + * 自定数据权限 + */ + public static final String DATA_SCOPE_CUSTOM = "2"; + + /** + * 部门数据权限 + */ + public static final String DATA_SCOPE_DEPT = "3"; + + /** + * 部门及以下数据权限 + */ + public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; + + /** + * 仅本人数据权限 + */ + public static final String DATA_SCOPE_SELF = "5"; + + /** + * 数据权限过滤关键字 + */ + public static final String DATA_SCOPE = "dataScope"; + + @Before("@annotation(controllerDataScope)") + public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable + { + clearDataScope(point); + handleDataScope(point, controllerDataScope); + } + + protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) + { + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNotNull(loginUser)) + { + SysUser currentUser = loginUser.getUser(); + // 如果是超级管理员,则不过滤数据 + if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) + { + String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext()); + dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), + controllerDataScope.userAlias(), permission); + } + } + } + + /** + * 数据范围过滤 + * + * @param joinPoint 切点 + * @param user 用户 + * @param deptAlias 部门别名 + * @param userAlias 用户别名 + * @param permission 权限字符 + */ + public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission) + { + StringBuilder sqlString = new StringBuilder(); + List conditions = new ArrayList(); + + for (SysRole role : user.getRoles()) + { + String dataScope = role.getDataScope(); + if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope)) + { + continue; + } + if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions()) + && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) + { + continue; + } + if (DATA_SCOPE_ALL.equals(dataScope)) + { + sqlString = new StringBuilder(); + break; + } + else if (DATA_SCOPE_CUSTOM.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, + role.getRoleId())); + } + else if (DATA_SCOPE_DEPT.equals(dataScope)) + { + sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); + } + else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", + deptAlias, user.getDeptId(), user.getDeptId())); + } + else if (DATA_SCOPE_SELF.equals(dataScope)) + { + if (StringUtils.isNotBlank(userAlias)) + { + sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); + } + else + { + // 数据权限为仅本人且没有userAlias别名不查询任何数据 + sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias)); + } + } + conditions.add(dataScope); + } + + if (StringUtils.isNotBlank(sqlString.toString())) + { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) + { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); + } + } + } + + /** + * 拼接权限sql前先清空params.dataScope参数防止注入 + */ + private void clearDataScope(final JoinPoint joinPoint) + { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) + { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, ""); + } + } +} diff --git a/maibu-framework/src/main/java/com/maibu/aspectj/DataSourceAspect.java b/maibu-framework/src/main/java/com/maibu/aspectj/DataSourceAspect.java new file mode 100644 index 0000000..d4997f6 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/aspectj/DataSourceAspect.java @@ -0,0 +1,73 @@ +package com.maibu.aspectj; + + +import java.util.Objects; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import com.fastbee.common.annotation.DataSource; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.framework.datasource.DynamicDataSourceContextHolder; + +/** + * 多数据源处理 + * + * @author ruoyi + */ +@Aspect +@Order(1) +@Component +public class DataSourceAspect +{ + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Pointcut("@annotation(com.fastbee.common.annotation.DataSource)" + + "|| @within(com.fastbee.common.annotation.DataSource)") + public void dsPointCut() + { + + } + + @Around("dsPointCut()") + public Object around(ProceedingJoinPoint point) throws Throwable + { + DataSource dataSource = getDataSource(point); + + if (StringUtils.isNotNull(dataSource)) + { + DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); + } + + try + { + return point.proceed(); + } + finally + { + // 销毁数据源 在执行方法之后 + DynamicDataSourceContextHolder.clearDataSourceType(); + } + } + + /** + * 获取需要切换的数据源 + */ + public DataSource getDataSource(ProceedingJoinPoint point) + { + MethodSignature signature = (MethodSignature) point.getSignature(); + DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); + if (Objects.nonNull(dataSource)) + { + return dataSource; + } + + return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/aspectj/LogAspect.java b/maibu-framework/src/main/java/com/maibu/aspectj/LogAspect.java new file mode 100644 index 0000000..04d6832 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/aspectj/LogAspect.java @@ -0,0 +1,229 @@ +package com.maibu.aspectj; + + +import java.util.Collection; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.validation.BindingResult; +import org.springframework.web.multipart.MultipartFile; +import com.alibaba.fastjson2.JSON; +import com.fastbee.common.annotation.Log; +import com.fastbee.common.core.domain.model.LoginUser; +import com.fastbee.common.enums.BusinessStatus; +import com.fastbee.common.enums.HttpMethod; +import com.fastbee.common.filter.PropertyPreExcludeFilter; +import com.fastbee.common.utils.SecurityUtils; +import com.fastbee.common.utils.ServletUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.common.utils.ip.IpUtils; +import com.fastbee.framework.manager.AsyncManager; +import com.fastbee.framework.manager.factory.AsyncFactory; +import com.fastbee.system.domain.SysOperLog; + +/** + * 操作日志记录处理 + * + * @author ruoyi + */ +@Aspect +@Component +public class LogAspect +{ + private static final Logger log = LoggerFactory.getLogger(LogAspect.class); + + /** 排除敏感属性字段 */ + public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" }; + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) + { + handleLog(joinPoint, controllerLog, null, jsonResult); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) + { + handleLog(joinPoint, controllerLog, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) + { + try + { + + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // *========数据库日志=========*// + SysOperLog operLog = new SysOperLog(); + operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); + // 请求的地址 + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + operLog.setOperIp(ip); + operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); + if (loginUser != null) + { + operLog.setOperName(loginUser.getUsername()); + } + + if (e != null) + { + operLog.setStatus(BusinessStatus.FAIL.ordinal()); + operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); + } + // 设置方法名称 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setMethod(className + "." + methodName + "()"); + // 设置请求方式 + operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); + // 处理设置注解上的参数 + getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); + // 保存数据库 + AsyncManager.me().execute(AsyncFactory.recordOper(operLog)); + } + catch (Exception exp) + { + // 记录本地异常日志 + log.error("异常信息:{}", exp.getMessage()); + exp.printStackTrace(); + } + } + + /** + * 获取注解中对方法的描述信息 用于Controller层注解 + * + * @param log 日志 + * @param operLog 操作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception + { + // 设置action动作 + operLog.setBusinessType(log.businessType().ordinal()); + // 设置标题 + operLog.setTitle(log.title()); + // 设置操作人类别 + operLog.setOperatorType(log.operatorType().ordinal()); + // 是否需要保存request,参数和值 + if (log.isSaveRequestData()) + { + // 获取参数的信息,传入到数据库中。 + setRequestValue(joinPoint, operLog); + } + // 是否需要保存response,参数和值 + if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) + { + operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000)); + } + } + + /** + * 获取请求的参数,放到log中 + * + * @param operLog 操作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception + { + String requestMethod = operLog.getRequestMethod(); + if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) + { + String params = argsArrayToString(joinPoint.getArgs()); + operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + } + else + { + Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); + operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter()), 0, 2000)); + } + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray) + { + String params = ""; + if (paramsArray != null && paramsArray.length > 0) + { + for (Object o : paramsArray) + { + if (StringUtils.isNotNull(o) && !isFilterObject(o)) + { + try + { + String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter()); + params += jsonObj.toString() + " "; + } + catch (Exception e) + { + } + } + } + } + return params.trim(); + } + + /** + * 忽略敏感属性 + */ + public PropertyPreExcludeFilter excludePropertyPreFilter() + { + return new PropertyPreExcludeFilter().addExcludes(EXCLUDE_PROPERTIES); + } + + /** + * 判断是否需要过滤的对象。 + * + * @param o 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) + { + Class clazz = o.getClass(); + if (clazz.isArray()) + { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } + else if (Collection.class.isAssignableFrom(clazz)) + { + Collection collection = (Collection) o; + for (Object value : collection) + { + return value instanceof MultipartFile; + } + } + else if (Map.class.isAssignableFrom(clazz)) + { + Map map = (Map) o; + for (Object value : map.entrySet()) + { + Map.Entry entry = (Map.Entry) value; + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse + || o instanceof BindingResult; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/aspectj/RateLimiterAspect.java b/maibu-framework/src/main/java/com/maibu/aspectj/RateLimiterAspect.java new file mode 100644 index 0000000..78250f6 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/aspectj/RateLimiterAspect.java @@ -0,0 +1,91 @@ +package com.maibu.aspectj; + + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.RedisScript; +import org.springframework.stereotype.Component; +import com.fastbee.common.annotation.RateLimiter; +import com.fastbee.common.enums.LimitType; +import com.fastbee.common.exception.ServiceException; +import com.fastbee.common.utils.ServletUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.common.utils.ip.IpUtils; + +/** + * 限流处理 + * + * @author ruoyi + */ +@Aspect +@Component +public class RateLimiterAspect +{ + private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class); + + private RedisTemplate redisTemplate; + + private RedisScript limitScript; + + @Autowired + public void setRedisTemplate1(RedisTemplate redisTemplate) + { + this.redisTemplate = redisTemplate; + } + + @Autowired + public void setLimitScript(RedisScript limitScript) + { + this.limitScript = limitScript; + } + + @Before("@annotation(rateLimiter)") + public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable + { + int time = rateLimiter.time(); + int count = rateLimiter.count(); + + String combineKey = getCombineKey(rateLimiter, point); + List keys = Collections.singletonList(combineKey); + try + { + Long number = redisTemplate.execute(limitScript, keys, count, time); + if (StringUtils.isNull(number) || number.intValue() > count) + { + throw new ServiceException("访问过于频繁,请稍候再试"); + } + log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey); + } + catch (ServiceException e) + { + throw e; + } + catch (Exception e) + { + throw new RuntimeException("服务器限流异常,请稍候再试"); + } + } + + public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) + { + StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); + if (rateLimiter.limitType() == LimitType.IP) + { + stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-"); + } + MethodSignature signature = (MethodSignature) point.getSignature(); + Method method = signature.getMethod(); + Class targetClass = method.getDeclaringClass(); + stringBuffer.append(targetClass.getName()).append("-").append(method.getName()); + return stringBuffer.toString(); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/ApplicationConfig.java b/maibu-framework/src/main/java/com/maibu/config/ApplicationConfig.java new file mode 100644 index 0000000..b3b1ee2 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/ApplicationConfig.java @@ -0,0 +1,30 @@ +package com.maibu.config; + +import java.util.TimeZone; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +/** + * 程序注解配置 + * + * @author ruoyi + */ +@Configuration +// 表示通过aop框架暴露该代理对象,AopContext能够访问 +@EnableAspectJAutoProxy(exposeProxy = true) +// 指定要扫描的Mapper类的包的路径 +@MapperScan("com.fastbee.**.mapper") +public class ApplicationConfig +{ + /** + * 时区配置 + */ + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() + { + return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault()); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/CacheConfig.java b/maibu-framework/src/main/java/com/maibu/config/CacheConfig.java new file mode 100644 index 0000000..9c91156 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/CacheConfig.java @@ -0,0 +1,45 @@ +package com.maibu.config; + +import com.fastbee.framework.manager.SpringCacheManager; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.TimeUnit; + +/** + * 缓存配置 + */ +@Configuration +@EnableCaching +@ConditionalOnProperty(name = "spring.cache.enable", havingValue = "true") +public class CacheConfig { + @Value("${spring.cache.ttl}") + private Long ttl; + + @Bean + public Cache caffeine() { + return Caffeine.newBuilder() + // 设置最后一次写入或访问后经过固定时间过期 + .expireAfterWrite(60, TimeUnit.SECONDS) + // 初始的缓存空间大小 + .initialCapacity(100) + // 缓存的最大条数 + .maximumSize(10000) + .build(); + } + + /** + * 自定义缓存管理器 整合spring-cache + */ + @Bean + public CacheManager cacheManager() { + return new SpringCacheManager(ttl); + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/config/CaptchaConfig.java b/maibu-framework/src/main/java/com/maibu/config/CaptchaConfig.java new file mode 100644 index 0000000..efa9a44 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/CaptchaConfig.java @@ -0,0 +1,83 @@ +package com.maibu.config; + +import java.util.Properties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.google.code.kaptcha.util.Config; +import static com.google.code.kaptcha.Constants.*; + +/** + * 验证码配置 + * + * @author ruoyi + */ +@Configuration +public class CaptchaConfig +{ + @Bean(name = "captchaProducer") + public DefaultKaptcha getKaptchaBean() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 是否有边框 默认为true 我们可以自己设置yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 验证码文本字符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); + // 验证码图片宽度 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验证码图片高度 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验证码文本字符大小 默认为40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); + // 验证码文本字符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); + // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } + + @Bean(name = "captchaProducerMath") + public DefaultKaptcha getKaptchaBeanMath() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 是否有边框 默认为true 我们可以自己设置yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 边框颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); + // 验证码文本字符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); + // 验证码图片宽度 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验证码图片高度 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验证码文本字符大小 默认为40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); + // 验证码文本生成器 + properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.fastbee.framework.config.KaptchaTextCreator"); + // 验证码文本字符间距 默认为2 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); + // 验证码文本字符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); + // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 验证码噪点颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); + // 干扰实现类 + properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); + // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/DataSourceConfig.java b/maibu-framework/src/main/java/com/maibu/config/DataSourceConfig.java new file mode 100644 index 0000000..22fd14d --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/DataSourceConfig.java @@ -0,0 +1,72 @@ +package com.maibu.config; + +import com.alibaba.druid.pool.DruidDataSource; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration; +import com.fastbee.framework.datasource.DynamicDataSource; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; +import java.io.IOException; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + + +@Configuration +@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class}) +public class DataSourceConfig { + + @Bean(name = "masterDataSource") + @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.master") + public DruidDataSource masterDataSource() { + return new DruidDataSource(); + } + +// @Bean(name = "slaveDataSource") +// @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.slave") +// public DruidDataSource slaveDataSource() { +// return new DruidDataSource(); +// } + + @Bean + @Primary + public DynamicDataSource dataSource(@Qualifier("masterDataSource") DataSource master) throws SQLException, IOException { + Map targetDataSources = new HashMap<>(); + targetDataSources.put("master", master); + //targetDataSources.put("slave", slave); + return new DynamicDataSource(master,targetDataSources); + } + + + @Bean + public DataSourceTransactionManager transactionManager(DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + +// /** +// * 将动态数据源设置为首选数据源 +// */ +// @Primary +// @Bean +// public DynamicDataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) { +//// DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource(); +//// dataSource.setPrimary(properties.getPrimary()); +//// dataSource.setStrict(properties.getStrict()); +//// dataSource.setStrategy(properties.getStrategy()); +//// dataSource.setProvider(dynamicDataSourceProvider); +//// dataSource.setP6spy(properties.getP6spy()); +//// dataSource.setSeata(properties.getSeata()); +//// return dataSource; +// Map targetDataSources = dynamicDataSourceProvider.loadDataSources(); +// Map objectObjectMap = new HashMap<>(targetDataSources); +// DataSource masterDataSource = targetDataSources.get(properties.getPrimary()); +// return new DynamicDataSource(masterDataSource,objectObjectMap); +// } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/DruidConfig.java b/maibu-framework/src/main/java/com/maibu/config/DruidConfig.java new file mode 100644 index 0000000..3522bf5 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/DruidConfig.java @@ -0,0 +1,74 @@ +package com.maibu.config; + +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; +import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; +import com.alibaba.druid.spring.boot.autoconfigure.stat.DruidFilterConfiguration; +import com.alibaba.druid.spring.boot.autoconfigure.stat.DruidSpringAopConfiguration; +import com.alibaba.druid.spring.boot.autoconfigure.stat.DruidStatViewServletConfiguration; +import com.alibaba.druid.spring.boot.autoconfigure.stat.DruidWebStatFilterConfiguration; +import com.alibaba.druid.util.Utils; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import javax.servlet.*; +import java.io.IOException; + +@Configuration +@ConditionalOnClass(value = DruidDataSourceAutoConfigure.class) +@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class}) +@Import({DruidSpringAopConfiguration.class, DruidStatViewServletConfiguration.class, DruidWebStatFilterConfiguration.class, DruidFilterConfiguration.class}) +public class DruidConfig { + public DruidConfig() { + } + /** + * 去除监控页面底部的广告 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + @ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true") + public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) + { + // 获取web监控页面的参数 + DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); + // 提取common.js的配置路径 + String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; + String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); + final String filePath = "support/http/resources/js/common.js"; + // 创建filter进行过滤 + Filter filter = new Filter() + { + @Override + public void init(javax.servlet.FilterConfig filterConfig) throws ServletException + { + } + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + chain.doFilter(request, response); + // 重置缓冲区,响应头不会被重置 + response.resetBuffer(); + // 获取common.js + String text = Utils.readFromResource(filePath); + // 正则替换banner, 除去底部的广告信息 + text = text.replaceAll("
", ""); + text = text.replaceAll("powered.*?shrek.wang", ""); + response.getWriter().write(text); + } + @Override + public void destroy() + { + } + }; + FilterRegistrationBean registrationBean = new FilterRegistrationBean(); + registrationBean.setFilter(filter); + registrationBean.addUrlPatterns(commonJsPattern); + return registrationBean; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/FastJson2JsonRedisSerializer.java b/maibu-framework/src/main/java/com/maibu/config/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..b84a639 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/FastJson2JsonRedisSerializer.java @@ -0,0 +1,48 @@ +package com.maibu.config; + +import java.nio.charset.Charset; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson2.JSONWriter; + +/** + * Redis使用FastJson序列化 + * + * @author ruoyi + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer +{ + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + public FastJson2JsonRedisSerializer(Class clazz) + { + super(); + this.clazz = clazz; + } + + @Override + public byte[] serialize(T t) throws SerializationException + { + if (t == null) + { + return new byte[0]; + } + return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + @Override + public T deserialize(byte[] bytes) throws SerializationException + { + if (bytes == null || bytes.length <= 0) + { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/FilterConfig.java b/maibu-framework/src/main/java/com/maibu/config/FilterConfig.java new file mode 100644 index 0000000..2a701e7 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/FilterConfig.java @@ -0,0 +1,58 @@ +package com.maibu.config; + +import java.util.HashMap; +import java.util.Map; +import javax.servlet.DispatcherType; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.fastbee.common.filter.RepeatableFilter; +import com.fastbee.common.filter.XssFilter; +import com.fastbee.common.utils.StringUtils; + +/** + * Filter配置 + * + * @author ruoyi + */ +@Configuration +public class FilterConfig +{ + @Value("${xss.excludes}") + private String excludes; + + @Value("${xss.urlPatterns}") + private String urlPatterns; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + @ConditionalOnProperty(value = "xss.enabled", havingValue = "true") + public FilterRegistrationBean xssFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setDispatcherTypes(DispatcherType.REQUEST); + registration.setFilter(new XssFilter()); + registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); + registration.setName("xssFilter"); + registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); + Map initParameters = new HashMap(); + initParameters.put("excludes", excludes); + registration.setInitParameters(initParameters); + return registration; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + public FilterRegistrationBean someFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new RepeatableFilter()); + registration.addUrlPatterns("/*"); + registration.setName("repeatableFilter"); + registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE); + return registration; + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/config/KaptchaTextCreator.java b/maibu-framework/src/main/java/com/maibu/config/KaptchaTextCreator.java new file mode 100644 index 0000000..1677324 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/KaptchaTextCreator.java @@ -0,0 +1,68 @@ +package com.maibu.config; + +import java.util.Random; +import com.google.code.kaptcha.text.impl.DefaultTextCreator; + +/** + * 验证码文本生成器 + * + * @author ruoyi + */ +public class KaptchaTextCreator extends DefaultTextCreator +{ + private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); + + @Override + public String getText() + { + Integer result = 0; + Random random = new Random(); + int x = random.nextInt(10); + int y = random.nextInt(10); + StringBuilder suChinese = new StringBuilder(); + int randomoperands = random.nextInt(3); + if (randomoperands == 0) + { + result = x * y; + suChinese.append(CNUMBERS[x]); + suChinese.append("*"); + suChinese.append(CNUMBERS[y]); + } + else if (randomoperands == 1) + { + if ((x != 0) && y % x == 0) + { + result = y / x; + suChinese.append(CNUMBERS[y]); + suChinese.append("/"); + suChinese.append(CNUMBERS[x]); + } + else + { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + } + else + { + if (x >= y) + { + result = x - y; + suChinese.append(CNUMBERS[x]); + suChinese.append("-"); + suChinese.append(CNUMBERS[y]); + } + else + { + result = y - x; + suChinese.append(CNUMBERS[y]); + suChinese.append("-"); + suChinese.append(CNUMBERS[x]); + } + } + suChinese.append("=?@" + result); + return suChinese.toString(); + } +} \ No newline at end of file diff --git a/maibu-framework/src/main/java/com/maibu/config/MyBatisConfig.java b/maibu-framework/src/main/java/com/maibu/config/MyBatisConfig.java new file mode 100644 index 0000000..7985ee6 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/MyBatisConfig.java @@ -0,0 +1,167 @@ +package com.maibu.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.framework.datasource.DynamicDataSource; +import org.apache.ibatis.io.VFS; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.util.ClassUtils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +/** + * Mybatis支持*匹配扫描包 + * + * @author ruoyi + */ +@Configuration +public class MyBatisConfig +{ + @Autowired + private Environment env; + + static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; + + public static String setTypeAliasesPackage(String typeAliasesPackage) + { + ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver(); + MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver); + List allResult = new ArrayList(); + try + { + for (String aliasesPackage : typeAliasesPackage.split(",")) + { + List result = new ArrayList(); + aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN; + Resource[] resources = resolver.getResources(aliasesPackage); + if (resources != null && resources.length > 0) + { + MetadataReader metadataReader = null; + for (Resource resource : resources) + { + if (resource.isReadable()) + { + metadataReader = metadataReaderFactory.getMetadataReader(resource); + try + { + result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName()); + } + catch (ClassNotFoundException e) + { + e.printStackTrace(); + } + } + } + } + if (result.size() > 0) + { + HashSet hashResult = new HashSet(result); + allResult.addAll(hashResult); + } + } + if (allResult.size() > 0) + { + typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0])); + } + else + { + throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包"); + } + } + catch (IOException e) + { + e.printStackTrace(); + } + return typeAliasesPackage; + } + + public Resource[] resolveMapperLocations(String[] mapperLocations) + { + ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); + List resources = new ArrayList(); + if (mapperLocations != null) + { + for (String mapperLocation : mapperLocations) + { + try + { + Resource[] mappers = resourceResolver.getResources(mapperLocation); + resources.addAll(Arrays.asList(mappers)); + } + catch (IOException e) + { + // ignore + } + } + } + return resources.toArray(new Resource[resources.size()]); + } + + /** + * mybatis-plus 配置:把 SqlSessionFactoryBean 换成 MybatisSqlSessionFactoryBean就行 + * @param dataSource 数据源 + * @return + */ + @Bean(name = "mysqlSessionFactory") + @Primary + public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception + { + String typeAliasesPackage = env.getProperty("mybatis-plus.typeAliasesPackage"); + String mapperLocations = env.getProperty("mybatis-plus.mapperLocations"); + String configLocation = env.getProperty("mybatis-plus.configLocation"); + typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage); + VFS.addImplClass(SpringBootVFS.class); + + final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean(); + sessionFactory.setDataSource(dataSource); + sessionFactory.setTypeAliasesPackage(typeAliasesPackage); + sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ","))); + sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation)); + + // 添加分页插件 + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + sessionFactory.setPlugins(interceptor); + + return sessionFactory.getObject(); + } + + /** + * 元对象字段填充控制器 + */ + @Bean + public MetaObjectHandler metaObjectHandler() { + return new MybatisPlusMetaObjectHandler(); + } + + @Bean(name = "mysqlSqlSessionTemplate") + @Primary + public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSessionFactory") SqlSessionFactory sqlSessionFactory) { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/config/MybatisPlusMetaObjectHandler.java b/maibu-framework/src/main/java/com/maibu/config/MybatisPlusMetaObjectHandler.java new file mode 100644 index 0000000..99c912a --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/MybatisPlusMetaObjectHandler.java @@ -0,0 +1,75 @@ +package com.maibu.config; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.fastbee.common.core.domain.model.LoginUser; +import com.fastbee.common.utils.SecurityUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.util.ClassUtils; + +import java.nio.charset.Charset; +import java.util.Date; + +/** + * MybatisPlus 自动填充配置 + * + * @author admin + */ +@Slf4j +public class MybatisPlusMetaObjectHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + log.debug("mybatisPlus插入填充--------------"); + Date date = new Date(); + + fillValIfNullByName("createTime", date, metaObject, false); + fillValIfNullByName("updateTime", date, metaObject, false); + fillValIfNullByName("createBy", getUserName(), metaObject, false); + fillValIfNullByName("updateBy", getUserName(), metaObject, false); + fillValIfNullByName("deleteFlag", "1", metaObject, false); + } + + @Override + public void updateFill(MetaObject metaObject) { + log.debug("mybatisPlus更新填充--------------"); + fillValIfNullByName("updateTime", new Date(), metaObject, true); + fillValIfNullByName("updateBy", getUserName(), metaObject, true); + } + + /** + * 填充值,先判断是否有手动设置,优先手动设置的值,例如:job必须手动设置 + * @param fieldName 属性名 + * @param fieldVal 属性值 + * @param metaObject MetaObject + * @param isCover 是否覆盖原有值,避免更新操作手动入参 + */ + private static void fillValIfNullByName(String fieldName, Object fieldVal, MetaObject metaObject, boolean isCover) { + // 1. 没有 get 方法 + if (!metaObject.hasSetter(fieldName)) { + return; + } + // 2. 如果用户有手动设置的值 + Object userSetValue = metaObject.getValue(fieldName); + String setValueStr = StrUtil.str(userSetValue, Charset.defaultCharset()); + if (StrUtil.isNotBlank(setValueStr) && !isCover) { + return; + } + // 3. field 类型相同时设置 + Class getterType = metaObject.getGetterType(fieldName); + if (ClassUtils.isAssignableValue(getterType, fieldVal)) { + metaObject.setValue(fieldName, fieldVal); + } + } + + /** + * 获取 spring security 当前的用户名 + * @return 当前用户名 + */ + private String getUserName() { + LoginUser loginUser = SecurityUtils.getLoginUser(); + return loginUser.getUsername(); + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/config/MybatisPlusPageConfigurer.java b/maibu-framework/src/main/java/com/maibu/config/MybatisPlusPageConfigurer.java new file mode 100644 index 0000000..812ead7 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/MybatisPlusPageConfigurer.java @@ -0,0 +1,47 @@ +package com.maibu.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; + +/** + * @author admin + */ +@Configuration(proxyBeanMethods = false) +public class MybatisPlusPageConfigurer implements WebMvcConfigurer { + + /** + * SQL 过滤器避免SQL 注入 + * @param argumentResolvers + */ + @Override + public void addArgumentResolvers(List argumentResolvers) { + argumentResolvers.add(new SqlFilterArgumentResolver()); + } + + /** + * 分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } + + /** + * 审计字段自动填充 + * @return {@link MybatisPlusMetaObjectHandler} + */ + @Bean + public MybatisPlusMetaObjectHandler mybatisPlusMetaObjectHandler() { + return new MybatisPlusMetaObjectHandler(); + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/config/OtaThreadPoolConfig.java b/maibu-framework/src/main/java/com/maibu/config/OtaThreadPoolConfig.java new file mode 100644 index 0000000..c57e0b0 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/OtaThreadPoolConfig.java @@ -0,0 +1,39 @@ +package com.maibu.config; + +import com.fastbee.common.constant.FastBeeConstant; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.ThreadPoolExecutor; + +@Configuration +public class OtaThreadPoolConfig +{ + // 核心线程池大小 + private int corePoolSize = 10; + // 最大可创建的线程数 + private int maxPoolSize = 20; + // 队列最大长度 + private int queueCapacity = 10000; + // 线程池维护线程所允许的空闲时间 + private int keepAliveSeconds = 30; + // 配置线程池的前缀 + private static final String threadNamePrefix = "ota-"; + + @Bean(name = FastBeeConstant.TASK.OTA_THREAD_POOL) + public ThreadPoolTaskExecutor threadPoolTaskExecutor() + { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setMaxPoolSize(maxPoolSize); + executor.setCorePoolSize(corePoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setKeepAliveSeconds(keepAliveSeconds); + executor.setThreadNamePrefix(threadNamePrefix); + // 线程池对拒绝任务(无线程可用)的处理策略 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + // 进行加载 + executor.initialize(); + return executor; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/RedisConfig.java b/maibu-framework/src/main/java/com/maibu/config/RedisConfig.java new file mode 100644 index 0000000..90c0fbd --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/RedisConfig.java @@ -0,0 +1,67 @@ +package com.maibu.config; + +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * redis配置 + * + * @author ruoyi + */ +@Configuration +public class RedisConfig extends CachingConfigurerSupport +{ + @Bean + @SuppressWarnings(value = { "unchecked", "rawtypes" }) + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) + { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); + + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(serializer); + + // Hash的key也采用StringRedisSerializer的序列化方式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(serializer); + + template.afterPropertiesSet(); + return template; + } + + @Bean + public DefaultRedisScript limitScript() + { + DefaultRedisScript redisScript = new DefaultRedisScript<>(); + redisScript.setScriptText(limitScriptText()); + redisScript.setResultType(Long.class); + return redisScript; + } + + /** + * 限流脚本 + */ + private String limitScriptText() + { + return "local key = KEYS[1]\n" + + "local count = tonumber(ARGV[1])\n" + + "local time = tonumber(ARGV[2])\n" + + "local current = redis.call('get', key);\n" + + "if current and tonumber(current) > count then\n" + + " return tonumber(current);\n" + + "end\n" + + "current = redis.call('incr', key)\n" + + "if tonumber(current) == 1 then\n" + + " redis.call('expire', key, time)\n" + + "end\n" + + "return tonumber(current);"; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/RedissonConfig.java b/maibu-framework/src/main/java/com/maibu/config/RedissonConfig.java new file mode 100644 index 0000000..acbbbb0 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/RedissonConfig.java @@ -0,0 +1,93 @@ +package com.maibu.config; + +import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import lombok.extern.slf4j.Slf4j; +import com.fastbee.framework.config.properties.RedissonProperties; +import org.redisson.client.codec.StringCodec; +import org.redisson.codec.CompositeCodec; +import org.redisson.codec.TypedJsonJacksonCodec; +import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.fastbee.framework.handler.KeyPrefixHandler; + + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.TimeZone; + +/** + * redis配置 + */ +@Slf4j +@Configuration +@EnableConfigurationProperties(RedissonProperties.class) +public class RedissonConfig { + + @Autowired + private RedissonProperties redissonProperties; + + @Bean + public RedissonAutoConfigurationCustomizer redissonCustomizer() { + return config -> { + JavaTimeModule javaTimeModule = new JavaTimeModule(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter)); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter)); + ObjectMapper om = new ObjectMapper(); + om.registerModule(javaTimeModule); + om.setTimeZone(TimeZone.getDefault()); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的。序列化时将对象全类名一起保存下来 + om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); + TypedJsonJacksonCodec jsonCodec = new TypedJsonJacksonCodec(Object.class, om); + // 组合序列化 key 使用 String 内容使用通用 json 格式 + CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, jsonCodec, jsonCodec); + config.setThreads(redissonProperties.getThreads()) + .setNettyThreads(redissonProperties.getNettyThreads()) + // 缓存 Lua 脚本 减少网络传输(redisson 大部分的功能都是基于 Lua 脚本实现) + .setUseScriptCache(true) + .setCodec(codec); + RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig(); + if (ObjectUtil.isNotNull(singleServerConfig)) { + // 使用单机模式 + config.useSingleServer() + //设置redis key前缀 + .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) + .setTimeout(singleServerConfig.getTimeout()) + .setClientName(singleServerConfig.getClientName()) + .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout()) + .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize()) + .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize()) + .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize()); + } + // 集群配置方式 参考下方注释 + RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig(); + if (ObjectUtil.isNotNull(clusterServersConfig)) { + config.useClusterServers() + //设置redis key前缀 + .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) + .setTimeout(clusterServersConfig.getTimeout()) + .setClientName(clusterServersConfig.getClientName()) + .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout()) + .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize()) + .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize()) + .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize()) + .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize()) + .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize()) + .setReadMode(clusterServersConfig.getReadMode()) + .setSubscriptionMode(clusterServersConfig.getSubscriptionMode()); + } + log.info("初始化 redis 配置"); + }; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/ResourcesConfig.java b/maibu-framework/src/main/java/com/maibu/config/ResourcesConfig.java new file mode 100644 index 0000000..96a5138 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/ResourcesConfig.java @@ -0,0 +1,82 @@ +package com.maibu.config; + +import java.util.concurrent.TimeUnit; + +import com.fastbee.framework.interceptor.LanguageInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.CacheControl; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import com.fastbee.common.config.RuoYiConfig; +import com.fastbee.common.constant.Constants; +import com.fastbee.framework.interceptor.RepeatSubmitInterceptor; + +import javax.annotation.Resource; + +/** + * 通用配置 + * + * @author ruoyi + */ +@Configuration +public class ResourcesConfig implements WebMvcConfigurer +{ + @Autowired + private RepeatSubmitInterceptor repeatSubmitInterceptor; + @Resource + private LanguageInterceptor languageInterceptor; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) + { + /** 本地文件上传路径 */ + registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**") + .addResourceLocations("file:" + RuoYiConfig.getProfile() + "/"); + + /** swagger配置 */ + registry.addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/") + .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());; + } + + /** + * 自定义拦截规则 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) + { + registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**"); + //这里配置国际化拦截器的白名单 + registry.addInterceptor(languageInterceptor).addPathPatterns("/**").excludePathPatterns("/v2/api-docs", + "/tool/gen/**"); + } + + /** + * 跨域配置 + */ + @Bean + public CorsFilter corsFilter() + { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + // 设置访问源地址 + config.addAllowedOriginPattern("*"); + // 设置访问源请求头 + config.addAllowedHeader("*"); + // 设置访问源请求方法 + config.addAllowedMethod("*"); + // 有效期 1800秒 + config.setMaxAge(1800L); + // 添加映射路径,拦截一切请求 + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + // 返回新的CorsFilter + return new CorsFilter(source); + } +} \ No newline at end of file diff --git a/maibu-framework/src/main/java/com/maibu/config/SecurityConfig.java b/maibu-framework/src/main/java/com/maibu/config/SecurityConfig.java new file mode 100644 index 0000000..cfd7bcf --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/SecurityConfig.java @@ -0,0 +1,221 @@ +package com.maibu.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.logout.LogoutFilter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import com.fastbee.framework.config.properties.PermitAllUrlProperties; +import com.fastbee.framework.security.filter.JwtAuthenticationTokenFilter; +import com.fastbee.framework.security.handle.AuthenticationEntryPointImpl; +import com.fastbee.framework.security.handle.LogoutSuccessHandlerImpl; + +import java.util.Arrays; + +/** + * spring security配置 + * + * @author ruoyi + */ +//@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +public class SecurityConfig extends WebSecurityConfigurerAdapter { + /** + * 自定义用户认证逻辑 + */ + @Autowired + private UserDetailsService userDetailsService; + + /** + * 认证失败处理类 + */ + @Autowired + private AuthenticationEntryPointImpl unauthorizedHandler; + + /** + * 退出处理类 + */ + @Autowired + private LogoutSuccessHandlerImpl logoutSuccessHandler; + + /** + * token认证过滤器 + */ + @Autowired + private JwtAuthenticationTokenFilter authenticationTokenFilter; + + /** + * 跨域过滤器 + */ + @Autowired + private CorsFilter corsFilter; + + /** + * 允许匿名访问的地址 + */ + @Autowired + private PermitAllUrlProperties permitAllUrl; + + /** + * 解决 无法直接注入 AuthenticationManager + * + * @return + * @throws Exception + */ + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + /** + * anyRequest | 匹配所有请求路径 + * access | SpringEl表达式结果为true时可以访问 + * anonymous | 匿名可以访问 + * denyAll | 用户不能访问 + * fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录) + * hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问 + * hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问 + * hasAuthority | 如果有参数,参数表示权限,则其权限可以访问 + * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问 + * hasRole | 如果有参数,参数表示角色,则其角色可以访问 + * permitAll | 用户可以任意访问 + * rememberMe | 允许通过remember-me登录的用户访问 + * authenticated | 用户登录后可访问 + */ + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + // 注解标记允许匿名访问的url + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests(); + permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll()); + + httpSecurity + // CSRF禁用,因为不使用session + .csrf().disable() + .cors().configurationSource(corsConfigurationSource()).and() + // 禁用HTTP响应标头 + .headers().cacheControl().disable().and() + // 认证失败处理类 + .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() + // 基于token,所以不需要session + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + .sessionManagement().sessionFixation().none().and() + // 过滤请求 + .authorizeRequests() + // 对于登录login 注册register 验证码captchaImage 允许匿名访问 + .antMatchers("/api/thermal/**","/iotDA/device/**", "/websocket/allMemory", "/iot/UAV/**", "/iot/api/**", "/iot/device/userDevice", "/external/sms/sendAliSmsCode", "/login", "/register", "/captchaImage", "/iot/tool/register", "/iot/tool/ntp", + "/iot/tool/mqtt/auth", "/iot/workRecord/**", "/iot/tool/mqtt/authv5", "/iot/tool/mqtt/webhook", "/iot/tool/mqtt/webhookv5", "/auth/**/**", + "/wechat/mobileLogin", "/wechat/miniLogin", "/wechat/wxBind/callback").permitAll() + .antMatchers("/zlmhook/**").permitAll() + .antMatchers("/srs/**").permitAll() //srs服务 + //.antMatchers("/sip/player/getBigScreenUrl/**").permitAll() + .antMatchers("/ruleengine/rulemanager/**").permitAll() + .antMatchers("/goview/sys/login", "/goview/project/getData").permitAll() + .antMatchers("/notify/smsLoginCaptcha", "/notify/emailRegisterCaptcha", "/auth/sms/login", "/notify/weComVerifyUrl" + , "/wechat/publicAccount/callback", "/notify/smsRegisterCaptcha").permitAll() + .antMatchers("/app/language/list").permitAll() + .antMatchers("/iot/news/bannerList", "/iot/news/topList", "/iot/news/getDetail").permitAll() + // 静态资源,可匿名访问 + .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() + .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() + .antMatchers("/druid/**").permitAll() + .antMatchers("/oauth2/**").permitAll() + .antMatchers("/swagger**", "/dev-api/swagger**", "/dev-api/swagger-ui/**", "/dev-api/v3/api-docs/**").permitAll() + .antMatchers("/**/device/**/**").permitAll() +// // oauth +// .antMatchers("/oauth/css/**","/oauth/fonts/**","/oauth/js/**").permitAll() + // dueros + .antMatchers("/dueros").permitAll() + + .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() + + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest().authenticated() + +// // oauth +// .and() +// .formLogin() +// .loginPage("/oauth/login") +// .permitAll() +// .and() +// .logout().logoutUrl("/oauth/logout") +// .permitAll() + + .and() + .headers().frameOptions().disable(); + // 添加Logout filter + httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); + // 添加JWT filter + httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + // 添加CORS filter + httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class); + httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class); + } + + /** + * 强散列哈希加密实现 + */ + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + /** + * 身份认证接口 + */ + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); + } + + @Bean + public CorsConfigurationSource corsConfigurationSource() { +// CorsConfiguration config = new CorsConfiguration(); +// config.setAllowCredentials(true); +// config.addAllowedOriginPattern("*"); // 通配支持 +// config.addAllowedHeader("*"); +// config.addAllowedMethod("*"); +// config.setMaxAge(1800L); +// +// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); +// source.registerCorsConfiguration("/**", config); +// return source; + + + CorsConfiguration config = new CorsConfiguration(); + // 关键:设置允许的前端源(替换为你的实际前端域名,如https://ri.satabot.com) + // 填* 会有问题 + config.setAllowedOrigins(Arrays.asList("https://ri.satabot.com", "https://ai.satabot.com", + "https://serviceai.satabot.com", "https://serviceri.satabot.com", "https://pvs.satabot.com", + "https://servicepvs.satabot.com", "https://servicepathplan.satabot.com", "https://solar.satabot.com", + "https://servicestream.satabot.com", "http://192.168.2.58", "http://192.168.2.58")); +// config.addAllowedOriginPattern("*"); + // 允许的请求方法(必须包含OPTIONS,支持业务请求的GET/POST等) + config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); + // 允许的请求头(*表示所有,若有自定义头可单独指定,如Token) + config.setAllowedHeaders(Arrays.asList("*")); + // 允许携带Cookie/Token(开启后,allowedOrigins不能用*,需指定具体域名) + config.setAllowCredentials(true); + // 预检请求缓存时间(单位:秒),减少OPTIONS请求次数 + config.setMaxAge(3600L); + + // 将跨域配置绑定到所有接口路径 + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + return source; + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/config/ServerConfig.java b/maibu-framework/src/main/java/com/maibu/config/ServerConfig.java new file mode 100644 index 0000000..540b437 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/ServerConfig.java @@ -0,0 +1,32 @@ +package com.maibu.config; + +import javax.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Component; +import com.fastbee.common.utils.ServletUtils; + +/** + * 服务相关配置 + * + * @author ruoyi + */ +@Component +public class ServerConfig +{ + /** + * 获取完整的请求路径,包括:域名,端口,上下文访问路径 + * + * @return 服务地址 + */ + public String getUrl() + { + HttpServletRequest request = ServletUtils.getRequest(); + return getDomain(request); + } + + public static String getDomain(HttpServletRequest request) + { + StringBuffer url = request.getRequestURL(); + String contextPath = request.getServletContext().getContextPath(); + return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString(); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/SqlFilterArgumentResolver.java b/maibu-framework/src/main/java/com/maibu/config/SqlFilterArgumentResolver.java new file mode 100644 index 0000000..939e0cc --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/SqlFilterArgumentResolver.java @@ -0,0 +1,92 @@ +package com.maibu.config; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * 解决Mybatis Plus Order By SQL注入问题 + * @author admin + */ +@Slf4j +public class SqlFilterArgumentResolver implements HandlerMethodArgumentResolver { + + private final static String[] KEYWORDS = { "master", "truncate", "insert", "select", "delete", "update", "declare", + "alter", "drop", "sleep" }; + + /** + * 判断Controller是否包含page 参数 + * @param parameter 参数 + * @return 是否过滤 + */ + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.getParameterType().equals(Page.class); + } + + /** + * @param parameter 入参集合 + * @param mavContainer model 和 view + * @param webRequest web相关 + * @param binderFactory 入参解析 + * @return 检查后新的page对象 + *

+ * page 只支持查询 GET .如需解析POST获取请求报文体处理 + */ + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { + + HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); + + String[] ascs = request.getParameterValues("ascs"); + String[] descs = request.getParameterValues("descs"); + String current = request.getParameter("current"); + String size = request.getParameter("size"); + + Page page = new Page<>(); + if (StrUtil.isNotBlank(current)) { + page.setCurrent(Long.parseLong(current)); + } + + if (StrUtil.isNotBlank(size)) { + page.setSize(Long.parseLong(size)); + } + List orderItemList = new ArrayList<>(); + Optional.ofNullable(ascs).ifPresent(s -> orderItemList.addAll( + Arrays.stream(s).filter(sqlInjectPredicate()).map(OrderItem::asc).collect(Collectors.toList()))); + Optional.ofNullable(descs).ifPresent(s -> orderItemList.addAll( + Arrays.stream(s).filter(sqlInjectPredicate()).map(OrderItem::desc).collect(Collectors.toList()))); + page.addOrder(orderItemList); + return page; + } + + /** + * 判断用户输入里面有没有关键字 + * @return Predicate + */ + private Predicate sqlInjectPredicate() { + return sql -> { + for (String keyword : KEYWORDS) { + if (StrUtil.containsIgnoreCase(sql, keyword)) { + return false; + } + } + return true; + }; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/ThreadPoolConfig.java b/maibu-framework/src/main/java/com/maibu/config/ThreadPoolConfig.java new file mode 100644 index 0000000..bcaa998 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/ThreadPoolConfig.java @@ -0,0 +1,63 @@ +package com.maibu.config; + +import com.fastbee.common.utils.Threads; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 线程池配置 + * + * @author ruoyi + **/ +@Configuration +public class ThreadPoolConfig +{ + // 核心线程池大小 + private int corePoolSize = 50; + + // 最大可创建的线程数 + private int maxPoolSize = 200; + + // 队列最大长度 + private int queueCapacity = 1000; + + // 线程池维护线程所允许的空闲时间 + private int keepAliveSeconds = 300; + + @Bean(name = "threadPoolTaskExecutor") + public ThreadPoolTaskExecutor threadPoolTaskExecutor() + { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setMaxPoolSize(maxPoolSize); + executor.setCorePoolSize(corePoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setKeepAliveSeconds(keepAliveSeconds); + // 线程池对拒绝任务(无线程可用)的处理策略 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } + + /** + * 执行周期性或定时任务 + */ + @Bean(name = "scheduledExecutorService") + protected ScheduledExecutorService scheduledExecutorService() + { + return new ScheduledThreadPoolExecutor(corePoolSize, + new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), + new ThreadPoolExecutor.CallerRunsPolicy()) + { + @Override + protected void afterExecute(Runnable r, Throwable t) + { + super.afterExecute(r, t); + Threads.printException(r, t); + } + }; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/properties/DruidProperties.java b/maibu-framework/src/main/java/com/maibu/config/properties/DruidProperties.java new file mode 100644 index 0000000..ee9e961 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/properties/DruidProperties.java @@ -0,0 +1,75 @@ +package com.maibu.config.properties; + +import org.springframework.context.annotation.Configuration; + +/** + * druid 配置属性 + * + * @author ruoyi + */ +@Configuration +public class DruidProperties +{ +// @Value("${spring.datasource.druid.initialSize}") +// private int initialSize; +// +// @Value("${spring.datasource.druid.minIdle}") +// private int minIdle; +// +// @Value("${spring.datasource.druid.maxActive}") +// private int maxActive; +// +// @Value("${spring.datasource.druid.maxWait}") +// private int maxWait; +// +// @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}") +// private int timeBetweenEvictionRunsMillis; +// +// @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}") +// private int minEvictableIdleTimeMillis; +// +// @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}") +// private int maxEvictableIdleTimeMillis; +// +// @Value("${spring.datasource.druid.validationQuery}") +// private String validationQuery; +// +// @Value("${spring.datasource.druid.testWhileIdle}") +// private boolean testWhileIdle; +// +// @Value("${spring.datasource.druid.testOnBorrow}") +// private boolean testOnBorrow; +// +// @Value("${spring.datasource.druid.testOnReturn}") +// private boolean testOnReturn; + +// public DruidDataSource dataSource(DruidDataSource datasource) +// { +// /** 配置初始化大小、最小、最大 */ +// datasource.setInitialSize(initialSize); +// datasource.setMaxActive(maxActive); +// datasource.setMinIdle(minIdle); +// +// /** 配置获取连接等待超时的时间 */ +// datasource.setMaxWait(maxWait); +// +// /** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */ +// datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); +// +// /** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */ +// datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); +// datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis); +// +// /** +// * 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 +// */ +// datasource.setValidationQuery(validationQuery); +// /** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */ +// datasource.setTestWhileIdle(testWhileIdle); +// /** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ +// datasource.setTestOnBorrow(testOnBorrow); +// /** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ +// datasource.setTestOnReturn(testOnReturn); +// return datasource; +// } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/properties/PermitAllUrlProperties.java b/maibu-framework/src/main/java/com/maibu/config/properties/PermitAllUrlProperties.java new file mode 100644 index 0000000..6edbca3 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/properties/PermitAllUrlProperties.java @@ -0,0 +1,72 @@ +package com.maibu.config.properties; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Pattern; +import org.apache.commons.lang3.RegExUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import com.fastbee.common.annotation.Anonymous; + +/** + * 设置Anonymous注解允许匿名访问的url + * + * @author ruoyi + */ +@Configuration +public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware +{ + private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}"); + + private ApplicationContext applicationContext; + + private List urls = new ArrayList<>(); + + public String ASTERISK = "*"; + + @Override + public void afterPropertiesSet() + { + RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class); + Map map = mapping.getHandlerMethods(); + + map.keySet().forEach(info -> { + HandlerMethod handlerMethod = map.get(info); + + // 获取方法上边的注解 替代path variable 为 * + Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class); + Optional.ofNullable(method).ifPresent(anonymous -> info.getPatternsCondition().getPatterns() + .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK)))); + + // 获取类上边的注解, 替代path variable 为 * + Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class); + Optional.ofNullable(controller).ifPresent(anonymous -> info.getPatternsCondition().getPatterns() + .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK)))); + }); + } + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException + { + this.applicationContext = context; + } + + public List getUrls() + { + return urls; + } + + public void setUrls(List urls) + { + this.urls = urls; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/properties/RedissonProperties.java b/maibu-framework/src/main/java/com/maibu/config/properties/RedissonProperties.java new file mode 100644 index 0000000..3ae6fce --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/properties/RedissonProperties.java @@ -0,0 +1,134 @@ +package com.maibu.config.properties; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.redisson.config.ReadMode; +import org.redisson.config.SubscriptionMode; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Redisson 配置属性 + * + */ +@Data +@ConfigurationProperties(prefix = "redisson") +public class RedissonProperties { + + /** + * redis缓存key前缀 + */ + private String keyPrefix; + + /** + * 线程池数量,默认值 = 当前处理核数量 * 2 + */ + private int threads; + + /** + * Netty线程池数量,默认值 = 当前处理核数量 * 2 + */ + private int nettyThreads; + + /** + * 单机服务配置 + */ + private SingleServerConfig singleServerConfig; + + /** + * 集群服务配置 + */ + private ClusterServersConfig clusterServersConfig; + + @Data + @NoArgsConstructor + public static class SingleServerConfig { + + /** + * 客户端名称 + */ + private String clientName; + + /** + * 最小空闲连接数 + */ + private int connectionMinimumIdleSize; + + /** + * 连接池大小 + */ + private int connectionPoolSize; + + /** + * 连接空闲超时,单位:毫秒 + */ + private int idleConnectionTimeout; + + /** + * 命令等待超时,单位:毫秒 + */ + private int timeout; + + /** + * 发布和订阅连接池大小 + */ + private int subscriptionConnectionPoolSize; + + } + + @Data + @NoArgsConstructor + public static class ClusterServersConfig { + + /** + * 客户端名称 + */ + private String clientName; + + /** + * master最小空闲连接数 + */ + private int masterConnectionMinimumIdleSize; + + /** + * master连接池大小 + */ + private int masterConnectionPoolSize; + + /** + * slave最小空闲连接数 + */ + private int slaveConnectionMinimumIdleSize; + + /** + * slave连接池大小 + */ + private int slaveConnectionPoolSize; + + /** + * 连接空闲超时,单位:毫秒 + */ + private int idleConnectionTimeout; + + /** + * 命令等待超时,单位:毫秒 + */ + private int timeout; + + /** + * 发布和订阅连接池大小 + */ + private int subscriptionConnectionPoolSize; + + /** + * 读取模式 + */ + private ReadMode readMode; + + /** + * 订阅模式 + */ + private SubscriptionMode subscriptionMode; + + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/config/sharding/ShardingAlgorithmTool.java b/maibu-framework/src/main/java/com/maibu/config/sharding/ShardingAlgorithmTool.java new file mode 100644 index 0000000..ac819a3 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/sharding/ShardingAlgorithmTool.java @@ -0,0 +1,262 @@ +package com.maibu.config.sharding; + +import cn.hutool.extra.spring.SpringUtil; +import com.alibaba.druid.util.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.fastbee.framework.config.sharding.enums.ShardingTableCacheEnum; +import lombok.extern.slf4j.Slf4j; +import org.apache.shardingsphere.driver.jdbc.core.datasource.ShardingSphereDataSource; +import org.apache.shardingsphere.infra.config.RuleConfiguration; +import org.apache.shardingsphere.mode.manager.ContextManager; +import org.apache.shardingsphere.sharding.algorithm.config.AlgorithmProvidedShardingRuleConfiguration; +import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration; +import org.springframework.core.env.Environment; + +import java.sql.*; +import java.time.YearMonth; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

@Title ShardingAlgorithmTool + *

@Description 按月分片算法工具 + * + */ +@Slf4j +public class ShardingAlgorithmTool { + + /** 表分片符号,例:siot_device_log_202201 中,分片符号为 "_" */ + private static final String TABLE_SPLIT_SYMBOL = "_"; + + /** 数据库配置 */ + private static final Environment ENV = SpringUtil.getApplicationContext().getEnvironment(); + private static final String DATASOURCE_URL = ENV.getProperty("spring.shardingsphere.datasource.ds0.url"); + private static final String DATASOURCE_USERNAME = ENV.getProperty("spring.shardingsphere.datasource.ds0.username"); + private static final String DATASOURCE_PASSWORD = ENV.getProperty("spring.shardingsphere.datasource.ds0.password"); + + + /** + * 检查分表获取的表名是否存在,不存在则自动建表 + * @param logicTable 逻辑表 + * @param resultTableNames 真实表名,例:iot_device_log_202201 + * @return 存在于数据库中的真实表名集合 + */ + public static Set getShardingTablesAndCreate(ShardingTableCacheEnum logicTable, Collection resultTableNames) { + return resultTableNames.stream().map(o -> getShardingTableAndCreate(logicTable, o)).collect(Collectors.toSet()); + } + + /** + * 检查分表获取的表名是否存在,不存在则自动建表 + * @param logicTable 逻辑表 + * @param resultTableName 真实表名,例:iot_device_log_202201 + * @return 确认存在于数据库中的真实表名 + */ + public static String getShardingTableAndCreate(ShardingTableCacheEnum logicTable, String resultTableName) { + // 缓存中有此表则返回,没有则判断创建 + if (logicTable.resultTableNamesCache().contains(resultTableName)) { + return resultTableName; + } else { + // 未创建的表返回逻辑空表 + boolean isSuccess = createShardingTable(logicTable, resultTableName); + return isSuccess ? resultTableName : logicTable.logicTableName(); + } + } + + /** + * 重载全部缓存 + */ + public static void tableNameCacheReloadAll() { + Arrays.stream(ShardingTableCacheEnum.values()).forEach(ShardingAlgorithmTool::tableNameCacheReload); + } + + /** + * 重载指定分表缓存 + * @param logicTable 逻辑表 + */ + public static void tableNameCacheReload(ShardingTableCacheEnum logicTable) { + // 读取数据库中所有表名 + List tableNameList = getAllTableNameBySchema(logicTable); + // 更新缓存、配置(原子操作) + logicTable.atomicUpdateCacheAndActualDataNodes(tableNameList); + // 删除旧的缓存(如果存在) + logicTable.resultTableNamesCache().clear(); + // 写入新的缓存 + logicTable.resultTableNamesCache().addAll(tableNameList); + // 动态更新配置 actualDataNodes + actualDataNodesRefresh(logicTable.logicTableName(), tableNameList); + } + + /** + * 获取所有表名 + * @return 表名集合 + * @param logicTable 逻辑表 + */ + public static List getAllTableNameBySchema(ShardingTableCacheEnum logicTable) { + List tableNames = new ArrayList<>(); + if (StringUtils.isEmpty(DATASOURCE_URL) || StringUtils.isEmpty(DATASOURCE_USERNAME) || StringUtils.isEmpty(DATASOURCE_PASSWORD)) { + log.error(">>>>>>>>>> 【ERROR】数据库连接配置有误,请稍后重试,URL:{}, username:{}, password:{}", DATASOURCE_URL, DATASOURCE_USERNAME, DATASOURCE_PASSWORD); + throw new IllegalArgumentException("数据库连接配置有误,请稍后重试"); + } + try (Connection conn = DriverManager.getConnection(DATASOURCE_URL, DATASOURCE_USERNAME, DATASOURCE_PASSWORD); + Statement st = conn.createStatement()) { + String logicTableName = logicTable.logicTableName(); + try (ResultSet rs = st.executeQuery("show TABLES like '" + logicTableName + TABLE_SPLIT_SYMBOL + "%'")) { + log.info("查询数据库所有表:{}","show TABLES like '" + logicTableName + TABLE_SPLIT_SYMBOL + "%'"); + while (rs.next()) { + String tableName = rs.getString(1); + log.info("分表格式:{}",String.format("^(%s\\d{6})$", logicTableName + TABLE_SPLIT_SYMBOL)); + // 匹配分表格式 例:^(t\_contract_\d{6})$ + if (org.apache.commons.lang3.StringUtils.isNotBlank(tableName) && tableName.matches(String.format("^(%s\\d{6})$", logicTableName + TABLE_SPLIT_SYMBOL))) { + tableNames.add(rs.getString(1)); + } + } + } + } catch (SQLException e) { + log.error(">>>>>>>>>> 【ERROR】数据库连接失败,请稍后重试,原因:{}", e.getMessage(), e); + throw new IllegalArgumentException("数据库连接失败,请稍后重试"); + } + return tableNames; + } + + /** + * 动态更新配置 actualDataNodes + * + * @param logicTableName 逻辑表名 + * @param tableNamesCache 真实表名集合 + */ + public static void actualDataNodesRefresh(String logicTableName, List tableNamesCache) { + try { + if (CollectionUtils.isEmpty(tableNamesCache)) { + return; + } + // 获取数据分片节点 + String dbName = "ds0"; + log.info(">>>>>>>>>> 【INFO】更新分表配置,logicTableName:{},tableNamesCache:{}", logicTableName, tableNamesCache); + + // generate actualDataNodes + String newActualDataNodes = tableNamesCache.stream().map(o -> String.format("%s.%s", dbName, o)).collect(Collectors.joining(",")); + ShardingSphereDataSource shardingSphereDataSource = SpringUtil.getBean(ShardingSphereDataSource.class); + updateShardRuleActualDataNodes(shardingSphereDataSource, logicTableName, newActualDataNodes); + }catch (Exception e){ + log.error("初始化 动态表单失败,原因:{}", e.getMessage(), e); + } + } + + + // -------------------------------------------------------------------------------------------------------------- + // 私有方法 + // -------------------------------------------------------------------------------------------------------------- + + + /** + * 刷新ActualDataNodes + */ + private static void updateShardRuleActualDataNodes(ShardingSphereDataSource dataSource, String logicTableName, String newActualDataNodes) { + // Context manager. + ContextManager contextManager = dataSource.getContextManager(); + + // Rule configuration. + String schemaName = "logic_db"; + Collection newRuleConfigList = new LinkedList<>(); + Collection oldRuleConfigList = dataSource.getContextManager() + .getMetaDataContexts() + .getMetaData(schemaName) + .getRuleMetaData() + .getConfigurations(); + + for (RuleConfiguration oldRuleConfig : oldRuleConfigList) { + if (oldRuleConfig instanceof AlgorithmProvidedShardingRuleConfiguration) { + + // Algorithm provided sharding rule configuration + AlgorithmProvidedShardingRuleConfiguration oldAlgorithmConfig = (AlgorithmProvidedShardingRuleConfiguration) oldRuleConfig; + AlgorithmProvidedShardingRuleConfiguration newAlgorithmConfig = new AlgorithmProvidedShardingRuleConfiguration(); + + // Sharding table rule configuration Collection + Collection newTableRuleConfigList = new LinkedList<>(); + Collection oldTableRuleConfigList = oldAlgorithmConfig.getTables(); + + oldTableRuleConfigList.forEach(oldTableRuleConfig -> { + if (logicTableName.equals(oldTableRuleConfig.getLogicTable())) { + ShardingTableRuleConfiguration newTableRuleConfig = new ShardingTableRuleConfiguration(oldTableRuleConfig.getLogicTable(), newActualDataNodes); + newTableRuleConfig.setTableShardingStrategy(oldTableRuleConfig.getTableShardingStrategy()); + newTableRuleConfig.setDatabaseShardingStrategy(oldTableRuleConfig.getDatabaseShardingStrategy()); + newTableRuleConfig.setKeyGenerateStrategy(oldTableRuleConfig.getKeyGenerateStrategy()); + + newTableRuleConfigList.add(newTableRuleConfig); + } else { + newTableRuleConfigList.add(oldTableRuleConfig); + } + }); + + newAlgorithmConfig.setTables(newTableRuleConfigList); + newAlgorithmConfig.setAutoTables(oldAlgorithmConfig.getAutoTables()); + newAlgorithmConfig.setBindingTableGroups(oldAlgorithmConfig.getBindingTableGroups()); + newAlgorithmConfig.setBroadcastTables(oldAlgorithmConfig.getBroadcastTables()); + newAlgorithmConfig.setDefaultDatabaseShardingStrategy(oldAlgorithmConfig.getDefaultDatabaseShardingStrategy()); + newAlgorithmConfig.setDefaultTableShardingStrategy(oldAlgorithmConfig.getDefaultTableShardingStrategy()); + newAlgorithmConfig.setDefaultKeyGenerateStrategy(oldAlgorithmConfig.getDefaultKeyGenerateStrategy()); + newAlgorithmConfig.setDefaultShardingColumn(oldAlgorithmConfig.getDefaultShardingColumn()); + newAlgorithmConfig.setShardingAlgorithms(oldAlgorithmConfig.getShardingAlgorithms()); + newAlgorithmConfig.setKeyGenerators(oldAlgorithmConfig.getKeyGenerators()); + newRuleConfigList.add(newAlgorithmConfig); + } + } + + // update context + contextManager.alterRuleConfiguration(schemaName, newRuleConfigList); + } + + /** + * 创建分表 + * @param logicTable 逻辑表 + * @param resultTableName 真实表名,例:sys_user_behavior_202201 + * @return 创建结果(true创建成功,false未创建) + */ + private static boolean createShardingTable(ShardingTableCacheEnum logicTable, String resultTableName) { + // 根据日期判断,当前月份之后分表不提前创建 + String month = resultTableName.replace(logicTable.logicTableName() + TABLE_SPLIT_SYMBOL,""); + YearMonth shardingMonth = YearMonth.parse(month, DateTimeFormatter.ofPattern("yyyyMM")); + if (shardingMonth.isAfter(YearMonth.now())) { + return false; + } + + synchronized (logicTable.logicTableName().intern()) { + // 缓存中有此表 返回 + if (logicTable.resultTableNamesCache().contains(resultTableName)) { + return false; + } + // 缓存中无此表,则建表并添加缓存 + executeSql(Collections.singletonList("CREATE TABLE IF NOT EXISTS `" + resultTableName + "` LIKE `" + logicTable.logicTableName() + "`;")); + // 缓存重载 + tableNameCacheReload(logicTable); + } + return true; + } + + /** + * 执行SQL + * @param sqlList SQL集合 + */ + private static void executeSql(List sqlList) { + if (StringUtils.isEmpty(DATASOURCE_URL) || StringUtils.isEmpty(DATASOURCE_USERNAME) || StringUtils.isEmpty(DATASOURCE_PASSWORD)) { + log.error(">>>>>>>>>> 【ERROR】数据库连接配置有误,请稍后重试,URL:{}, username:{}, password:{}", DATASOURCE_URL, DATASOURCE_USERNAME, DATASOURCE_PASSWORD); + throw new IllegalArgumentException("数据库连接配置有误,请稍后重试"); + } + try (Connection conn = DriverManager.getConnection(DATASOURCE_URL, DATASOURCE_USERNAME, DATASOURCE_PASSWORD)) { + try (Statement st = conn.createStatement()) { + conn.setAutoCommit(false); + for (String sql : sqlList) { + st.execute(sql); + } + } catch (Exception e) { + conn.rollback(); + log.error(">>>>>>>>>> 【ERROR】数据表创建执行失败,请稍后重试,原因:{}", e.getMessage(), e); + throw new IllegalArgumentException("数据表创建执行失败,请稍后重试"); + } + } catch (SQLException e) { + log.error(">>>>>>>>>> 【ERROR】数据库连接失败,请稍后重试,原因:{}", e.getMessage(), e); + throw new IllegalArgumentException("数据库连接失败,请稍后重试"); + } + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/sharding/ShardingTablesLoadRunner.java b/maibu-framework/src/main/java/com/maibu/config/sharding/ShardingTablesLoadRunner.java new file mode 100644 index 0000000..6c65231 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/sharding/ShardingTablesLoadRunner.java @@ -0,0 +1,21 @@ +package com.maibu.config.sharding; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + *

@Title ShardingTablesLoadRunner + *

@Description 项目启动后,读取已有分表,进行缓存 + * + */ +@Order(value = 1) // 数字越小,越先执行 +@Component +public class ShardingTablesLoadRunner implements CommandLineRunner { + + @Override + public void run(String... args) { + // 读取已有分表,进行缓存 + //ShardingAlgorithmTool.tableNameCacheReloadAll(); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/sharding/TimeShardingAlgorithm.java b/maibu-framework/src/main/java/com/maibu/config/sharding/TimeShardingAlgorithm.java new file mode 100644 index 0000000..89eea86 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/sharding/TimeShardingAlgorithm.java @@ -0,0 +1,191 @@ +package com.maibu.config.sharding; + +import com.fastbee.framework.config.sharding.enums.ShardingTableCacheEnum; +import com.google.common.collect.Range; +import lombok.extern.slf4j.Slf4j; +import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue; +import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue; +import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm; +import org.springframework.util.CollectionUtils; + +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.function.Function; + +/** + *

@Title TimeShardingAlgorithm + *

@Description 分片算法,按月分片 + * + */ +@Slf4j +public class TimeShardingAlgorithm implements StandardShardingAlgorithm { + /** + * Date类型的分片时间格式 + */ + private static final SimpleDateFormat TABLE_SHARD_Date_FORMATTER = new SimpleDateFormat("yyyyMM"); + + /** + * 分片时间格式 + */ + private static final DateTimeFormatter TABLE_SHARD_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMM"); + + /** + * 完整时间格式 + */ + private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss"); + /** + * 完整时间格式 + */ + private static final SimpleDateFormat DATE_TIME_FORMATTER_SPILE = new SimpleDateFormat("yyyy-MM-dd"); + + /** + * 表分片符号,例:t_user_202201 中,分片符号为 "_" + */ + private final String TABLE_SPLIT_SYMBOL = "_"; + + + /** + * 精准分片 + * @param tableNames 对应分片库中所有分片表的集合 + * @param preciseShardingValue 分片键值,其中 logicTableName 为逻辑表,columnName 分片键,value 为从 SQL 中解析出来的分片键的值 + * @return 表名 + */ + @Override + public String doSharding(Collection tableNames, PreciseShardingValue preciseShardingValue) { + String logicTableName = preciseShardingValue.getLogicTableName(); + ShardingTableCacheEnum logicTable = ShardingTableCacheEnum.of(logicTableName); + createAllTable(logicTable, tableNames); + + /// 打印分片信息 + log.info(">>>>>>>>>> 【INFO】精确分片,节点配置表名:{},数据库缓存表名:{}", tableNames, logicTable.resultTableNamesCache()); + + Date date = preciseShardingValue.getValue(); + Instant instant = date.toInstant(); + LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime(); + String resultTableName = logicTableName + "_" + TABLE_SHARD_TIME_FORMATTER.format(localDateTime); + // 检查分表获取的表名是否存在,不存在则自动建表 + if (!tableNames.contains(resultTableName)){ + tableNames.add(resultTableName); + } + return ShardingAlgorithmTool.getShardingTableAndCreate(logicTable, resultTableName); + } + + /** + * 范围分片 + * @param tableNames 对应分片库中所有分片表的集合 + * @param rangeShardingValue 分片范围 + * @return 表名集合 + */ + @Override + public Collection doSharding(Collection tableNames, RangeShardingValue rangeShardingValue) { + log.info("开始分表查询开始:{}",System.currentTimeMillis()); + String logicTableName = rangeShardingValue.getLogicTableName(); + ShardingTableCacheEnum logicTable = ShardingTableCacheEnum.of(logicTableName); + createAllTable(logicTable, tableNames); + + /// 打印分片信息 + log.info(">>>>>>>>>> 【INFO】范围分片,节点配置表名:{},数据库缓存表名:{}", tableNames, logicTable.resultTableNamesCache()); + + // between and 的起始值 + Range valueRange = rangeShardingValue.getValueRange(); + boolean hasLowerBound = valueRange.hasLowerBound(); + boolean hasUpperBound = valueRange.hasUpperBound(); + + // 获取最大值和最小值 + Set tableNameCache = logicTable.resultTableNamesCache(); + String min = hasLowerBound ? String.valueOf(valueRange.lowerEndpoint()) : getLowerEndpoint(tableNameCache); + String max = hasUpperBound ? String.valueOf(valueRange.upperEndpoint()) : getUpperEndpoint(tableNameCache); + // 循环计算分表范围 + Set resultTableNames = new LinkedHashSet<>(); + try { + Date minDate = DATE_TIME_FORMATTER_SPILE.parse(min); + Date maxDate = DATE_TIME_FORMATTER_SPILE.parse(max); + Calendar calendar = Calendar.getInstance(); + while (minDate.before(maxDate) || minDate.equals(maxDate)) { + String tableName = logicTableName + TABLE_SPLIT_SYMBOL + TABLE_SHARD_Date_FORMATTER.format(minDate); + resultTableNames.add(tableName); + calendar.setTime(minDate); // 设置Calendar的时间为Date对象的时间 + calendar.add(Calendar.DAY_OF_MONTH, 1); // 给日期加一天 + minDate = calendar.getTime(); + } + log.info("开始分表查询结束:{}",System.currentTimeMillis()); + return ShardingAlgorithmTool.getShardingTablesAndCreate(logicTable, resultTableNames); + } catch (Exception e) { + return ShardingAlgorithmTool.getShardingTablesAndCreate(logicTable, logicTable.resultTableNamesCache()); + } + } + + + @Override + public void init() { + + } + + @Override + public String getType() { + return null; + } + + // -------------------------------------------------------------------------------------------------------------- + // 私有方法 + // -------------------------------------------------------------------------------------------------------------- + + /** + * 获取 最小分片值 + * @param tableNames 表名集合 + * @return 最小分片值 + */ + private String getLowerEndpoint(Collection tableNames) { + Optional optional = tableNames.stream() + .map(o -> LocalDateTime.parse(o.replace(TABLE_SPLIT_SYMBOL, "") + "01 00:00:00", DATE_TIME_FORMATTER)) + .min(Comparator.comparing(Function.identity())); + if (optional.isPresent()) { + ZonedDateTime zonedDateTime = optional.get().atZone(ZoneId.systemDefault()); + Instant instant = zonedDateTime.toInstant(); + return String.valueOf(Date.from(instant)); + } else { + log.error(">>>>>>>>>> 【ERROR】获取数据最小分表失败,请稍后重试,tableName:{}", tableNames); + throw new IllegalArgumentException("获取数据最小分表失败,请稍后重试"); + } + } + + /** + * 获取 最大分片值 + * @param tableNames 表名集合 + * @return 最大分片值 + */ + private String getUpperEndpoint(Collection tableNames) { + Optional optional = tableNames.stream() + .map(o -> LocalDateTime.parse(o.replace(TABLE_SPLIT_SYMBOL, "") + "01 00:00:00", DATE_TIME_FORMATTER)) + .max(Comparator.comparing(Function.identity())); + if (optional.isPresent()) { + ZonedDateTime zonedDateTime = optional.get().atZone(ZoneId.systemDefault()); + Instant instant = zonedDateTime.toInstant(); + return String.valueOf(Date.from(instant)); + } else { + log.error(">>>>>>>>>> 【ERROR】获取数据最大分表失败,请稍后重试,tableName:{}", tableNames); + throw new IllegalArgumentException("获取数据最大分表失败,请稍后重试"); + } + } + + /** + * 根据分片规则获取的表,创建所有的表 + * @param logicTable + * @param tableNames + */ + private void createAllTable(ShardingTableCacheEnum logicTable, Collection tableNames) { + if (!CollectionUtils.isEmpty(logicTable.resultTableNamesCache())) { + //如果缓存中有表了,则证明已经创建了表,无需再创建 + return; + } + //根据分片规则创建表 + ShardingAlgorithmTool.getShardingTablesAndCreate(logicTable,tableNames); + //刷新缓存 + ShardingAlgorithmTool.tableNameCacheReload(logicTable); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/config/sharding/enums/ShardingTableCacheEnum.java b/maibu-framework/src/main/java/com/maibu/config/sharding/enums/ShardingTableCacheEnum.java new file mode 100644 index 0000000..c47fc75 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/config/sharding/enums/ShardingTableCacheEnum.java @@ -0,0 +1,83 @@ +package com.maibu.config.sharding.enums; + +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import java.util.*; + +import static com.fastbee.framework.config.sharding.ShardingAlgorithmTool.actualDataNodesRefresh; + + +/** + *

@Title ShardingTableCacheEnum + *

@Description 分片表缓存枚举 + * + */ +public enum ShardingTableCacheEnum { + + /** + * 用户埋点表 + */ + DEVICE_LOG("iot_device_log", new HashSet<>()); + + /** + * 逻辑表名 + */ + private final String logicTableName; + /** + * 实际表名 + */ + private final Set resultTableNamesCache; + + private static Map valueMap = new HashMap<>(); + + static { + Arrays.stream(ShardingTableCacheEnum.values()).forEach(o -> valueMap.put(o.logicTableName, o)); + } + + ShardingTableCacheEnum(String logicTableName, Set resultTableNamesCache) { + this.logicTableName = logicTableName; + this.resultTableNamesCache = resultTableNamesCache; + } + + public static ShardingTableCacheEnum of(String value) { + return valueMap.get(value); + } + + public String logicTableName() { + return logicTableName; + } + + public Set resultTableNamesCache() { + return resultTableNamesCache; + } + + /** + * 更新缓存、配置(原子操作) + * + * @param tableNameList + */ + public void atomicUpdateCacheAndActualDataNodes(List tableNameList) { + if (CollectionUtils.isEmpty(tableNameList)) { + return; + } + synchronized (resultTableNamesCache) { + // 删除缓存 + resultTableNamesCache.clear(); + // 写入新的缓存 + resultTableNamesCache.addAll(tableNameList); + // 动态更新配置 actualDataNodes + actualDataNodesRefresh(logicTableName, tableNameList); + } + } + + public static Set logicTableNames() { + return valueMap.keySet(); + } + + @Override + public String toString() { + return "ShardingTableCacheEnum{" + + "logicTableName='" + logicTableName + '\'' + + ", resultTableNamesCache=" + resultTableNamesCache + + '}'; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/datasource/DynamicDataSource.java b/maibu-framework/src/main/java/com/maibu/datasource/DynamicDataSource.java new file mode 100644 index 0000000..ae408f3 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/datasource/DynamicDataSource.java @@ -0,0 +1,30 @@ +package com.maibu.datasource; + +import java.util.Map; +import javax.sql.DataSource; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +/** + * 动态数据源 + * + * @author ruoyi + */ +@Slf4j +public class DynamicDataSource extends AbstractRoutingDataSource +{ + public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) + { + super.setDefaultTargetDataSource(defaultTargetDataSource); + super.setTargetDataSources(targetDataSources); + super.afterPropertiesSet(); + } + + @Override + protected Object determineCurrentLookupKey() + { + //log.debug("数据源:" + DynamicDataSourceContextHolder.getDataSourceType()); + return DynamicDataSourceContextHolder.getDataSourceType(); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/datasource/DynamicDataSourceContextHolder.java b/maibu-framework/src/main/java/com/maibu/datasource/DynamicDataSourceContextHolder.java new file mode 100644 index 0000000..d546ae1 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/datasource/DynamicDataSourceContextHolder.java @@ -0,0 +1,45 @@ +package com.maibu.datasource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 数据源切换处理 + * + * @author ruoyi + */ +public class DynamicDataSourceContextHolder +{ + public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class); + + /** + * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本, + * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 + */ + private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); + + /** + * 设置数据源的变量 + */ + public static void setDataSourceType(String dsType) + { + log.info("切换到{}数据源", dsType); + CONTEXT_HOLDER.set(dsType); + } + + /** + * 获得数据源的变量 + */ + public static String getDataSourceType() + { + return CONTEXT_HOLDER.get(); + } + + /** + * 清空数据源变量 + */ + public static void clearDataSourceType() + { + CONTEXT_HOLDER.remove(); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/handler/KeyPrefixHandler.java b/maibu-framework/src/main/java/com/maibu/handler/KeyPrefixHandler.java new file mode 100644 index 0000000..a48af7b --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/handler/KeyPrefixHandler.java @@ -0,0 +1,50 @@ +package com.maibu.handler; + +import com.fastbee.common.utils.StringUtils; +import org.redisson.api.NameMapper; + +/** + * redis缓存key前缀处理 + * + * @author ye + * @date 2022/7/14 17:44 + * @since 4.3.0 + */ +public class KeyPrefixHandler implements NameMapper { + + private final String keyPrefix; + + public KeyPrefixHandler(String keyPrefix) { + //前缀为空 则返回空前缀 + this.keyPrefix = StringUtils.isBlank(keyPrefix) ? "" : keyPrefix + ":"; + } + + /** + * 增加前缀 + */ + @Override + public String map(String name) { + if (StringUtils.isBlank(name)) { + return null; + } + if (StringUtils.isNotBlank(keyPrefix) && !name.startsWith(keyPrefix)) { + return keyPrefix + name; + } + return name; + } + + /** + * 去除前缀 + */ + @Override + public String unmap(String name) { + if (StringUtils.isBlank(name)) { + return null; + } + if (StringUtils.isNotBlank(keyPrefix) && name.startsWith(keyPrefix)) { + return name.substring(keyPrefix.length()); + } + return name; + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/interceptor/LanguageInterceptor.java b/maibu-framework/src/main/java/com/maibu/interceptor/LanguageInterceptor.java new file mode 100644 index 0000000..ff6a282 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/interceptor/LanguageInterceptor.java @@ -0,0 +1,58 @@ +package com.maibu.interceptor; + +import com.fastbee.common.utils.SecurityUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.system.enums.Language; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Locale; + +import static com.fastbee.common.constant.Constants.LANGUAGE; + + +/** + * 国际化语言拦截器 + */ +@Component +@Slf4j +public class LanguageInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String language = request.getHeader(LANGUAGE); + if (StringUtils.isEmpty(language) || language.equals("undefined") + || language.equals("")|| language.equals("null")){ + //针对有些接口没有增加语言字段,先去token获取 + language = SecurityUtils.getLanguage(); + }else if (!language.contains("-")){ + language = Language.matches(language); + } + // 前端传递的language必须是zh-CN格式的,中间的-必须要完整,不能只传递zh或en + Locale locale = new Locale(language.split("-")[0],language.split("-")[1]); + // 这样赋值以后,MessageUtils.message方法就不用修改了 + LocaleContextHolder.setLocale(locale); + return true; + } + + /** + * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后) + */ + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { + } + + /** + * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) + */ + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + } + + +} diff --git a/maibu-framework/src/main/java/com/maibu/interceptor/RepeatSubmitInterceptor.java b/maibu-framework/src/main/java/com/maibu/interceptor/RepeatSubmitInterceptor.java new file mode 100644 index 0000000..a5e3c35 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/interceptor/RepeatSubmitInterceptor.java @@ -0,0 +1,55 @@ +package com.maibu.interceptor; + +import java.lang.reflect.Method; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import com.alibaba.fastjson2.JSON; +import com.fastbee.common.annotation.RepeatSubmit; +import com.fastbee.common.core.domain.AjaxResult; +import com.fastbee.common.utils.ServletUtils; + +/** + * 防止重复提交拦截器 + * + * @author ruoyi + */ +@Component +public abstract class RepeatSubmitInterceptor implements HandlerInterceptor +{ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception + { + if (handler instanceof HandlerMethod) + { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); + if (annotation != null) + { + if (this.isRepeatSubmit(request, annotation)) + { + AjaxResult ajaxResult = AjaxResult.error(annotation.message()); + ServletUtils.renderString(response, JSON.toJSONString(ajaxResult)); + return false; + } + } + return true; + } + else + { + return true; + } + } + + /** + * 验证是否重复提交由子类实现具体的防重复提交的规则 + * + * @param request + * @return + * @throws Exception + */ + public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation); +} diff --git a/maibu-framework/src/main/java/com/maibu/interceptor/impl/SameUrlDataInterceptor.java b/maibu-framework/src/main/java/com/maibu/interceptor/impl/SameUrlDataInterceptor.java new file mode 100644 index 0000000..1b8cea4 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/interceptor/impl/SameUrlDataInterceptor.java @@ -0,0 +1,110 @@ +package com.maibu.interceptor.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson2.JSON; +import com.fastbee.common.annotation.RepeatSubmit; +import com.fastbee.common.constant.CacheConstants; +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.filter.RepeatedlyRequestWrapper; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.common.utils.http.HttpHelper; +import com.fastbee.framework.interceptor.RepeatSubmitInterceptor; + +/** + * 判断请求url和数据是否和上一次相同, + * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。 + * + * @author ruoyi + */ +@Component +public class SameUrlDataInterceptor extends RepeatSubmitInterceptor +{ + public final String REPEAT_PARAMS = "repeatParams"; + + public final String REPEAT_TIME = "repeatTime"; + + // 令牌自定义标识 + @Value("${token.header}") + private String header; + + @Autowired + private RedisCache redisCache; + + @SuppressWarnings("unchecked") + @Override + public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) + { + String nowParams = ""; + if (request instanceof RepeatedlyRequestWrapper) + { + RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; + nowParams = HttpHelper.getBodyString(repeatedlyRequest); + } + + // body参数为空,获取Parameter的数据 + if (StringUtils.isEmpty(nowParams)) + { + nowParams = JSON.toJSONString(request.getParameterMap()); + } + Map nowDataMap = new HashMap(); + nowDataMap.put(REPEAT_PARAMS, nowParams); + nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); + + // 请求地址(作为存放cache的key值) + String url = request.getRequestURI(); + + // 唯一值(没有消息头则使用请求地址) + String submitKey = StringUtils.trimToEmpty(request.getHeader(header)); + + // 唯一标识(指定key + url + 消息头) + String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey; + + Object sessionObj = redisCache.getCacheObject(cacheRepeatKey); + if (sessionObj != null) + { + Map sessionMap = (Map) sessionObj; + if (sessionMap.containsKey(url)) + { + Map preDataMap = (Map) sessionMap.get(url); + if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) + { + return true; + } + } + } + Map cacheMap = new HashMap(); + cacheMap.put(url, nowDataMap); + redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS); + return false; + } + + /** + * 判断参数是否相同 + */ + private boolean compareParams(Map nowMap, Map preMap) + { + String nowParams = (String) nowMap.get(REPEAT_PARAMS); + String preParams = (String) preMap.get(REPEAT_PARAMS); + return nowParams.equals(preParams); + } + + /** + * 判断两次间隔时间 + */ + private boolean compareTime(Map nowMap, Map preMap, int interval) + { + long time1 = (Long) nowMap.get(REPEAT_TIME); + long time2 = (Long) preMap.get(REPEAT_TIME); + if ((time1 - time2) < interval) + { + return true; + } + return false; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/manager/AsyncManager.java b/maibu-framework/src/main/java/com/maibu/manager/AsyncManager.java new file mode 100644 index 0000000..9418d1e --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/manager/AsyncManager.java @@ -0,0 +1,55 @@ +package com.maibu.manager; + +import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import com.fastbee.common.utils.Threads; +import com.fastbee.common.utils.spring.SpringUtils; + +/** + * 异步任务管理器 + * + * @author ruoyi + */ +public class AsyncManager +{ + /** + * 操作延迟10毫秒 + */ + private final int OPERATE_DELAY_TIME = 10; + + /** + * 异步操作任务调度线程池 + */ + private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); + + /** + * 单例模式 + */ + private AsyncManager(){} + + private static AsyncManager me = new AsyncManager(); + + public static AsyncManager me() + { + return me; + } + + /** + * 执行任务 + * + * @param task 任务 + */ + public void execute(TimerTask task) + { + executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); + } + + /** + * 停止任务线程池 + */ + public void shutdown() + { + Threads.shutdownAndAwaitTermination(executor); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/manager/CaffeineCacheDecorator.java b/maibu-framework/src/main/java/com/maibu/manager/CaffeineCacheDecorator.java new file mode 100644 index 0000000..4e31195 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/manager/CaffeineCacheDecorator.java @@ -0,0 +1,88 @@ +package com.maibu.manager; + +import org.springframework.cache.Cache; +import com.fastbee.common.utils.spring.SpringUtils; +import java.util.concurrent.Callable; + +/** + * Cache 装饰器模式(用于扩展 Caffeine 一级缓存) + * + */ +public class CaffeineCacheDecorator implements Cache { + + private static final com.github.benmanes.caffeine.cache.Cache + CAFFEINE = SpringUtils.getBean("caffeine"); + + private final Cache cache; + + public CaffeineCacheDecorator(Cache cache) { + this.cache = cache; + } + + @Override + public String getName() { + return cache.getName(); + } + + @Override + public Object getNativeCache() { + return cache.getNativeCache(); + } + + public String getUniqueKey(Object key) { + return cache.getName() + ":" + key; + } + + @Override + public ValueWrapper get(Object key) { + Object o = CAFFEINE.get(getUniqueKey(key), k -> cache.get(key)); + return (ValueWrapper) o; + } + + @SuppressWarnings("unchecked") + public T get(Object key, Class type) { + Object o = CAFFEINE.get(getUniqueKey(key), k -> cache.get(key, type)); + return (T) o; + } + + @Override + public void put(Object key, Object value) { + CAFFEINE.invalidate(getUniqueKey(key)); + cache.put(key, value); + } + + public ValueWrapper putIfAbsent(Object key, Object value) { + CAFFEINE.invalidate(getUniqueKey(key)); + return cache.putIfAbsent(key, value); + } + + @Override + public void evict(Object key) { + evictIfPresent(key); + } + + public boolean evictIfPresent(Object key) { + boolean b = cache.evictIfPresent(key); + if (b) { + CAFFEINE.invalidate(getUniqueKey(key)); + } + return b; + } + + @Override + public void clear() { + cache.clear(); + } + + public boolean invalidate() { + return cache.invalidate(); + } + + @SuppressWarnings("unchecked") + @Override + public T get(Object key, Callable valueLoader) { + Object o = CAFFEINE.get(getUniqueKey(key), k -> cache.get(key, valueLoader)); + return (T) o; + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/manager/DeleteKeyGenerator.java b/maibu-framework/src/main/java/com/maibu/manager/DeleteKeyGenerator.java new file mode 100644 index 0000000..db49c23 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/manager/DeleteKeyGenerator.java @@ -0,0 +1,30 @@ +package com.maibu.manager; + +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.util.*; + +@Component +public class DeleteKeyGenerator implements KeyGenerator { + + @Override + public Object generate(Object target, Method method, Object... params) { + if (params.length > 0) { + Object ids = params[0]; + Collection collection = Collections.singletonList(ids); + if (collection.stream().allMatch(item -> item instanceof Long)) { + // 将 Collection 转换为 String[] + String[] keys = collection.stream() + .map(Object::toString) + .toArray(String[]::new); + // 使用 keys + List keysList = new ArrayList<>(keys.length); + keysList.addAll(Arrays.asList(keys)); + return keysList; + } + } + return new String[0]; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/manager/ShutdownManager.java b/maibu-framework/src/main/java/com/maibu/manager/ShutdownManager.java new file mode 100644 index 0000000..b63f1f4 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/manager/ShutdownManager.java @@ -0,0 +1,39 @@ +package com.maibu.manager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import javax.annotation.PreDestroy; + +/** + * 确保应用退出时能关闭后台线程 + * + * @author ruoyi + */ +@Component +public class ShutdownManager +{ + private static final Logger logger = LoggerFactory.getLogger("sys-user"); + + @PreDestroy + public void destroy() + { + shutdownAsyncManager(); + } + + /** + * 停止异步执行任务 + */ + private void shutdownAsyncManager() + { + try + { + logger.info("====关闭后台任务任务线程池===="); + AsyncManager.me().shutdown(); + } + catch (Exception e) + { + logger.error(e.getMessage(), e); + } + } +} diff --git a/maibu-framework/src/main/java/com/maibu/manager/SpringCacheManager.java b/maibu-framework/src/main/java/com/maibu/manager/SpringCacheManager.java new file mode 100644 index 0000000..c706dce --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/manager/SpringCacheManager.java @@ -0,0 +1,186 @@ +package com.maibu.manager; + +import com.fastbee.framework.utils.RedisUtils; +import org.redisson.api.RMap; +import org.redisson.api.RMapCache; +import org.redisson.spring.cache.CacheConfig; +import org.redisson.spring.cache.RedissonCache; +import org.springframework.boot.convert.DurationStyle; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.transaction.TransactionAwareCacheDecorator; +import org.springframework.util.StringUtils; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * A {@link CacheManager} implementation + * backed by Redisson instance. + *

+ * 修改 RedissonSpringCacheManager 源码 + * 重写 cacheName 处理方法 支持多参数 + * + * + */ +@SuppressWarnings("unchecked") +public class SpringCacheManager implements CacheManager { + + private boolean dynamic = true; + + private boolean allowNullValues = true; + + private boolean transactionAware = true; + + private Long ttl; + + Map configMap = new ConcurrentHashMap<>(); + ConcurrentMap instanceMap = new ConcurrentHashMap<>(); + + /** + * Creates CacheManager supplied by Redisson instance + */ + public SpringCacheManager() { + } + + public SpringCacheManager(Long ttl) { + this.ttl = ttl; + } + + + /** + * Defines possibility of storing {@code null} values. + *

+ * Default is true + * + * @param allowNullValues stores if true + */ + public void setAllowNullValues(boolean allowNullValues) { + this.allowNullValues = allowNullValues; + } + + /** + * Defines if cache aware of Spring-managed transactions. + * If {@code true} put/evict operations are executed only for successful transaction in after-commit phase. + *

+ * Default is false + * + * @param transactionAware cache is transaction aware if true + */ + public void setTransactionAware(boolean transactionAware) { + this.transactionAware = transactionAware; + } + + /** + * Defines 'fixed' cache names. + * A new cache instance will not be created in dynamic for non-defined names. + *

+ * `null` parameter setups dynamic mode + * + * @param names of caches + */ + public void setCacheNames(Collection names) { + if (names != null) { + for (String name : names) { + getCache(name); + } + dynamic = false; + } else { + dynamic = true; + } + } + + /** + * Set cache config mapped by cache name + * + * @param config object + */ + public void setConfig(Map config) { + this.configMap = (Map) config; + } + + protected CacheConfig createDefaultConfig() { + return new CacheConfig(); + } + + @Override + public Cache getCache(String name) { + // 重写 cacheName 支持多参数 + String[] array = StringUtils.delimitedListToStringArray(name, "#"); + name = array[0]; + + Cache cache = instanceMap.get(name); + if (cache != null) { + return cache; + } + if (!dynamic) { + return cache; + } + + CacheConfig config = configMap.get(name); + if (config == null) { + config = createDefaultConfig(); + configMap.put(name, config); + } + + if (ttl > 0) { + config.setTTL(ttl * 1000); + } + + if (array.length > 1) { + config.setTTL(DurationStyle.detectAndParse(array[1]).toMillis()); + } + if (array.length > 2) { + config.setMaxIdleTime(DurationStyle.detectAndParse(array[2]).toMillis()); + } + if (array.length > 3) { + config.setMaxSize(Integer.parseInt(array[3])); + } + + if (config.getMaxIdleTime() == 0 && config.getTTL() == 0 && config.getMaxSize() == 0) { + return createMap(name, config); + } + + return createMapCache(name, config); + } + + private Cache createMap(String name, CacheConfig config) { + RMap map = RedisUtils.getClient().getMap(name); + + Cache cache = new CaffeineCacheDecorator(new RedissonCache(map, allowNullValues)); + if (transactionAware) { + cache = new TransactionAwareCacheDecorator(cache); + } + Cache oldCache = instanceMap.putIfAbsent(name, cache); + if (oldCache != null) { + cache = oldCache; + } + return cache; + } + + private Cache createMapCache(String name, CacheConfig config) { + RMapCache map = RedisUtils.getClient().getMapCache(name); + + Cache cache = new CaffeineCacheDecorator(new RedissonCache(map, config, allowNullValues)); + if (transactionAware) { + cache = new TransactionAwareCacheDecorator(cache); + } + Cache oldCache = instanceMap.putIfAbsent(name, cache); + if (oldCache != null) { + cache = oldCache; + } else { + map.setMaxSize(config.getMaxSize()); + } + return cache; + } + + @Override + public Collection getCacheNames() { + return Collections.unmodifiableSet(configMap.keySet()); + } + + +} diff --git a/maibu-framework/src/main/java/com/maibu/manager/factory/AsyncFactory.java b/maibu-framework/src/main/java/com/maibu/manager/factory/AsyncFactory.java new file mode 100644 index 0000000..48568b1 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/manager/factory/AsyncFactory.java @@ -0,0 +1,102 @@ +package com.maibu.manager.factory; + +import java.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.fastbee.common.constant.Constants; +import com.fastbee.common.utils.LogUtils; +import com.fastbee.common.utils.ServletUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.common.utils.ip.AddressUtils; +import com.fastbee.common.utils.ip.IpUtils; +import com.fastbee.common.utils.spring.SpringUtils; +import com.fastbee.system.domain.SysLogininfor; +import com.fastbee.system.domain.SysOperLog; +import com.fastbee.system.service.ISysLogininforService; +import com.fastbee.system.service.ISysOperLogService; +import eu.bitwalker.useragentutils.UserAgent; + +/** + * 异步工厂(产生任务用) + * + * @author ruoyi + */ +public class AsyncFactory +{ + private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user"); + + /** + * 记录登录信息 + * + * @param username 用户名 + * @param status 状态 + * @param message 消息 + * @param args 列表 + * @return 任务task + */ + public static TimerTask recordLogininfor(final String username, final String status, final String message, + final Object... args) + { + final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + final String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + return new TimerTask() + { + @Override + public void run() + { + String address = AddressUtils.getRealAddressByIP(ip); + StringBuilder s = new StringBuilder(); + s.append(LogUtils.getBlock(ip)); + s.append(address); + s.append(LogUtils.getBlock(username)); + s.append(LogUtils.getBlock(status)); + s.append(LogUtils.getBlock(message)); + // 打印信息到日志 + sys_user_logger.info(s.toString(), args); + // 获取客户端操作系统 + String os = userAgent.getOperatingSystem().getName(); + // 获取客户端浏览器 + String browser = userAgent.getBrowser().getName(); + // 封装对象 + SysLogininfor logininfor = new SysLogininfor(); + logininfor.setUserName(username); + logininfor.setIpaddr(ip); + logininfor.setLoginLocation(address); + logininfor.setBrowser(browser); + logininfor.setOs(os); + logininfor.setMsg(message); + // 日志状态 + if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) + { + logininfor.setStatus(Constants.SUCCESS); + } + else if (Constants.LOGIN_FAIL.equals(status)) + { + logininfor.setStatus(Constants.FAIL); + } + // 插入数据 + SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor); + } + }; + } + + /** + * 操作日志记录 + * + * @param operLog 操作日志信息 + * @return 任务task + */ + public static TimerTask recordOper(final SysOperLog operLog) + { + return new TimerTask() + { + @Override + public void run() + { + // 远程查询操作地点 + operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); + SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog); + } + }; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/mybatis/LambdaQueryWrapperX.java b/maibu-framework/src/main/java/com/maibu/mybatis/LambdaQueryWrapperX.java new file mode 100644 index 0000000..784486f --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/mybatis/LambdaQueryWrapperX.java @@ -0,0 +1,136 @@ +package com.maibu.mybatis; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.util.StringUtils; + +import java.util.Collection; + +/** + * 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能: + *

+ * 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。 + * + * @param 数据类型 + */ +public class LambdaQueryWrapperX extends LambdaQueryWrapper { + + public LambdaQueryWrapperX likeIfPresent(SFunction column, String val) { + if (StringUtils.hasText(val)) { + return (LambdaQueryWrapperX) super.like(column, val); + } + return this; + } + + public LambdaQueryWrapperX inIfPresent(SFunction column, Collection values) { + if (!CollectionUtils.isEmpty(values)) { + return (LambdaQueryWrapperX) super.in(column, values); + } + return this; + } + + public LambdaQueryWrapperX inIfPresent(SFunction column, Object... values) { + if (!ArrayUtil.isEmpty(values)) { + return (LambdaQueryWrapperX) super.in(column, values); + } + return this; + } + + public LambdaQueryWrapperX eqIfPresent(SFunction column, Object val) { + if (ObjectUtil.isNotEmpty(val)) { + return (LambdaQueryWrapperX) super.eq(column, val); + } + return this; + } + + public LambdaQueryWrapperX neIfPresent(SFunction column, Object val) { + if (ObjectUtil.isNotEmpty(val)) { + return (LambdaQueryWrapperX) super.ne(column, val); + } + return this; + } + + public LambdaQueryWrapperX gtIfPresent(SFunction column, Object val) { + if (val != null) { + return (LambdaQueryWrapperX) super.gt(column, val); + } + return this; + } + + public LambdaQueryWrapperX geIfPresent(SFunction column, Object val) { + if (val != null) { + return (LambdaQueryWrapperX) super.ge(column, val); + } + return this; + } + + public LambdaQueryWrapperX ltIfPresent(SFunction column, Object val) { + if (val != null) { + return (LambdaQueryWrapperX) super.lt(column, val); + } + return this; + } + + public LambdaQueryWrapperX leIfPresent(SFunction column, Object val) { + if (val != null) { + return (LambdaQueryWrapperX) super.le(column, val); + } + return this; + } + + public LambdaQueryWrapperX betweenIfPresent(SFunction column, Object val1, Object val2) { + if (val1 != null && val2 != null) { + return (LambdaQueryWrapperX) super.between(column, val1, val2); + } + if (val1 != null) { + return (LambdaQueryWrapperX) ge(column, val1); + } + if (val2 != null) { + return (LambdaQueryWrapperX) le(column, val2); + } + return this; + } + + public LambdaQueryWrapperX betweenIfPresent(SFunction column, Object[] values) { + Object val1 = ArrayUtils.get(values, 0); + Object val2 = ArrayUtils.get(values, 1); + return betweenIfPresent(column, val1, val2); + } + + // ========== 重写父类方法,方便链式调用 ========== + + @Override + public LambdaQueryWrapperX eq(boolean condition, SFunction column, Object val) { + super.eq(condition, column, val); + return this; + } + + @Override + public LambdaQueryWrapperX eq(SFunction column, Object val) { + super.eq(column, val); + return this; + } + + @Override + public LambdaQueryWrapperX orderByDesc(SFunction column) { + super.orderByDesc(true, column); + return this; + } + + @Override + public LambdaQueryWrapperX last(String lastSql) { + super.last(lastSql); + return this; + } + + @Override + public LambdaQueryWrapperX in(SFunction column, Collection coll) { + super.in(column, coll); + return this; + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/mybatis/QueryWrapperX.java b/maibu-framework/src/main/java/com/maibu/mybatis/QueryWrapperX.java new file mode 100644 index 0000000..468e813 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/mybatis/QueryWrapperX.java @@ -0,0 +1,140 @@ +package com.maibu.mybatis; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.ArrayUtils; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.util.Collection; + +/** + * 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能: + * + * 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。 + * + * @param 数据类型 + */ +public class QueryWrapperX extends QueryWrapper { + + public QueryWrapperX likeIfPresent(String column, String val) { + if (StringUtils.hasText(val)) { + return (QueryWrapperX) super.like(column, val); + } + return this; + } + + public QueryWrapperX inIfPresent(String column, Collection values) { + if (!CollectionUtils.isEmpty(values)) { + return (QueryWrapperX) super.in(column, values); + } + return this; + } + + public QueryWrapperX inIfPresent(String column, Object... values) { + if (!ArrayUtils.isEmpty(values)) { + return (QueryWrapperX) super.in(column, values); + } + return this; + } + + public QueryWrapperX eqIfPresent(String column, Object val) { + if (val != null) { + return (QueryWrapperX) super.eq(column, val); + } + return this; + } + + public QueryWrapperX neIfPresent(String column, Object val) { + if (val != null) { + return (QueryWrapperX) super.ne(column, val); + } + return this; + } + + public QueryWrapperX gtIfPresent(String column, Object val) { + if (val != null) { + return (QueryWrapperX) super.gt(column, val); + } + return this; + } + + public QueryWrapperX geIfPresent(String column, Object val) { + if (val != null) { + return (QueryWrapperX) super.ge(column, val); + } + return this; + } + + public QueryWrapperX ltIfPresent(String column, Object val) { + if (val != null) { + return (QueryWrapperX) super.lt(column, val); + } + return this; + } + + public QueryWrapperX leIfPresent(String column, Object val) { + if (val != null) { + return (QueryWrapperX) super.le(column, val); + } + return this; + } + + public QueryWrapperX betweenIfPresent(String column, Object val1, Object val2) { + if (val1 != null && val2 != null) { + return (QueryWrapperX) super.between(column, val1, val2); + } + if (val1 != null) { + return (QueryWrapperX) ge(column, val1); + } + if (val2 != null) { + return (QueryWrapperX) le(column, val2); + } + return this; + } + + public QueryWrapperX betweenIfPresent(String column, Object[] values) { + if (values!= null && values.length != 0 && values[0] != null && values[1] != null) { + return (QueryWrapperX) super.between(column, values[0], values[1]); + } + if (values!= null && values.length != 0 && values[0] != null) { + return (QueryWrapperX) ge(column, values[0]); + } + if (values!= null && values.length != 0 && values[1] != null) { + return (QueryWrapperX) le(column, values[1]); + } + return this; + } + + // ========== 重写父类方法,方便链式调用 ========== + + @Override + public QueryWrapperX eq(boolean condition, String column, Object val) { + super.eq(condition, column, val); + return this; + } + + @Override + public QueryWrapperX eq(String column, Object val) { + super.eq(column, val); + return this; + } + + @Override + public QueryWrapperX orderByDesc(String column) { + super.orderByDesc(true, column); + return this; + } + + @Override + public QueryWrapperX last(String lastSql) { + super.last(lastSql); + return this; + } + + @Override + public QueryWrapperX in(String column, Collection coll) { + super.in(column, coll); + return this; + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/mybatis/mapper/BaseMapperX.java b/maibu-framework/src/main/java/com/maibu/mybatis/mapper/BaseMapperX.java new file mode 100644 index 0000000..313b3c6 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/mybatis/mapper/BaseMapperX.java @@ -0,0 +1,112 @@ +package com.maibu.mybatis.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.baomidou.mybatisplus.extension.toolkit.Db; +import com.fastbee.common.core.domain.PageParam; +import com.fastbee.common.core.domain.PageResult; +import com.fastbee.framework.mybatis.utils.MyBatisUtils; +import org.apache.ibatis.annotations.Param; + +import java.util.Collection; +import java.util.List; + +/** + * 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力 + *

+ * 为什么继承 MPJBaseMapper 接口?支持 MyBatis Plus 多表 Join 的能力。 + */ +public interface BaseMapperX extends BaseMapper { + + default PageResult selectPage(PageParam pageParam, @Param("ew") Wrapper queryWrapper) { + // MyBatis Plus 查询 + IPage mpPage = MyBatisUtils.buildPage(pageParam); + selectPage(mpPage, queryWrapper); + // 转换返回 + return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); + } + + default T selectOne(String field, Object value) { + return selectOne(new QueryWrapper().eq(field, value)); + } + + default T selectOne(SFunction field, Object value) { + return selectOne(new LambdaQueryWrapper().eq(field, value)); + } + + default T selectOne(String field1, Object value1, String field2, Object value2) { + return selectOne(new QueryWrapper().eq(field1, value1).eq(field2, value2)); + } + + default T selectOne(SFunction field1, Object value1, SFunction field2, Object value2) { + return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)); + } + + default Long selectCount() { + return selectCount(new QueryWrapper()); + } + + default Long selectCount(String field, Object value) { + return selectCount(new QueryWrapper().eq(field, value)); + } + + default Long selectCount(SFunction field, Object value) { + return selectCount(new LambdaQueryWrapper().eq(field, value)); + } + + default List selectList() { + return selectList(new QueryWrapper<>()); + } + + default List selectList(String field, Object value) { + return selectList(new QueryWrapper().eq(field, value)); + } + + default List selectList(SFunction field, Object value) { + return selectList(new LambdaQueryWrapper().eq(field, value)); + } + + default List selectList(String field, Collection values) { + return selectList(new QueryWrapper().in(field, values)); + } + + default List selectList(SFunction field, Collection values) { + return selectList(new LambdaQueryWrapper().in(field, values)); + } + + default List selectList(SFunction leField, SFunction geField, Object value) { + return selectList(new LambdaQueryWrapper().le(leField, value).ge(geField, value)); + } + + /** + * 批量插入,适合大量数据插入 + * + * @param entities 实体们 + */ + default void insertBatch(Collection entities) { + Db.saveBatch(entities); + } + + /** + * 批量插入,适合大量数据插入 + * + * @param entities 实体们 + * @param size 插入数量 Db.saveBatch 默认为 1000 + */ + default void insertBatch(Collection entities, int size) { + Db.saveBatch(entities, size); + } + + default void updateBatch(T update) { + update(update, new QueryWrapper<>()); + } + + default void updateBatch(Collection entities, int size) { + Db.updateBatchById(entities, size); + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/mybatis/utils/MyBatisUtils.java b/maibu-framework/src/main/java/com/maibu/mybatis/utils/MyBatisUtils.java new file mode 100644 index 0000000..7dce200 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/mybatis/utils/MyBatisUtils.java @@ -0,0 +1,88 @@ +package com.maibu.mybatis.utils; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fastbee.common.core.domain.PageParam; +import com.fastbee.common.core.domain.SortingField; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.schema.Table; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * MyBatis 工具类 + */ +public class MyBatisUtils { + + private static final String MYSQL_ESCAPE_CHARACTER = "`"; + + public static Page buildPage(PageParam pageParam) { + return buildPage(pageParam, null); + } + + public static Page buildPage(PageParam pageParam, Collection sortingFields) { + // 页码 + 数量 + Page page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize()); + // 排序字段 + if (!CollectionUtil.isEmpty(sortingFields)) { + page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder()) ? + OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField())) + .collect(Collectors.toList())); + } + return page; + } + + /** + * 将拦截器添加到链中 + * 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置 + * + * @param interceptor 链 + * @param inner 拦截器 + * @param index 位置 + */ + public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner, int index) { + List inners = new ArrayList<>(interceptor.getInterceptors()); + inners.add(index, inner); + interceptor.setInterceptors(inners); + } + + /** + * 获得 Table 对应的表名 + * + * 兼容 MySQL 转义表名 `t_xxx` + * + * @param table 表 + * @return 去除转移字符后的表名 + */ + public static String getTableName(Table table) { + String tableName = table.getName(); + if (tableName.startsWith(MYSQL_ESCAPE_CHARACTER) && tableName.endsWith(MYSQL_ESCAPE_CHARACTER)) { + tableName = tableName.substring(1, tableName.length() - 1); + } + return tableName; + } + + /** + * 构建 Column 对象 + * + * @param tableName 表名 + * @param tableAlias 别名 + * @param column 字段名 + * @return Column 对象 + */ + public static Column buildColumn(String tableName, Alias tableAlias, String column) { + if (tableAlias != null) { + tableName = tableAlias.getName(); + } + return new Column(tableName + StringPool.DOT + column); + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/security/context/AuthenticationContextHolder.java b/maibu-framework/src/main/java/com/maibu/security/context/AuthenticationContextHolder.java new file mode 100644 index 0000000..85b804a --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/security/context/AuthenticationContextHolder.java @@ -0,0 +1,28 @@ +package com.maibu.security.context; + +import org.springframework.security.core.Authentication; + +/** + * 身份验证信息 + * + * @author ruoyi + */ +public class AuthenticationContextHolder +{ + private static final ThreadLocal contextHolder = new ThreadLocal<>(); + + public static Authentication getContext() + { + return contextHolder.get(); + } + + public static void setContext(Authentication context) + { + contextHolder.set(context); + } + + public static void clearContext() + { + contextHolder.remove(); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/security/context/PermissionContextHolder.java b/maibu-framework/src/main/java/com/maibu/security/context/PermissionContextHolder.java new file mode 100644 index 0000000..3755ae2 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/security/context/PermissionContextHolder.java @@ -0,0 +1,27 @@ +package com.maibu.security.context; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import com.fastbee.common.core.text.Convert; + +/** + * 权限信息 + * + * @author ruoyi + */ +public class PermissionContextHolder +{ + private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT"; + + public static void setContext(String permission) + { + RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission, + RequestAttributes.SCOPE_REQUEST); + } + + public static String getContext() + { + return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES, + RequestAttributes.SCOPE_REQUEST)); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/security/filter/JwtAuthenticationTokenFilter.java b/maibu-framework/src/main/java/com/maibu/security/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..bc2bf57 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/security/filter/JwtAuthenticationTokenFilter.java @@ -0,0 +1,55 @@ +package com.maibu.security.filter; + +import java.io.IOException; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import com.fastbee.common.core.domain.model.LoginUser; +import com.fastbee.common.utils.SecurityUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.framework.web.service.TokenService; + +/** + * token过滤器 验证token有效性 + * + * @author ruoyi + */ +@Component +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter +{ + @Autowired + private TokenService tokenService; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws ServletException, IOException + { + if ("OPTIONS".equals(request.getMethod())) { + response.setStatus(HttpServletResponse.SC_OK); + return; + } + // 若为 WebSocket 路径,直接放行 + if (request.getRequestURI().contains("/ws")) { + chain.doFilter(request, response); + return; + } + LoginUser loginUser = tokenService.getLoginUser(request); + if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) + { + tokenService.verifyToken(loginUser); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + } + chain.doFilter(request, response); + } + + +} diff --git a/maibu-framework/src/main/java/com/maibu/security/handle/AuthenticationEntryPointImpl.java b/maibu-framework/src/main/java/com/maibu/security/handle/AuthenticationEntryPointImpl.java new file mode 100644 index 0000000..134246e --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/security/handle/AuthenticationEntryPointImpl.java @@ -0,0 +1,44 @@ +package com.maibu.security.handle; + +import java.io.IOException; +import java.io.Serializable; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson2.JSON; +import com.fastbee.common.constant.HttpStatus; +import com.fastbee.common.core.domain.AjaxResult; +import com.fastbee.common.utils.ServletUtils; +import com.fastbee.common.utils.StringUtils; + +/** + * 认证失败处理类 返回未授权 + * + * @author ruoyi + */ +@Component +public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable +{ + private static final long serialVersionUID = -8970718410437077606L; + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) + throws IOException + { +// if (isAjaxRequest(request)){ + int code = HttpStatus.UNAUTHORIZED; + String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI()); + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); +// }else { +// response.sendRedirect("/oauth/login"); +// } + } + + + public static boolean isAjaxRequest(HttpServletRequest request) { + String ajaxFlag = request.getHeader("X-Requested-With"); + return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/security/handle/LogoutSuccessHandlerImpl.java b/maibu-framework/src/main/java/com/maibu/security/handle/LogoutSuccessHandlerImpl.java new file mode 100644 index 0000000..0dc36de --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/security/handle/LogoutSuccessHandlerImpl.java @@ -0,0 +1,52 @@ +package com.maibu.security.handle; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import com.alibaba.fastjson2.JSON; +import com.fastbee.common.constant.Constants; +import com.fastbee.common.core.domain.AjaxResult; +import com.fastbee.common.core.domain.model.LoginUser; +import com.fastbee.common.utils.ServletUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.framework.manager.AsyncManager; +import com.fastbee.framework.manager.factory.AsyncFactory; +import com.fastbee.framework.web.service.TokenService; + +/** + * 自定义退出处理类 返回成功 + * + * @author ruoyi + */ +@Configuration +public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler +{ + @Autowired + private TokenService tokenService; + + /** + * 退出处理 + * + * @return + */ + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException, ServletException + { + LoginUser loginUser = tokenService.getLoginUser(request); + if (StringUtils.isNotNull(loginUser)) + { + String userName = loginUser.getUsername(); + // 删除用户缓存记录 + tokenService.delLoginUser(loginUser.getToken()); + // 记录用户退出日志 + AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功")); + } + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success("退出成功"))); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/utils/CacheUtils.java b/maibu-framework/src/main/java/com/maibu/utils/CacheUtils.java new file mode 100644 index 0000000..c299e43 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/utils/CacheUtils.java @@ -0,0 +1,75 @@ +package com.maibu.utils; + +import com.fastbee.common.utils.spring.SpringUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.redisson.api.RMap; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +import java.util.Set; + +/** + * 缓存操作工具类 {@link } + * + * @author Michelle.Chung + * @date 2022/8/13 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@SuppressWarnings(value = {"unchecked"}) +public class CacheUtils { + + private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class); + + /** + * 获取缓存组内所有的KEY + * + * @param cacheNames 缓存组名称 + */ + public static Set keys(String cacheNames) { + RMap rmap = (RMap) CACHE_MANAGER.getCache(cacheNames).getNativeCache(); + return rmap.keySet(); + } + + /** + * 获取缓存值 + * + * @param cacheNames 缓存组名称 + * @param key 缓存key + */ + public static T get(String cacheNames, Object key) { + Cache.ValueWrapper wrapper = CACHE_MANAGER.getCache(cacheNames).get(key); + return wrapper != null ? (T) wrapper.get() : null; + } + + /** + * 保存缓存值 + * + * @param cacheNames 缓存组名称 + * @param key 缓存key + * @param value 缓存值 + */ + public static void put(String cacheNames, Object key, Object value) { + CACHE_MANAGER.getCache(cacheNames).put(key, value); + } + + /** + * 删除缓存值 + * + * @param cacheNames 缓存组名称 + * @param key 缓存key + */ + public static void evict(String cacheNames, Object key) { + CACHE_MANAGER.getCache(cacheNames).evict(key); + } + + /** + * 清空缓存值 + * + * @param cacheNames 缓存组名称 + */ + public static void clear(String cacheNames) { + CACHE_MANAGER.getCache(cacheNames).clear(); + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/utils/QueueUtils.java b/maibu-framework/src/main/java/com/maibu/utils/QueueUtils.java new file mode 100644 index 0000000..7b46e09 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/utils/QueueUtils.java @@ -0,0 +1,236 @@ +package com.maibu.utils; + +import com.fastbee.common.utils.spring.SpringUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.redisson.api.*; + +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +/** + * 分布式队列工具 + * 轻量级队列 重量级数据量 请使用 MQ + * 要求 redis 5.X 以上 + * + * @author Lion Li + * @version 3.6.0 新增 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class QueueUtils { + + private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class); + + + /** + * 获取客户端实例 + */ + public static RedissonClient getClient() { + return CLIENT; + } + + /** + * 添加普通队列数据 + * + * @param queueName 队列名 + * @param data 数据 + */ + public static boolean addQueueObject(String queueName, T data) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + return queue.offer(data); + } + + /** + * 通用获取一个队列数据 没有数据返回 null(不支持延迟队列) + * + * @param queueName 队列名 + */ + public static T getQueueObject(String queueName) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + return queue.poll(); + } + + /** + * 通用删除队列数据(不支持延迟队列) + */ + public static boolean removeQueueObject(String queueName, T data) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + return queue.remove(data); + } + + /** + * 通用销毁队列 所有阻塞监听 报错(不支持延迟队列) + */ + public static boolean destroyQueue(String queueName) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + return queue.delete(); + } + + /** + * 添加延迟队列数据 默认毫秒 + * + * @param queueName 队列名 + * @param data 数据 + * @param time 延迟时间 + */ + public static void addDelayedQueueObject(String queueName, T data, long time) { + addDelayedQueueObject(queueName, data, time, TimeUnit.MILLISECONDS); + } + + /** + * 添加延迟队列数据 + * + * @param queueName 队列名 + * @param data 数据 + * @param time 延迟时间 + * @param timeUnit 单位 + */ + public static void addDelayedQueueObject(String queueName, T data, long time, TimeUnit timeUnit) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + RDelayedQueue delayedQueue = CLIENT.getDelayedQueue(queue); + delayedQueue.offer(data, time, timeUnit); + } + + /** + * 获取一个延迟队列数据 没有数据返回 null + * + * @param queueName 队列名 + */ + public static T getDelayedQueueObject(String queueName) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + RDelayedQueue delayedQueue = CLIENT.getDelayedQueue(queue); + return delayedQueue.poll(); + } + + /** + * 删除延迟队列数据 + */ + public static boolean removeDelayedQueueObject(String queueName, T data) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + RDelayedQueue delayedQueue = CLIENT.getDelayedQueue(queue); + return delayedQueue.remove(data); + } + + /** + * 销毁延迟队列 所有阻塞监听 报错 + */ + public static void destroyDelayedQueue(String queueName) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + RDelayedQueue delayedQueue = CLIENT.getDelayedQueue(queue); + delayedQueue.destroy(); + } + + /** + * 添加优先队列数据 + * + * @param queueName 队列名 + * @param data 数据 + */ + public static boolean addPriorityQueueObject(String queueName, T data) { + RPriorityBlockingQueue priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName); + return priorityBlockingQueue.offer(data); + } + + /** + * 优先队列获取一个队列数据 没有数据返回 null(不支持延迟队列) + * + * @param queueName 队列名 + */ + public static T getPriorityQueueObject(String queueName) { + RPriorityBlockingQueue queue = CLIENT.getPriorityBlockingQueue(queueName); + return queue.poll(); + } + + /** + * 优先队列删除队列数据(不支持延迟队列) + */ + public static boolean removePriorityQueueObject(String queueName, T data) { + RPriorityBlockingQueue queue = CLIENT.getPriorityBlockingQueue(queueName); + return queue.remove(data); + } + + /** + * 优先队列销毁队列 所有阻塞监听 报错(不支持延迟队列) + */ + public static boolean destroyPriorityQueue(String queueName) { + RPriorityBlockingQueue queue = CLIENT.getPriorityBlockingQueue(queueName); + return queue.delete(); + } + + /** + * 尝试设置 有界队列 容量 用于限制数量 + * + * @param queueName 队列名 + * @param capacity 容量 + */ + public static boolean trySetBoundedQueueCapacity(String queueName, int capacity) { + RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); + return boundedBlockingQueue.trySetCapacity(capacity); + } + + /** + * 尝试设置 有界队列 容量 用于限制数量 + * + * @param queueName 队列名 + * @param capacity 容量 + * @param destroy 已存在是否销毁 + */ + public static boolean trySetBoundedQueueCapacity(String queueName, int capacity, boolean destroy) { + RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); + if (boundedBlockingQueue.isExists() && destroy) { + destroyQueue(queueName); + } + return boundedBlockingQueue.trySetCapacity(capacity); + } + + /** + * 添加有界队列数据 + * + * @param queueName 队列名 + * @param data 数据 + * @return 添加成功 true 已达到界限 false + */ + public static boolean addBoundedQueueObject(String queueName, T data) { + RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); + return boundedBlockingQueue.offer(data); + } + + /** + * 有界队列获取一个队列数据 没有数据返回 null(不支持延迟队列) + * + * @param queueName 队列名 + */ + public static T getBoundedQueueObject(String queueName) { + RBoundedBlockingQueue queue = CLIENT.getBoundedBlockingQueue(queueName); + return queue.poll(); + } + + /** + * 有界队列删除队列数据(不支持延迟队列) + */ + public static boolean removeBoundedQueueObject(String queueName, T data) { + RBoundedBlockingQueue queue = CLIENT.getBoundedBlockingQueue(queueName); + return queue.remove(data); + } + + /** + * 有界队列销毁队列 所有阻塞监听 报错(不支持延迟队列) + */ + public static boolean destroyBoundedQueue(String queueName) { + RBoundedBlockingQueue queue = CLIENT.getBoundedBlockingQueue(queueName); + return queue.delete(); + } + + /** + * 订阅阻塞队列(可订阅所有实现类 例如: 延迟 优先 有界 等) + */ + public static void subscribeBlockingQueue(String queueName, Consumer consumer, boolean isDelayed) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + if (isDelayed) { + // 订阅延迟队列 + CLIENT.getDelayedQueue(queue); + } + queue.subscribeOnElements(consumer); + } + +} diff --git a/maibu-framework/src/main/java/com/maibu/utils/RedisUtils.java b/maibu-framework/src/main/java/com/maibu/utils/RedisUtils.java new file mode 100644 index 0000000..398145a --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/utils/RedisUtils.java @@ -0,0 +1,548 @@ +package com.maibu.utils; + +import com.fastbee.common.utils.spring.SpringUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.redisson.api.*; + +import java.time.Duration; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * redis 工具类 + * + * @author Lion Li + * @version 3.1.0 新增 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@SuppressWarnings(value = {"unchecked", "rawtypes"}) +public class RedisUtils { + + private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class); + + /** + * 限流 + * + * @param key 限流key + * @param rateType 限流类型 + * @param rate 速率 + * @param rateInterval 速率间隔 + * @return -1 表示失败 + */ + public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) { + RRateLimiter rateLimiter = CLIENT.getRateLimiter(key); + rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS); + if (rateLimiter.tryAcquire()) { + return rateLimiter.availablePermits(); + } else { + return -1L; + } + } + + /** + * 获取客户端实例 + */ + public static RedissonClient getClient() { + return CLIENT; + } + + /** + * 发布通道消息 + * + * @param channelKey 通道key + * @param msg 发送数据 + * @param consumer 自定义处理 + */ + public static void publish(String channelKey, T msg, Consumer consumer) { + RTopic topic = CLIENT.getTopic(channelKey); + topic.publish(msg); + consumer.accept(msg); + } + + /** + * 发布消息到指定的频道 + * + * @param channelKey 通道key + * @param msg 发送数据 + */ + public static void publish(String channelKey, T msg) { + RTopic topic = CLIENT.getTopic(channelKey); + topic.publish(msg); + } + + /** + * 订阅通道接收消息 + * + * @param channelKey 通道key + * @param clazz 消息类型 + * @param consumer 自定义处理 + */ + public static void subscribe(String channelKey, Class clazz, Consumer consumer) { + RTopic topic = CLIENT.getTopic(channelKey); + topic.addListener(clazz, (channel, msg) -> consumer.accept(msg)); + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + */ + public static void setCacheObject(final String key, final T value) { + setCacheObject(key, value, false); + } + + /** + * 缓存基本的对象,保留当前对象 TTL 有效期 + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @param isSaveTtl 是否保留TTL有效期(例如: set之前ttl剩余90 set之后还是为90) + * @since Redis 6.X 以上使用 setAndKeepTTL 兼容 5.X 方案 + */ + public static void setCacheObject(final String key, final T value, final boolean isSaveTtl) { + RBucket bucket = CLIENT.getBucket(key); + if (isSaveTtl) { + try { + bucket.setAndKeepTTL(value); + } catch (Exception e) { + long timeToLive = bucket.remainTimeToLive(); + if (timeToLive == -1) { + setCacheObject(key, value); + } else { + setCacheObject(key, value, Duration.ofMillis(timeToLive)); + } + } + } else { + bucket.set(value); + } + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @param duration 时间 + */ + public static void setCacheObject(final String key, final T value, final Duration duration) { + RBatch batch = CLIENT.createBatch(); + RBucketAsync bucket = batch.getBucket(key); + bucket.setAsync(value); + bucket.expireAsync(duration); + batch.execute(); + } + + /** + * 如果不存在则设置 并返回 true 如果存在则返回 false + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @return set成功或失败 + */ + public static boolean setObjectIfAbsent(final String key, final T value, final Duration duration) { + RBucket bucket = CLIENT.getBucket(key); + return bucket.setIfAbsent(value, duration); + } + + /** + * 如果存在则设置 并返回 true 如果存在则返回 false + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @return set成功或失败 + */ + public static boolean setObjectIfExists(final String key, final T value, final Duration duration) { + RBucket bucket = CLIENT.getBucket(key); + return bucket.setIfExists(value, duration); + } + + /** + * 注册对象监听器 + *

+ * key 监听器需开启 `notify-keyspace-events` 等 redis 相关配置 + * + * @param key 缓存的键值 + * @param listener 监听器配置 + */ + public static void addObjectListener(final String key, final ObjectListener listener) { + RBucket result = CLIENT.getBucket(key); + result.addListener(listener); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @return true=设置成功;false=设置失败 + */ + public static boolean expire(final String key, final long timeout) { + return expire(key, Duration.ofSeconds(timeout)); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param duration 超时时间 + * @return true=设置成功;false=设置失败 + */ + public static boolean expire(final String key, final Duration duration) { + RBucket rBucket = CLIENT.getBucket(key); + return rBucket.expire(duration); + } + + /** + * 获得缓存的基本对象。 + * + * @param key 缓存键值 + * @return 缓存键值对应的数据 + */ + public static T getCacheObject(final String key) { + RBucket rBucket = CLIENT.getBucket(key); + return rBucket.get(); + } + + /** + * 获得key剩余存活时间 + * + * @param key 缓存键值 + * @return 剩余存活时间 + */ + public static long getTimeToLive(final String key) { + RBucket rBucket = CLIENT.getBucket(key); + return rBucket.remainTimeToLive(); + } + + /** + * 删除单个对象 + * + * @param key 缓存的键值 + */ + public static boolean deleteObject(final String key) { + return CLIENT.getBucket(key).delete(); + } + + /** + * 删除集合对象 + * + * @param collection 多个对象 + */ + public static void deleteObject(final Collection collection) { + RBatch batch = CLIENT.createBatch(); + collection.forEach(t -> { + batch.getBucket(t.toString()).deleteAsync(); + }); + batch.execute(); + } + + /** + * 检查缓存对象是否存在 + * + * @param key 缓存的键值 + */ + public static boolean isExistsObject(final String key) { + return CLIENT.getBucket(key).isExists(); + } + + /** + * 缓存List数据 + * + * @param key 缓存的键值 + * @param dataList 待缓存的List数据 + * @return 缓存的对象 + */ + public static boolean setCacheList(final String key, final List dataList) { + RList rList = CLIENT.getList(key); + return rList.addAll(dataList); + } + + /** + * 追加缓存List数据 + * + * @param key 缓存的键值 + * @param data 待缓存的数据 + * @return 缓存的对象 + */ + public static boolean addCacheList(final String key, final T data) { + RList rList = CLIENT.getList(key); + return rList.add(data); + } + + /** + * 注册List监听器 + *

+ * key 监听器需开启 `notify-keyspace-events` 等 redis 相关配置 + * + * @param key 缓存的键值 + * @param listener 监听器配置 + */ + public static void addListListener(final String key, final ObjectListener listener) { + RList rList = CLIENT.getList(key); + rList.addListener(listener); + } + + /** + * 获得缓存的list对象 + * + * @param key 缓存的键值 + * @return 缓存键值对应的数据 + */ + public static List getCacheList(final String key) { + RList rList = CLIENT.getList(key); + return rList.readAll(); + } + + /** + * 获得缓存的list对象(范围) + * + * @param key 缓存的键值 + * @param form 起始下标 + * @param to 截止下标 + * @return 缓存键值对应的数据 + */ + public static List getCacheListRange(final String key, int form, int to) { + RList rList = CLIENT.getList(key); + return rList.range(form, to); + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public static boolean setCacheSet(final String key, final Set dataSet) { + RSet rSet = CLIENT.getSet(key); + return rSet.addAll(dataSet); + } + + /** + * 追加缓存Set数据 + * + * @param key 缓存的键值 + * @param data 待缓存的数据 + * @return 缓存的对象 + */ + public static boolean addCacheSet(final String key, final T data) { + RSet rSet = CLIENT.getSet(key); + return rSet.add(data); + } + + /** + * 注册Set监听器 + *

+ * key 监听器需开启 `notify-keyspace-events` 等 redis 相关配置 + * + * @param key 缓存的键值 + * @param listener 监听器配置 + */ + public static void addSetListener(final String key, final ObjectListener listener) { + RSet rSet = CLIENT.getSet(key); + rSet.addListener(listener); + } + + /** + * 获得缓存的set + * + * @param key 缓存的key + * @return set对象 + */ + public static Set getCacheSet(final String key) { + RSet rSet = CLIENT.getSet(key); + return rSet.readAll(); + } + + /** + * 缓存Map + * + * @param key 缓存的键值 + * @param dataMap 缓存的数据 + */ + public static void setCacheMap(final String key, final Map dataMap) { + if (dataMap != null) { + RMap rMap = CLIENT.getMap(key); + rMap.putAll(dataMap); + } + } + + /** + * 注册Map监听器 + *

+ * key 监听器需开启 `notify-keyspace-events` 等 redis 相关配置 + * + * @param key 缓存的键值 + * @param listener 监听器配置 + */ + public static void addMapListener(final String key, final ObjectListener listener) { + RMap rMap = CLIENT.getMap(key); + rMap.addListener(listener); + } + + /** + * 获得缓存的Map + * + * @param key 缓存的键值 + * @return map对象 + */ + public static Map getCacheMap(final String key) { + RMap rMap = CLIENT.getMap(key); + return rMap.getAll(rMap.keySet()); + } + + /** + * 获得缓存Map的key列表 + * + * @param key 缓存的键值 + * @return key列表 + */ + public static Set getCacheMapKeySet(final String key) { + RMap rMap = CLIENT.getMap(key); + return rMap.keySet(); + } + + /** + * 往Hash中存入数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @param value 值 + */ + public static void setCacheMapValue(final String key, final String hKey, final T value) { + RMap rMap = CLIENT.getMap(key); + rMap.put(hKey, value); + } + + /** + * 获取Hash中的数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return Hash中的对象 + */ + public static T getCacheMapValue(final String key, final String hKey) { + RMap rMap = CLIENT.getMap(key); + return rMap.get(hKey); + } + + /** + * 删除Hash中的数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return Hash中的对象 + */ + public static T delCacheMapValue(final String key, final String hKey) { + RMap rMap = CLIENT.getMap(key); + return rMap.remove(hKey); + } + + /** + * 删除Hash中的数据 + * + * @param key Redis键 + * @param hKeys Hash键 + */ + public static void delMultiCacheMapValue(final String key, final Set hKeys) { + RBatch batch = CLIENT.createBatch(); + RMapAsync rMap = batch.getMap(key); + for (String hKey : hKeys) { + rMap.removeAsync(hKey); + } + batch.execute(); + } + + /** + * 获取多个Hash中的数据 + * + * @param key Redis键 + * @param hKeys Hash键集合 + * @return Hash对象集合 + */ + public static Map getMultiCacheMapValue(final String key, final Set hKeys) { + RMap rMap = CLIENT.getMap(key); + return rMap.getAll(hKeys); + } + + /** + * 设置原子值 + * + * @param key Redis键 + * @param value 值 + */ + public static void setAtomicValue(String key, long value) { + RAtomicLong atomic = CLIENT.getAtomicLong(key); + atomic.set(value); + } + + /** + * 获取原子值 + * + * @param key Redis键 + * @return 当前值 + */ + public static long getAtomicValue(String key) { + RAtomicLong atomic = CLIENT.getAtomicLong(key); + return atomic.get(); + } + + /** + * 递增原子值 + * + * @param key Redis键 + * @return 当前值 + */ + public static long incrAtomicValue(String key) { + RAtomicLong atomic = CLIENT.getAtomicLong(key); + return atomic.incrementAndGet(); + } + + /** + * 递减原子值 + * + * @param key Redis键 + * @return 当前值 + */ + public static long decrAtomicValue(String key) { + RAtomicLong atomic = CLIENT.getAtomicLong(key); + return atomic.decrementAndGet(); + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern 字符串前缀 + * @return 对象列表 + */ + public static Collection keys(final String pattern) { + Stream stream = CLIENT.getKeys().getKeysStreamByPattern(pattern); + return stream.collect(Collectors.toList()); + } + + /** + * 删除缓存的基本对象列表 + * + * @param pattern 字符串前缀 + */ + public static void deleteKeys(final String pattern) { + CLIENT.getKeys().deleteByPattern(pattern); + } + + /** + * 检查redis中是否存在key + * + * @param key 键 + */ + public static Boolean hasKey(String key) { + RKeys rKeys = CLIENT.getKeys(); + return rKeys.countExists(key) > 0; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/domain/Server.java b/maibu-framework/src/main/java/com/maibu/web/domain/Server.java new file mode 100644 index 0000000..dccf662 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/domain/Server.java @@ -0,0 +1,237 @@ +package com.maibu.web.domain; + +import java.net.UnknownHostException; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +import com.maibu.utils.Arith; +import com.maibu.utils.ip.IpUtils; +import com.maibu.web.domain.server.*; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.CentralProcessor.TickType; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.Util; + +/** + * 服务器相关信息 + * + * @author ruoyi + */ +public class Server +{ + private static final int OSHI_WAIT_SECOND = 1000; + + /** + * CPU相关信息 + */ + private Cpu cpu = new Cpu(); + + /** + * 內存相关信息 + */ + private Mem mem = new Mem(); + + /** + * JVM相关信息 + */ + private Jvm jvm = new Jvm(); + + /** + * 服务器相关信息 + */ + private Sys sys = new Sys(); + + /** + * 磁盘相关信息 + */ + private List sysFiles = new LinkedList(); + + public Cpu getCpu() + { + return cpu; + } + + public void setCpu(Cpu cpu) + { + this.cpu = cpu; + } + + public Mem getMem() + { + return mem; + } + + public void setMem(Mem mem) + { + this.mem = mem; + } + + public Jvm getJvm() + { + return jvm; + } + + public void setJvm(Jvm jvm) + { + this.jvm = jvm; + } + + public Sys getSys() + { + return sys; + } + + public void setSys(Sys sys) + { + this.sys = sys; + } + + public List getSysFiles() + { + return sysFiles; + } + + public void setSysFiles(List sysFiles) + { + this.sysFiles = sysFiles; + } + + public void copyTo() throws Exception + { + SystemInfo si = new SystemInfo(); + HardwareAbstractionLayer hal = si.getHardware(); + + setCpuInfo(hal.getProcessor()); + + setMemInfo(hal.getMemory()); + + setSysInfo(); + + setJvmInfo(); + + setSysFiles(si.getOperatingSystem()); + } + + /** + * 设置CPU信息 + */ + private void setCpuInfo(CentralProcessor processor) + { + // CPU信息 + long[] prevTicks = processor.getSystemCpuLoadTicks(); + Util.sleep(OSHI_WAIT_SECOND); + long[] ticks = processor.getSystemCpuLoadTicks(); + long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()]; + long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()]; + long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()]; + long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()]; + long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; + long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; + long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; + long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; + long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; + cpu.setCpuNum(processor.getLogicalProcessorCount()); + cpu.setTotal(totalCpu); + cpu.setSys(cSys); + cpu.setUsed(user); + cpu.setWait(iowait); + cpu.setFree(idle); + } + + /** + * 设置内存信息 + */ + private void setMemInfo(GlobalMemory memory) + { + mem.setTotal(memory.getTotal()); + mem.setUsed(memory.getTotal() - memory.getAvailable()); + mem.setFree(memory.getAvailable()); + } + + /** + * 设置服务器信息 + */ + private void setSysInfo() + { + Properties props = System.getProperties(); + sys.setComputerName(IpUtils.getHostName()); + sys.setComputerIp(IpUtils.getHostIp()); + sys.setOsName(props.getProperty("os.name")); + sys.setOsArch(props.getProperty("os.arch")); + sys.setUserDir(props.getProperty("user.dir")); + } + + /** + * 设置Java虚拟机 + */ + private void setJvmInfo() throws UnknownHostException + { + Properties props = System.getProperties(); + jvm.setTotal(Runtime.getRuntime().totalMemory()); + jvm.setMax(Runtime.getRuntime().maxMemory()); + jvm.setFree(Runtime.getRuntime().freeMemory()); + jvm.setVersion(props.getProperty("java.version")); + jvm.setHome(props.getProperty("java.home")); + } + + /** + * 设置磁盘信息 + */ + private void setSysFiles(OperatingSystem os) + { + FileSystem fileSystem = os.getFileSystem(); + List fsArray = fileSystem.getFileStores(); + for (OSFileStore fs : fsArray) + { + long free = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + long used = total - free; + SysFile sysFile = new SysFile(); + sysFile.setDirName(fs.getMount()); + sysFile.setSysTypeName(fs.getType()); + sysFile.setTypeName(fs.getName()); + sysFile.setTotal(convertFileSize(total)); + sysFile.setFree(convertFileSize(free)); + sysFile.setUsed(convertFileSize(used)); + sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100)); + sysFiles.add(sysFile); + } + } + + /** + * 字节转换 + * + * @param size 字节大小 + * @return 转换后值 + */ + public String convertFileSize(long size) + { + long kb = 1024; + long mb = kb * 1024; + long gb = mb * 1024; + if (size >= gb) + { + return String.format("%.1f GB", (float) size / gb); + } + else if (size >= mb) + { + float f = (float) size / mb; + return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); + } + else if (size >= kb) + { + float f = (float) size / kb; + return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); + } + else + { + return String.format("%d B", size); + } + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/domain/dto/LoginResultDto.java b/maibu-framework/src/main/java/com/maibu/web/domain/dto/LoginResultDto.java new file mode 100644 index 0000000..f3bf9fd --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/domain/dto/LoginResultDto.java @@ -0,0 +1,17 @@ +package com.maibu.web.domain.dto; + +import lombok.Data; + +@Data +public class LoginResultDto { + + private boolean success; + private String msg; + private boolean toRegister; + private String userName; + private String password; + private String nickName; + private Integer aiChatNum; + private int resultCode; + private boolean skipLogin = false; //跳过登录 冗余 +} diff --git a/maibu-framework/src/main/java/com/maibu/web/domain/server/Cpu.java b/maibu-framework/src/main/java/com/maibu/web/domain/server/Cpu.java new file mode 100644 index 0000000..362bd12 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/domain/server/Cpu.java @@ -0,0 +1,102 @@ +package com.maibu.web.domain.server; + + +import com.maibu.utils.Arith; + +/** + * CPU相关信息 + * + * @author ruoyi + */ +public class Cpu +{ + /** + * 核心数 + */ + private int cpuNum; + + /** + * CPU总的使用率 + */ + private double total; + + /** + * CPU系统使用率 + */ + private double sys; + + /** + * CPU用户使用率 + */ + private double used; + + /** + * CPU当前等待率 + */ + private double wait; + + /** + * CPU当前空闲率 + */ + private double free; + + public int getCpuNum() + { + return cpuNum; + } + + public void setCpuNum(int cpuNum) + { + this.cpuNum = cpuNum; + } + + public double getTotal() + { + return Arith.round(Arith.mul(total, 100), 2); + } + + public void setTotal(double total) + { + this.total = total; + } + + public double getSys() + { + return Arith.round(Arith.mul(sys / total, 100), 2); + } + + public void setSys(double sys) + { + this.sys = sys; + } + + public double getUsed() + { + return Arith.round(Arith.mul(used / total, 100), 2); + } + + public void setUsed(double used) + { + this.used = used; + } + + public double getWait() + { + return Arith.round(Arith.mul(wait / total, 100), 2); + } + + public void setWait(double wait) + { + this.wait = wait; + } + + public double getFree() + { + return Arith.round(Arith.mul(free / total, 100), 2); + } + + public void setFree(double free) + { + this.free = free; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/domain/server/Jvm.java b/maibu-framework/src/main/java/com/maibu/web/domain/server/Jvm.java new file mode 100644 index 0000000..7c41f1d --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/domain/server/Jvm.java @@ -0,0 +1,131 @@ +package com.maibu.web.domain.server; + +import com.maibu.utils.Arith; +import com.maibu.utils.DateUtils; + +import java.lang.management.ManagementFactory; + +/** + * JVM相关信息 + * + * @author ruoyi + */ +public class Jvm +{ + /** + * 当前JVM占用的内存总数(M) + */ + private double total; + + /** + * JVM最大可用内存总数(M) + */ + private double max; + + /** + * JVM空闲内存(M) + */ + private double free; + + /** + * JDK版本 + */ + private String version; + + /** + * JDK路径 + */ + private String home; + + public double getTotal() + { + return Arith.div(total, (1024 * 1024), 2); + } + + public void setTotal(double total) + { + this.total = total; + } + + public double getMax() + { + return Arith.div(max, (1024 * 1024), 2); + } + + public void setMax(double max) + { + this.max = max; + } + + public double getFree() + { + return Arith.div(free, (1024 * 1024), 2); + } + + public void setFree(double free) + { + this.free = free; + } + + public double getUsed() + { + return Arith.div(total - free, (1024 * 1024), 2); + } + + public double getUsage() + { + return Arith.mul(Arith.div(total - free, total, 4), 100); + } + + /** + * 获取JDK名称 + */ + public String getName() + { + return ManagementFactory.getRuntimeMXBean().getVmName(); + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public String getHome() + { + return home; + } + + public void setHome(String home) + { + this.home = home; + } + + /** + * JDK启动时间 + */ + public String getStartTime() + { + return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate()); + } + + /** + * JDK运行时间 + */ + public String getRunTime() + { + return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate()); + } + + /** + * 运行参数 + */ + public String getInputArgs() + { + return ManagementFactory.getRuntimeMXBean().getInputArguments().toString(); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/domain/server/Mem.java b/maibu-framework/src/main/java/com/maibu/web/domain/server/Mem.java new file mode 100644 index 0000000..c199a0d --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/domain/server/Mem.java @@ -0,0 +1,62 @@ +package com.maibu.web.domain.server; + + +import com.maibu.utils.Arith; + +/** + * 內存相关信息 + * + * @author ruoyi + */ +public class Mem +{ + /** + * 内存总量 + */ + private double total; + + /** + * 已用内存 + */ + private double used; + + /** + * 剩余内存 + */ + private double free; + + public double getTotal() + { + return Arith.div(total, (1024 * 1024 * 1024), 2); + } + + public void setTotal(long total) + { + this.total = total; + } + + public double getUsed() + { + return Arith.div(used, (1024 * 1024 * 1024), 2); + } + + public void setUsed(long used) + { + this.used = used; + } + + public double getFree() + { + return Arith.div(free, (1024 * 1024 * 1024), 2); + } + + public void setFree(long free) + { + this.free = free; + } + + public double getUsage() + { + return Arith.mul(Arith.div(used, total, 4), 100); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/domain/server/Sys.java b/maibu-framework/src/main/java/com/maibu/web/domain/server/Sys.java new file mode 100644 index 0000000..1024a5d --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/domain/server/Sys.java @@ -0,0 +1,84 @@ +package com.maibu.web.domain.server; + +/** + * 系统相关信息 + * + * @author ruoyi + */ +public class Sys +{ + /** + * 服务器名称 + */ + private String computerName; + + /** + * 服务器Ip + */ + private String computerIp; + + /** + * 项目路径 + */ + private String userDir; + + /** + * 操作系统 + */ + private String osName; + + /** + * 系统架构 + */ + private String osArch; + + public String getComputerName() + { + return computerName; + } + + public void setComputerName(String computerName) + { + this.computerName = computerName; + } + + public String getComputerIp() + { + return computerIp; + } + + public void setComputerIp(String computerIp) + { + this.computerIp = computerIp; + } + + public String getUserDir() + { + return userDir; + } + + public void setUserDir(String userDir) + { + this.userDir = userDir; + } + + public String getOsName() + { + return osName; + } + + public void setOsName(String osName) + { + this.osName = osName; + } + + public String getOsArch() + { + return osArch; + } + + public void setOsArch(String osArch) + { + this.osArch = osArch; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/domain/server/SysFile.java b/maibu-framework/src/main/java/com/maibu/web/domain/server/SysFile.java new file mode 100644 index 0000000..1f1bacd --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/domain/server/SysFile.java @@ -0,0 +1,114 @@ +package com.maibu.web.domain.server; + +/** + * 系统文件相关信息 + * + * @author ruoyi + */ +public class SysFile +{ + /** + * 盘符路径 + */ + private String dirName; + + /** + * 盘符类型 + */ + private String sysTypeName; + + /** + * 文件类型 + */ + private String typeName; + + /** + * 总大小 + */ + private String total; + + /** + * 剩余大小 + */ + private String free; + + /** + * 已经使用量 + */ + private String used; + + /** + * 资源的使用率 + */ + private double usage; + + public String getDirName() + { + return dirName; + } + + public void setDirName(String dirName) + { + this.dirName = dirName; + } + + public String getSysTypeName() + { + return sysTypeName; + } + + public void setSysTypeName(String sysTypeName) + { + this.sysTypeName = sysTypeName; + } + + public String getTypeName() + { + return typeName; + } + + public void setTypeName(String typeName) + { + this.typeName = typeName; + } + + public String getTotal() + { + return total; + } + + public void setTotal(String total) + { + this.total = total; + } + + public String getFree() + { + return free; + } + + public void setFree(String free) + { + this.free = free; + } + + public String getUsed() + { + return used; + } + + public void setUsed(String used) + { + this.used = used; + } + + public double getUsage() + { + return usage; + } + + public void setUsage(double usage) + { + this.usage = usage; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/exception/GlobalExceptionHandler.java b/maibu-framework/src/main/java/com/maibu/web/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..a165fc8 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/exception/GlobalExceptionHandler.java @@ -0,0 +1,115 @@ +package com.maibu.web.exception; + +import javax.servlet.http.HttpServletRequest; + +import com.maibu.constant.HttpStatus; +import com.maibu.core.domain.AjaxResult; +import com.maibu.exception.DemoModeException; +import com.maibu.exception.ServiceException; +import com.maibu.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.validation.BindException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * 全局异常处理器 + * + * @author ruoyi + */ +@RestControllerAdvice +public class GlobalExceptionHandler +{ + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + /** + * 权限校验异常 + */ + @ExceptionHandler(AccessDeniedException.class) + public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage()); + return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权"); + } + + /** + * 请求方式不支持 + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, + HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod()); + return AjaxResult.error(e.getMessage()); + } + + /** + * 业务异常 + */ + @ExceptionHandler(ServiceException.class) + public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request) + { + log.error(e.getMessage(), e); + Integer code = e.getCode(); + return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage()); + } + + /** + * 拦截未知的运行时异常 + */ + @ExceptionHandler(RuntimeException.class) + public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生未知异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 系统异常 + */ + @ExceptionHandler(Exception.class) + public AjaxResult handleException(Exception e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生系统异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(BindException.class) + public AjaxResult handleBindException(BindException e) + { + log.error(e.getMessage(), e); + String message = e.getAllErrors().get(0).getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) + { + log.error(e.getMessage(), e); + String message = e.getBindingResult().getFieldError().getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 演示模式异常 + */ + @ExceptionHandler(DemoModeException.class) + public AjaxResult handleDemoModeException(DemoModeException e) + { + return AjaxResult.error("演示模式,不允许操作"); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/service/PermissionService.java b/maibu-framework/src/main/java/com/maibu/web/service/PermissionService.java new file mode 100644 index 0000000..0d39cf8 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/service/PermissionService.java @@ -0,0 +1,168 @@ +package com.maibu.web.service; + +import java.util.Set; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import com.fastbee.common.core.domain.entity.SysRole; +import com.fastbee.common.core.domain.model.LoginUser; +import com.fastbee.common.utils.SecurityUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.framework.security.context.PermissionContextHolder; + +/** + * RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母 + * + * @author ruoyi + */ +@Service("ss") +public class PermissionService +{ + /** 所有权限标识 */ + private static final String ALL_PERMISSION = "*:*:*"; + + /** 管理员角色权限标识 */ + private static final String SUPER_ADMIN = "admin"; + + private static final String ROLE_DELIMETER = ","; + + private static final String PERMISSION_DELIMETER = ","; + + /** + * 验证用户是否具备某权限 + * + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermi(String permission) + { + if (StringUtils.isEmpty(permission)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) + { + return false; + } + PermissionContextHolder.setContext(permission); + return hasPermissions(loginUser.getPermissions(), permission); + } + + /** + * 验证用户是否不具备某权限,与 hasPermi逻辑相反 + * + * @param permission 权限字符串 + * @return 用户是否不具备某权限 + */ + public boolean lacksPermi(String permission) + { + return hasPermi(permission) != true; + } + + /** + * 验证用户是否具有以下任意一个权限 + * + * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表 + * @return 用户是否具有以下任意一个权限 + */ + public boolean hasAnyPermi(String permissions) + { + if (StringUtils.isEmpty(permissions)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) + { + return false; + } + PermissionContextHolder.setContext(permissions); + Set authorities = loginUser.getPermissions(); + for (String permission : permissions.split(PERMISSION_DELIMETER)) + { + if (permission != null && hasPermissions(authorities, permission)) + { + return true; + } + } + return false; + } + + /** + * 判断用户是否拥有某个角色 + * + * @param role 角色字符串 + * @return 用户是否具备某角色 + */ + public boolean hasRole(String role) + { + if (StringUtils.isEmpty(role)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) + { + return false; + } + for (SysRole sysRole : loginUser.getUser().getRoles()) + { + String roleKey = sysRole.getRoleKey(); + if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) + { + return true; + } + } + return false; + } + + /** + * 验证用户是否不具备某角色,与 isRole逻辑相反。 + * + * @param role 角色名称 + * @return 用户是否不具备某角色 + */ + public boolean lacksRole(String role) + { + return hasRole(role) != true; + } + + /** + * 验证用户是否具有以下任意一个角色 + * + * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表 + * @return 用户是否具有以下任意一个角色 + */ + public boolean hasAnyRoles(String roles) + { + if (StringUtils.isEmpty(roles)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) + { + return false; + } + for (String role : roles.split(ROLE_DELIMETER)) + { + if (hasRole(role)) + { + return true; + } + } + return false; + } + + /** + * 判断是否包含权限 + * + * @param permissions 权限列表 + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + private boolean hasPermissions(Set permissions, String permission) + { + return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission)); + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/service/SysLoginService.java b/maibu-framework/src/main/java/com/maibu/web/service/SysLoginService.java new file mode 100644 index 0000000..afb6a0d --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/service/SysLoginService.java @@ -0,0 +1,511 @@ +package com.maibu.web.service; + +import cn.hutool.core.util.ObjectUtil; +import com.maibu.ali.AliSmsService; +import com.maibu.constant.CacheConstants; +import com.maibu.constant.Constants; +import com.maibu.constant.HttpStatus; +import com.maibu.core.domain.entity.SysDept; +import com.maibu.core.domain.entity.SysUser; +import com.maibu.core.domain.model.LoginBody; +import com.maibu.core.domain.model.LoginUser; +import com.maibu.core.redis.RedisCache; +import com.maibu.enums.UserStatus; +import com.maibu.exception.ServiceException; +import com.maibu.exception.user.CaptchaException; +import com.maibu.exception.user.CaptchaExpireException; +import com.maibu.exception.user.UserPasswordNotMatchException; +import com.maibu.manager.AsyncManager; +import com.maibu.manager.factory.AsyncFactory; +import com.maibu.mapper.SysUserMapper; +import com.maibu.security.context.AuthenticationContextHolder; +import com.maibu.service.ISysConfigService; +import com.maibu.service.ISysDeptService; +import com.maibu.service.ISysUserService; +import com.maibu.utils.*; +import com.maibu.utils.ip.IpUtils; +import com.maibu.web.domain.dto.LoginResultDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +/** + * 登录校验方法 + * + * @author ruoyi + */ +@Component +public class SysLoginService { + @Autowired + private TokenService tokenService; + + @Resource + private AuthenticationManager authenticationManager; + + @Autowired + private RedisCache redisCache; + + @Autowired + private ISysUserService userService; + + @Autowired + private ISysConfigService configService; + + @Autowired + private UserDetailsServiceImpl userDetailsServiceImpl; + + @Resource + private SysPasswordService passwordService; + @Resource + private ISysDeptService sysDeptService; + + @Autowired + private SysUserMapper userMapper; + @Autowired + private AliSmsService aliSmsService; + + private static final String redisLoginKey = "phone:login:time"; + + private static final String redisOpenIdLoginKey = "openId:login:time"; + + /** + * 登录验证 + * + * @param username 用户名 + * @param password 密码 + * @param code 验证码 + * @param uuid 唯一标识 + * @return 结果 + */ + public String login(String username, String password, String code, String uuid, Integer sourceType, String language) { + // boolean captchaEnabled = configService.selectCaptchaEnabled(); + boolean captchaEnabled = false; + // 验证码开关 + if (captchaEnabled) { + validateCaptcha(username, code, uuid); + } + // 用户验证 + Authentication authentication = null; + try { + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); + AuthenticationContextHolder.setContext(authenticationToken); + // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername + authentication = authenticationManager.authenticate(authenticationToken); + } catch (Exception e) { + if (e instanceof BadCredentialsException) { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); + throw new UserPasswordNotMatchException(); + } else { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); + throw new ServiceException(e.getMessage()); + } + } finally { + AuthenticationContextHolder.clearContext(); + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + // 设置端类型 + loginUser.setSourceType(sourceType == null ? 1 : sourceType); + // 移动端、小程序限制终端用户登录 + Long deptId = loginUser.getDeptId(); + + /// TODO限制租户登录 +// if (null != sourceType && 1 == sourceType && null == deptId) { +// throw new ServiceException("web端只允许租户登录!"); +// } +// if (!"admin".equals(loginUser.getUsername()) && null != sourceType) { +// Long deptId = loginUser.getDeptId(); +// if (1 == sourceType && null == deptId) { +// throw new ServiceException("web端只允许租户登录!"); +// } +// if (1 != sourceType && null != deptId) { +// throw new ServiceException("只允许终端用户登录!"); +// } +// } + SysDept sysDept = sysDeptService.selectDeptById(deptId); + recordLoginInfo(loginUser.getUserId()); + loginUser.setLanguage(language); + if (null != sysDept) { + loginUser.setDeptUserId(sysDept.getDeptUserId()); + } + // 生成token + return loginUser.getUserId() + "====" + tokenService.createToken(loginUser); + } + + /** + * 第三方验证后,调用登录方法 + * + * @param username 用户名 + * @param password 密码 + * @return token + */ + public String socialLogin(String username, String password, String language) { + // 用户验证 + Authentication authentication = null; + try { + // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername + authentication = authenticationManager + .authenticate(new UsernamePasswordAuthenticationToken(username, password)); + } catch (Exception e) { + if (e instanceof BadCredentialsException) { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); + throw new UserPasswordNotMatchException(); + } else { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); + throw new ServiceException(e.getMessage()); + } + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + recordLoginInfo(loginUser.getUserId()); + loginUser.setLanguage(language); + // 生成token + return tokenService.createToken(loginUser); + } + + /** + * 三方跳转登录认证方法 + * + * @param username 系统用户名 + * @param encodePwd 系统用户密码 + * @return + */ + public String redirectLogin(String username, String encodePwd, String language) { +// UserDetails userDetails=userDetailsServiceImpl.loadUserByUsername(username); + SysUser user = userService.selectUserByUserName(username); + if (StringUtils.isNull(user)) { + throw new ServiceException("登录用户:" + username + " 不存在"); + } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { + throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); + } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + throw new ServiceException("对不起,您的账号:" + username + " 已停用"); + } + // 重写验证方法 + passwordService.socialValidate(user, encodePwd); + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + UserDetails userDetails = userDetailsServiceImpl.createLoginUser(user); + LoginUser loginUser = (LoginUser) userDetails; + recordLoginInfo(loginUser.getUserId()); + loginUser.setLanguage(language); + // 生成token + return tokenService.createToken(loginUser); + + } + + /** + * 组态分享页面生成token + * + * @param username 系统用户名 + * @return + */ + public String shareUserLogin(String username, String language) { + SysUser user = userService.selectUserByUserName(username); + if (StringUtils.isNull(user)) { + throw new ServiceException("分享用户:" + username + " 不存在"); + } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { + throw new ServiceException("对不起,您的分享账号:" + username + " 已被删除"); + } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + throw new ServiceException("对不起,您的分享账号:" + username + " 已停用"); + } + // 重写验证方法 + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + UserDetails userDetails = userDetailsServiceImpl.createLoginUser(user); + LoginUser loginUser = (LoginUser) userDetails; + recordLoginInfo(loginUser.getUserId()); + loginUser.setLanguage(language); + loginUser.setNeverExpire(Boolean.TRUE); + // 生成token + return tokenService.createToken(loginUser); + + } + + /** + * 校验验证码 + * + * @param username 用户名 + * @param code 验证码 + * @param uuid 唯一标识 + * @return 结果 + */ + public void validateCaptcha(String username, String code, String uuid) { + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); + String captcha = redisCache.getCacheObject(verifyKey); + redisCache.deleteObject(verifyKey); + if (captcha == null) { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); + throw new CaptchaExpireException(); + } + if (!code.equalsIgnoreCase(captcha)) { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); + throw new CaptchaException(); + } + } + + /** + * 记录登录信息 + * + * @param userId 用户ID + */ + public void recordLoginInfo(Long userId) { + SysUser sysUser = userService.selectUserById(userId); + sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest())); + sysUser.setLoginDate(DateUtils.getNowDate()); + userService.updateUserProfile(sysUser); + } + + public String ssoLogin(String username, String password, String language) { + SysUser user = userService.selectUserByUserName(username); + if (StringUtils.isNull(user)) { + throw new ServiceException("登录用户:" + username + " 不存在"); + } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { + throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); + } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + throw new ServiceException("对不起,您的账号:" + username + " 已停用"); + } + // 重写验证方法 + passwordService.ssoValidate(user, password); + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + UserDetails userDetails = userDetailsServiceImpl.createLoginUser(user); + LoginUser loginUser = (LoginUser) userDetails; + recordLoginInfo(loginUser.getUserId()); + loginUser.setLanguage(language); + // 生成token + return tokenService.createToken(loginUser); + } + + /** + * 微信服务号登录 未注册的需要跳转手机验证码登录 + */ + public synchronized LoginResultDto threePlatformOpenIdVerify(LoginBody loginBody) { + String openId = loginBody.getOpenId(); + LoginResultDto dto = new LoginResultDto(); + if (StringUtils.isEmpty(openId)) { + dto.setSuccess(false); + dto.setMsg("openId为空"); + dto.setResultCode(HttpStatus.ERROR); + return dto; + } + //重复验证怎么跳过 怎么判断手机号刚登录 + String key = redisOpenIdLoginKey + openId; + Long lastLoginTime = redisCache.getCacheObject(key); + if (lastLoginTime == null) { + SysUser sysUser = userMapper.selectUserByOpenId(openId); + if (sysUser != null) { + String phoneNumber = sysUser.getPhonenumber(); + if (StringUtils.isEmpty(phoneNumber)) { +// dto.setSuccess(false); +// dto.setMsg("用户绑定的手机号为空"); +// dto.setResultCode(HttpStatus.ERROR); +// return dto; + + //todo 更新 假如有openId 没有手机号 也注册账号 没有手机号 + dto.setSuccess(true); + dto.setMsg("用户绑定的手机号为空"); + dto.setUserName(sysUser.getUserName()); + dto.setPassword(StringUtils.isEmpty(sysUser.getDisplayPassword()) ? "12345" : sysUser.getDisplayPassword()); + dto.setResultCode(HttpStatus.SUCCESS); //需要告诉前端跳转登录 + dto.setAiChatNum(sysUser.getAiChatNum()); + dto.setNickName(sysUser.getNickName()); + redisCache.setCacheObject(key, System.currentTimeMillis(), 5, TimeUnit.SECONDS); + return dto; + } else { + dto.setSuccess(true); + dto.setUserName(sysUser.getUserName()); + dto.setPassword(StringUtils.isEmpty(sysUser.getDisplayPassword()) ? "12345" : sysUser.getDisplayPassword()); + dto.setResultCode(HttpStatus.SUCCESS); + dto.setAiChatNum(sysUser.getAiChatNum()); + dto.setNickName(sysUser.getNickName()); + redisCache.setCacheObject(key, System.currentTimeMillis(), 5, TimeUnit.SECONDS); + return dto; + } + } else { +// dto.setSuccess(false); +// dto.setMsg("用户未注册"); +// dto.setResultCode(300); //需要告诉前端跳转登录 + //todo 更新 假如有openId 没有手机号 也注册账号 没有手机号 ai限制10条 2025-12-15 + sysUser = verifySmsCodeAndCreate(null, openId, 10); + dto.setMsg("用户未注册"); + dto.setSuccess(true); + dto.setUserName(sysUser.getUserName()); + dto.setPassword(StringUtils.isEmpty(sysUser.getDisplayPassword()) ? "12345" : sysUser.getDisplayPassword()); + dto.setResultCode(HttpStatus.SUCCESS); + dto.setAiChatNum(sysUser.getAiChatNum()); + dto.setNickName(sysUser.getNickName()); + redisCache.setCacheObject(key, System.currentTimeMillis(), 5, TimeUnit.SECONDS); + return dto; + } + } else { + dto.setSuccess(true); + dto.setMsg("重复验证,跳过登录!"); + dto.setResultCode(HttpStatus.SUCCESS); + dto.setSkipLogin(true); + return dto; + } + } + + /** + * 手机号登录 + * + */ + public synchronized LoginResultDto phoneNumberLoginVerify(LoginBody loginBody) { + + String phoneParam = loginBody.getPhonenumber(); + String smsCode = loginBody.getSmsCode(); + String openId = loginBody.getOpenId(); + Long userId = loginBody.getUserId(); + LoginResultDto dto = new LoginResultDto(); + if (StringUtils.isEmpty(phoneParam)) { + dto.setSuccess(false); + dto.setMsg("手机号为空"); + dto.setResultCode(HttpStatus.ERROR); + return dto; + } + if (StringUtils.isEmpty(smsCode)) { + dto.setSuccess(false); + dto.setMsg("短信验证码为空"); + dto.setResultCode(HttpStatus.ERROR); + return dto; + } + //重复验证怎么跳过 怎么判断手机号刚登录 + String key = redisLoginKey + phoneParam; + Long lastLoginTime = redisCache.getCacheObject(key); + if (lastLoginTime == null) { + boolean result = aliSmsService.verifySmsCode(phoneParam, smsCode); + if (result) { + SysUser sysUser = userMapper.selectUserByPhoneNumber(phoneParam); + if (sysUser == null) { + //更新到openId 如果有openId走更新 没有 看userId + if (!org.apache.commons.lang3.StringUtils.isEmpty(openId)) { + sysUser = userMapper.selectUserByOpenId(openId); + if (sysUser != null) { + sysUser.setAiChatNum(-1); + sysUser.setUpdateTime(new Date()); + sysUser.setPhonenumber(phoneParam); + userMapper.updateUser(sysUser); + } else { + sysUser = verifySmsCodeAndCreate(phoneParam, openId, -1); + } + dto.setSuccess(true); + dto.setUserName(sysUser.getUserName()); + dto.setPassword(sysUser.getDisplayPassword()); + dto.setAiChatNum(sysUser.getAiChatNum()); + //登录成功记录当前手机号 登录成功时间 5秒后自动删除 + redisCache.setCacheObject(key, System.currentTimeMillis(), 5, TimeUnit.SECONDS); + return dto; + } else { + if (userId != null) { + sysUser = userMapper.selectUserById(userId); + if (sysUser != null) { + sysUser.setAiChatNum(-1); + sysUser.setUpdateTime(new Date()); + sysUser.setPhonenumber(phoneParam); + userMapper.updateUser(sysUser); + } else { + sysUser = verifySmsCodeAndCreate(phoneParam, null, -1); + } + } else { + sysUser = verifySmsCodeAndCreate(phoneParam, null, -1); + } + dto.setSuccess(true); + dto.setUserName(sysUser.getUserName()); + dto.setPassword(sysUser.getDisplayPassword()); + dto.setAiChatNum(sysUser.getAiChatNum()); + //登录成功记录当前手机号 登录成功时间 5秒后自动删除 + redisCache.setCacheObject(key, System.currentTimeMillis(), 5, TimeUnit.SECONDS); + return dto; + } + } else { + //手机号已注册的情况判断openId 是否匹配 + if (!org.apache.commons.lang3.StringUtils.isEmpty(openId)) { + if (!openId.equals(sysUser.getOpenId())) { + dto.setSuccess(false); + dto.setMsg("手机号已注册"); + dto.setResultCode(HttpStatus.ERROR); + return dto; + } + } else { + //手机号已注册的情况判断userId 是否匹配 + if (userId != null) { + if (!userId.equals(sysUser.getUserId())) { + dto.setSuccess(false); + dto.setMsg("手机号已注册"); + dto.setResultCode(HttpStatus.ERROR); + return dto; + } + } + } + if (sysUser.getAiChatNum() != -1) { + sysUser.setAiChatNum(-1); + sysUser.setUpdateTime(new Date()); + userMapper.updateUser(sysUser); + } + dto.setSuccess(true); + dto.setUserName(sysUser.getUserName()); + dto.setPassword(sysUser.getDisplayPassword()); + dto.setAiChatNum(sysUser.getAiChatNum()); + //登录成功记录当前手机号 登录成功时间 5秒后自动删除 + redisCache.setCacheObject(key, System.currentTimeMillis(), 5, TimeUnit.SECONDS); + return dto; + } + } else { + dto.setSuccess(false); + dto.setMsg("短信验证码验证失败"); + dto.setResultCode(HttpStatus.ERROR); + return dto; + } + } else { + dto.setSuccess(true); + dto.setMsg("重复验证,跳过登录!"); + dto.setResultCode(HttpStatus.SUCCESS); + dto.setSkipLogin(true); + return dto; + } + } + + public SysUser verifySmsCodeAndCreate(String phoneNumber, String openId, int aiCount) { + // 创建账号 初始化账号名等 + SysUser sysUser = new SysUser(); + String randomName = generateUserName(); + sysUser.setUserName(randomName); + sysUser.setNickName(randomName); + sysUser.setDisplayPassword("12345"); + sysUser.setPassword(SecurityUtils.encryptPassword("12345")); //初始密码12345 + sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest())); + sysUser.setPhonenumber(phoneNumber); + sysUser.setOpenId(openId); + sysUser.setCreateBy("admin"); + sysUser.setAiChatNum(aiCount); + // 默认部门默认迈步 + sysUser.setDeptId(100L); + sysUser.setLoginDate(new Date()); + userMapper.insertUser(sysUser); + // 关联角色如果没有角色且是迈步的默认角色(设备用户 roleid:3) + if (sysUser.getDeptId() != null && sysUser.getDeptId() == 100L && ObjectUtil.isEmpty(sysUser.getRoleIds())) { + userService.insertUserAuth(sysUser.getUserId(), new Long[]{3L}); + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(randomName, Constants.REGISTER, MessageUtils.message("user.register.success"))); + return sysUser; + } + + public String generateUserName() { + // 获取当前时间戳后8位 + String timestamp = String.valueOf(System.currentTimeMillis()).substring(5); + // 生成随机数确保不重复 + String random = String.format("%03d", (int) (Math.random() * 1000)); + // 组合成8位ID(取时间戳5位+随机数3位) + return timestamp.substring(0, 5) + random; + } + + + public void switchLoginPlatForm() { + + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/service/SysPasswordService.java b/maibu-framework/src/main/java/com/maibu/web/service/SysPasswordService.java new file mode 100644 index 0000000..014226e --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/service/SysPasswordService.java @@ -0,0 +1,159 @@ +package com.maibu.web.service; + +import java.util.concurrent.TimeUnit; + +import com.maibu.constant.CacheConstants; +import com.maibu.constant.Constants; +import com.maibu.core.domain.entity.SysUser; +import com.maibu.core.redis.RedisCache; +import com.maibu.exception.user.UserPasswordNotMatchException; +import com.maibu.exception.user.UserPasswordRetryLimitExceedException; +import com.maibu.manager.AsyncManager; +import com.maibu.manager.factory.AsyncFactory; +import com.maibu.security.context.AuthenticationContextHolder; +import com.maibu.utils.MessageUtils; +import com.maibu.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +/** + * 登录密码方法 + * + * @author ruoyi + */ +@Component +public class SysPasswordService +{ + @Autowired + private RedisCache redisCache; + + @Value(value = "${user.password.maxRetryCount}") + private int maxRetryCount; + + @Value(value = "${user.password.lockTime}") + private int lockTime; + + /** + * 登录账户密码错误次数缓存键名 + * + * @param username 用户名 + * @return 缓存键key + */ + private String getCacheKey(String username) + { + return CacheConstants.PWD_ERR_CNT_KEY + username; + } + + public void validate(SysUser user) + { + Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext(); + String username = usernamePasswordAuthenticationToken.getName(); + String password = usernamePasswordAuthenticationToken.getCredentials().toString(); + + Integer retryCount = redisCache.getCacheObject(getCacheKey(username)); + + if (retryCount == null) + { + retryCount = 0; + } + + if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime))); + throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime); + } + + if (!matches(user, password)) + { + retryCount = retryCount + 1; + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.count", retryCount))); + redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); + throw new UserPasswordNotMatchException(); + } + else + { + clearLoginRecordCache(username); + } + } + + public void socialValidate(SysUser user, String encodePwd) + { + String username = user.getUserName(); + String password = user.getPassword(); + + Integer retryCount = redisCache.getCacheObject(getCacheKey(username)); + + if (retryCount == null) + { + retryCount = 0; + } + + if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime))); + throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime); + } + + if(!password.equals(encodePwd)){ + retryCount = retryCount + 1; + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.count", retryCount))); + redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); + throw new UserPasswordNotMatchException(); + } + else + { + clearLoginRecordCache(username); + } + } + + public boolean matches(SysUser user, String rawPassword) + { + return SecurityUtils.matchesPassword(rawPassword, user.getPassword()); + } + + public void clearLoginRecordCache(String loginName) + { + if (redisCache.hasKey(getCacheKey(loginName))) + { + redisCache.deleteObject(getCacheKey(loginName)); + } + } + + public void ssoValidate(SysUser user, String encodePwd) { + String username = user.getUserName(); + String password = user.getPassword(); + + Integer retryCount = redisCache.getCacheObject(getCacheKey(username)); + + if (retryCount == null) + { + retryCount = 0; + } + + if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime))); + throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime); + } + + if (!matches(user, encodePwd)) + { + retryCount = retryCount + 1; + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.count", retryCount))); + redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); + throw new UserPasswordNotMatchException(); + } + else + { + clearLoginRecordCache(username); + } + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/service/SysPermissionService.java b/maibu-framework/src/main/java/com/maibu/web/service/SysPermissionService.java new file mode 100644 index 0000000..4abc9d6 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/service/SysPermissionService.java @@ -0,0 +1,80 @@ +package com.maibu.web.service; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.maibu.core.domain.entity.SysRole; +import com.maibu.core.domain.entity.SysUser; +import com.maibu.service.ISysMenuService; +import com.maibu.service.ISysRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 用户权限处理 + * + * @author ruoyi + */ +@Component +public class SysPermissionService +{ + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysMenuService menuService; + + /** + * 获取角色数据权限 + * + * @param user 用户信息 + * @return 角色权限信息 + */ + public Set getRolePermission(SysUser user) + { + Set roles = new HashSet(); + // 管理员拥有所有权限 + if (user.isAdmin()) + { + roles.add("admin"); + } + else + { + roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId())); + } + return roles; + } + + /** + * 获取菜单数据权限 + * + * @param user 用户信息 + * @return 菜单权限信息 + */ + public Set getMenuPermission(SysUser user) + { + Set perms = new HashSet(); + // 管理员拥有所有权限 + if (user.isAdmin()) { + perms.add("*:*:*"); + } else { + List roles = user.getRoles(); + if (!roles.isEmpty() && roles.size() > 1) + { + // 多角色设置permissions属性,以便数据权限匹配权限 + for (SysRole role : roles) + { + Set rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId()); + role.setPermissions(rolePerms); + perms.addAll(rolePerms); + } + } + else + { + perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); + } + } + return perms; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/service/SysRegisterService.java b/maibu-framework/src/main/java/com/maibu/web/service/SysRegisterService.java new file mode 100644 index 0000000..1d084e7 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/service/SysRegisterService.java @@ -0,0 +1,135 @@ +package com.maibu.web.service; + +import cn.hutool.core.util.ObjectUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.fastbee.common.constant.CacheConstants; +import com.fastbee.common.constant.Constants; +import com.fastbee.common.constant.UserConstants; +import com.fastbee.common.core.domain.entity.SysUser; +import com.fastbee.common.core.domain.model.RegisterBody; +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.exception.user.CaptchaException; +import com.fastbee.common.exception.user.CaptchaExpireException; +import com.fastbee.common.utils.MessageUtils; +import com.fastbee.common.utils.SecurityUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.framework.manager.AsyncManager; +import com.fastbee.framework.manager.factory.AsyncFactory; +import com.fastbee.system.service.ISysConfigService; +import com.fastbee.system.service.ISysUserService; + +/** + * 注册校验方法 + * + * @author ruoyi + */ +@Component +public class SysRegisterService +{ + @Autowired + private ISysUserService userService; + + @Autowired + private ISysConfigService configService; + + @Autowired + private RedisCache redisCache; + + + /** + * 注册 + */ + public String register(RegisterBody registerBody) + { + String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword(),email=registerBody.getEmail(),phonenumber=registerBody.getPhonenumber(); + SysUser sysUser = new SysUser(); + sysUser.setUserName(username); + + // 验证码开关 + boolean captchaEnabled = configService.selectCaptchaEnabled(); + if (captchaEnabled) + { + validateCaptcha(username, registerBody.getCode(), registerBody.getEmail()); + } + + if (StringUtils.isEmpty(username)) + { + msg = "用户名不能为空"; + } + else if (StringUtils.isEmpty(password)) + { + msg = "用户密码不能为空"; + } + else if (StringUtils.isEmpty(email)) + { + msg = "邮箱不能为空"; + } + else if (StringUtils.isEmpty(phonenumber)) + { + msg = "手机号不能为空"; + } + else if (username.length() < UserConstants.USERNAME_MIN_LENGTH + || username.length() > UserConstants.USERNAME_MAX_LENGTH) + { + msg = "账户长度必须在2到20个字符之间"; + } + else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) + { + msg = "密码长度必须在5到20个字符之间"; + } + else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser))) + { + msg = "保存用户'" + username + "'失败,注册账号已存在"; + } + else + { + sysUser.setNickName(username); + sysUser.setPassword(SecurityUtils.encryptPassword(password)); + sysUser.setEmail(email); + sysUser.setPhonenumber(phonenumber); + if (sysUser.getDeptId() == null) { + // 默认部门默认迈步 + sysUser.setDeptId(100L); + } + boolean regFlag = userService.registerUser(sysUser); + if (!regFlag) + { + msg = "注册失败,请联系系统管理人员"; + } + else + { + // 关联角色如果没有角色且是迈步的默认角色(设备用户 roleid:3) + if (sysUser.getDeptId() != null&&sysUser.getDeptId()==100L&& ObjectUtil.isEmpty(sysUser.getRoleIds())){ + userService.insertUserAuth(sysUser.getUserId(),new Long[]{3L}); + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"))); + } + } + return msg; + } + + /** + * 校验验证码 + * + * @param username 用户名 + * @param code 验证码 + * @param email 邮箱 + * @return 结果 + */ + public void validateCaptcha(String username, String code, String email) + { + String verifyKey = CacheConstants.REGISTER_EMAIL_CAPTCHA + StringUtils.nvl(email, ""); + String captcha = redisCache.getCacheObject(verifyKey); + redisCache.deleteObject(verifyKey); + if (captcha == null) + { + throw new CaptchaExpireException(); + } + if (!code.equalsIgnoreCase(captcha)) + { + throw new CaptchaException(); + } + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/service/TokenService.java b/maibu-framework/src/main/java/com/maibu/web/service/TokenService.java new file mode 100644 index 0000000..31f03a9 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/service/TokenService.java @@ -0,0 +1,349 @@ +package com.maibu.web.service; + +import com.fastbee.common.constant.CacheConstants; +import com.fastbee.common.constant.Constants; +import com.fastbee.common.core.domain.entity.SysUser; +import com.fastbee.common.core.domain.model.LoginUser; +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.exception.ServiceException; +import com.fastbee.common.utils.ServletUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.common.utils.ip.AddressUtils; +import com.fastbee.common.utils.ip.IpUtils; +import com.fastbee.common.utils.uuid.IdUtils; +import com.fastbee.system.domain.SysClient; +import com.fastbee.system.service.ISysClientService; +import eu.bitwalker.useragentutils.UserAgent; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + + +/** + * token验证处理 + * + * @author ruoyi + */ +@Component +public class TokenService { + // 令牌自定义标识 + @Value("${token.header}") + private String header; + + // 令牌秘钥 + @Value("${token.secret}") + private String secret; + + // 令牌有效期(默认30分钟) + @Value("${token.expireTime}") + private int expireTime; + + protected static final long MILLIS_SECOND = 1000; + + protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; + + private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; + + @Autowired + private RedisCache redisCache; + + @Autowired + private ISysClientService sysClientService; + + @Autowired + private UserDetailsServiceImpl userDetailsServiceImpl; + + /** + * 获取用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getLoginUser(HttpServletRequest request) { + // 获取请求携带的令牌 + String token = getToken(request); + if (StringUtils.isNotEmpty(token)) { + try { + Claims claims = parseToken(token); + // 解析对应的权限以及用户信息 + String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); + String userKey = getTokenKey(uuid); + LoginUser user = redisCache.getCacheObject(userKey); + return user; + } catch (Exception e) { + } + } + return null; + } + + /** + * 获取用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getLoginUserByToken(String token) { + if (StringUtils.isNotEmpty(token)) { + try { + Claims claims = parseToken(token); + // 解析对应的权限以及用户信息 + String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); + String userKey = getTokenKey(uuid); + LoginUser user = redisCache.getCacheObject(userKey); + return user; + } catch (Exception e) { + } + } + return null; + } + + /** + * 根据用户id获取用户身份信息 + * 由于多端登录,根据token获取的用户信息不一样,所以增加一个根据用户id获取用户信息的缓存key,以后多端需要获取用户最新信息就用这个方法吧 + * + * @return 用户信息 + */ + public LoginUser getLoginUserByUserId(Long userId) { + if (userId != null) { + try { + String userKey = getUserIdKey(userId); + return redisCache.getCacheObject(userKey); + } catch (Exception e) { + } + } + return null; + } + + /** + * 设置用户身份信息 + */ + public void setLoginUser(LoginUser loginUser) { + if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) { + refreshToken(loginUser); + } + } + + /** + * 删除用户身份信息 + */ + public void delLoginUser(String token) { + if (StringUtils.isNotEmpty(token)) { + String userKey = getTokenKey(token); + LoginUser loginUser = redisCache.getCacheObject(userKey); + if (loginUser != null) { + // 删除按端缓存 + String userSourceKey = CacheConstants.LOGIN_USERID_SOURCE_KEY + loginUser.getUserId() + ":" + loginUser.getSourceType(); + redisCache.deleteObject(userSourceKey); + } + redisCache.deleteObject(userKey); + } + } + + /** + * 创建令牌 + * + * @param loginUser 用户信息 + * @return 令牌 + */ + public String createToken(LoginUser loginUser) { + //todo 直接关闭页面的 先注释 +// if(loginUser.getSourceType() == 1){ +// // 检查同端是否已存在登录记录 +// String userSourceKey = CacheConstants.LOGIN_USERID_SOURCE_KEY + loginUser.getUserId() + ":" + loginUser.getSourceType(); +// LoginUser existingUser = redisCache.getCacheObject(userSourceKey); +// if (existingUser != null) { +// // 同端已存在登录,拒绝新登录 +// throw new ServiceException("当前端已有登录会话,请先退出登录"); +// } +// } + String token = IdUtils.fastUUID(); + loginUser.setToken(token); + setUserAgent(loginUser); + refreshToken(loginUser); + + Map claims = new HashMap<>(); + claims.put(Constants.LOGIN_USER_KEY, token); + return createToken(claims); + + } + + public int addToken(SysUser user, SysClient sysClient) { + UserDetails userDetails = userDetailsServiceImpl.createLoginUser(user); + LoginUser loginUser = (LoginUser) userDetails; + sysClient.setToken(Constants.TOKEN_PREFIX + createToken(loginUser, sysClient.getClientSecret(), Math.toIntExact(sysClient.getTimeout()))); + return sysClientService.insertSysClient(sysClient); + } + + public int updateToken(SysUser user, SysClient sysClient) { + UserDetails userDetails = userDetailsServiceImpl.createLoginUser(user); + LoginUser loginUser = (LoginUser) userDetails; + sysClient.setToken(Constants.TOKEN_PREFIX + createToken(loginUser, sysClient.getClientSecret(), Math.toIntExact(sysClient.getTimeout()))); + return sysClientService.updateSysClient(sysClient); + } + + public String createToken(LoginUser loginUser, String secret, int expireTime) { + String token = IdUtils.fastUUID(); + loginUser.setToken(token); + setUserAgent(loginUser); + refreshToken(loginUser, expireTime); + + Map claims = new HashMap<>(); + claims.put(Constants.LOGIN_USER_KEY, token); + return createToken(claims, secret); + } + + /** + * 验证令牌有效期,相差不足20分钟,自动刷新缓存 + * + * @param loginUser + * @return 令牌 + */ + public void verifyToken(LoginUser loginUser) { + long expireTime = loginUser.getExpireTime(); + long currentTime = System.currentTimeMillis(); + if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { + refreshToken(loginUser); + } + } + + /** + * 刷新令牌有效期 + * + * @param loginUser 登录信息 + */ + public void refreshToken(LoginUser loginUser, int expireTime) { + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); + // 根据uuid将loginUser缓存 + String userKey = getTokenKey(loginUser.getToken()); + redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); + // 使用token作为用户信息缓存key,多端不能同步最新信息,需要重新登录,因此添加一个使用用户id作为缓存key + String userIdKey = getUserIdKey(loginUser.getUserId()); + redisCache.setCacheObject(userIdKey, loginUser, expireTime, TimeUnit.MINUTES); + } + + public void refreshToken(LoginUser loginUser) { + + + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); + + // 根据token缓存loginUser + String userKey = getTokenKey(loginUser.getToken()); + + // 根据userId缓存loginUser(最新登录信息) + String userIdKey = getUserIdKey(loginUser.getUserId()); + + // 根据userId和sourceType缓存loginUser(按端登录信息) + String userSourceKey = CacheConstants.LOGIN_USERID_SOURCE_KEY + loginUser.getUserId() + ":" + loginUser.getSourceType(); + + if (Boolean.TRUE.equals(loginUser.getNeverExpire())) { + redisCache.setCacheObject(userKey, loginUser); + redisCache.setCacheObject(userIdKey, loginUser); + redisCache.setCacheObject(userSourceKey, loginUser); + } else { + redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); + redisCache.setCacheObject(userIdKey, loginUser, expireTime, TimeUnit.MINUTES); + redisCache.setCacheObject(userSourceKey, loginUser, expireTime, TimeUnit.MINUTES); + } + } + + /** + * 设置用户代理信息 + * + * @param loginUser 登录信息 + */ + public void setUserAgent(LoginUser loginUser) { + UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + loginUser.setIpaddr(ip); + loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); + loginUser.setBrowser(userAgent.getBrowser().getName()); + loginUser.setOs(userAgent.getOperatingSystem().getName()); + } + + /** + * 从数据声明生成令牌 + * + * @param claims 数据声明 + * @return 令牌 + */ + private String createToken(Map claims) { + String token = Jwts.builder() + .setClaims(claims) + .signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + private String createToken(Map claims, String secret) { + String token = Jwts.builder() + .setClaims(claims) + .signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + /** + * 从令牌中获取数据声明 + * + * @param token 令牌 + * @return 数据声明 + */ + private Claims parseToken(String token) { + SysClient sysClient = new SysClient(); + sysClient.setEnable("1"); + sysClient.setToken(Constants.TOKEN_PREFIX + token); + List list = sysClientService.selectSysClientList(sysClient); + if (!list.isEmpty()) { + return Jwts.parser() + .setSigningKey(list.get(0).getClientSecret()) + .parseClaimsJws(token) + .getBody(); + } else { + return Jwts.parser() + .setSigningKey(secret) + .parseClaimsJws(token) + .getBody(); + } + } + + /** + * 从令牌中获取用户名 + * + * @param token 令牌 + * @return 用户名 + */ + public String getUsernameFromToken(String token) { + Claims claims = parseToken(token); + return claims.getSubject(); + } + + /** + * 获取请求token + * + * @param request + * @return token + */ + private String getToken(HttpServletRequest request) { + String token = request.getHeader(header); + if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { + token = token.replace(Constants.TOKEN_PREFIX, ""); + } + return token; + } + + private String getTokenKey(String uuid) { + return CacheConstants.LOGIN_TOKEN_KEY + uuid; + } + + private String getUserIdKey(Long userId) { + return CacheConstants.LOGIN_USERID_KEY + userId; + } +} diff --git a/maibu-framework/src/main/java/com/maibu/web/service/UserDetailsServiceImpl.java b/maibu-framework/src/main/java/com/maibu/web/service/UserDetailsServiceImpl.java new file mode 100644 index 0000000..271bf74 --- /dev/null +++ b/maibu-framework/src/main/java/com/maibu/web/service/UserDetailsServiceImpl.java @@ -0,0 +1,65 @@ +package com.maibu.web.service; + +import com.maibu.core.domain.entity.SysUser; +import com.maibu.core.domain.model.LoginUser; +import com.maibu.enums.UserStatus; +import com.maibu.exception.ServiceException; +import com.maibu.service.ISysUserService; +import com.maibu.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +/** + * 用户验证处理 + * + * @author ruoyi + */ +@Service +public class UserDetailsServiceImpl implements UserDetailsService +{ + private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class); + + @Autowired + private ISysUserService userService; + + @Autowired + private SysPasswordService passwordService; + + @Autowired + private SysPermissionService permissionService; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException + { + SysUser user = userService.selectUserByUserName(username); + if (StringUtils.isNull(user)) + { + log.info("登录用户:{} 不存在.", username); + throw new ServiceException("登录用户:" + username + " 不存在"); + } + else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) + { + log.info("登录用户:{} 已被删除.", username); + throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); + } + else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) + { + log.info("登录用户:{} 已被停用.", username); + throw new ServiceException("对不起,您的账号:" + username + " 已停用"); + } + + passwordService.validate(user); + + return createLoginUser(user); + } + + public UserDetails createLoginUser(SysUser user) + { + return new LoginUser(user.getUserId(), user.getDeptId(), user.getLanguage(), user, permissionService.getMenuPermission(user)); + } +} diff --git a/maibu-iotDA/pom.xml b/maibu-iotDA/pom.xml new file mode 100644 index 0000000..9d3feb6 --- /dev/null +++ b/maibu-iotDA/pom.xml @@ -0,0 +1,90 @@ + + + 4.0.0 + + com.maibu + MiddlePlatform + 4.0.0 + + + maibu-iotDA + + + + com.maibu + maibu-common + 4.0.0 + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.1 + + + org.apache.qpid + qpid-jms-client + 0.50.0 + + + + org.apache.logging.log4j + log4j-core + 2.20.0 + + + org.apache.logging.log4j + log4j-api + 2.20.0 + + + + org.projectlombok + lombok + 1.18.8 + + + + org.apache.commons + commons-lang3 + 3.12.0 + compile + + + io.vertx + vertx-core + 4.5.7 + + + com.huaweicloud + iot-device-sdk-java + 1.2.2 + + + com.huaweicloud.sdk + huaweicloud-sdk-core + 3.1.9 + + + com.huaweicloud.sdk + huaweicloud-sdk-iotda + 3.1.9 + + + com.maibu + maibu-framework + + + com.maibu + maibu-netty-server + + + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/maibu-iotDA/src/main/java/com/maibu/controller/IoTDADeviceController.java b/maibu-iotDA/src/main/java/com/maibu/controller/IoTDADeviceController.java new file mode 100644 index 0000000..4483cb2 --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/controller/IoTDADeviceController.java @@ -0,0 +1,139 @@ +package com.maibu.controller; + +import com.fastbee.common.core.domain.AjaxResult; +import com.fastbee.common.utils.json.JsonUtils; +import com.fastbee.dto.IoTDACommandDTO; +import com.fastbee.dto.IoTDARuleDTO; +import com.fastbee.service.IoTDADeviceService; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.IOException; + +@RestController +@RequestMapping("/iotDA/device") +public class IoTDADeviceController { + + @Autowired + private IoTDADeviceService ioTDADeviceService; + + @GetMapping("/list") + public AjaxResult list() { + return AjaxResult.success(ioTDADeviceService.list()); + } + + @GetMapping("/detail") + public AjaxResult detail(@RequestParam String deviceId) { + return AjaxResult.success(ioTDADeviceService.detail(deviceId)); + } + + @PostMapping("/command") + public AjaxResult command(@RequestBody IoTDACommandDTO dto) { + return AjaxResult.success(ioTDADeviceService.command(dto)); + } + + @GetMapping("/ruleList") + public AjaxResult ruleList() { + return AjaxResult.success(ioTDADeviceService.ruleList()); + } + + @PostMapping("/deleteRule") + public AjaxResult deleteRule(@RequestParam String ruleId) { + return AjaxResult.success(ioTDADeviceService.deleteRule(ruleId)); + } + + @PostMapping("/createRule") + public AjaxResult createRule(@RequestBody IoTDARuleDTO dto) { + return AjaxResult.success(ioTDADeviceService.createRule(dto)); + } + + @GetMapping("/ruleActionList") + public AjaxResult ruleActionList(@RequestParam String ruleId) { + return AjaxResult.success(ioTDADeviceService.ruleActionList(ruleId)); + } + + @PostMapping("/createRuleAction") + public AjaxResult createRuleAction(@RequestParam String ruleId) { + return AjaxResult.success(ioTDADeviceService.createRuleAction(ruleId)); + } + + @PostMapping("/deleteRuleAction") + public AjaxResult deleteRuleAction(@RequestParam String actionId) { + return AjaxResult.success(ioTDADeviceService.deleteRuleAction(actionId)); + } + + @PostMapping("/callback") + public AjaxResult callback(@RequestBody Object obj) { + System.out.println("收到触发消息:" + JsonUtils.toJsonString(obj)); + return AjaxResult.success(); + } + + + @PostMapping("/addDevice") + public AjaxResult addDevice(@RequestParam String nodeId) throws IOException { + return AjaxResult.success(ioTDADeviceService.addDevice(nodeId)); + } + + @PostMapping("/deleteDevice") + public AjaxResult deleteDevice(@RequestParam String deviceId) { + ioTDADeviceService.deleteDevice(deviceId); + return AjaxResult.success(); + } + + @PostMapping("/updateDevice") + public AjaxResult updateDevice(@RequestParam String deviceName, @RequestParam String deviceId) { + return AjaxResult.success(ioTDADeviceService.updateDevice(deviceName, deviceId)); + } + + @PostMapping("/freezeDevice") + public AjaxResult freezeDevice(@RequestParam String deviceId) { + return AjaxResult.success(ioTDADeviceService.freezeDevice(deviceId)); + } + + @PostMapping("/unfreezeDevice") + public AjaxResult unfreezeDevice(@RequestParam String deviceId) { + return AjaxResult.success(ioTDADeviceService.unfreezeDevice(deviceId)); + } + + @PostMapping("/createMessage") + public AjaxResult createMessage(@RequestParam String deviceId, @RequestParam String json) { + return AjaxResult.success(ioTDADeviceService.createMessage(deviceId, json)); + } + + @PostMapping("/listDeviceMessages") + public AjaxResult listDeviceMessages(@RequestParam String deviceId) { + return AjaxResult.success(ioTDADeviceService.listDeviceMessages(deviceId)); + } + + @PostMapping("/addDeviceGroup") + public AjaxResult addDeviceGroup(@RequestParam String name) { + return AjaxResult.success(ioTDADeviceService.addDeviceGroup(name)); + } + + // actionId: addDevice/removeDevice + @PostMapping("/manageDeviceGroup") + public AjaxResult manageDeviceGroup(@RequestParam String groupId, @RequestParam String actionId, @RequestParam String deviceId) { + return AjaxResult.success(ioTDADeviceService.manageDeviceGroup(groupId, actionId, deviceId)); + } + + @PostMapping("/deleteDeviceGroup") + public AjaxResult deleteDeviceGroup(@RequestParam String groupId) { + return AjaxResult.success(ioTDADeviceService.deleteDeviceGroup(groupId)); + } + + @PostMapping("/listDeviceGroups") + public AjaxResult listDeviceGroups() { + return AjaxResult.success(ioTDADeviceService.listDeviceGroups()); + } + + @PostMapping("/showDevicesInGroup") + public AjaxResult showDevicesInGroup(@RequestParam String groupId) { + return AjaxResult.success(ioTDADeviceService.showDevicesInGroup(groupId)); + } + + @PostMapping("/updateDeviceGroup") + public AjaxResult updateDeviceGroup(@RequestParam String groupId, @RequestParam String name, @RequestParam String description) { + return AjaxResult.success(ioTDADeviceService.updateDeviceGroup(groupId, name, description)); + } + + +} diff --git a/maibu-iotDA/src/main/java/com/maibu/dto/IoTDACommandDTO.java b/maibu-iotDA/src/main/java/com/maibu/dto/IoTDACommandDTO.java new file mode 100644 index 0000000..fa86571 --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/dto/IoTDACommandDTO.java @@ -0,0 +1,10 @@ +package com.maibu.dto; + +import lombok.Data; + +@Data +public class IoTDACommandDTO { + private String commandName; + private Object param; + private String deviceId; +} diff --git a/maibu-iotDA/src/main/java/com/maibu/dto/IoTDARuleDTO.java b/maibu-iotDA/src/main/java/com/maibu/dto/IoTDARuleDTO.java new file mode 100644 index 0000000..1d1d237 --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/dto/IoTDARuleDTO.java @@ -0,0 +1,10 @@ +package com.maibu.dto; + +import lombok.Data; + +@Data +public class IoTDARuleDTO { + private String resource; // device.property + private String event; + private String ruleName;//report +} diff --git a/maibu-iotDA/src/main/java/com/maibu/entity/IoTDADeviceRunningStatus.java b/maibu-iotDA/src/main/java/com/maibu/entity/IoTDADeviceRunningStatus.java new file mode 100644 index 0000000..09bf55c --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/entity/IoTDADeviceRunningStatus.java @@ -0,0 +1,26 @@ +package com.maibu.entity; + +import lombok.Data; + +@Data +public class IoTDADeviceRunningStatus { + + private String deviceId; + + private String voltage; //电压 + + private String latitude;//纬度 + + private String longitude;//经度 + + private Integer onlineStatus; + + private String time; + + private String battery;//电池电量 + + private String workingArea;//作业面积 + + + +} diff --git a/maibu-iotDA/src/main/java/com/maibu/entity/IoTDADeviceSecret.java b/maibu-iotDA/src/main/java/com/maibu/entity/IoTDADeviceSecret.java new file mode 100644 index 0000000..05b1ea4 --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/entity/IoTDADeviceSecret.java @@ -0,0 +1,23 @@ +package com.maibu.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + + +@Data +@TableName("iotda_device_secret") +public class IoTDADeviceSecret implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.AUTO) + private Long id; + + private String deviceId; + + private String secretId; + +} diff --git a/maibu-iotDA/src/main/java/com/maibu/init/InitIotResource.java b/maibu-iotDA/src/main/java/com/maibu/init/InitIotResource.java new file mode 100644 index 0000000..50bea06 --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/init/InitIotResource.java @@ -0,0 +1,144 @@ +package com.maibu.init; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.fastbee.entity.IoTDADeviceSecret; +import com.fastbee.mapper.IoTDADeviceSecretMapper; +import com.fastbee.memory.IotGlobalMemory; +import com.fastbee.utils.IoTDAAMQClient; +import com.fastbee.utils.IoTDAMqttClient; +import com.huaweicloud.sdk.iotda.v5.model.QueryDeviceSimplify; +import io.vertx.core.Vertx; +import io.vertx.core.VertxOptions; +import lombok.Getter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.io.IOException; +import java.util.List; + +/** + * 系统初始化资源类 + * 实现CommandLineRunner接口,在Spring Boot启动时自动执行 + */ +@Getter +@Component +public class InitIotResource implements CommandLineRunner { + + private static final Logger logger = LoggerFactory.getLogger(InitIotResource.class); + + @Resource + private IoTDAMqttClient ioTDAMqttClient; + @Resource + private IoTDAAMQClient client; + + @Value("${ioTDA.serverIp}") + private String serverIp; + +// @Value("${ioTDA.deviceId}") +// private String deviceId; + + @Value("${ioTDA.secret}") + private String secret; + + @Value("${ioTDA.serviceId}") + private String serviceId; + + @Autowired + private IoTDADeviceSecretMapper secretMapper; + + @Override + public void run(String... args) throws Exception { + logger.info("InitResource 开始初始化系统资源..."); + + // 初始化Vert.x + initResource(); + logger.info("InitResource 系统资源初始化完成"); + initDeviceConnectAndMesPush(); + + } + + /** + * 初始化Vert.x + */ + private void initResource() { + try { + VertxOptions options = new VertxOptions() + .setWorkerPoolSize(20) + .setEventLoopPoolSize(10) + .setWarningExceptionTime(5000000000L); + + IotGlobalMemory.vertx = Vertx.vertx(options); + logger.info("Vert.x 初始化成功"); + + IotGlobalMemory.ioTDAAMQClient = this.client; + IotGlobalMemory.ioTDAAMQClient.connect(); + + List list = IotGlobalMemory.ioTDAAMQClient.listDevices(); + if (!CollectionUtils.isEmpty(list)) { + list.forEach(x -> { + + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(IoTDADeviceSecret::getDeviceId, x.getDeviceId()); + IoTDADeviceSecret secret = secretMapper.selectOne(lqw); + IoTDAMqttClient c = new IoTDAMqttClient(); + if (secret == null) { + c.secret = this.secret; + } else { + c.secret = secret.getSecretId(); + } + c.serverIp = this.serverIp; + c.serviceId = this.serviceId; + c.deviceId = x.getDeviceId(); +// try { +// c.connect(true); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } + IotGlobalMemory.ioTDAMqttClientMap.put(x.getDeviceId(), c); + }); + } + logger.info("iotDevice AMQ 初始化结束"); + + + } catch (Exception e) { + logger.error("初始化失败: {}", e.getMessage(), e); + } + } + + public void initDeviceConnectAndMesPush() { + IotGlobalMemory.vertx.setPeriodic(3000, timerId -> { + //todo 查看当前存在的所有设备循环推送状态? + try { + if (!CollectionUtils.isEmpty(IotGlobalMemory.ioTDAMqttClientMap.values())) { + IotGlobalMemory.ioTDAMqttClientMap.values().forEach(x -> { + if (x.status != 0) { + try { + x.judeConnect(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + if (x.status == 0) { + x.publishProperty(); + } + }); + } +// if (IotGlobalMemory.ioTDAAMQClient != null) { +// IotGlobalMemory.ioTDAAMQClient.deviceShadow(null); +// } + } catch (Exception e) { + logger.error("循环执行设备状态任务异常", e); + } + }); + } + + +} \ No newline at end of file diff --git a/maibu-iotDA/src/main/java/com/maibu/mapper/IoTDADeviceSecretMapper.java b/maibu-iotDA/src/main/java/com/maibu/mapper/IoTDADeviceSecretMapper.java new file mode 100644 index 0000000..579b2b6 --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/mapper/IoTDADeviceSecretMapper.java @@ -0,0 +1,13 @@ +package com.maibu.mapper; + +import com.fastbee.entity.IoTDADeviceSecret; +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import org.springframework.stereotype.Repository; + +/** + * 设备历史状态 + */ +@Repository +public interface IoTDADeviceSecretMapper extends BaseMapperX { + +} diff --git a/maibu-iotDA/src/main/java/com/maibu/memory/IotGlobalMemory.java b/maibu-iotDA/src/main/java/com/maibu/memory/IotGlobalMemory.java new file mode 100644 index 0000000..7cff18c --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/memory/IotGlobalMemory.java @@ -0,0 +1,47 @@ +package com.maibu.memory; + + +import com.fastbee.utils.IoTDAAMQClient; +import com.fastbee.utils.IoTDAMqttClient; +import io.vertx.core.Vertx; +import lombok.Data; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +@Data +public class IotGlobalMemory { + + private static final Logger logger = LoggerFactory.getLogger(IotGlobalMemory.class); + /** + * -- GETTER -- + * 获取Vert.x实例 + */ + public static Vertx vertx; + + public static Map ioTDAMqttClientMap = new ConcurrentHashMap<>(); + + public static IoTDAAMQClient ioTDAAMQClient; + + + /** + * 关闭资源 + */ + public void vertxClose() { + if (vertx != null) { + vertx.close(res -> { + if (res.succeeded()) { + logger.info("Vert.x 关闭成功"); + } else { + logger.error("Vert.x 关闭失败: {}", res.cause().getMessage()); + } + }); + } + } + + +} diff --git a/maibu-iotDA/src/main/java/com/maibu/service/IoTDADeviceService.java b/maibu-iotDA/src/main/java/com/maibu/service/IoTDADeviceService.java new file mode 100644 index 0000000..885f320 --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/service/IoTDADeviceService.java @@ -0,0 +1,156 @@ +package com.maibu.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.fastbee.dto.IoTDACommandDTO; +import com.fastbee.dto.IoTDARuleDTO; +import com.fastbee.entity.IoTDADeviceSecret; +import com.fastbee.mapper.IoTDADeviceSecretMapper; +import com.fastbee.memory.IotGlobalMemory; +import com.fastbee.utils.IoTDAMqttClient; +import com.huaweicloud.sdk.iotda.v5.model.*; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.List; + +@Service +public class IoTDADeviceService { + + + @Value("${ioTDA.serverIp}") + private String serverIp; + +// @Value("${ioTDA.deviceId}") +// private String deviceId; + + @Value("${ioTDA.secret}") + private String secret; + + @Value("${ioTDA.serviceId}") + private String serviceId; + + @Autowired + private IoTDADeviceSecretMapper secretMapper; + + public List list() { + return IotGlobalMemory.ioTDAAMQClient.listDevices(); + } + + public Object detail(String id) { + return IotGlobalMemory.ioTDAAMQClient.deviceShadow(id); + } + + public String command(IoTDACommandDTO dto) { + return IotGlobalMemory.ioTDAAMQClient.command(dto.getDeviceId(), dto.getCommandName(), dto.getParam()); + } + + public List ruleList() { + return IotGlobalMemory.ioTDAAMQClient.ruleList(); + } + + public String createRule(IoTDARuleDTO dto) { + return IotGlobalMemory.ioTDAAMQClient.createRule(dto.getRuleName(), dto.getResource(), dto.getEvent()); + } + + public String deleteRule(String ruleId) { + return IotGlobalMemory.ioTDAAMQClient.deleteRule(ruleId); + } + + public List ruleActionList(String ruleId) { + return IotGlobalMemory.ioTDAAMQClient.ruleActionList(ruleId); + } + + public String createRuleAction(String ruleId) { + return IotGlobalMemory.ioTDAAMQClient.createRuleAction(ruleId); + } + + public String deleteRuleAction(String actionId) { + return IotGlobalMemory.ioTDAAMQClient.deleteRuleAction(actionId); + } + + public String addDevice(String nodeId) throws IOException { + AddDeviceResponse response = IotGlobalMemory.ioTDAAMQClient.addDevice(nodeId); + String id = null; + if (response != null) { + id = response.getDeviceId(); + if (!StringUtils.isEmpty(id)) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(IoTDADeviceSecret::getDeviceId, id); + IoTDADeviceSecret secret = secretMapper.selectOne(lqw); + if (secret == null) { + secret = new IoTDADeviceSecret(); + secret.setDeviceId(id); + secret.setSecretId(response.getAuthInfo().getSecret()); + secretMapper.insert(secret); + } else { + secret.setSecretId(response.getAuthInfo().getSecret()); + secretMapper.updateById(secret); + } + IoTDAMqttClient c = new IoTDAMqttClient(); + c.secret = response.getAuthInfo().getSecret(); + c.serverIp = this.serverIp; + c.serviceId = this.serviceId; + c.deviceId = id; +// c.connect(true); + IotGlobalMemory.ioTDAMqttClientMap.put(id, c); + } + } + return id; + } + + public void deleteDevice(String id) { + IotGlobalMemory.ioTDAAMQClient.deleteDevice(id); + IotGlobalMemory.ioTDAMqttClientMap.remove(id); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(IoTDADeviceSecret::getDeviceId, id); + secretMapper.delete(lqw); + } + + public String updateDevice(String deviceName, String deviceId) { + return IotGlobalMemory.ioTDAAMQClient.updateDevice(deviceName, deviceId); + } + + public String freezeDevice(String deviceId) { + return IotGlobalMemory.ioTDAAMQClient.freezeDevice(deviceId); + } + + public String unfreezeDevice(String deviceId) { + return IotGlobalMemory.ioTDAAMQClient.unfreezeDevice(deviceId); + } + + public String createMessage(String deviceId, String json) { + return IotGlobalMemory.ioTDAAMQClient.createMessage(deviceId, json); + } + + public List listDeviceMessages(String deviceId) { + return IotGlobalMemory.ioTDAAMQClient.listDeviceMessages(deviceId); + } + + public String addDeviceGroup(String name) { + return IotGlobalMemory.ioTDAAMQClient.addDeviceGroup(name); + } + + public String manageDeviceGroup(String groupId, String actionId, String deviceId) { + return IotGlobalMemory.ioTDAAMQClient.manageDeviceGroup(groupId, actionId, deviceId); + } + + public String deleteDeviceGroup(String groupId) { + return IotGlobalMemory.ioTDAAMQClient.deleteDeviceGroup(groupId); + } + + public List listDeviceGroups() { + return IotGlobalMemory.ioTDAAMQClient.listDeviceGroups(); + } + + public List showDevicesInGroup(String groupId) { + return IotGlobalMemory.ioTDAAMQClient.showDevicesInGroup(groupId); + } + + public String updateDeviceGroup(String groupId, String name, String description) { + return IotGlobalMemory.ioTDAAMQClient.updateDeviceGroup(groupId, name, description); + } +} diff --git a/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAAMQClient.java b/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAAMQClient.java new file mode 100644 index 0000000..f2b6146 --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAAMQClient.java @@ -0,0 +1,409 @@ +package com.maibu.utils; + +import com.fastbee.common.utils.json.JsonUtils; +import com.huaweicloud.sdk.core.auth.BasicCredentials; +import com.huaweicloud.sdk.core.auth.ICredential; +import com.huaweicloud.sdk.core.exception.ConnectionException; +import com.huaweicloud.sdk.core.exception.RequestTimeoutException; +import com.huaweicloud.sdk.core.exception.ServiceResponseException; +import com.huaweicloud.sdk.core.region.Region; +import com.huaweicloud.sdk.iotda.v5.*; +import com.huaweicloud.sdk.iotda.v5.model.*; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Component +public class IoTDAAMQClient { + + @Value("${ioTDA.REGION_ID}") + private String REGION_ID; + + @Value("${ioTDA.ENDPOINT}") + private String ENDPOINT; + + @Value("${ioTDA.ak}") + private String ak; + + @Value("${ioTDA.sk}") + private String sk; + + @Value("${ioTDA.projectId}") + private String projectId; + +// @Value("${ioTDA.deviceId}") +// private String deviceId; + + @Value("${ioTDA.serviceId}") + private String serviceId; + + @Value("${ioTDA.productId}") + private String productId; + + public ICredential auth; + + public static IoTDAClient client; + + public void connect() { + // 创建认证 + auth = new BasicCredentials() + .withAk(ak) + .withSk(sk) + // 标准版/企业版需要使用衍生算法,基础版请删除配置"withDerivedPredicate" + .withDerivedPredicate(BasicCredentials.DEFAULT_DERIVED_PREDICATE) + .withProjectId(projectId); + + // 创建IoTDAClient实例并初始化 + client = IoTDAClient.newBuilder() + .withCredential(auth) + // 标准版/企业版:需自行创建Region对象,基础版:请使用IoTDARegion的region对象,如"withRegion(IoTDARegion.CN_NORTH_4)" + .withRegion(new Region(REGION_ID, ENDPOINT)) + // .withRegion(IoTDARegion.CN_NORTH_4) + // 配置是否忽略SSL证书校验, 默认不忽略 + // .withHttpConfig(new HttpConfig().withIgnoreSSLVerification(true)) + .build(); + } + + public List listDevices() { + // 实例化请求对象 + ListDevicesRequest request = new ListDevicesRequest(); + try { + System.out.println("通过SDK下发获取设备列表"); + // 调用查询设备列表接口 + ListDevicesResponse response = client.listDevices(request); + System.out.println("获取设备列表方法返回结果: " + JsonUtils.toJsonString(response.getDevices())); + return response.getDevices(); + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return Collections.emptyList(); + } + + + public Object deviceShadow(String id) { + // 实例化请求对象 + ShowDeviceShadowRequest request = new ShowDeviceShadowRequest(); + try { + request.withDeviceId(id); +// request.withInstanceId() + List list = Collections.emptyList(); + ShowDeviceShadowResponse response = client.showDeviceShadow(request); + if (response != null && !CollectionUtils.isEmpty(response.getShadow())) { + List data = response.getShadow(); + list = data.stream().filter(x -> x.getServiceId().equals(serviceId)).collect(Collectors.toList()); + } + if (!CollectionUtils.isEmpty(list) && list.get(0).getReported() != null) { + return list.get(0).getReported().getProperties(); + } + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return null; + } + + + public String command(String deviceId, String commandName, Object params) { + CreateCommandRequest request = new CreateCommandRequest(); + request.withDeviceId(deviceId); + DeviceCommandRequest body = new DeviceCommandRequest(); + body.setServiceId(serviceId); + body.setCommandName(commandName); + body.setParas(params); + request.withBody(body); + try { + CreateCommandResponse response = client.createCommand(request); + return response.getCommandId(); + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return null; + } + + public String deleteRule(String ruleId) { + DeleteRoutingRuleRequest request = new DeleteRoutingRuleRequest(); + request.withRuleId(ruleId); + try { + DeleteRoutingRuleResponse response = client.deleteRoutingRule(request); + System.out.println(response.toString()); + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return null; + } + + public String createRule(String ruleName, String resource, String event) { + CreateRoutingRuleRequest request = new CreateRoutingRuleRequest(); + AddRuleReq body = new AddRuleReq(); + body.withRuleName(ruleName); + RoutingRuleSubject subjectbody = new RoutingRuleSubject(); + subjectbody.withResource(resource) + .withEvent(event); + body.withSubject(subjectbody); + request.withBody(body); + try { + CreateRoutingRuleResponse response = client.createRoutingRule(request); + if (response != null && !StringUtils.isEmpty(response.getRuleId())) { + createRuleAction(response.getRuleId()); + updateRule(true, response.getRuleId()); + return response.getRuleId(); + } + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return null; + } + + public Boolean updateRule(Boolean b, String ruleId) { + UpdateRoutingRuleRequest request = new UpdateRoutingRuleRequest(); + request.withRuleId(ruleId); + UpdateRuleReq body = new UpdateRuleReq(); + body.withActive(b); + request.withBody(body); + try { + UpdateRoutingRuleResponse response = client.updateRoutingRule(request); + return response.getActive(); + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return null; + } + + public List ruleList() { + ListRoutingRulesRequest request = new ListRoutingRulesRequest(); + try { + ListRoutingRulesResponse response = client.listRoutingRules(request); + return response.getRules(); + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return null; + } + + + public String deleteRuleAction(String actionId) { + DeleteRuleActionRequest request = new DeleteRuleActionRequest(); + request.withActionId(actionId); + try { + DeleteRuleActionResponse response = client.deleteRuleAction(request); + System.out.println(response.toString()); + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return null; + } + + public String createRuleAction(String ruleId) { + CreateRuleActionRequest request = new CreateRuleActionRequest(); + AddActionReq body = new AddActionReq(); + HttpForwarding httpForwardingChannelDetail = new HttpForwarding(); + httpForwardingChannelDetail.withUrl("https://serviceri.satabot.com/iotDA/device/callback"); + ChannelDetail channelDetailbody = new ChannelDetail(); + channelDetailbody.withHttpForwarding(httpForwardingChannelDetail); + body.withChannelDetail(channelDetailbody); + body.withChannel("HTTP_FORWARDING"); + body.withRuleId(ruleId); + request.withBody(body); + try { + CreateRuleActionResponse response = client.createRuleAction(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + public List ruleActionList(String ruleId) { + ListRuleActionsRequest request = new ListRuleActionsRequest(); + request.withRuleId(ruleId); + try { + ListRuleActionsResponse response = client.listRuleActions(request); + return response.getActions(); + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return null; + } + + public AddDeviceResponse addDevice(String nodeId) { + AddDeviceRequest request = new AddDeviceRequest(); + AddDevice body = new AddDevice(); + body.withProductId(productId); + body.withNodeId(nodeId); + request.withBody(body); + try { + AddDeviceResponse response = client.addDevice(request); + return response; + } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) { + e.printStackTrace(); + } + return null; + } + + public String deleteDevice(String id) { + DeleteDeviceRequest request = new DeleteDeviceRequest(); + request.withDeviceId(id); + try { + DeleteDeviceResponse response = client.deleteDevice(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + public String updateDevice(String deviceName, String deviceId) { + UpdateDeviceRequest request = new UpdateDeviceRequest(); + request.withDeviceId(deviceId); + UpdateDevice body = new UpdateDevice(); + body.withDeviceName(deviceName); + request.withBody(body); + try { + UpdateDeviceResponse response = client.updateDevice(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + public String freezeDevice(String deviceId) { + FreezeDeviceRequest request = new FreezeDeviceRequest(); + request.withDeviceId(deviceId); + try { + FreezeDeviceResponse response = client.freezeDevice(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + + public String unfreezeDevice(String deviceId) { + UnfreezeDeviceRequest request = new UnfreezeDeviceRequest(); + request.withDeviceId(deviceId); + try { + UnfreezeDeviceResponse response = client.unfreezeDevice(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + public String createMessage(String deviceId, String json) { + CreateMessageRequest request = new CreateMessageRequest(); + request.withDeviceId(deviceId); + DeviceMessageRequest body = new DeviceMessageRequest(); + body.withMessage(json); + request.withBody(body); + try { + CreateMessageResponse response = client.createMessage(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + public List listDeviceMessages(String deviceId) { + ListDeviceMessagesRequest request = new ListDeviceMessagesRequest(); + request.withDeviceId(deviceId); + try { + ListDeviceMessagesResponse response = client.listDeviceMessages(request); + return response.getMessages(); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + + public String addDeviceGroup(String name) { + AddDeviceGroupRequest request = new AddDeviceGroupRequest(); + AddDeviceGroupDTO body = new AddDeviceGroupDTO(); + body.withName(name); + request.withBody(body); + try { + AddDeviceGroupResponse response = client.addDeviceGroup(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + + public String manageDeviceGroup(String groupId, String actionId, String deviceId) { + CreateOrDeleteDeviceInGroupRequest request = new CreateOrDeleteDeviceInGroupRequest(); + request.withGroupId(groupId); + request.withActionId(actionId); + request.withDeviceId(deviceId); + try { + CreateOrDeleteDeviceInGroupResponse response = client.createOrDeleteDeviceInGroup(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + + public String deleteDeviceGroup(String groupId) { + DeleteDeviceGroupRequest request = new DeleteDeviceGroupRequest(); + request.withGroupId(groupId); + try { + DeleteDeviceGroupResponse response = client.deleteDeviceGroup(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + public List listDeviceGroups() { + ListDeviceGroupsRequest request = new ListDeviceGroupsRequest(); + try { + ListDeviceGroupsResponse response = client.listDeviceGroups(request); + return response.getDeviceGroups(); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + public List showDevicesInGroup(String groupId) { + ShowDevicesInGroupRequest request = new ShowDevicesInGroupRequest(); + request.withGroupId(groupId); + try { + ShowDevicesInGroupResponse response = client.showDevicesInGroup(request); + return response.getDevices(); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + public String updateDeviceGroup(String groupId, String name, String description) { + UpdateDeviceGroupRequest request = new UpdateDeviceGroupRequest(); + request.withGroupId(groupId); + UpdateDeviceGroupDTO body = new UpdateDeviceGroupDTO(); + body.withDescription(description); + body.withName(name); + request.withBody(body); + try { + UpdateDeviceGroupResponse response = client.updateDeviceGroup(request); + System.out.println(response.toString()); + } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) { + e.printStackTrace(); + } + return null; + } + + +} \ No newline at end of file diff --git a/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java b/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java new file mode 100644 index 0000000..b8196cd --- /dev/null +++ b/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java @@ -0,0 +1,213 @@ +package com.maibu.utils; + +import com.fastbee.common.NettyCacheKey; +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.utils.spring.SpringUtils; +import com.fastbee.dto.NettyDevice; +import com.fastbee.iot.domain.DeviceRunningStatusHistory; +import com.fastbee.iot.domain.DeviceStatusRecordDTO; +import com.fastbee.manager.DeviceSessionManager; +import com.huaweicloud.sdk.iot.device.IoTDevice; +import com.huaweicloud.sdk.iot.device.client.listener.CommandListener; +import com.huaweicloud.sdk.iot.device.client.requests.CommandRsp; +import com.huaweicloud.sdk.iot.device.client.requests.DeviceMessage; +import com.huaweicloud.sdk.iot.device.client.requests.ServiceProperty; +import com.huaweicloud.sdk.iot.device.transport.ActionListener; +import org.apache.commons.collections.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +@Component +public class IoTDAMqttClient { + + private static final Logger logger = LoggerFactory.getLogger(IoTDAMqttClient.class); + + public String serverIp; +// @Value("${ioTDA.deviceId}") +// private String deviceId; + + public String secret; + + public String serviceId; + + private final SecureRandom random = new SecureRandom(); + public IoTDevice device; + + public String deviceId; + public int status = -1; + + private static final RedisCache redisCache = SpringUtils.getBean(RedisCache.class); + + private static final DeviceSessionManager deviceSessionManager = SpringUtils.getBean(DeviceSessionManager.class); + + + public void judeConnect() throws IOException { + String[] s = deviceId.split("_"); + String nettyDeviceId = s[1]; + NettyDevice nettyDevice = deviceSessionManager.getDevice(nettyDeviceId); + if (nettyDevice == null || nettyDevice.getOnlineStatus() != 1) { + if (device != null) { + device.getClient().close(); + device = null; + } + } else { + this.connect(true); + } + } + + + public void connect(boolean isSSL) throws IOException { + // 获取证书路径:加载iot平台的ca证书,进行服务端校验,使用sdk默认的ca.jks即可。 +// URL resource = IoTDAMqttClient.class.getClassLoader().getResource("ca.jks"); + InputStream inputStream = IoTDAMqttClient.class.getClassLoader().getResourceAsStream("ca.jks"); + if (inputStream == null) { + throw new FileNotFoundException("无法在 classpath 中找到 ca.jks"); + } + + // 2. 创建临时文件 (这会在服务器硬盘上生成一个真实的文件,例如 /tmp/iot_ca_xxx.jks) + // deleteOnExit() 保证程序退出时自动删除,避免垃圾堆积 + File tempCertFile = File.createTempFile("iot_ca_", ".jks"); + tempCertFile.deleteOnExit(); + + // 3. 将流内容复制到临时文件 + Files.copy(inputStream, tempCertFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + + // 关闭流 + inputStream.close(); + + System.out.println("证书已解压至临时文件: " + tempCertFile.getAbsolutePath()); + + // 4. 【关键】使用这个临时文件的路径,而不是原始 resource 的路径 + // 假设你的 SDK 初始化代码是这样写的,请替换掉原来的 new File(resource.getPath()) + + // 原错误代码: + // URL resource = IoTDAMqttClient.class.getClassLoader().getResource("ca.jks"); + // File file = new File(resource.getPath()); + + // ✅ 修正后的代码: + File file = tempCertFile; + + //例如在iot-device-demo文件 MessageSample.java中修改以下参数 + String url; + if (isSSL) { + url = "ssl://" + serverIp + ":" + 8883; //mqtts连接 + } else { + url = "tcp://" + serverIp + ":" + 1883; //mqtt连接 + } + + device = new IoTDevice(url, + deviceId, secret, file); + // 设置监听器接收下行命令 + device.getClient().setCommandListener(new CommandListener() { + @Override + public void onCommand(String requestId, String serviceId, String commandName, Map paras) { + System.out.println("收到命令: serviceId=" + serviceId + ", commandName=" + commandName); + System.out.println("命令参数: " + paras.toString()); + //todo + // 处理命令逻辑(示例:打印参数并响应) + System.out.println("正在处理命令..."); + + // 发送命令响应(必须调用) + device.getClient().respondCommand(requestId, new CommandRsp(0)); // 0表示执行成功 + } + }); + this.status = device.init(); + } + + + /** + * 上报json数据,注意serviceId要与Profile中的定义对应 + */ + public void publishMessage() { + + //todo 模拟推送 + String jsonMsg = "{\"services\":[{\"service_id\":\"BasicData\",\"properties\":{\"luminance\":%s},\"eventTime\":null}]}"; + String upMsg = String.format(jsonMsg, random.nextInt(100)); + DeviceMessage message = new DeviceMessage(upMsg); + try { + device.getClient().reportDeviceMessage(message, new ActionListener() { + @Override + public void onSuccess(Object context) { + logger.info("reportDeviceMessage ok"); + } + + @Override + public void onFailure(Object context, Throwable var2) { + logger.error("reportDeviceMessage fail: {}", String.valueOf(var2)); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 上报json数据,注意serviceId要与Profile中的定义对应 + */ + public void publishProperty() { + + Map json = new HashMap<>(); + + String[] s = deviceId.split("_"); + String nettyDeviceId = s[1]; + String key = NettyCacheKey.deviceRunningStatusKey + nettyDeviceId; + DeviceStatusRecordDTO recordDTO = redisCache.getCacheObject(key); + NettyDevice nettyDevice = deviceSessionManager.getDevice(nettyDeviceId); + if (nettyDevice == null || nettyDevice.getOnlineStatus() != 1) { + if (device != null) { + device.getClient().close(); + device = null; + } + } else { + if (recordDTO != null && !CollectionUtils.isEmpty(recordDTO.getHistories())) { + DeviceRunningStatusHistory history = recordDTO.getHistories().get(recordDTO.getHistories().size() - 1); + //按照物模型设置属性 + json.put("latitude", history.getLatitude()); + json.put("longitude", history.getLongitude()); + + json.put("onlineStatus", nettyDevice.getOnlineStatus()); + json.put("time", nettyDevice.getLatestStatus() == null ? null : nettyDevice.getLatestStatus().getTime()); + + json.put("battery", history.getBattery()); + json.put("workingArea", history.getWorkingArea()); + + json.put("voltage", history.getVoltage()); + json.put("leftMeasureSpeed", history.getLeftMeasureSpeed()); + json.put("leftCurrent", history.getLeftCurrent()); + json.put("rightMeasureSpeed", history.getRightMeasureSpeed()); + json.put("rightCurrent", history.getRightCurrent()); + json.put("chipTemp", history.getChipTemp()); + + } + ServiceProperty serviceProperty = new ServiceProperty(); + serviceProperty.setProperties(json); + serviceProperty.setServiceId(serviceId);//serviceId要和物模型一致 + + device.getClient().reportProperties(Arrays.asList(serviceProperty), new ActionListener() { + @Override + public void onSuccess(Object context) { + logger.info("pubMessage success"); + } + + @Override + public void onFailure(Object context, Throwable var2) { + logger.error("reportProperties failed{}", var2.toString()); + } + }); + } + + + } +} diff --git a/maibu-iotDA/src/main/resources/ca.jks b/maibu-iotDA/src/main/resources/ca.jks new file mode 100644 index 0000000..238f5d3 Binary files /dev/null and b/maibu-iotDA/src/main/resources/ca.jks differ diff --git a/maibu-netty-server/pom.xml b/maibu-netty-server/pom.xml new file mode 100644 index 0000000..88868c0 --- /dev/null +++ b/maibu-netty-server/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.maibu + MiddlePlatform + 4.0.0 + + + maibu-netty-server + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/maibu-netty-server/src/main/java/com/maibu/Main.java b/maibu-netty-server/src/main/java/com/maibu/Main.java new file mode 100644 index 0000000..1f18d67 --- /dev/null +++ b/maibu-netty-server/src/main/java/com/maibu/Main.java @@ -0,0 +1,17 @@ +package com.maibu; + +//TIP To Run code, press or +// click the icon in the gutter. +public class Main { + public static void main(String[] args) { + //TIP Press with your caret at the highlighted text + // to see how IntelliJ IDEA suggests fixing it. + System.out.printf("Hello and welcome!"); + + for (int i = 1; i <= 5; i++) { + //TIP Press to start debugging your code. We have set one breakpoint + // for you, but you can always add more by pressing . + System.out.println("i = " + i); + } + } +} \ No newline at end of file diff --git a/maibu-service/maibu-iot-service/pom.xml b/maibu-service/maibu-iot-service/pom.xml new file mode 100644 index 0000000..bb06dc0 --- /dev/null +++ b/maibu-service/maibu-iot-service/pom.xml @@ -0,0 +1,154 @@ + + + 4.0.0 + + com.maibu + maibu-service + 4.0.0 + + + maibu-iot-service + + + + + + com.maibu + maibu-common + + + + io.swagger + swagger-annotations + 1.6.2 + compile + + + org.apache.velocity + velocity-engine-core + ${velocity.version} + + + com.maibu + maibu-framework + + + org.apache.commons + commons-text + 1.6 + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.5 + + + + + org.springframework + spring-context + 5.2.3.RELEASE + + + + + me.zhyd.oauth + JustAuth + ${justAuth.version} + + + + + com.dtflys.forest + forest-spring-boot-starter + ${forest.version} + + + + + + com.taosdata.jdbc + taos-jdbcdriver + 3.3.2 + + + + + cn.hutool + hutool-all + + + + com.yomahub + liteflow-spring-boot-starter + ${liteflow.version} + + + + com.yomahub + liteflow-rule-sql + ${liteflow.version} + + + + com.yomahub + liteflow-script-groovy + ${liteflow.version} + + + + com.fasterxml.jackson.core + jackson-databind + + + com.microsoft.sqlserver + mssql-jdbc + 8.4.1.jre8 + + + org.postgresql + postgresql + 42.5.0 + + + com.oracle.database.jdbc + ojdbc8 + 19.3.0.0 + + + com.h2database + h2 + 1.4.200 + + + + com.dtflys.forest + forest-spring-boot-starter + 1.5.36 + + + + + com.hikvision.ga + artemis-http-client + 1.1.3 + + + + + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IDeviceCache.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IDeviceCache.java new file mode 100644 index 0000000..ea86664 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IDeviceCache.java @@ -0,0 +1,35 @@ +package com.maibu.cache; + +import com.fastbee.common.core.mq.DeviceStatusBo; +import com.fastbee.common.enums.DeviceStatus; +import com.fastbee.iot.domain.Device; + +import java.util.List; + +/** + * 设备缓存 + * @author bill + */ +public interface IDeviceCache { + + /** + * 更新设备状态 + * @param dto dto + */ + public void updateDeviceStatusCache(DeviceStatusBo dto,Device device); + + /** + * 获取设备在线总数 + * @return 设备在线总数 + */ + public long deviceOnlineTotal(); + + + /** + * 批量更新redis缓存设备状态 + * @param serialNumbers 设备列表 + * @param status 状态 + */ + void updateBatchDeviceStatusCache(List serialNumbers, DeviceStatus status); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IFirmwareCache.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IFirmwareCache.java new file mode 100644 index 0000000..5b430e7 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IFirmwareCache.java @@ -0,0 +1,30 @@ +package com.maibu.cache; + +/** + * 固件版本缓存 + * @author gsb + * @date 2022/10/25 11:34 + */ +public interface IFirmwareCache { + + /** + * 固件版本缓存 + * @param firmwareId 固件ID + * @param urlName 升级URL + * @return + */ + public void setFirmwareCache(Long firmwareId,String urlName); + + /** + * 获取固件版本信息 + * @param firmwareId 固件ID + * @return 升级URL + */ + public String getFirmwareCache(Long firmwareId); + + /** + * 移除固件版本 + * @param firmwareId 固件id + */ + public void remove(Long firmwareId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IModbusConfigCache.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IModbusConfigCache.java new file mode 100644 index 0000000..b26fc3a --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IModbusConfigCache.java @@ -0,0 +1,47 @@ +package com.maibu.cache; + +import com.fastbee.iot.domain.ModbusConfig; + +import java.util.List; +import java.util.Map; + +/** + * 产品对应modbus配置参数缓存 + * @author gsb + * @date 2024/6/13 9:44 + */ +public interface IModbusConfigCache { + + + /** + * 获取modbus参数 --返回 Map + * @param productId + * @return + *

+ * 返回key-value + * key: 物模型标识符 + * value:ModbusConfig + *

+ */ + Map> getModbusConfigCacheByProductId(Long productId); + + + /** + * 缓存modbus参数-返回Map + * @param productId + *

+ * 返回key-value + * key: 物模型标识符 + * value:ModbusConfig + *

+ */ + Map> setModbusConfigCacheByProductId(Long productId); + + /** + * 获取单个modbus参数缓存值 + * @param productId 产品id + * @param identify 标识符 + * @return ModbusConfig + */ + public List getSingleModbusConfig(Long productId, String identify); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IOtaTaskCache.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IOtaTaskCache.java new file mode 100644 index 0000000..bb1fee4 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/IOtaTaskCache.java @@ -0,0 +1,17 @@ +package com.maibu.cache; + + +import java.util.Map; + +public interface IOtaTaskCache { + + void setOtaCache(String serialNumber, Map hMap, long timeout); + + void removeOtaCache(String serialNumber); + + String getOtaCacheValue(String serialNumber, String hKey); + + void setOtaCacheValue(String serialNumber, String hKey, String value, long timeout); + + boolean checkOtaCacheExist(String serialNumber); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/ITSLCache.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/ITSLCache.java new file mode 100644 index 0000000..532262f --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/ITSLCache.java @@ -0,0 +1,103 @@ +package com.maibu.cache; + +import com.fastbee.iot.model.ThingsModels.ThingsModelValueItem; + +import java.util.List; +import java.util.Map; + +/** + * 物模型缓存 + * @author gsb + * @date 2024/6/12 15:57 + */ +public interface ITSLCache { + + + /** + * 获取JSON物模型 -组装的方式是为了兼容前端数据结构 + * @param productId 产品id + * @return + *

+ * { + * "functions": [ + * ], + * "events": [ + * ], + * "properties": [ + * { + * "datatype": { + * "max": 100, + * "min": 1, + * "step": 1, + * "type": "integer", + * "unit": "流明" + * }, + * "id": "light", + * "isChart": 1, + * "isHistory": 1, + * "isMonitor": 1, + * "isReadonly": 1, + * "name": "光强", + * "order": 0, + * "regId": "light", + * "type": 1 + * } + * ] + * } + *

+ * + */ + String getCacheThingsModelByProductId(Long productId); + + + /** + * 缓存物模型 + * + * @param productId 产品id + * @return

+ * {\"functions\":[],\"events\":[],\"properties\":[{\"datatype\":{\"max\":100,\"min\":1 + * ,\"step\":1,\"type\":\"integer\",\"unit\":\"流明\"}, + * \"id\":\"light\",\"isChart\":1,\"isHistory\":1,\"isMonitor\":1,\"isReadonly\":1, + * \"name\":\"光强\",\"order\":0,\"regId\":\"light\",\"type\":1}]} + *

+ */ + public String setCacheThingsModelByProductId(Long productId); + + /** + * 获取map物模型 --返回 Map + * @param productId + * @return + *

+ * 返回key-value + * key: 物模型标识符 + * value:PropertyDto + *

+ */ + Map getCacheThMapByProductId(Long productId); + + + /** + * 获取List集合物模型 + */ + List getThingsModelList(Long productId); + + /** + * 缓存物模型-返回Map + * @param productId + *

+ * 返回key-value + * key: 物模型标识符 + * value:PropertyDto + *

+ */ + public Map setCacheThMapByProductId(Long productId); + + /** + * 获取单个物模型缓存 + * @param productId 产品id + * @param identify 标识符 + * @return PropertyDto + */ + public ThingsModelValueItem getSingleThingModels(Long productId, String identify); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/ITSLValueCache.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/ITSLValueCache.java new file mode 100644 index 0000000..817df20 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/ITSLValueCache.java @@ -0,0 +1,49 @@ +package com.maibu.cache; + +import com.fastbee.iot.model.ThingsModels.ValueItem; + +import java.util.List; + +/** + * @author gsb + * @date 2024/3/22 16:37 + */ +public interface ITSLValueCache { + + + + /** + * 获取Redis缓存的设备物模型值 + * + * @param productId 产品ID + * @param deviceNumber 设备编号 + * @return + */ + public List getCacheDeviceStatus(Long productId, String deviceNumber); + + + /** + * 缓存设备物模型值到redis + * + * @return + */ + public List addCacheDeviceStatus(Long productId, String serialNumber); + + /** + * 获取单个物模型的值 + * @param productId 产品id + * @param: deviceNumber 设备编号 + * @param: identifier 物模型标识 + * @return java.lang.String + */ + String getCacheIdentifierValue(Long productId, String serialNumber, String identifier); + + /** + * 获取单个物模型的值 + * @param productId 产品id + * @param: deviceNumber 设备编号 + * @param: identifier 物模型标识 + * @return java.lang.String + */ + ValueItem getCacheIdentifier(Long productId, String serialNumber, String identifier); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/SceneModelTagCache.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/SceneModelTagCache.java new file mode 100644 index 0000000..c168ff4 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/SceneModelTagCache.java @@ -0,0 +1,25 @@ +package com.maibu.cache; + +import com.fastbee.iot.model.scenemodel.SceneModelTagCacheVO; + +/** + * @author gsb + * @date 2024/3/22 16:37 + */ +public interface SceneModelTagCache { + + /** + * 缓存场景运算型变量值 + * @param sceneModelId 场景id + * @param: value 值 + * @return void + */ + void addSceneModelTagValue(Long sceneModelId, SceneModelTagCacheVO sceneModelTagCacheVO); + + /** + * 获取场景运算型变量值 + * @param sceneModelTagId 场景变量id + * @return java.lang.String + */ + SceneModelTagCacheVO getSceneModelTagValue(Long sceneModelId, Long sceneModelTagId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/DeviceCacheImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/DeviceCacheImpl.java new file mode 100644 index 0000000..56e732a --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/DeviceCacheImpl.java @@ -0,0 +1,99 @@ +package com.maibu.cache.impl; + +import com.fastbee.common.core.mq.DeviceStatusBo; +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.core.redis.RedisKeyBuilder; +import com.fastbee.common.enums.DeviceStatus; +import com.fastbee.common.exception.ServiceException; +import com.fastbee.common.utils.DateUtils; +import com.fastbee.iot.cache.IDeviceCache; +import com.fastbee.iot.domain.Device; +import com.fastbee.iot.service.IDeviceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import javax.annotation.PreDestroy; +import java.util.List; +import java.util.Optional; + +/** + * @author bill + */ +@Service +@Slf4j +public class DeviceCacheImpl implements IDeviceCache { + + @Autowired + private RedisCache redisCache; + @Autowired + private IDeviceService deviceService; + + + /** + * 更新设备状态 + * 如果设备状态保持不变,更新redis设备最新在线时间 + * 如果设备状态更改,更新redis同时,更新MySQL数据库设备状态 + * + * @param dto dto + */ + @Override + public void updateDeviceStatusCache(DeviceStatusBo dto,Device device) { + + Optional.ofNullable(device).orElseThrow(() -> new ServiceException("设备不存在" + "[{" + dto.getSerialNumber() + "}]")); + if (dto.getStatus() == DeviceStatus.ONLINE) { + /*redis设备在线列表*/ + redisCache.zSetAdd(RedisKeyBuilder.buildDeviceOnlineListKey(), dto.getSerialNumber(), DateUtils.getTimestampSeconds()); + device.setStatus(DeviceStatus.ONLINE.getType()); + } else { + /*在redis设备在线列表移除设备*/ + redisCache.zRem(RedisKeyBuilder.buildDeviceOnlineListKey(), dto.getSerialNumber()); + //更新一下mysql的设备状态为离线 + device.setStatus(DeviceStatus.OFFLINE.getType()); + } + device.setUpdateTime(DateUtils.getNowDate()); + deviceService.updateDeviceStatusAndLocation(device, dto.getIp()); + + } + + /** + * 获取设备在线总数 + * + * @return 设备在线总数 + */ + @Override + public long deviceOnlineTotal() { + return redisCache.zSize(RedisKeyBuilder.buildDeviceOnlineListKey()); + } + + + /** + * 批量更新redis缓存设备状态 + * + * @param serialNumbers 设备列表 + * @param status 状态 + */ + @Override + public void updateBatchDeviceStatusCache(List serialNumbers, DeviceStatus status) { + if (CollectionUtils.isEmpty(serialNumbers)) { + return; + } + for (String serialNumber : serialNumbers) { + DeviceStatusBo statusBo = new DeviceStatusBo(); + statusBo.setStatus(status); + statusBo.setSerialNumber(serialNumber); + //this.updateDeviceStatusCache(statusBo); + } + } + + /** + * 系统停止时,更新所有设备为离线状态 + */ + @PreDestroy + public void resetDeviceStatus(){ + deviceService.reSetDeviceStatus(); + } + + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/FirmwareCacheImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/FirmwareCacheImpl.java new file mode 100644 index 0000000..1444f98 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/FirmwareCacheImpl.java @@ -0,0 +1,56 @@ +package com.maibu.cache.impl; + +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.core.redis.RedisKeyBuilder; +import com.fastbee.iot.cache.IFirmwareCache; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.concurrent.TimeUnit; + +/** + * 固件版本缓存 + * @author gsb + * @date 2022/10/25 11:37 + */ +@Service +@Slf4j +public class FirmwareCacheImpl implements IFirmwareCache { + + @Autowired + private RedisCache redisCache; + + /** + * 固件版本缓存 + * @param firmwareId 固件ID + * @param urlName 升级URL + * @return + */ + @Override + public void setFirmwareCache(Long firmwareId,String urlName){ + String cachedKey = RedisKeyBuilder.buildFirmwareCachedKey(firmwareId); + redisCache.setCacheObject(cachedKey,urlName,60*60*12, TimeUnit.SECONDS); + } + + /** + * 获取固件版本信息 + * @param firmwareId 固件ID + * @return 升级URL + */ + @Override + public String getFirmwareCache(Long firmwareId){ + String cachedKey = RedisKeyBuilder.buildFirmwareCachedKey(firmwareId); + return redisCache.getCacheObject(cachedKey); + } + + /** + * 移除固件版本 + * @param firmwareId 固件id + */ + @Override + public void remove(Long firmwareId){ + String cachedKey = RedisKeyBuilder.buildFirmwareCachedKey(firmwareId); + redisCache.deleteObject(cachedKey); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/ModbusConfigCacheImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/ModbusConfigCacheImpl.java new file mode 100644 index 0000000..8e96191 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/ModbusConfigCacheImpl.java @@ -0,0 +1,105 @@ +package com.maibu.cache.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.core.redis.RedisKeyBuilder; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.iot.cache.IModbusConfigCache; +import com.fastbee.iot.domain.ModbusConfig; +import com.fastbee.iot.service.IModbusConfigService; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author gsb + * @date 2024/6/13 9:45 + */ +@Service +public class ModbusConfigCacheImpl implements IModbusConfigCache { + + @Resource + private IModbusConfigService modbusConfigService; + @Resource + private RedisCache redisCache; + + /** + * 获取modbus参数 --返回 Map + * @param productId + * @return + *

+ * 返回key-value + * key: 物模型标识符 + * value:ModbusConfig + *

+ */ + @Override + public Map> getModbusConfigCacheByProductId(Long productId){ + Map> resultMap = new HashMap<>(); + String modbusKey = RedisKeyBuilder.buildModbusKey(productId); + Map map = redisCache.hashEntity(modbusKey); + if (!CollectionUtils.isEmpty(map)){ + for (Map.Entry entry : map.entrySet()) { + List modbusConfigList = JSON.parseArray(entry.getValue(), ModbusConfig.class); + resultMap.put(Integer.parseInt(entry.getKey()), modbusConfigList); + } + return resultMap; + } + return setModbusConfigCacheByProductId(productId); + } + + /** + * 缓存modbus参数-返回Map + * @param productId + *

+ * 返回key-value + * key: 物模型标识符 + * value:ModbusConfig + *

+ */ + @Override + public Map> setModbusConfigCacheByProductId(Long productId){ + Map resultMap = new HashMap<>(); + ModbusConfig modbusConfig = new ModbusConfig(); + modbusConfig.setProductId(productId); + List modbusConfigList = modbusConfigService.selectShortListByProductId(modbusConfig); + Map> listMap = modbusConfigList.stream().collect(Collectors.groupingBy(ModbusConfig::getAddress)); + for (Map.Entry> entry : listMap.entrySet()) { + List value = entry.getValue(); + String valueStr = JSONObject.toJSONString(value); + resultMap.put(entry.getKey()+"", valueStr); + } + String modbusKey = RedisKeyBuilder.buildModbusKey(productId); + redisCache.hashPutAll(modbusKey, resultMap); + return listMap; + } + /** + * 获取单个modbus参数缓存值 + * @param productId 产品id + * @param address 标识符 + * @return ModbusConfig + */ + @Override + public List getSingleModbusConfig(Long productId, String address){ + String modbusKey = RedisKeyBuilder.buildModbusKey(productId); + String cacheMapValue = redisCache.getCacheMapValue(modbusKey, address); + if (!StringUtils.isEmpty(cacheMapValue)){ + return JSON.parseArray(cacheMapValue, ModbusConfig.class); + } + ModbusConfig modbusConfig = new ModbusConfig(); + modbusConfig.setProductId(productId); + modbusConfig.setAddress(Integer.parseInt(address)); + List modbusConfigList = modbusConfigService.selectShortListByProductId(modbusConfig); + if (!CollectionUtils.isEmpty(modbusConfigList)){ + setModbusConfigCacheByProductId(productId); + } + return modbusConfigList; + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/OtaTaskCacheImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/OtaTaskCacheImpl.java new file mode 100644 index 0000000..73c17b0 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/OtaTaskCacheImpl.java @@ -0,0 +1,51 @@ +package com.maibu.cache.impl; + + +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.core.redis.RedisKeyBuilder; +import com.fastbee.iot.cache.IOtaTaskCache; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@Service +public class OtaTaskCacheImpl implements IOtaTaskCache { + + + @Resource + private RedisCache redisCache; + + @Override + public void setOtaCache(String serialNumber, Map hMap, long timeout) { + String cacheKey = RedisKeyBuilder.buildDeviceOtaKey(serialNumber); + redisCache.hashPutAll(cacheKey, hMap); + redisCache.expire(cacheKey, timeout, TimeUnit.MINUTES); + } + + @Override + public void removeOtaCache(String serialNumber) { + String cacheKey = RedisKeyBuilder.buildDeviceOtaKey(serialNumber); + redisCache.deleteObject(cacheKey); + } + + @Override + public String getOtaCacheValue(String serialNumber, String hKey) { + String cacheKey = RedisKeyBuilder.buildDeviceOtaKey(serialNumber); + return redisCache.getCacheMapValue(cacheKey, hKey); + } + + @Override + public void setOtaCacheValue(String serialNumber, String hKey, String value, long timeout) { + String cacheKey = RedisKeyBuilder.buildDeviceOtaKey(serialNumber); + redisCache.setCacheMapValue(cacheKey, hKey, value); + redisCache.expire(cacheKey, timeout, TimeUnit.MINUTES); + } + + @Override + public boolean checkOtaCacheExist(String serialNumber) { + return redisCache.hasKey(RedisKeyBuilder.buildDeviceOtaKey(serialNumber)); + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/SceneModelTagCacheImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/SceneModelTagCacheImpl.java new file mode 100644 index 0000000..ed88c2a --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/SceneModelTagCacheImpl.java @@ -0,0 +1,36 @@ +package com.maibu.cache.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.core.redis.RedisKeyBuilder; +import com.fastbee.iot.cache.SceneModelTagCache; +import com.fastbee.iot.model.scenemodel.SceneModelTagCacheVO; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * 物模型缓存和物模型值缓存 + * @author gsb + * @date 2024/3/22 16:37 + */ +@Service +public class SceneModelTagCacheImpl implements SceneModelTagCache { + + @Resource + private RedisCache redisCache; + + + @Override + public void addSceneModelTagValue(Long sceneModelId, SceneModelTagCacheVO sceneModelTagCacheVO) { + String key = RedisKeyBuilder.buildSceneModelTagCacheKey(sceneModelId); + redisCache.setHashValue(key, sceneModelTagCacheVO.getId().toString(), JSON.toJSONString(sceneModelTagCacheVO)); + } + + @Override + public SceneModelTagCacheVO getSceneModelTagValue(Long sceneModelId, Long sceneModelTagId) { + String key = RedisKeyBuilder.buildSceneModelTagCacheKey(sceneModelId); + return JSONObject.parseObject(redisCache.getCacheMapValue(key, sceneModelTagId.toString()), SceneModelTagCacheVO.class); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/TSLCacheImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/TSLCacheImpl.java new file mode 100644 index 0000000..7b5001d --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/TSLCacheImpl.java @@ -0,0 +1,334 @@ +package com.maibu.cache.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.core.redis.RedisKeyBuilder; +import com.fastbee.common.enums.ThingsModelType; +import com.fastbee.common.utils.SecurityUtils; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.iot.cache.ITSLCache; +import com.fastbee.iot.domain.ModbusConfig; +import com.fastbee.iot.domain.Product; +import com.fastbee.iot.domain.ThingsModel; +import com.fastbee.iot.mapper.ProductMapper; +import com.fastbee.iot.model.ThingsModelItem.Datatype; +import com.fastbee.iot.model.ThingsModels.IdentifierVO; +import com.fastbee.iot.model.ThingsModels.PropertyDto; +import com.fastbee.iot.model.ThingsModels.ThingsModelValueItem; +import com.fastbee.iot.service.IModbusConfigService; +import com.fastbee.iot.service.IThingsModelService; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static com.fastbee.common.constant.Constants.EN_US; +import static com.fastbee.common.constant.Constants.ZH_CN; + +/** + * 物模型缓存 + * + * @author gsb + * @date 2024/6/12 15:58 + */ +@Service +public class TSLCacheImpl implements ITSLCache { + + @Resource + private RedisCache redisCache; + @Resource + private ProductMapper productMapper; + @Resource + private IThingsModelService thingsModelService; + @Resource + private IModbusConfigService modbusConfigService; + + /** + * 根据产品ID获取JSON物模型 -组装的方式是为了兼容前端数据结构 + * + * @param productId + * @return

+ * { + * "functions": [ + * ], + * "events": [ + * ], + * "properties": [ + * { + * "datatype": { + * "max": 100, + * "min": 1, + * "step": 1, + * "type": "integer", + * "unit": "流明" + * }, + * "id": "light", + * "isChart": 1, + * "isHistory": 1, + * "isMonitor": 1, + * "isReadonly": 1, + * "name": "光强", + * "order": 0, + * "regId": "light", + * "type": 1 + * } + * ] + * } + *

+ */ + @Override + public String getCacheThingsModelByProductId(Long productId) { + assert !Objects.isNull(productId) : "产品id为空"; + // redis获取物模型 + Map map = redisCache.getCacheMap(RedisKeyBuilder.buildTSLCacheKey(productId)); + if (!CollectionUtils.isEmpty(map)) { + //兼容原页面物模型的数据格式 + Map> listMap = map.values().stream().map(v -> JSON.parseObject(v.toString(), PropertyDto.class)) + .collect(Collectors.groupingBy(dto -> ThingsModelType.getName(dto.getType()))); + if (listMap != null) { + for (List dtoList : listMap.values()) { + for (PropertyDto dto : dtoList) { + convertModelName(dto, SecurityUtils.getLanguage()); + } + } + } + return JSON.toJSONString(listMap); + } + return setCacheThingsModelByProductId(productId); + } + + + /** + * 缓存物模型 -返回JSON字符串 + * + * @param productId + * @return

+ * {\"functions\":[],\"events\":[],\"properties\":[{\"datatype\":{\"max\":100,\"min\":1 + * ,\"step\":1,\"type\":\"integer\",\"unit\":\"流明\"}, + * \"id\":\"light\",\"isChart\":1,\"isHistory\":1,\"isMonitor\":1,\"isReadonly\":1, + * \"name\":\"光强\",\"order\":0,\"regId\":\"light\",\"type\":1}]} + *

+ */ + public String setCacheThingsModelByProductId(Long productId) { + Map thingsModelMap = setThingModelAndModbusConfig(productId); + /*组装成原格式数据*/ + Map> result = thingsModelMap.values().stream().map(x -> JSON.parseObject(x, ThingsModelValueItem.class)) + .collect(Collectors.groupingBy(dto -> ThingsModelType.getName(dto.getType()))); + if (result != null) { + for (List itemList : result.values()) { + for (ThingsModelValueItem item : itemList) { + convertModelName(item, SecurityUtils.getLanguage()); + } + } + } + String jsonString = JSON.toJSONString(result); + Product product = new Product(); + product.setProductId(productId); + product.setThingsModelsJson(jsonString); + productMapper.updateThingsModelJson(product); + return jsonString; + } + + + + /** + * 获取map物模型 + * @param productId + * @return + *

+ * 返回key-value + * key: 物模型标识符 + * value:PropertyDto + *

+ */ + public Map getCacheThMapByProductId(Long productId) { + assert !Objects.isNull(productId) : "产品id为空"; + // redis获取物模型 + Map map = redisCache.getCacheMap(RedisKeyBuilder.buildTSLCacheKey(productId)); + if (!CollectionUtils.isEmpty(map)) { + Map itemMap = map.values().stream().map(v -> JSON.parseObject(v.toString(), ThingsModelValueItem.class)).collect( + Collectors.toMap(ThingsModelValueItem::getId, Function.identity())); + for (ThingsModelValueItem item : itemMap.values()) { + convertModelName(item, SecurityUtils.getLanguage()); + } + return itemMap; + } + return setCacheThMapByProductId(productId); + } + + /** + * 获取List集合物模型 + */ + @Override + public List getThingsModelList(Long productId){ + Map thingsModelMap = this.getCacheThMapByProductId(productId); + if (thingsModelMap != null) { + for (ThingsModelValueItem item : thingsModelMap.values()) { + convertModelName(item, SecurityUtils.getLanguage()); + } + } + return new ArrayList<>(thingsModelMap.values()); + } + + + /** + * 缓存物模型-返回Map + * @param productId + *

+ * 返回key-value + * key: 物模型标识符 + * value:PropertyDto + *

+ */ + public Map setCacheThMapByProductId(Long productId) { + Map thingsModelMap = setThingModelAndModbusConfig(productId); + Map itemMap = thingsModelMap.values().stream().map(value -> JSON.parseObject(value, ThingsModelValueItem.class)).collect(Collectors.toMap(ThingsModelValueItem::getId, Function.identity())); + if (itemMap != null) { + for (ThingsModelValueItem item : itemMap.values()) { + convertModelName(item, SecurityUtils.getLanguage()); + } + } + return itemMap; + } + + /** + * 获取单个物模型缓存值 + * @param productId 产品id + * @param identify 标识符 + * @return PropertyDto + */ + @Override + public ThingsModelValueItem getSingleThingModels(Long productId, String identify){ + String cacheKey = RedisKeyBuilder.buildTSLCacheKey(productId); + String itemStr; + // 物模型缓存有变动,需要特殊处理一下 + IdentifierVO identifierVO = thingsModelService.revertObjectOrArrayIdentifier(identify); + // 数组或数组对象 + String identifier = identifierVO.getIdentifier(); + if (null != identifierVO.getIndex()) { + itemStr = redisCache.getCacheMapValue(cacheKey, identifier); + if (StringUtils.isEmpty(itemStr) && identifier.contains("_")) { + String substring = identifier.substring(0, identifier.indexOf("_")); + itemStr = redisCache.getCacheMapValue(cacheKey, substring); + } + } else { + itemStr = redisCache.getCacheMapValue(cacheKey, identifier); + if (StringUtils.isEmpty(itemStr) && identifier.contains("_")) { + String substring = identifier.substring(0, identifier.indexOf("_")); + itemStr = redisCache.getCacheMapValue(cacheKey, substring); + } + } + if (StringUtils.isEmpty(itemStr)) {return null;} + ThingsModelValueItem item = JSONObject.parseObject(itemStr,ThingsModelValueItem.class); + convertModelName(item, SecurityUtils.getLanguage()); + // 处理数组、对象、数组对象 + if (identifier.equals(item.getId())) { + return item; + } + Datatype datatype = item.getDatatype(); + List params = datatype.getParams(); + ThingsModelValueItem resultItem = params.stream().filter(t -> identifier.equals(t.getId())).findFirst().orElse(null); + if (Objects.isNull(resultItem)) { + return null; + } + resultItem.setType(item.getType()); + return resultItem; + } + + + /** + * 整合物模型 & 整合modbus配置参数 & redis缓存 + * + * @param productId + */ + private Map setThingModelAndModbusConfig(Long productId) { + // 数据库查询物模型集合 + ThingsModel model = new ThingsModel(); + model.setProductId(productId); + model.setLimitValue(SecurityUtils.getLanguage()); + List thingsModels = thingsModelService.selectThingsModelList(model); + //modbus配置参数整合到物模型 + ModbusConfig config = new ModbusConfig(); + config.setProductId(productId); + List modbusConfigList = modbusConfigService.selectShortListByProductId(config); + if (!CollectionUtils.isEmpty(modbusConfigList)) { + Map modbusMap = modbusConfigList.stream().collect(Collectors.toMap(ModbusConfig::getIdentifier, Function.identity())); + for (ThingsModel thingsModel : thingsModels) { + if (modbusMap.containsKey(thingsModel.getIdentifier())) { + ModbusConfig modbusConfig = modbusMap.get(thingsModel.getIdentifier()); + thingsModel.setModbusConfig(modbusConfig); + } + } + } + //List -> MAP + Map thingsModelMap = thingsModels.stream().collect(Collectors.toMap(ThingsModel::getIdentifier, + thingsModel -> { + //转换数据,减少不必要数据 + ThingsModelValueItem dto = new ThingsModelValueItem(); + BeanUtils.copyProperties(thingsModel, dto); + dto.setDatatype(JSONObject.parseObject(thingsModel.getSpecs(), Datatype.class)) + .setId(thingsModel.getIdentifier()) + .setName(thingsModel.getModelName()) + .setName_zh_CN(thingsModel.getModelName_zh_CN()) + .setName_en_US(thingsModel.getModelName_en_US()) + .setOrder(thingsModel.getModelOrder()) + .setModelId(thingsModel.getModelId()) + .setConfig(thingsModel.getModbusConfig()); + return JSONObject.toJSONString(dto); + })); + + /*缓存到redis*/ + String cacheKey = RedisKeyBuilder.buildTSLCacheKey(productId); + //先删除缓存 + if (redisCache.containsKey(cacheKey)) { + redisCache.deleteObject(cacheKey); + } + redisCache.hashPutAll(cacheKey, thingsModelMap); + return thingsModelMap; + } + + /** + * 将物模型名称转换为对应语言 + * @param item + * @param language + */ + private static void convertModelName(ThingsModelValueItem item, String language) { + switch (language) { + case EN_US: + if (StringUtils.isNotEmpty(item.getName_en_US())){ + item.setName(item.getName_en_US()); + } + break; + case ZH_CN: + if (StringUtils.isNotEmpty(item.getName_zh_CN())){ + item.setName(item.getName_zh_CN()); + } + break; + } + } + + /** + * 将物模型名称转换为对应语言 + * @param item + * @param language + */ + private static void convertModelName(PropertyDto item, String language) { + switch (language) { + case EN_US: + item.setName(item.getName_en_US()); + break; + case ZH_CN: + item.setName(item.getName_zh_CN()); + break; + } + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/TSLValueCacheImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/TSLValueCacheImpl.java new file mode 100644 index 0000000..473ed00 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/cache/impl/TSLValueCacheImpl.java @@ -0,0 +1,149 @@ +package com.maibu.cache.impl; + +import com.alibaba.fastjson2.JSONObject; +import com.fastbee.common.core.redis.RedisCache; +import com.fastbee.common.core.redis.RedisKeyBuilder; +import com.fastbee.common.enums.DataEnum; +import com.fastbee.iot.cache.ITSLCache; +import com.fastbee.iot.cache.ITSLValueCache; +import com.fastbee.iot.model.ThingsModels.ThingsModelValueItem; +import com.fastbee.iot.model.ThingsModels.ValueItem; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 物模型值缓存 + * + * @author gsb + * @date 2024/3/22 16:37 + */ +@Service +public class TSLValueCacheImpl implements ITSLValueCache { + + @Resource + private RedisCache redisCache; + @Resource + private ITSLCache itslCache; + + + /** + * 获取Redis缓存的设备物模型值 + * + * @param productId 产品ID + * @param deviceNumber 设备编号 + * @return + */ + @Override + public List getCacheDeviceStatus(Long productId, String deviceNumber) { + String key = RedisKeyBuilder.buildTSLVCacheKey(productId, deviceNumber); + Map map = redisCache.hashEntity(key); + List valueList = new ArrayList<>(); + if (map == null || map.size() == 0) { + // 缓存设备状态(物模型值)到redis + valueList = addCacheDeviceStatus(productId, deviceNumber); + } else { + // 获取redis缓存的物模型值 + valueList = map.values().stream().map(s -> JSONObject.parseObject(s, ValueItem.class)) + .collect(Collectors.toList()); + } + return valueList; + } + + + /** + * 缓存设备物模型值到redis + * + * @return + */ + @Override + public List addCacheDeviceStatus(Long productId, String serialNumber) { + List resultList = new ArrayList<>(); + // 获取物模型值 + List valueList = itslCache.getThingsModelList(productId); + // redis存储设备默认状态 键:产品ID_设备编号 + String key = RedisKeyBuilder.buildTSLVCacheKey(productId, serialNumber); + Map maps = new HashMap<>(); + for (ThingsModelValueItem item : valueList) { + ValueItem valueItem = new ValueItem(); + valueItem.setId(item.getId()); + valueItem.setValue(""); + valueItem.setShadow(""); + DataEnum dataType = DataEnum.convert(item.getDatatype().getType()); + if (dataType.equals(DataEnum.ARRAY) || dataType.equals(DataEnum.OBJECT)) { + //数组和对象类型额外处理 + this.handleOtherType(maps, item, dataType, valueItem); + } else { + maps.put(item.getId(), JSONObject.toJSONString(valueItem)); + } + resultList.add(valueItem); + } + redisCache.hashPutAll(key, maps); + return resultList; + } + + @Override + public String getCacheIdentifierValue(Long productId, String serialNumber, String identifier) { + String key = RedisKeyBuilder.buildTSLVCacheKey(productId, serialNumber); + ValueItem valueItem = JSONObject.parseObject(redisCache.getCacheMapValue(key, identifier), ValueItem.class); + return null != valueItem ? valueItem.getValue() : ""; + } + + @Override + public ValueItem getCacheIdentifier(Long productId, String serialNumber, String identifier) { + String key = RedisKeyBuilder.buildTSLVCacheKey(productId, serialNumber); + return JSONObject.parseObject(redisCache.getCacheMapValue(key, identifier), ValueItem.class); + } + + /** + * 数组和对象类型额外处理 + * @param maps + * @param item + * @param dataType + * @param valueItem + */ + private void handleOtherType(Map maps, ThingsModelValueItem item, DataEnum dataType, ValueItem valueItem) { + List params = item.getDatatype().getParams(); + switch (dataType) { + case ARRAY: + // 数组元素赋值(英文逗号分割的字符串,包含简单类型数组和对象类型数组,数组元素ID格式:array_01_humidity) + StringBuilder defaultValue = new StringBuilder(" "); + if (item.getDatatype().getArrayType().equals("object")) { + for (int i = 0; i < item.getDatatype().getArrayCount(); i++) { + // 默认值需要保留为空格,便于解析字符串为数组 + defaultValue.append(", "); + } + for (ThingsModelValueItem param : params) { + valueItem.setValue(defaultValue.toString()); + valueItem.setShadow(defaultValue.toString()); + valueItem.setName(param.getName()); + valueItem.setId(param.getId()); + maps.put(param.getId(), JSONObject.toJSONString(valueItem)); + } + } else { + for (int i = 0; i < item.getDatatype().getArrayCount(); i++) { + defaultValue.append(", "); + } + valueItem.setValue(defaultValue.toString()); + valueItem.setShadow(defaultValue.toString()); + valueItem.setName(item.getName()); + valueItem.setId(item.getId()); + maps.put(item.getId(), JSONObject.toJSONString(valueItem)); + } + break; + case OBJECT: + for (ThingsModelValueItem param : params) { + valueItem.setName(param.getName()); + valueItem.setId(param.getId()); + maps.put(param.getId(), JSONObject.toJSONString(valueItem)); + } + break; + } + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/DeviceRecordConvert.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/DeviceRecordConvert.java new file mode 100644 index 0000000..f341769 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/DeviceRecordConvert.java @@ -0,0 +1,38 @@ +package com.maibu.convert; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fastbee.iot.domain.DeviceRecord; +import com.fastbee.iot.model.DeviceRecordVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * @description: 设备记录转换工具类 + * @author admin + * @date 2024-07-19 16:14 + * @version 1.0 + */ +@Mapper +public interface DeviceRecordConvert { + + DeviceRecordConvert INSTANCE = Mappers.getMapper(DeviceRecordConvert.class); + + /** + * @description: 单个实体类转换 + * @param: deviceRecord 设备记录 + * @return: com.fastbee.iot.model.DeviceRecordVO + */ + DeviceRecordVO convertDeviceRecordVO(DeviceRecord deviceRecord); + + /** + * @description: 集合转换 + * @param: deviceRecordList 设备记录集合 + * @return: java.util.List + */ + List convertDeviceRecordVOList(List deviceRecordList); + + Page convertDeviceRecordVOPage(Page deviceRecordPage); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/FirmwareTaskConvert.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/FirmwareTaskConvert.java new file mode 100644 index 0000000..731babb --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/FirmwareTaskConvert.java @@ -0,0 +1,42 @@ +package com.maibu.convert; + +import com.fastbee.iot.domain.FirmwareTask; +import com.fastbee.iot.model.FirmwareTaskInput; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * @description: 网关与子产品关联对象 + * @author admin + * @date 2024-07-19 16:14 + * @version 1.0 + */ +@Mapper +public interface FirmwareTaskConvert { + + FirmwareTaskConvert INSTANCE = Mappers.getMapper(FirmwareTaskConvert.class); + + /** + * @description: 单个实体类转换 + * @param: deviceRecord 设备记录 + * @return: com.fastbee.iot.model.DeviceRecordVO + */ + FirmwareTaskInput convertFirmwareTaskInput(FirmwareTask firmwareTask); + + /** + * @description: 集合转换 + * @param: deviceRecordList 设备记录集合 + * @return: java.util.List + */ + List convertFirmwareTaskInputList(List FirmwareTaskList); + + /** + * @description: 单个实体类转换 + * @param: deviceRecord 设备记录 + * @return: com.fastbee.iot.model.DeviceRecordVO + */ + FirmwareTask inputConvertFirmwareTask(FirmwareTaskInput firmwareTaskInput); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/ProductModbusJobConvert.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/ProductModbusJobConvert.java new file mode 100644 index 0000000..f76350b --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/ProductModbusJobConvert.java @@ -0,0 +1,35 @@ +package com.maibu.convert; + +import com.fastbee.iot.domain.ProductModbusJob; +import com.fastbee.iot.model.modbus.ProductModbusJobVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * @description: 网关与子产品关联对象 + * @author admin + * @date 2024-07-19 16:14 + * @version 1.0 + */ +@Mapper +public interface ProductModbusJobConvert { + + ProductModbusJobConvert INSTANCE = Mappers.getMapper(ProductModbusJobConvert.class); + + /** + * @description: 单个实体类转换 + * @param: deviceRecord 设备记录 + * @return: com.fastbee.iot.model.DeviceRecordVO + */ + ProductModbusJobVO convertProductModbusJobVO(ProductModbusJob productModbusJob); + + /** + * @description: 集合转换 + * @param: deviceRecordList 设备记录集合 + * @return: java.util.List + */ + List convertProductModbusJobVOList(List ProductModbusJobList); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/ProductSubGatewayConvert.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/ProductSubGatewayConvert.java new file mode 100644 index 0000000..5e938f6 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/convert/ProductSubGatewayConvert.java @@ -0,0 +1,35 @@ +package com.maibu.convert; + +import com.fastbee.iot.domain.ProductSubGateway; +import com.fastbee.iot.model.gateWay.ProductSubGatewayVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * @description: 网关与子产品关联对象 + * @author admin + * @date 2024-07-19 16:14 + * @version 1.0 + */ +@Mapper +public interface ProductSubGatewayConvert { + + ProductSubGatewayConvert INSTANCE = Mappers.getMapper(ProductSubGatewayConvert.class); + + /** + * @description: 单个实体类转换 + * @param: deviceRecord 设备记录 + * @return: com.fastbee.iot.model.DeviceRecordVO + */ + ProductSubGatewayVO convertProductSubGatewayVO(ProductSubGateway productSubGateway); + + /** + * @description: 集合转换 + * @param: deviceRecordList 设备记录集合 + * @return: java.util.List + */ + List convertProductSubGatewayVOList(List ProductSubGatewayList); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Alert.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Alert.java new file mode 100644 index 0000000..17ca2b4 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Alert.java @@ -0,0 +1,152 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import com.fastbee.notify.domain.NotifyTemplate; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.List; + +/** + * 设备告警对象 iot_alert + * + * @author kerwincui + * @date 2022-01-13 + */ +@ApiModel(value = "Alert", description = "设备告警实体 iot_alert") +public class Alert extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 告警ID + */ + @ApiModelProperty("告警ID") + private Long alertId; + + /** + * 告警名称 + */ + @ApiModelProperty("告警名称") + @Excel(name = "告警名称") + private String alertName; + + /** + * 告警级别(1=提醒通知,2=轻微问题,3=严重警告) + */ + @ApiModelProperty("告警级别(1=提醒通知,2=轻微问题,3=严重警告)") + @Excel(name = "告警级别", readConverterExp = "1==提醒通知,2=轻微问题,3=严重警告") + private Long alertLevel; + + /** + * 告警状态(1-启动,2-停止) + */ + @Excel(name = "告警状态", readConverterExp = "1=-启动,2-停止") + private Integer status; + + /** + * 通知方式 格式:"1,2,3" + */ + @Excel(name = "通知方式") + private String notify; + + private List scenes; + + private List notifyTemplateList; + + /** 租户id */ + private Long tenantId; + + public Long getTenantId() { + return tenantId; + } + + public void setTenantId(Long tenantId) { + this.tenantId = tenantId; + } + + public String getTenantName() { + return tenantName; + } + + public void setTenantName(String tenantName) { + this.tenantName = tenantName; + } + + /** 租户名称 */ + private String tenantName; + + public List getNotifyTemplateList() { + return notifyTemplateList; + } + + public void setNotifyTemplateList(List notifyTemplateList) { + this.notifyTemplateList = notifyTemplateList; + } + + public List getScenes() { + return scenes; + } + + public void setScenes(List scenes) { + this.scenes = scenes; + } + + public Long getAlertId() { + return alertId; + } + + public void setAlertId(Long alertId) { + this.alertId = alertId; + } + + public String getAlertName() { + return alertName; + } + + public void setAlertName(String alertName) { + this.alertName = alertName; + } + + public Long getAlertLevel() { + return alertLevel; + } + + public void setAlertLevel(Long alertLevel) { + this.alertLevel = alertLevel; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getNotify() { + return notify; + } + + public void setNotify(String notify) { + this.notify = notify; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("alertId", getAlertId()) + .append("alertName", getAlertName()) + .append("alertLevel", getAlertLevel()) + .append("status", getStatus()) + .append("notify", getNotify()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/AlertLog.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/AlertLog.java new file mode 100644 index 0000000..78fe12b --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/AlertLog.java @@ -0,0 +1,73 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 设备告警对象 iot_alert_log + * + * @author kerwincui + * @date 2022-01-13 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "AlertLog", description = "设备告警日志实体 iot_alert_log") +public class AlertLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 告警ID */ + @ApiModelProperty("告警ID") + private Long alertLogId; + + /** 告警名称 */ + @ApiModelProperty("告警名称") + @Excel(name = "告警名称") + private String alertName; + + /** 告警级别(1=提醒通知,2=轻微问题,3=严重警告,4=场景联动) */ + @ApiModelProperty("告警级别(1=提醒通知,2=轻微问题,3=严重警告,4=场景联动)") + @Excel(name = "告警级别", readConverterExp = "1==提醒通知,2=轻微问题,3=严重警告,4=场景联动") + private Long alertLevel; + + /** 处理状态(1=不需要处理,2=未处理,3=已处理) */ + @ApiModelProperty("处理状态(1=不需要处理,2=未处理,3=已处理)") + @Excel(name = "处理状态(1=不需要处理,2=未处理,3=已处理)") + private Integer status; + + /** 产品ID */ + @ApiModelProperty("产品ID") + @Excel(name = "产品ID") + private Long productId; + + /** 设备编号 */ + @ApiModelProperty("设备编号") + private String serialNumber; + + /** 告警详情 */ + @ApiModelProperty("告警详情") + private String detail; + + private Long userId; + + private String deviceName; + + private Long deviceId; + private Long sceneId; + private String sceneName; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date beginTime; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date endTime; + + private Long deptUserId; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/AlertNotifyTemplate.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/AlertNotifyTemplate.java new file mode 100644 index 0000000..beb51ff --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/AlertNotifyTemplate.java @@ -0,0 +1,52 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 告警通知模版关联对象 iot_alert_notify_template + * + * @author kerwincui + * @date 2024-01-29 + */ +public class AlertNotifyTemplate extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 告警id */ + @Excel(name = "告警id") + private Long alertId; + + /** 通知模版id */ + @Excel(name = "通知模版id") + private Long notifyTemplateId; + + public void setAlertId(Long alertId) + { + this.alertId = alertId; + } + + public Long getAlertId() + { + return alertId; + } + public void setNotifyTemplateId(Long notifyTemplateId) + { + this.notifyTemplateId = notifyTemplateId; + } + + public Long getNotifyTemplateId() + { + return notifyTemplateId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("alertId", getAlertId()) + .append("notifyTemplateId", getNotifyTemplateId()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/AlertScene.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/AlertScene.java new file mode 100644 index 0000000..6c87c40 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/AlertScene.java @@ -0,0 +1,42 @@ +package com.maibu.domain; + +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; + +/** + * 设备告警对象 iot_alert_scene + * + * @author kerwincui + * @date 2022-01-13 + */ + +public class AlertScene extends BaseEntity { + + /** + * 告警ID + */ + @ApiModelProperty("告警ID") + private Long alertId; + + /** + * 场景ID + */ + @ApiModelProperty("场景ID") + private Long sceneId; + + public Long getAlertId() { + return alertId; + } + + public void setAlertId(Long alertId) { + this.alertId = alertId; + } + + public Long getSceneId() { + return sceneId; + } + + public void setSceneId(Long sceneId) { + this.sceneId = sceneId; + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Bridge.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Bridge.java new file mode 100644 index 0000000..50b8de2 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Bridge.java @@ -0,0 +1,105 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +/** + * 数据桥接对象 bridge + * + * @author kerwincui + * @date 2024-08-20 + */ + +@ApiModel(value = "Bridge", description = "数据桥接 bridge") +@Data +@TableName("bridge" ) +public class Bridge implements Serializable{ + private static final long serialVersionUID=1L; + + /** id唯一标识 */ + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("id唯一标识") + private Long id; + + /** 桥接配置信息 */ + @ApiModelProperty("桥接配置信息") + private String configJson; + + /** 连接器名称 */ + @ApiModelProperty("连接器名称") + private String name; + + /** 是否生效(0-不生效,1-生效) */ + @ApiModelProperty("是否生效") + private String enable; + + /** 状态(0-未连接,1-连接中) */ + @ApiModelProperty("状态") + private String status; + + /** 桥接类型(3=Http推送,4=Mqtt桥接,5=数据库存储) */ + @ApiModelProperty("桥接类型(3=Http推送,4=Mqtt桥接,5=数据库存储 2=Mqtt外部服务器连接)") + private Integer type; + + /** 桥接方向(1=输入,2=输出) */ + @ApiModelProperty("桥接方向(1=输入,2=输出)") + private Integer direction; + + /** 转发路由(mqtt topic,http url) */ + @ApiModelProperty("转发路由") + private String route; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志") + private String delFlag; + + /** 创建者 */ + @ApiModelProperty("创建者") + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty("创建时间") + private Date createTime; + + /** 更新者 */ + @ApiModelProperty("更新者") + private String updateBy; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty("更新时间") + private Date updateTime; + + /** 备注 */ + @ApiModelProperty("备注") + private String remark; + + @Setter + @TableField(exist = false) + @ApiModelProperty("请求参数") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public Map getParams(){ + if (params == null){ + params = new HashMap<>(); + } + return params; + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Category.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Category.java new file mode 100644 index 0000000..ceb9b4c --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Category.java @@ -0,0 +1,167 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 产品分类对象 iot_category + * + * @author kerwincui + * @date 2021-12-16 + */ +@ApiModel(value = "Category", description = "产品分类对象 iot_category") +public class Category extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 产品分类ID */ + @ApiModelProperty("产品分类ID") + private Long categoryId; + + /** 产品分类名称 */ + @ApiModelProperty("产品分类名称") + @Excel(name = "产品分类名称") + private String categoryName; + + /** 租户ID */ + @ApiModelProperty("租户ID") + @Excel(name = "租户ID") + private Long tenantId; + + /** 租户名称 */ + @ApiModelProperty("租户名称") + @Excel(name = "租户名称") + private String tenantName; + + /** 是否系统通用(0-否,1-是) */ + @ApiModelProperty("是否系统通用(0-否,1-是)") + @Excel(name = "是否系统通用", readConverterExp = "0=-否,1-是") + private Integer isSys; + + /** 显示顺序 */ + @ApiModelProperty("显示顺序") + @Excel(name = "显示顺序") + private Integer orderNum; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志(0代表存在 2代表删除)") + private String delFlag; + + @ApiModelProperty("是否显示上级品类") + private Boolean showSenior; + + @ApiModelProperty("是否是总账号") + private Boolean isAdmin; + + @ApiModelProperty("机构ID") + private Long deptId; + + public Boolean getShowSenior() { + return showSenior; + } + + public void setShowSenior(Boolean showSenior) { + this.showSenior = showSenior; + } + + public Long getDeptId() { + return deptId; + } + + public void setDeptId(Long deptId) { + this.deptId = deptId; + } + + public Boolean getAdmin() { + return isAdmin; + } + + public void setAdmin(Boolean admin) { + isAdmin = admin; + } + + public void setCategoryId(Long categoryId) + { + this.categoryId = categoryId; + } + + public Long getCategoryId() + { + return categoryId; + } + public void setCategoryName(String categoryName) + { + this.categoryName = categoryName; + } + + public String getCategoryName() + { + return categoryName; + } + public void setTenantId(Long tenantId) + { + this.tenantId = tenantId; + } + + public Long getTenantId() + { + return tenantId; + } + public void setTenantName(String tenantName) + { + this.tenantName = tenantName; + } + + public String getTenantName() + { + return tenantName; + } + public void setIsSys(Integer isSys) + { + this.isSys = isSys; + } + public Integer getIsSys() + { + return isSys; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + public Integer getOrderNum() + { + return orderNum; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("categoryId", getCategoryId()) + .append("categoryName", getCategoryName()) + .append("tenantId", getTenantId()) + .append("tenantName", getTenantName()) + .append("isSys", getIsSys()) + .append("orderNum", getOrderNum()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/CommandPreferences.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/CommandPreferences.java new file mode 100644 index 0000000..559d56d --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/CommandPreferences.java @@ -0,0 +1,49 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 指令偏好设置对象 command_preferences + * + * @author kerwincui + * @date 2024-06-29 + */ +@ApiModel(value = "CommandPreferences", description = "指令偏好设置 command_preferences") +@Data +@EqualsAndHashCode(callSuper = true) +public class CommandPreferences extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 指令id + */ + private Long id; + + /** + * 指令名称 + */ + @Excel(name = "指令名称") + @ApiModelProperty("指令名称") + private String name; + + /** + * 指令 + */ + @Excel(name = "指令") + @ApiModelProperty("指令") + private String command; + + /** + * 设备编号 + */ + @Excel(name = "设备编号") + @ApiModelProperty("设备编号") + private String serialNumber; + + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Device.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Device.java new file mode 100644 index 0000000..ec196aa --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Device.java @@ -0,0 +1,285 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.maibu.annotation.Excel; +import com.maibu.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.data.annotation.Transient; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 设备对象 iot_device + * + * @author kerwincui + * @date 2021-12-16 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "Device", description = "设备对象 iot_device") +@JsonInclude(JsonInclude.Include.NON_NULL) +@Data +@TableName("iot_device") +public class Device extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 设备ID + */ + @ApiModelProperty("设备ID") + private Long deviceId; + + /** + * 设备名称 + */ + @ApiModelProperty("设备名称") + @Excel(name = "设备名称") + private String deviceName; + + /** + * 设备别名 + */ + @ApiModelProperty("设备别名") + @Excel(name = "设备别名") + private String deviceAlias; + + /** + * 产品ID + */ + @ApiModelProperty("产品ID") + @Excel(name = "产品ID") + private Long productId; + + /** + * 产品名称 + */ + @ApiModelProperty("产品名称") + @Excel(name = "产品名称") + private String productName; + + + /** + * 租户ID + */ + @ApiModelProperty("租户ID") + @Excel(name = "租户ID") + private Long tenantId; + + /** + * 租户名称 + */ + @ApiModelProperty("租户名称") + @Excel(name = "租户名称") + private String tenantName; + + /** + * 设备编号 + */ + @ApiModelProperty("设备编号") + @Excel(name = "设备编号") + private String serialNumber; + + /** + * 固件版本 + */ + @ApiModelProperty("固件版本") + @Excel(name = "固件版本") + private BigDecimal firmwareVersion; + + + /** + * WIFI固件版本 + */ + @ApiModelProperty("HTTP推送固件版本") + @Excel(name = "HTTP推送固件版本") + private BigDecimal wirelessVersion; + + /** + * 设备类型(1-直连设备、2-网关设备、3-监控设备) + */ + @ApiModelProperty("设备类型(1-直连设备、2-网关设备、3-监控设备 4-网关子设备)") + private Integer deviceType; + + /** + * 设备状态(1-未激活,2-禁用,3-在线,4-离线) + */ + @ApiModelProperty("设备状态(1-未激活,2-禁用,3-在线,4-离线)") + @Excel(name = "设备状态") + private Integer status; + + /** + * 设备在线状态(1-在线,2-离线) + */ + @ApiModelProperty("设备状态(1-在线,2-离线)") + @Excel(name = "设备在线状态") + private Integer onlineStatus; + + @TableField(exist = false) + private Integer feStatus; //前端大屏显示 1任务中/2空闲/3离线 + + /** + * wifi信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85]) + */ + @ApiModelProperty("wifi信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85])") + @Excel(name = "wifi信号强度") + private Integer rssi; + + /** + * 设备影子 + */ + @ApiModelProperty("是否启用设备影子(0=禁用,1=启用)") + private Integer isShadow; + + /** + * 设备所在地址 + */ + @ApiModelProperty("设备所在地址") + @Excel(name = "设备所在地址") + private String networkAddress; + + /** + * 设备入网IP + */ + @ApiModelProperty("设备入网IP") + @Excel(name = "设备入网IP") + private String networkIp; + + /** + * 设备经度 + */ + @ApiModelProperty("设备经度") + @Excel(name = "设备经度") + private BigDecimal longitude; + + /** + * 设备纬度 + */ + @ApiModelProperty("设备纬度") + @Excel(name = "设备纬度") + private BigDecimal latitude; + + /** + * 激活时间 + */ + @ApiModelProperty("激活时间") + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "激活时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date activeTime; + + /** + * 子设备网关编号 + */ + @ApiModelProperty("子设备网关编号") + @Excel(name = "网关设备编号(子设备使用)") + private String gwDevCode; + + /** + * 物模型值 + */ + @ApiModelProperty("物模型值") + @Excel(name = "物模型") + private String thingsModelValue; + + /** + * 图片地址 + */ + @ApiModelProperty("图片地址") + private String imgUrl; + + /** + * 是否自定义位置 + **/ + @ApiModelProperty("定位方式(1=ip自动定位,2=设备定位,3=自定义)") + private Integer locationWay; + + /** + * 设备摘要 + **/ + @ApiModelProperty("设备摘要") + private String summary; + + /** + * 分组ID,用于分组查询 + **/ + @ApiModelProperty("分组ID,用于分组查询") + private Long groupId; + + /** + * 是否设备所有者,用于查询 + **/ + @ApiModelProperty("是否设备所有者,用于查询") + private Integer isOwner; + /** + * 子设备数量 + */ + @ApiModelProperty("子设备数量") + private Integer subDeviceCount; + /** + * 是否是模拟设备 + */ + @ApiModelProperty("是否是模拟设备") + private Integer isSimulate; + /** + * 子设备地址 + */ + @ApiModelProperty("子设备地址") + private Integer slaveId; + /** + * 设备传输协议 + */ + @ApiModelProperty("设备传输协议") + private String transport; + + @Transient + @ApiModelProperty("机构id") + private Long deptId; + + @Transient + @ApiModelProperty("是否显示下级") + private Boolean showChild; + + private List subDeviceList; + + /** + * 删除标志(0代表存在 2代表删除) + */ + @ApiModelProperty("删除标志") + private String delFlag; + + @Transient + @ApiModelProperty("用户id") + private Long userId; + + /** + * 协议 + */ + private String protocolCode; + + /** + * 关联组态,来源产品 + */ + private String guid; + + private List sipRelationList; + + /** + * 是否可以配置轮询 + */ + private Boolean canConfigPoll = false; + + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + @TableField(exist = false) + private DeviceRunningStatusHistory lastRunningStatus; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceAlertUser.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceAlertUser.java new file mode 100644 index 0000000..a69f8d3 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceAlertUser.java @@ -0,0 +1,25 @@ +package com.maibu.domain; + +import lombok.Data; + +/** + * 设备告警用户对象 iot_device_alert_user + * + * @author kerwincui + * @date 2024-05-15 + */ +@Data +public class DeviceAlertUser +{ + + /** 设备id */ + private Long deviceId; + + /** 用户id */ + private Long userId; + + private String userName; + + private String phoneNumber; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceGroup.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceGroup.java new file mode 100644 index 0000000..a540c93 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceGroup.java @@ -0,0 +1,42 @@ +package com.maibu.domain; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * 设备分组对象 iot_device_group + * + * @author kerwincui + * @date 2021-12-16 + */ +@ApiModel(value = "DeviceGroup", description = "设备分组对象 iot_device_group") +public class DeviceGroup +{ + private static final long serialVersionUID = 1L; + + /** 分组ID */ + @ApiModelProperty("分组ID") + private Long groupId; + + /** 设备ID */ + @ApiModelProperty("设备ID") + private Long deviceId; + + public Long getGroupId() { + return groupId; + } + + public void setGroupId(Long groupId) { + this.groupId = groupId; + } + + public Long getDeviceId() { + return deviceId; + } + + public void setDeviceId(Long deviceId) { + this.deviceId = deviceId; + } + + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceJob.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceJob.java new file mode 100644 index 0000000..45a650c --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceJob.java @@ -0,0 +1,325 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.annotation.Excel.ColumnType; +import com.fastbee.common.constant.ScheduleConstants; +import com.fastbee.common.core.domain.BaseEntity; +import com.fastbee.common.utils.StringUtils; +import com.fastbee.quartz.util.CronUtils; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.util.Date; + +/** + * 设备定时任务 + * + * @author kerwincui + */ +@ApiModel(value = "DeviceJob", description = "设备定时任务 iot_device_job") +public class DeviceJob extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 任务ID */ + @ApiModelProperty("任务ID") + @Excel(name = "任务序号", cellType = ColumnType.NUMERIC) + private Long jobId; + + /** 任务名称 */ + @ApiModelProperty("任务名称") + @Excel(name = "任务名称") + private String jobName; + + /** 设备编号 */ + @ApiModelProperty("设备编号") + @Excel(name = "设备编号") + private String serialNumber; + + /** 设备id */ + @ApiModelProperty("设备id") + private Long deviceId; + + /** 设备名称 */ + @ApiModelProperty("设备名称") + private String deviceName; + + /** 执行动作 */ + @ApiModelProperty("执行动作") + private String actions; + + /** 告警触发器 */ + @ApiModelProperty("告警触发器") + private String alertTrigger; + + /** 任务组名 */ + @ApiModelProperty("任务组名") + @Excel(name = "任务组名") + private String jobGroup; + + /** cron执行表达式 */ + @ApiModelProperty("cron执行表达式") + @Excel(name = "执行表达式 ") + private String cronExpression; + + /** cron计划策略 */ + @ApiModelProperty(value = "cron执行表达式", notes = "0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行") + @Excel(name = "计划策略 ", readConverterExp = "0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行") + private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT; + + /** 是否并发执行(0允许 1禁止) */ + @ApiModelProperty(value = "是否并发执行", notes = "0=允许,1=禁止") + @Excel(name = "并发执行", readConverterExp = "0=允许,1=禁止") + private String concurrent; + + /** 任务状态(0正常 1暂停) */ + @ApiModelProperty("任务状态(0正常 1暂停)") + @Excel(name = "任务状态", readConverterExp = "0=正常,1=暂停") + private String status; + + /** 是否详细corn表达式 */ + @ApiModelProperty("是否详细corn表达式") + private Integer isAdvance; + + /** 定时类型(1=设备定时,2=设备告警,3=场景联动) */ + @ApiModelProperty(value = "定时类型", notes = "(1=设备定时,2=设备告警,3=场景联动)") + @Excel(name = "定时类型", readConverterExp = "1==设备定时,2=设备告警,3=场景联动") + private Integer jobType; + + /** 产品ID */ + @ApiModelProperty("产品ID") + @Excel(name = "产品ID") + private Long productId; + + /** 产品名称 */ + @ApiModelProperty("产品名称") + @Excel(name = "产品名称") + private String productName; + + /** 场景联动ID */ + @ApiModelProperty("场景联动ID") + @Excel(name = "场景联动ID") + private Long sceneId; + + /** 告警ID */ + @ApiModelProperty("告警ID") + @Excel(name = "告警ID") + private Long alertId; + + /** + * 执行其他模块主键ID + * 通过jobType区分 + * */ + @ApiModelProperty("执行其他模块主键ID") + @Excel(name = "执行其他模块主键ID") + private Long datasourceId; + + + public Long getDatasourceId() { + return datasourceId; + } + + public void setDatasourceId(Long datasourceId) { + this.datasourceId = datasourceId; + } + + public String getAlertTrigger() { + return alertTrigger; + } + + public void setAlertTrigger(String alertTrigger) { + this.alertTrigger = alertTrigger; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getSerialNumber() { + return serialNumber; + } + + public void setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; + } + + public Integer getIsAdvance() { + return isAdvance; + } + + public void setIsAdvance(Integer isAdvance) { + this.isAdvance = isAdvance; + } + + public Integer getJobType() { + return jobType; + } + + public void setJobType(Integer jobType) { + this.jobType = jobType; + } + + public Long getProductId() { + return productId; + } + + public void setProductId(Long productId) { + this.productId = productId; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public Long getSceneId() { + return sceneId; + } + + public void setSceneId(Long sceneId) { + this.sceneId = sceneId; + } + + public Long getAlertId() { + return alertId; + } + + public void setAlertId(Long alertId) { + this.alertId = alertId; + } + + public Long getJobId() + { + return jobId; + } + + public void setJobId(Long jobId) + { + this.jobId = jobId; + } + + @NotBlank(message = "任务名称不能为空") + @Size(min = 0, max = 64, message = "任务名称不能超过64个字符") + public String getJobName() + { + return jobName; + } + + public void setJobName(String jobName) + { + this.jobName = jobName; + } + + public String getJobGroup() + { + return jobGroup; + } + + public void setJobGroup(String jobGroup) + { + this.jobGroup = jobGroup; + } + + public Long getDeviceId() { + return deviceId; + } + + public void setDeviceId(Long deviceId) { + this.deviceId = deviceId; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public String getActions() { + return actions; + } + + public void setActions(String actions) { + this.actions = actions; + } + + @NotBlank(message = "Cron执行表达式不能为空") + @Size(min = 0, max = 255, message = "Cron执行表达式不能超过255个字符") + public String getCronExpression() + { + return cronExpression; + } + + public void setCronExpression(String cronExpression) + { + this.cronExpression = cronExpression; + } + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + public Date getNextValidTime() + { + if (StringUtils.isNotEmpty(cronExpression)) + { + return CronUtils.getNextExecution(cronExpression); + } + return null; + } + + public String getMisfirePolicy() + { + return misfirePolicy; + } + + public void setMisfirePolicy(String misfirePolicy) + { + this.misfirePolicy = misfirePolicy; + } + + public String getConcurrent() + { + return concurrent; + } + + public void setConcurrent(String concurrent) + { + this.concurrent = concurrent; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("jobId", getJobId()) + .append("jobName", getJobName()) + .append("jobGroup", getJobGroup()) + .append("cronExpression", getCronExpression()) + .append("nextValidTime", getNextValidTime()) + .append("misfirePolicy", getMisfirePolicy()) + .append("concurrent", getConcurrent()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceLog.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceLog.java new file mode 100644 index 0000000..a603b3e --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceLog.java @@ -0,0 +1,256 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 设备日志对象 iot_device_log + * + * @author kerwincui + * @date 2022-01-13 + */ + +@ApiModel(value = "DeviceLog", description = "设备日志对象 iot_device_log") +@JsonInclude(JsonInclude.Include.NON_NULL) +@Data +@EqualsAndHashCode(callSuper = true) +public class DeviceLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + @Excel(name = "时间戳") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date ts; + /** 设备日志ID */ + @ApiModelProperty("设备日志ID") + private Long logId; + + /** 类型(1=属性上报,2=事件上报,3=调用功能,4=设备升级,5=设备上线,6=设备离线,7=运算数据上报) */ + @ApiModelProperty(value = "类型", notes = "1=属性上报,2=事件上报,3=调用功能,4=设备升级,5=设备上线,6=设备离线,7=运算数据上报") + @Excel(name = "类型", readConverterExp = "1=属性上报,2=事件上报,3=调用功能,4=设备升级,5=设备上线,6=设备离线,7=运算数据上报") + private Integer logType; + + /** 日志值 */ + @ApiModelProperty("日志值") + @Excel(name = "日志值") + private String logValue; + + /** 物模型名称 */ + @ApiModelProperty("物模型名称") + @Excel(name = "物模型名称") + private String modelName; + + /** 设备ID */ + @ApiModelProperty("设备ID") + @Excel(name = "设备ID") + private Long deviceId; + + /** 设备名称 */ + @ApiModelProperty("设备名称") + @Excel(name = "设备名称") + private String deviceName; + + /** 设备编号 */ + @ApiModelProperty("设备编号") + @Excel(name = "设备编号") + private String serialNumber; + + /** 标识符 */ + @ApiModelProperty("标识符") + @Excel(name = "标识符") + private String identity; + + /** 是否监测数据(1=是,0=否) */ + @ApiModelProperty("是否监测数据(1=是,0=否)") + @Excel(name = "是否监测数据", readConverterExp = "1=是,0=否") + private Integer isMonitor; + + /** 模式 */ + @ApiModelProperty(value = "模式", notes = "1=影子模式,2=在线模式,3=其他") + @Excel(name = "模式", readConverterExp = "1=影子模式,2=在线模式,3=其他") + private Integer mode; + + /** 用户ID */ + @ApiModelProperty("用户ID") + @Excel(name = "用户ID") + private Long userId; + + /** 用户昵称 */ + @ApiModelProperty("用户昵称") + @Excel(name = "用户昵称") + private String userName; + + /** 租户ID */ + @ApiModelProperty("租户ID") + @Excel(name = "租户ID") + private Long tenantId; + + /** 租户名称 */ + @ApiModelProperty("租户名称") + @Excel(name = "租户名称") + private String tenantName; + + /** 查询用的开始时间 */ + @ApiModelProperty("查询用的开始时间") + private String beginTime; + + /** 查询用的结束时间 */ + @ApiModelProperty("查询用的结束时间") + private String endTime; + + /** 查询的总数 */ + @ApiModelProperty("查询的总数") + private int total; + + /*消息ID,或消息流水号*/ + @ApiModelProperty("消息ID,或消息流水号") + private String serNo; + + private String specs; + + private DataType dataType; + + private Integer slaveId; + /** + * 计算公式 + */ + private String formula; + + private Integer isParams; + + /*是否历史存储*/ + private Integer isHistory; + + private Integer operation; + + + private List identityList; + + + @ApiModel + public static class DataType{ + private String type; + private String falseText; + private String trueText; + private Integer maxLength; + private String arrayType; + private String unit; + private BigDecimal min; + private BigDecimal max; + private BigDecimal step; + private List enumList; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getFalseText() { + return falseText; + } + + public void setFalseText(String falseText) { + this.falseText = falseText; + } + + public String getTrueText() { + return trueText; + } + + public void setTrueText(String trueText) { + this.trueText = trueText; + } + + public Integer getMaxLength() { + return maxLength; + } + + public void setMaxLength(Integer maxLength) { + this.maxLength = maxLength; + } + + public String getArrayType() { + return arrayType; + } + + public void setArrayType(String arrayType) { + this.arrayType = arrayType; + } + + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + + public BigDecimal getMin() { + return min; + } + + public void setMin(BigDecimal min) { + this.min = min; + } + + public BigDecimal getMax() { + return max; + } + + public void setMax(BigDecimal max) { + this.max = max; + } + + public BigDecimal getStep() { + return step; + } + + public void setStep(BigDecimal step) { + this.step = step; + } + + public List getEnumList() { + return enumList; + } + + public void setEnumList(List enumList) { + this.enumList = enumList; + } + } + + @ApiModel + public static class EnumItem + { + private String text; + private String value; + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DevicePlan.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DevicePlan.java new file mode 100644 index 0000000..228cd81 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DevicePlan.java @@ -0,0 +1,55 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.fastbee.iot.enums.DeviceTaskStaus; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@TableName(value = "iot_device_plan", autoResultMap = true) +public class DevicePlan { + + @TableId(type = IdType.AUTO) + private Long id; + + private String deviceId; + + @TableField(exist = false) + private String deviceAlias; + + @TableField(exist = false) + private String taskStausTranslate; //任务状态 + + private String planName; + + private DeviceTaskStaus taskStaus; //任务状态 + + private Long routeId; // 线路id + + private Long userId; // 用户id + + @TableField(typeHandler = JacksonTypeHandler.class) + private DeviceTaskPlanRule deviceTaskPlanRules; //计划 + + private LocalDateTime createTime; + + private String createBy; + + private LocalDateTime updateTime; + + private String updateBy; + + private LocalDateTime finishTime; + + private LocalDateTime startTime; //开始时间 时分秒 + + private int delFlag = 0; //删除状态 1删除 + + @TableField(exist = false) + private boolean dayTriggerFlag = false; //当天的任务是否已经生成 +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DevicePlanTask.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DevicePlanTask.java new file mode 100644 index 0000000..89fd7c9 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DevicePlanTask.java @@ -0,0 +1,38 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fastbee.iot.enums.DeviceTaskStaus; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@TableName("iot_device_task") +public class DevicePlanTask { + + @TableId(type = IdType.AUTO) + private Long id; + + private Long planId; //归属于某个计划任务 + + private String deviceId; + + private DeviceTaskStaus taskStaus; //任务状态 + + @TableField(exist = false) + private String taskStausTranslate; //任务状态 + + private Long routeId; // 线路id + + private LocalDateTime finishTime; + + private LocalDateTime startTime; //开始时间 时分秒 + + private LocalDateTime createTime; //创建时间 + + private String taskType; //任务类型分类 + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceRecord.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceRecord.java new file mode 100644 index 0000000..996b5cf --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceRecord.java @@ -0,0 +1,93 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + * 设备记录对象 iot_device_record + * + * @author zhangzhiyi + * @date 2024-07-16 + */ +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("iot_device_record") +public class DeviceRecord extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 主键id */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** 操作者机构id */ + @Excel(name = "操作者机构id") + private Long operateDeptId; + + /** 目标机构id */ + @Excel(name = "目标机构id") + private Long targetDeptId; + + /** 产品id */ + @Excel(name = "产品id") + private Long productId; + + /** 设备id */ + @Excel(name = "设备id") + private Long deviceId; + + /** 设备记录类型(1-导入记录;2-回收记录;3-分配记录;4-分配详细记录) */ + @Excel(name = "设备记录类型", readConverterExp = "1=-导入记录;2-回收记录;3-分配记录;4-分配详细记录") + private Integer type; + + /** 分配类型(1-选择分配;2-导入分配) */ + @Excel(name = "分配类型", readConverterExp = "1=-选择分配;2-导入分配") + private Integer distributeType; + + /** 总数 */ + @Excel(name = "总数") + private Integer total; + + /** 成功数量 */ + @Excel(name = "成功数量") + private Integer successQuantity; + + /** 失败数量 */ + @Excel(name = "失败数量") + private Integer failQuantity; + + /** 状态 */ + @Excel(name = "状态") + private Integer status; + + /** 租户id */ + @Excel(name = "租户id") + private Long tenantId; + + /** 租户名称 */ + @Excel(name = "租户名称") + private String tenantName; + + /** 逻辑删除标识 */ + private Integer delFlag; + + /** 设备编号 */ + @Excel(name = "设备编号") + private String serialNumber; + + /** 父id */ + @Excel(name = "父id") + private Long parentId; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceRunStatistics.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceRunStatistics.java new file mode 100644 index 0000000..fed300f --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceRunStatistics.java @@ -0,0 +1,32 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + + +@Data +@TableName(" iot_device_run_statistics" ) +public class DeviceRunStatistics implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.AUTO) + private Long id; + + private LocalDateTime startTime; + + private LocalDateTime endTime; + + private Double workArea; //作业面积 + + private Double distance; //作业距离 + + private Long time; //时长 分钟 + + private String deviceId; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceRunningStatusHistory.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceRunningStatusHistory.java new file mode 100644 index 0000000..2496def --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceRunningStatusHistory.java @@ -0,0 +1,69 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("iot_device_running_status_history") +public class DeviceRunningStatusHistory implements Serializable { + @TableId(type = IdType.AUTO) + private Long id; + + private String deviceId; + + private String voltage; //电压 + + private String leftTargetSpeed; // 左轮目标速度 + + private String rightTargetSpeed;// 右轮目标速度 + + private String leftMeasureSpeed;// 左轮测量速度 + + private String rightMeasureSpeed;// 右轮测量速度 + + private String leftCurrent;// 左轮电流 + + private String rightCurrent;// 右轮电流 + + private String leftMotorTemp;// 左轮温度 + + private String rightMotorTemp;// 右轮温度 + + private String chipTemp;//芯片温度 + + private String yaw;//偏航角 + + private String pitch;//仰俯角 + + private String roll;//翻滚角 + + private String satelliteCnt;//跟踪的卫星数 + + private String qual;//定位质量 + + private String headingStatus;//航向角状态 + + private String latitude;//纬度 + + private String longitude;//经度 + + private Date time; + + private String cuttingSpeed;//割刀速度 + + private String controlMode;//控制模式 + + private String battery;//电池电量 + + private String workingArea;//作业面积 + + private String obstacleSign;//障碍物标志位 + + private Date createTime; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceShare.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceShare.java new file mode 100644 index 0000000..37ad6ad --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceShare.java @@ -0,0 +1,46 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.data.annotation.Transient; + +/** + * 设备分享对象 iot_device_share + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +public class DeviceShare extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 设备id */ + @ApiModelProperty("设备ID") + private Long deviceId; + + /** 用户id */ + private Long userId; + + /** 手机 */ + @Excel(name = "手机") + private String phonenumber; + + /** 用户物模型权限,多个以英文逗号分隔 */ + @Excel(name = "用户物模型权限,多个以英文逗号分隔") + private String perms; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + @Transient + @ApiModelProperty("标识是否是拥有者") + private Integer isOwner; + + @Transient + private String userName; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceStatusRecordDTO.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceStatusRecordDTO.java new file mode 100644 index 0000000..fac9376 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceStatusRecordDTO.java @@ -0,0 +1,11 @@ +package com.maibu.domain; + +import lombok.Data; + +import java.util.List; + +@Data +public class DeviceStatusRecordDTO { + private List histories; + private long lastRecordTime; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceTaskPlanRule.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceTaskPlanRule.java new file mode 100644 index 0000000..c957ff1 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceTaskPlanRule.java @@ -0,0 +1,27 @@ +package com.maibu.domain; + +import com.fastbee.iot.enums.DeviceTaskPlanRepeatType; +import lombok.Data; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.util.List; + +@Data +public class DeviceTaskPlanRule { + + private DeviceTaskPlanRepeatType type; //类型 天 周 月 + + private String startDate; //开始日期 年月 + + private String dayTime; //时分秒 + + private List dayOfMonth; //月某天 + + private LocalDate endTime; //结束时间 时分秒 + + private List days; //星期 + + private List daysTranslate; //星期翻译 + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceUser.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceUser.java new file mode 100644 index 0000000..4b12656 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/DeviceUser.java @@ -0,0 +1,44 @@ +package com.maibu.domain; + +import com.fastbee.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.data.annotation.Transient; + +/** + * 设备用户对象 iot_device_user + * + * @author kerwincui + * @date 2021-12-16 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "DeviceUser", description = "设备用户对象 iot_device_user") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DeviceUser extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 固件ID */ + @ApiModelProperty("设备ID") + private Long deviceId; + + /** 用户ID */ + @ApiModelProperty("用户ID") + private Long userId; + + /** 手机号码 */ + @ApiModelProperty("手机号码") + private String phonenumber; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志(0代表存在 2代表删除)") + private String delFlag; + + @Transient + private String userName; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/EventLog.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/EventLog.java new file mode 100644 index 0000000..4ad9aa5 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/EventLog.java @@ -0,0 +1,171 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 事件日志对象 iot_event_log + * + * @author kerwincui + * @date 2024-08-16 + */ + +@ApiModel(value = "EventLog" , description = "事件日志 iot_event_log" ) +@Data +@TableName("iot_event_log" ) +public class EventLog { + private static final long serialVersionUID = 1L; + + + /** + * 设备事件日志ID + */ + @TableId(value = "log_id" , type = IdType.AUTO) + private Long logId; + + + /** + * 标识符 + */ + @ApiModelProperty("标识符" ) + private String identity; + + + /** + * 物模型名称 + */ + @ApiModelProperty("物模型名称" ) + private String modelName; + + + /** + * 类型(3=事件上报,5=设备上线,6=设备离线) + */ + @ApiModelProperty("类型" ) + private Integer logType; + + + /** + * 日志值 + */ + @ApiModelProperty("日志值" ) + private String logValue; + + + /** + * 设备ID + */ + @ApiModelProperty("设备ID" ) + private Long deviceId; + + + /** + * 设备名称 + */ + @ApiModelProperty("设备名称" ) + private String deviceName; + + + /** + * 设备编号 + */ + @ApiModelProperty("设备编号" ) + private String serialNumber; + + + /** + * 是否监测数据(1=是,0=否) + */ + @ApiModelProperty("是否监测数据" ) + private Integer isMonitor; + + + /** + * 模式(1=影子模式,2=在线模式,3=其他) + */ + @ApiModelProperty("模式(1=影子模式,2=在线模式,3=其他)" ) + private Integer mode; + + + /** + * 用户ID + */ + @ApiModelProperty("用户ID" ) + private Long userId; + + + /** + * 用户昵称 + */ + @ApiModelProperty("用户昵称" ) + private String userName; + + + /** + * 租户ID + */ + @ApiModelProperty("租户ID" ) + private Long tenantId; + + + /** + * 租户名称 + */ + @ApiModelProperty("租户名称" ) + private String tenantName; + + + /** + * 创建者 + */ + private String createBy; + + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + + /** + * 备注 + */ + @ApiModelProperty("备注" ) + private String remark; + + @TableField(exist = false) + private List identityList; + + + @TableField(exist = false) + @ApiModelProperty("请求参数") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public Map getParams() + { + if (params == null) + { + params = new HashMap<>(); + } + return params; + } + + public void setParams(Map params) + { + this.params = params; + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Firmware.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Firmware.java new file mode 100644 index 0000000..73577da --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Firmware.java @@ -0,0 +1,141 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 产品固件对象 iot_firmware + * + * @author kerwincui + * @date 2024-08-18 + */ + +@ApiModel(value = "Firmware" , description = "产品固件 iot_firmware" ) +@Data +@TableName("iot_firmware" ) +public class Firmware { +private static final long serialVersionUID=1L; + + + /** 固件ID */ + @TableId(value = "firmware_id", type = IdType.AUTO) + @ApiModelProperty("固件ID" ) + private Long firmwareId; + + + /** 固件名称 */ + @ApiModelProperty("固件名称" ) + private String firmwareName; + + + /** 1,二进制包升级2.http升级 */ + @ApiModelProperty("1,二进制包升级2.http升级" ) + private Integer firmwareType; + + + /** 产品ID */ + @ApiModelProperty("产品ID" ) + private Long productId; + + + /** 产品名称 */ + @ApiModelProperty("产品名称" ) + private String productName; + + + /** 租户ID */ + @ApiModelProperty("租户ID" ) + private Long tenantId; + + + /** 租户名称 */ + @ApiModelProperty("租户名称" ) + private String tenantName; + + + /** 是否系统通用(0-否,1-是) */ + @ApiModelProperty("是否系统通用" ) + private Integer isSys; + + + /** 是否最新版本(0-否,1-是) */ + @ApiModelProperty("是否最新版本" ) + private Integer isLatest; + + + /** 固件版本 */ + @ApiModelProperty("固件版本" ) + private BigDecimal version; + + + /** 分包字节大小 */ + @ApiModelProperty("分包字节大小" ) + private Integer byteSize; + + + /** 文件路径 */ + @ApiModelProperty("文件路径" ) + private String filePath; + + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志" ) + private String delFlag; + + + /** 创建者 */ + @ApiModelProperty("创建者" ) + private String createBy; + + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd" ) + @ApiModelProperty("创建时间" ) + private Date createTime; + + + /** 更新者 */ + @ApiModelProperty("更新者" ) + private String updateBy; + + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd" ) + @ApiModelProperty("更新时间" ) + private Date updateTime; + + + /** 备注 */ + @ApiModelProperty("备注" ) + private String remark; + + @TableField(exist = false) + @ApiModelProperty("请求参数") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public Map getParams(){ + if (params == null){ + params = new HashMap<>(); + } + return params; + } + + public void setParams(Map params){ + this.params = params; + } + + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/FirmwareTask.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/FirmwareTask.java new file mode 100644 index 0000000..0a079ed --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/FirmwareTask.java @@ -0,0 +1,102 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 固件升级任务对象对象 iot_firmware_task + * + * @author kerwincui + * @date 2024-08-18 + */ + +@ApiModel(value = "FirmwareTask" , description = "固件升级任务对象 iot_firmware_task" ) +@Data +@TableName("iot_firmware_task" ) +public class FirmwareTask { +private static final long serialVersionUID=1L; + + + + /** 主键 */ + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("主键" ) + private Long id; + + + /** 任务名称 */ + @ApiModelProperty("任务名称" ) + private String taskName; + + + /** 关联固件ID */ + @ApiModelProperty("关联固件ID" ) + private Long firmwareId; + + + /** 1:指定设备 2:产品级别 */ + @ApiModelProperty("1:指定设备 2:产品级别" ) + private Long upgradeType; + + + /** $column.columnComment */ + @ApiModelProperty("${comment}" ) + private String taskDesc; + + + /** 选中的设备总数 */ + @ApiModelProperty("选中的设备总数" ) + private Long deviceAmount; + + + /** $column.columnComment */ + @ApiModelProperty("${comment}" ) + private Long delFlag; + + + /** $column.columnComment */ + @ApiModelProperty("${comment}" ) + @JsonFormat(pattern = "yyyy-MM-dd" ) + private Date updateTime; + + + /** $column.columnComment */ + @ApiModelProperty("${comment}" ) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" ) + private Date createTime; + + + /** 预定时间升级 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" ) + @ApiModelProperty("预定时间升级" ) + private Date bookTime; + + @TableField(exist = false) + @ApiModelProperty("请求参数") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public Map getParams(){ + if (params == null){ + params = new HashMap<>(); + } + return params; + } + + public void setParams(Map params){ + this.params = params; + } + + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/FirmwareTaskDetail.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/FirmwareTaskDetail.java new file mode 100644 index 0000000..1a0e6d8 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/FirmwareTaskDetail.java @@ -0,0 +1,91 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 固件升级任务详细对象对象 iot_firmware_task_detail + * + * @author kerwincui + * @date 2024-08-18 + */ + +@ApiModel(value = "FirmwareTaskDetail" , description = "固件升级任务详细对象 iot_firmware_task_detail" ) +@Data +@TableName("iot_firmware_task_detail" ) +public class FirmwareTaskDetail { +private static final long serialVersionUID=1L; + + + + /** 主键 */ + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("主键" ) + private Long id; + + + /** $column.columnComment */ + @ApiModelProperty("${comment}" ) + private Long taskId; + + + /** 设备编码 */ + @ApiModelProperty("设备编码" ) + private String serialNumber; + + + /** 0:等待升级 1:已发送设备 2:设备收到 3:升级成功 4:升级失败 */ + @ApiModelProperty("0:等待升级 1:已发送设备 2:设备收到 3:升级成功 4:升级失败" ) + private Integer upgradeStatus; + + + /** 描述 */ + @ApiModelProperty("描述" ) + private String detailMsg; + + + /** $column.columnComment */ + @ApiModelProperty("${comment}" ) + @JsonFormat(pattern = "yyyy-MM-dd" ) + private Date createTime; + + + /** 消息ID */ + @ApiModelProperty("消息ID" ) + private String messageId; + + + /** $column.columnComment */ + @ApiModelProperty("${comment}" ) + @JsonFormat(pattern = "yyyy-MM-dd" ) + private Date updateTime; + + @TableField(exist = false) + @ApiModelProperty("请求参数") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public Map getParams(){ + if (params == null){ + params = new HashMap<>(); + } + return params; + } + + public void setParams(Map params){ + this.params = params; + } + + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/FunctionLog.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/FunctionLog.java new file mode 100644 index 0000000..1ffd168 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/FunctionLog.java @@ -0,0 +1,117 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; +import java.util.List; + +/** + * 设备服务下发日志对象 iot_function_log + * + * @author kerwincui + * @date 2022-10-22 + */ +@ApiModel(value = "FunctionLog", description = "设备服务下发日志对象 iot_function_log") +@Data +public class FunctionLog +{ + private static final long serialVersionUID = 1L; + + /** 设备日志ID */ + @ApiModelProperty("设备日志ID") + private Long id; + + /** 标识符 */ + @ApiModelProperty("标识符") + @Excel(name = "标识符") + private String identify; + + /** 仅用于查询时筛选条件 */ + private String prefixIdentify; + + @ApiModelProperty("物模型名称") + private String modelName; + + + /** 类型(1=服务下发,2=属性获取,3.OTA升级) */ + @ApiModelProperty(value = "类型", notes = "(1=服务下发,2=属性获取,3.OTA升级,4=场景变量下发)") + @Excel(name = "类型", readConverterExp = "1==服务下发,2=属性获取,3.OTA升级,4=场景变量下发") + private Integer funType; + + /** 日志值 */ + @ApiModelProperty("日志值") + @Excel(name = "日志值") + private String funValue; + /** + * 显示值 + */ + @ApiModelProperty("显示值") + private String showValue; + + /** 消息id */ + @ApiModelProperty("消息id") + @Excel(name = "消息id") + private String messageId; + + /** 设备名称 */ + @ApiModelProperty("设备名称") + @Excel(name = "设备名称") + private String deviceName; + + /** 设备编号 */ + @ApiModelProperty("设备编号") + @Excel(name = "设备编号") + private String serialNumber; + + /** 模式(1=影子模式,2=在线模式,3=其他) */ + @ApiModelProperty(value = "模式", notes = "(1=影子模式,2=在线模式,3=其他)") + @Excel(name = "模式(1=影子模式,2=在线模式,3=其他)") + private Integer mode; + + /** 用户ID */ + @ApiModelProperty("用户ID") + @Excel(name = "用户ID") + private Long userId; + + /** 下发结果描述 */ + @ApiModelProperty("下发结果描述") + @Excel(name = "下发结果描述") + private String resultMsg; + + /** 下发结果代码 */ + @ApiModelProperty("下发结果代码") + @Excel(name = "下发结果代码") + private Integer resultCode; + + /** + * 设备回复时间 + */ + @ApiModelProperty("设备回复时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date replyTime; + + /** 创建者 */ + @ApiModelProperty("创建者") + private String createBy; + + /** 创建时间 */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date beginTime; + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date endTime; + private List list; + /** 备注 */ + private String remark; + + private List identifyList; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/GoviewProject.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/GoviewProject.java new file mode 100644 index 0000000..d902082 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/GoviewProject.java @@ -0,0 +1,139 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 项目对象 iot_goview_project + * + * @author kami + * @date 2022-10-27 + */ +@ApiModel(value = "GoviewProject", description = "项目对象 iot_goview_project") +public class GoviewProject extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 主键 */ + @ApiModelProperty("主键ID") + private String id; + + /** 项目名称 */ + @ApiModelProperty("项目名称") + @Excel(name = "项目名称") + private String projectName; + + /** 项目状态[-1未发布,1发布] */ + @ApiModelProperty(value = "项目状态", notes = "[-1未发布,1发布]") + @Excel(name = "项目状态[0未发布,1发布]") + private Integer state; + + /** 删除状态[1删除,-1未删除] */ + @ApiModelProperty("删除状态") + private Long delFlag; + + /** 首页图片 */ + @ApiModelProperty("首页图片") + @Excel(name = "首页图片") + private String indexImage; + + /** 项目介绍 */ + @ApiModelProperty("项目介绍") + @Excel(name = "项目介绍") + private String remarks; + + /** 租户id */ + private Long tenantId; + + /** 租户名称 */ + private String tenantName; + + public Long getTenantId() { + return tenantId; + } + + public void setTenantId(Long tenantId) { + this.tenantId = tenantId; + } + + public String getTenantName() { + return tenantName; + } + + public void setTenantName(String tenantName) { + this.tenantName = tenantName; + } + + public void setId(String id) + { + this.id = id; + } + + public String getId() + { + return id; + } + public void setProjectName(String projectName) + { + this.projectName = projectName; + } + + public String getProjectName() + { + return projectName; + } + public void setState(Integer state) + { + this.state = state; + } + + public Integer getState() + { + return state; + } + public void setDelFlag(Long delFlag) + { + this.delFlag = delFlag; + } + + public Long getDelFlag() + { + return delFlag; + } + public void setIndexImage(String indexImage) + { + this.indexImage = indexImage; + } + + public String getIndexImage() + { + return indexImage; + } + public void setRemarks(String remarks) + { + this.remarks = remarks; + } + + public String getRemarks() + { + return remarks; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("projectName", getProjectName()) + .append("state", getState()) + .append("createTime", getCreateTime()) + .append("createBy", getCreateBy()) + .append("delFlag", getDelFlag()) + .append("indexImage", getIndexImage()) + .append("remarks", getRemarks()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/GoviewProjectData.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/GoviewProjectData.java new file mode 100644 index 0000000..5cbe03f --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/GoviewProjectData.java @@ -0,0 +1,76 @@ +package com.maibu.domain; + +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 项目数据关联对象 iot_goview_project_data + * + * @author kami + * @date 2022-10-27 + */ +@ApiModel(value = "GoviewProjectData", description = "项目数据关联对象 iot_goview_project_data") +public class GoviewProjectData extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** 主键 */ + @ApiModelProperty("主键ID") + private String id; + + /** 项目id */ + @ApiModelProperty("项目id") + private String projectId; + + /** 存储数据 */ + @ApiModelProperty("存储数据") + private byte[] content; + + public void setId(String id) + { + this.id = id; + } + + public String getId() + { + return id; + } + public void setProjectId(String projectId) + { + this.projectId = projectId; + } + + public String getProjectId() + { + return projectId; + } + + public byte[] getContent() { + return content; + } + + public void setContent(byte[] content) { + this.content = content; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("projectId", getProjectId()) + .append("createTime", getCreateTime()) + .append("createBy", getCreateBy()) + .append("content", getContent()) + .toString(); + } + + public String getDataToStr() { + byte[] bs = getContent(); + String str = "二进制转换错误"; + str = new String(bs); + return str; + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Group.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Group.java new file mode 100644 index 0000000..bf316c0 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Group.java @@ -0,0 +1,120 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 设备分组对象 iot_group + * + * @author kerwincui + * @date 2021-12-16 + */ +@ApiModel(value = "Group", description = "设备分组对象 iot_group") +public class Group extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 分组ID */ + @ApiModelProperty("分组ID") + private Long groupId; + + /** 分组名称 */ + @ApiModelProperty("分组名称") + @Excel(name = "分组名称") + private String groupName; + + /** 分组排序 */ + @ApiModelProperty("分组排序") + @Excel(name = "分组排序") + private Long groupOrder; + + /** 用户ID */ + @ApiModelProperty("用户ID") + @Excel(name = "用户ID") + private Long userId; + + /** 用户昵称 */ + @ApiModelProperty("用户昵称") + @Excel(name = "用户昵称") + private String userName; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志") + private String delFlag; + + public void setGroupId(Long groupId) + { + this.groupId = groupId; + } + + public Long getGroupId() + { + return groupId; + } + public void setGroupName(String groupName) + { + this.groupName = groupName; + } + + public String getGroupName() + { + return groupName; + } + public void setGroupOrder(Long groupOrder) + { + this.groupOrder = groupOrder; + } + + public Long getGroupOrder() + { + return groupOrder; + } + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getUserName() + { + return userName; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("groupId", getGroupId()) + .append("groupName", getGroupName()) + .append("groupOrder", getGroupOrder()) + .append("userId", getUserId()) + .append("userName", getUserName()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/HttpClient.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/HttpClient.java new file mode 100644 index 0000000..efb6490 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/HttpClient.java @@ -0,0 +1,41 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import lombok.Data; + +/** + * http桥接配置对象 http_client + * + * @author gx_magx_ma + * @date 2024-05-29 + */ +@Data +public class HttpClient extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 请求方法 */ + @Excel(name = "请求方法") + private String method; + + /** 桥接地址 */ + @Excel(name = "桥接地址") + private String hostUrl; + + /** 请求头 */ + @Excel(name = "请求头") + private String requestHeaders; + + /** 请求参数 */ + @Excel(name = "请求参数") + private String requestQuerys; + + /** 请求参数 */ + @Excel(name = "请求参数") + private String requestConfig; + + /** 请求体 */ + @Excel(name = "请求体") + private String requestBody; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonDevice.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonDevice.java new file mode 100644 index 0000000..c63b814 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonDevice.java @@ -0,0 +1,125 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fastbee.common.core.domain.BaseDO; +import com.fastbee.iot.enums.ConnectType; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.data.annotation.Id; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.Map; + +/** + * 除了割草机器人之外的设备 包含其他的物联设备 + * + * @author rqian + * @date 2026-3-11 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@TableName("iot_device_common") +public class IoTCommonDevice extends BaseDO { + + + @Id + private Long id; + + private String siteId; //场地id + /** + * 设备ID + */ + private String deviceId; + + /** + * 设备名称 + */ + private String deviceName; + + /** + * 产品ID + */ + private Long productId; + + private String productName; + + /** + * 设备编号 + */ + private String serialNumber; + + /** + * 固件版本 + */ + private BigDecimal firmwareVersion; + + /** + * 设备类型(1-直连设备、2-网关设备、3-监控设备) + */ + private Integer deviceType; + + /** + * 设备状态(1-未激活,2-禁用,3-在线,4-离线) + */ + private Integer status; + + /** + * 设备在线状态(1-在线,2-离线) + */ + private Integer onlineStatus; + + /** + * 设备所在地址 + */ + private String networkAddress; + + /** + * 设备入网IP + */ + private String networkIp; + + /** + * 设备经度 + */ + private BigDecimal longitude; + + /** + * 设备纬度 + */ + private BigDecimal latitude; + + /** + * 激活时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + private Date activeTime; + + /** + * 物模型值 + */ + @TableField(exist = false) + private Map properties; + + /** + * 设备备注 + **/ + private String remark; + + /** + * 分组ID,用于分组查询 + **/ + private Long groupId; + + /** + * 是否是模拟设备 + */ + private Integer isSimulate; + + private ConnectType connectType; + + @TableField(exist = false) + private Boolean hasRegister; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonDeviceAction.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonDeviceAction.java new file mode 100644 index 0000000..3e2a79b --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonDeviceAction.java @@ -0,0 +1,21 @@ +package com.maibu.domain; + +import lombok.Data; + +import java.util.Map; + +@Data +public class IoTCommonDeviceAction { + + private String actionId; + + private String deviceId; + + private String command; + + private String actionName; + + private Map params; // 动作参数 + + private Integer status; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonProduct.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonProduct.java new file mode 100644 index 0000000..dca7ce9 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonProduct.java @@ -0,0 +1,46 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.fastbee.common.core.domain.BaseDO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.data.annotation.Id; + +import java.util.List; + + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("iot_common_product") +public class IoTCommonProduct extends BaseDO { + + @Id + private Long id; + + private String code; + + private String name; + + private Long categoryId; + + private String categoryName; + + private String protocolCode; + + private String transport; + + private Integer vertificateMethod; + + @TableField(typeHandler = JacksonTypeHandler.class) + private List thingsModels; + + @TableField(typeHandler = JacksonTypeHandler.class) + private List deviceActions; + + private List events; + + private Integer status; + +} \ No newline at end of file diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonThingsModel.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonThingsModel.java new file mode 100644 index 0000000..b340f43 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/IoTCommonThingsModel.java @@ -0,0 +1,29 @@ +package com.maibu.domain; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class IoTCommonThingsModel { + + private String name; + + private String code; + + private Boolean required; + + private Object min; + + private Object max; + + private String unit; + + private String description; + + private Object defaultValue; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ModbusConfig.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ModbusConfig.java new file mode 100644 index 0000000..a569fab --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ModbusConfig.java @@ -0,0 +1,64 @@ +package com.maibu.domain; + +import com.fastbee.common.core.domain.BaseEntity; +import com.fastbee.common.core.protocol.modbus.ModbusCode; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * modbus配置对象 iot_modbus_config + ** @date 2024-05-22 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ModbusConfig extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 业务id */ + private Long id; + + /**所属产品id*/ + @ApiModelProperty(value = "所属产品id") + private Long productId; + + /**从机地址*/ + @ApiModelProperty(value = "从机地址") + private Integer slave; + /** 关联属性 */ + @ApiModelProperty(value = "关联属性") + private String identifier; + + /** 寄存器地址 */ + @ApiModelProperty(value = "寄存器地址") + private Integer address; + + /** 是否只读(0-否,1-是) */ + @ApiModelProperty(value = "是否只读(0-否,1-是)") + private Integer isReadonly; + + /** modbus数据类型 */ + @ApiModelProperty(value = "modbus数据类型") + private String dataType; + + /** 读取个数 */ + @ApiModelProperty(value = "读取个数") + private Integer quantity; + + /** 寄存器类型 1-IO寄存器 2-数据寄存器 */ + @ApiModelProperty(value = "寄存器类型 1-IO寄存器 2-数据寄存器") + private Integer type; + + @ApiModelProperty(value = "BIT位") + private Integer bitOrder; + + @ApiModelProperty(value = "排序") + private Integer sort; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + private ModbusCode modbusCode; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ModbusJob.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ModbusJob.java new file mode 100644 index 0000000..7d659c2 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ModbusJob.java @@ -0,0 +1,78 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * 轮训任务列对象 iot_modbus_job + * + * @author kerwincui + * @date 2024-07-05 + */ +@ApiModel(value = "ModbusJob", description = "轮训任务列 iot_modbus_job") +@Data +@EqualsAndHashCode(callSuper = true) +public class ModbusJob extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 任务id + */ + private Long taskId; + + + @ApiModelProperty("任务名") + private String jobName; + /** + * 子设备id + */ + @Excel(name = "子设备id") + @ApiModelProperty("子设备id") + private Long subDeviceId; + + /** + * 子设备编号 + */ + @Excel(name = "子设备编号") + @ApiModelProperty("子设备编号") + private String subSerialNumber; + + /** + * 指令 + */ + @Excel(name = "指令") + @ApiModelProperty("指令") + private String command; + + /** + * 任务id + */ + @Excel(name = "任务id") + @ApiModelProperty("任务id") + private Long jobId; + + /** + * 状态(0正常 1暂停) + */ + @Excel(name = "状态", readConverterExp = "0=正常,1=暂停") + @ApiModelProperty("状态") + private String status; + + @ApiModelProperty("设备类型") + private Integer deviceType; + + private List subDeviceList; + + /** + * 时间周期描述 + */ + private String remarkStr; + + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ModbusParams.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ModbusParams.java new file mode 100644 index 0000000..b40c3ac --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ModbusParams.java @@ -0,0 +1,96 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +/** + * 产品modbus配置参数对象 iot_modbus_params + * + * @date 2024-08-20 + */ + +@ApiModel(value = "ModbusParams", description = "产品modbus配置参数 iot_modbus_params") +@Data +@TableName("iot_modbus_params" ) +public class ModbusParams implements Serializable{ + private static final long serialVersionUID=1L; + + /** 业务id */ + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("业务id") + private Long id; + + /** 产品id */ + @ApiModelProperty("产品id") + private Long productId; + + /** 是否启动云端轮训(1-云端轮训,2-边缘采集) */ + @ApiModelProperty("是否启动云端轮训(0-云端轮训,1-边缘采集)") + private Integer pollType; + + /** 默认的子设备地址 */ + @ApiModelProperty("默认的子设备地址") + private Integer slaveId; + + /** 子设备状态判断方式 1-设备数据 2- 网关 */ + @ApiModelProperty("子设备状态判断方式 1-设备数据 2- 网关") + private Integer statusDeter; + + /** 设备数据来判断子设备状态的时长(s) */ + @ApiModelProperty("设备数据来判断子设备状态的时长(s)") + private String deterTimer; + + /** 批量读取的个数 */ + @ApiModelProperty("批量读取的个数") + private Integer pollLength; + + /** 创建者 */ + @ApiModelProperty("创建者") + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty("创建时间") + private Date createTime; + + /** 更新者 */ + @ApiModelProperty("更新者") + private String updateBy; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty("更新时间") + private Date updateTime; + + /** 备注 */ + @ApiModelProperty("备注") + private String remark; + + @Setter + @TableField(exist = false) + @ApiModelProperty("请求参数") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public Map getParams(){ + if (params == null){ + params = new HashMap<>(); + } + return params; + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/MqttClient.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/MqttClient.java new file mode 100644 index 0000000..afc4c24 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/MqttClient.java @@ -0,0 +1,34 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import lombok.Data; + +/** + * mqtt桥接配置表对象 mqtt_client + * + * @author gx_ma + * @date 2024-06-03 + */ +@Data +public class MqttClient +{ + /** 连接器名称 */ + @Excel(name = "连接器名称") + private String name; + + /** MQTT服务地址(broker.emqx.io:1883) */ + @Excel(name = "MQTT服务地址", readConverterExp = "b=roker.emqx.io:1883") + private String hostUrl; + + /** 用户名 */ + @Excel(name = "用户名") + private String username; + + /** 密码 */ + @Excel(name = "密码") + private String password; + + /** 客户端ID */ + @Excel(name = "客户端ID") + private String clientId; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/MultipleDataSource.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/MultipleDataSource.java new file mode 100644 index 0000000..a996add --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/MultipleDataSource.java @@ -0,0 +1,46 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import lombok.Data; + +/** + * 数据源配置对象 multiple_data_source + * + * @author gx_ma + * @date 2024-06-17 + */ +@Data +public class MultipleDataSource extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 数据源 */ + @Excel(name = "数据源") + private String databaseSource; + + /** sql语句 */ + @Excel(name = "sql语句") + private String sql; + + /** 类型 */ + @Excel(name = "类型") + private String type; + + /** 数据库名称 */ + @Excel(name = "数据库名称") + private String dataBaseName; + + /** 连接地址 */ + @Excel(name = "连接地址") + private String host; + + /** 用户名 */ + @Excel(name = "用户名") + private String userName; + + /** 密码 */ + @Excel(name = "密码") + private String password; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/News.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/News.java new file mode 100644 index 0000000..8835131 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/News.java @@ -0,0 +1,195 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 新闻资讯对象 news + * + * @author kerwincui + * @date 2022-04-09 + */ +@ApiModel(value = "News", description = "新闻资讯对象 news") +public class News extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 新闻ID */ + @ApiModelProperty("新闻ID") + private Long newsId; + + /** 标题 */ + @ApiModelProperty("标题") + @Excel(name = "标题") + private String title; + + /** 内容 */ + @ApiModelProperty("内容") + @Excel(name = "内容") + private String content; + + /** 图片 */ + @ApiModelProperty("图片") + @Excel(name = "图片") + private String imgUrl; + + /** 置顶 */ + @ApiModelProperty("是否置顶") + @Excel(name = "置顶") + private Integer isTop; + + /** 广告 */ + @ApiModelProperty("广告") + @Excel(name = "广告") + private Integer isBanner; + + /** 分类ID */ + @ApiModelProperty("分类ID") + @Excel(name = "分类ID") + private Long categoryId; + + /** 分类名称 */ + @ApiModelProperty("分类名称") + @Excel(name = "分类名称") + private String categoryName; + + /** 发布 */ + @ApiModelProperty("新闻状态(0-未发布,1-已发布)") + @Excel(name = "发布") + private Integer status; + + /** 作者 */ + @ApiModelProperty("作者") + @Excel(name = "作者") + private String author; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志") + private String delFlag; + + public void setNewsId(Long newsId) + { + this.newsId = newsId; + } + + public Long getNewsId() + { + return newsId; + } + public void setTitle(String title) + { + this.title = title; + } + + public String getTitle() + { + return title; + } + public void setContent(String content) + { + this.content = content; + } + + public String getContent() + { + return content; + } + public void setImgUrl(String imgUrl) + { + this.imgUrl = imgUrl; + } + + public String getImgUrl() + { + return imgUrl; + } + public void setIsTop(Integer isTop) + { + this.isTop = isTop; + } + + public Integer getIsTop() + { + return isTop; + } + public void setIsBanner(Integer isBanner) + { + this.isBanner = isBanner; + } + + public Integer getIsBanner() + { + return isBanner; + } + public void setCategoryId(Long categoryId) + { + this.categoryId = categoryId; + } + + public Long getCategoryId() + { + return categoryId; + } + public void setCategoryName(String categoryName) + { + this.categoryName = categoryName; + } + + public String getCategoryName() + { + return categoryName; + } + public void setStatus(Integer status) + { + this.status = status; + } + + public Integer getStatus() + { + return status; + } + public void setAuthor(String author) + { + this.author = author; + } + + public String getAuthor() + { + return author; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("newsId", getNewsId()) + .append("title", getTitle()) + .append("content", getContent()) + .append("imgUrl", getImgUrl()) + .append("isTop", getIsTop()) + .append("isBanner", getIsBanner()) + .append("categoryId", getCategoryId()) + .append("categoryName", getCategoryName()) + .append("status", getStatus()) + .append("author", getAuthor()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/NewsCategory.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/NewsCategory.java new file mode 100644 index 0000000..2ca70c0 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/NewsCategory.java @@ -0,0 +1,91 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 新闻分类对象 news_category + * + * @author kerwincui + * @date 2022-04-09 + */ +@ApiModel(value = "NewsCategory", description = "新闻分类对象 news_category") +public class NewsCategory extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 分类ID */ + @ApiModelProperty("分类ID") + @Excel(name = "分类ID") + private Long categoryId; + + /** 分类名字 */ + @ApiModelProperty("分类名字") + @Excel(name = "分类名字") + private String categoryName; + + /** 显示顺序 */ + @ApiModelProperty("显示顺序") + @Excel(name = "显示顺序") + private Integer orderNum; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志") + private String delFlag; + + public void setCategoryId(Long categoryId) + { + this.categoryId = categoryId; + } + + public Long getCategoryId() + { + return categoryId; + } + public void setCategoryName(String categoryName) + { + this.categoryName = categoryName; + } + + public String getCategoryName() + { + return categoryName; + } + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + public Integer getOrderNum() + { + return orderNum; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("categoryId", getCategoryId()) + .append("categoryName", getCategoryName()) + .append("orderNum", getOrderNum()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/OrderControl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/OrderControl.java new file mode 100644 index 0000000..2c2032e --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/OrderControl.java @@ -0,0 +1,92 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 指令权限控制对象 order_control + * + * @author kerwincui + * @date 2024-07-01 + */ +@ApiModel(value = "OrderControl", description = "指令权限控制 order_control") +@Data +@EqualsAndHashCode(callSuper = true) +public class OrderControl extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 租户id + */ + @Excel(name = "租户id") + @ApiModelProperty("租户id") + private Long tenantId; + + /** + * 逗号分隔 + */ + @Excel(name = "逗号分隔") + @ApiModelProperty("逗号分隔") + private String selectOrder; + + /** + * 是否生效 0-否 1-是 + */ + @Excel(name = "是否生效 0-否 1-是") + @ApiModelProperty("是否生效 0-否 1-是") + private String status; + + /** + * 被限制的用户id + */ + @Excel(name = "被限制的用户id") + @ApiModelProperty("被限制的用户id") + private Long userId; + + /** + * 设备id + */ + @Excel(name = "设备id") + @ApiModelProperty("设备id") + private Long deviceId; + + /** + * 可操作次数 + */ + @Excel(name = "可操作次数") + @ApiModelProperty("可操作次数") + private Integer count; + + @ApiModelProperty("文件") + private String filePath; + + @ApiModelProperty("图片") + private String imgUrl; + + @ApiModelProperty("开始时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date startTime; + + @ApiModelProperty("结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date endTime; + + private String modelNames; + + private String deviceName; + + private String userName; +} + diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Product.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Product.java new file mode 100644 index 0000000..4c4cb5d --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Product.java @@ -0,0 +1,405 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.springframework.data.annotation.Transient; + +/** + * 产品对象 iot_product + * + * @author kerwincui + * @date 2021-12-16 + */ +@ApiModel(value = "Product", description = "产品对象 iot_product") +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Product extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 产品ID */ + @ApiModelProperty("产品ID") + private Long productId; + + /** 产品名称 */ + @ApiModelProperty("产品名称") + @Excel(name = "产品名称") + private String productName; + + /** 产品分类ID */ + @ApiModelProperty("产品分类ID") + @Excel(name = "产品分类ID") + private Long categoryId; + + /** 产品分类名称 */ + @ApiModelProperty("产品分类名称") + @Excel(name = "产品分类名称") + private String categoryName; + + /** 租户ID */ + @ApiModelProperty("租户ID") + @Excel(name = "租户ID") + private Long tenantId; + + /** 租户名称 */ + @ApiModelProperty("租户名称") + @Excel(name = "租户名称") + private String tenantName; + + /** 是否私有产品(0-否,1-是)私有下级不能共享 */ + @ApiModelProperty(value = "是否私有产品", notes = "(0-否,1-是)") + @Excel(name = "是否私有产品", readConverterExp = "0-否,1-是") + private Integer isSys; + + /** 是否启用授权码(0-否,1-是) */ + @ApiModelProperty(value = "是否启用授权码", notes = "(0-否,1-是)") + @Excel(name = "是否启用授权码", readConverterExp = "0=-否,1-是") + private Integer isAuthorize; + + /** mqtt账号 */ + @ApiModelProperty("mqtt账号") + private String mqttAccount; + + /** mqtt密码 */ + @ApiModelProperty("mqtt密码") + private String mqttPassword; + + /** 产品秘钥 */ + @ApiModelProperty("产品秘钥") + private String mqttSecret; + + /*产品协议编号*/ + @ApiModelProperty("产品协议编号") + private String protocolCode; + + /*产品支持的传输协议,多个的选一个即可*/ + @ApiModelProperty("产品支持的传输协议,多个的选一个即可") + private String transport; + + /** 是否自定义位置 **/ + @ApiModelProperty("定位方式(1=ip自动定位,2=设备定位,3=自定义)") + private Integer locationWay; + + public String getTransport() { + return transport; + } + + public void setTransport(String transport) { + this.transport = transport; + } + + public String getProtocolCode() { + return protocolCode; + } + + public void setProtocolCode(String protocolCode) { + this.protocolCode = protocolCode; + } + + public String getMqttSecret() { + return mqttSecret; + } + + public void setMqttSecret(String mqttSecret) { + this.mqttSecret = mqttSecret; + } + + /** 状态(1-未发布,2-已发布,不能修改) */ + @ApiModelProperty(value = "状态", notes = "(1-未发布,2-已发布,不能修改)") + @Excel(name = "状态", readConverterExp = "1==未发布,2=已发布,不能修改") + private Integer status; + + /** 设备类型(1-直连设备、2-网关子设备、3-网关设备) */ + @ApiModelProperty(value = "设备类型", notes = "(1-直连设备、2-网关子设备、3-网关设备、4-网关子设备)") + @Excel(name = "设备类型", readConverterExp = "1=直连设备、2=网关设备、3=监控设备、4-网关子设备") + private Integer deviceType; + + /** 联网方式(1=-wifi、2-蜂窝(2G/3G/4G/5G)、3-以太网、4-其他) */ + @ApiModelProperty(value = "联网方式", notes = "(1=-wifi、2-蜂窝(2G/3G/4G/5G)、3-以太网、4-其他)") + @Excel(name = "联网方式", readConverterExp = "1=-wifi、2=蜂窝(2G/3G/4G/5G)、3=以太网、4=其他") + private Integer networkMethod; + + /** 认证方式(1-账号密码、2-证书、3-Http) */ + @ApiModelProperty(value = "认证方式", notes = "(1-账号密码、2-证书、3-Http)") + @Excel(name = "认证方式", readConverterExp = "1=账号密码、2=证书、3=Http") + private Integer vertificateMethod; + + /** 图片地址 */ + @ApiModelProperty("图片地址") + private String imgUrl; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty(value = "删除标志", notes = "(0代表存在 2代表删除)") + private String delFlag; + + /** 物模型Json **/ + @ApiModelProperty("物模型Json") + private String thingsModelsJson; + + /**采集点模板id*/ + @ApiModelProperty("采集点模板id") + private Long templateId; + + @Transient + @ApiModelProperty("是否显示上级") + private Boolean showSenior; + + @Transient + @ApiModelProperty("机构ID") + private Long deptId; + + @Transient + @ApiModelProperty("是否属于本机构 1-是,0-否") + private Integer isOwner; + + @Transient + private Boolean isAdmin; + + @ApiModelProperty("关联组态guId") + private String guid; + + /** + * 组态主键id + */ + @ApiModelProperty("关联组态id") + private Long scadaId; + + public Long getScadaId() { + return scadaId; + } + + public void setScadaId(Long scadaId) { + this.scadaId = scadaId; + } + + public String getGuid() { + return guid; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + public Boolean getAdmin() { + return isAdmin; + } + + public void setAdmin(Boolean admin) { + isAdmin = admin; + } + + public Integer getIsOwner() { + return isOwner; + } + + public void setIsOwner(Integer isOwner) { + this.isOwner = isOwner; + } + + public Boolean getShowSenior() { + return showSenior; + } + + public void setShowSenior(Boolean showSenior) { + this.showSenior = showSenior; + } + + public Long getDeptId() { + return deptId; + } + + public void setDeptId(Long deptId) { + this.deptId = deptId; + } + + public Integer getLocationWay() { + return locationWay; + } + + public void setLocationWay(Integer locationWay) { + this.locationWay = locationWay; + } + + public Long getTemplateId() { + return templateId; + } + + public void setTemplateId(Long templateId) { + this.templateId = templateId; + } + + public String getThingsModelsJson() { + return thingsModelsJson; + } + + public void setThingsModelsJson(String thingsModelsJson) { + this.thingsModelsJson = thingsModelsJson; + } + + public String getImgUrl() { + return imgUrl; + } + + public void setImgUrl(String imgUrl) { + this.imgUrl = imgUrl; + } + + public void setProductId(Long productId) + { + this.productId = productId; + } + + public Long getProductId() + { + return productId; + } + public void setProductName(String productName) + { + this.productName = productName; + } + + public String getProductName() + { + return productName; + } + public void setCategoryId(Long categoryId) + { + this.categoryId = categoryId; + } + + public Long getCategoryId() + { + return categoryId; + } + public void setCategoryName(String categoryName) + { + this.categoryName = categoryName; + } + + public String getCategoryName() + { + return categoryName; + } + public void setTenantId(Long tenantId) + { + this.tenantId = tenantId; + } + + public Long getTenantId() + { + return tenantId; + } + + public void setTenantName(String tenantName) + { + this.tenantName = tenantName; + } + public String getTenantName() + { + return tenantName; + } + + public void setIsSys(Integer isSys) + { + this.isSys = isSys; + } + public Integer getIsSys() + { + return isSys; + } + + public void setIsAuthorize(Integer isAuthorize) {this.isAuthorize = isAuthorize;} + public Integer getIsAuthorize() {return isAuthorize;} + + public void setMqttAccount(String mqttAccount) + { + this.mqttAccount = mqttAccount; + } + public String getMqttAccount() + { + return mqttAccount; + } + + public void setMqttPassword(String mqttPassword) + { + this.mqttPassword = mqttPassword; + } + public String getMqttPassword() + { + return mqttPassword; + } + + public void setStatus(Integer status) + { + this.status = status; + } + + public Integer getStatus() + { + return status; + } + public void setDeviceType(Integer deviceType) + { + this.deviceType = deviceType; + } + + public Integer getDeviceType() + { + return deviceType; + } + public void setNetworkMethod(Integer networkMethod) + { + this.networkMethod = networkMethod; + } + + public Integer getNetworkMethod() + { + return networkMethod; + } + public void setVertificateMethod(Integer vertificateMethod) + { + this.vertificateMethod = vertificateMethod; + } + + public Integer getVertificateMethod() + { + return vertificateMethod; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("productId", getProductId()) + .append("productName", getProductName()) + .append("categoryId", getCategoryId()) + .append("categoryName", getCategoryName()) + .append("tenantId", getTenantId()) + .append("tenantName", getTenantName()) + .append("isSys", getIsSys()) + .append("isAuthorize", getIsAuthorize()) + .append("status", getStatus()) + .append("deviceType", getDeviceType()) + .append("networkMethod", getNetworkMethod()) + .append("vertificateMethod", getVertificateMethod()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ProductAuthorize.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ProductAuthorize.java new file mode 100644 index 0000000..49eb077 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ProductAuthorize.java @@ -0,0 +1,171 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 产品授权码对象 iot_product_authorize + * + * @author kami + * @date 2022-04-11 + */ +@ApiModel(value = "ProductAuthorize", description = "产品授权码对象 iot_product_authorize") +public class ProductAuthorize extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 授权码ID */ + @ApiModelProperty("授权码ID") + private Long authorizeId; + + /** 授权码 */ + @ApiModelProperty("授权码") + @Excel(name = "授权码") + private String authorizeCode; + + /** 产品ID */ + @ApiModelProperty("产品ID") + @Excel(name = "产品ID") + private Long productId; + + /** 设备ID */ + @ApiModelProperty("设备ID") + @Excel(name = "设备ID") + private Long deviceId; + + /** 设备编号 */ + @ApiModelProperty("设备编号") + @Excel(name = "设备编号") + private String serialNumber; + + /** 用户ID */ + @ApiModelProperty("用户ID") + @Excel(name = "用户ID") + private Long userId; + + /** 用户名称 */ + @ApiModelProperty("用户名称") + @Excel(name = "用户名称") + private String userName; + + /** 状态(1-未发布,2-已发布,不能修改) */ + @ApiModelProperty(value = "状态", notes = "(1-未发布,2-已发布,不能修改)") + @Excel(name = "状态", readConverterExp = "1=未使用,2=已使用") + private Integer status; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志") + private String delFlag; + + public ProductAuthorize() { + } + + public ProductAuthorize(String authorizeCode, Long productId) { + this.authorizeCode = authorizeCode; + this.productId = productId; + } + + public void setStatus(Integer status) + { + this.status = status; + } + public Integer getStatus() + { + return status; + } + public void setAuthorizeId(Long authorizeId) + { + this.authorizeId = authorizeId; + } + + public Long getAuthorizeId() + { + return authorizeId; + } + public void setAuthorizeCode(String authorizeCode) + { + this.authorizeCode = authorizeCode; + } + + public String getAuthorizeCode() + { + return authorizeCode; + } + public void setProductId(Long productId) + { + this.productId = productId; + } + + public Long getProductId() + { + return productId; + } + public void setDeviceId(Long deviceId) + { + this.deviceId = deviceId; + } + + public Long getDeviceId() + { + return deviceId; + } + public void setSerialNumber(String serialNumber) + { + this.serialNumber = serialNumber; + } + + public String getSerialNumber() + { + return serialNumber; + } + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getUserName() + { + return userName; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("authorizeId", getAuthorizeId()) + .append("authorizeCode", getAuthorizeCode()) + .append("productId", getProductId()) + .append("deviceId", getDeviceId()) + .append("serialNumber", getSerialNumber()) + .append("userId", getUserId()) + .append("userName", getUserName()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ProductModbusJob.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ProductModbusJob.java new file mode 100644 index 0000000..9f3ac77 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ProductModbusJob.java @@ -0,0 +1,82 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +/** + * 产品轮训任务列对象 iot_product_modbus_job + * + * @author zhuangpeng.li + * @date 2024-09-04 + */ + +@ApiModel(value = "ProductModbusJob", description = "产品轮训任务列 iot_product_modbus_job") +@Data +@TableName("iot_product_modbus_job" ) +public class ProductModbusJob implements Serializable{ + private static final long serialVersionUID=1L; + + /** 任务id */ + @TableId(value = "task_id", type = IdType.AUTO) + @ApiModelProperty("任务id") + private Long taskId; + + /** 任务名称 */ + @ApiModelProperty("任务名称") + private String jobName; + + /** 产品id */ + @ApiModelProperty("产品id") + private Long productId; + + /** 指令 */ + @ApiModelProperty("指令") + private String command; + + /** 创建者 */ + @ApiModelProperty("创建者") + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty("创建时间") + private Date createTime; + + /** 备注信息 */ + @ApiModelProperty("备注信息") + private String remark; + + /** + * 状态(0正常 1暂停) + */ + @ApiModelProperty("状态") + private String status; + + @Setter + @TableField(exist = false) + @ApiModelProperty("请求参数") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public Map getParams(){ + if (params == null){ + params = new HashMap<>(); + } + return params; + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ProductSubGateway.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ProductSubGateway.java new file mode 100644 index 0000000..ae2a07c --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ProductSubGateway.java @@ -0,0 +1,85 @@ +package com.maibu.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +/** + * 网关与子产品关联对象 iot_product_sub_gateway + * + * @author zhuangpeng.li + * @date 2024-09-04 + */ + +@ApiModel(value = "ProductSubGateway", description = "网关与子产品关联 iot_product_sub_gateway") +@Data +@TableName("iot_product_sub_gateway" ) +public class ProductSubGateway implements Serializable{ + private static final long serialVersionUID=1L; + + /** 业务id */ + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("业务id") + private Long id; + + /** 网关产品id */ + @ApiModelProperty("网关产品id") + private Long gwProductId; + + /** 子产品id */ + @ApiModelProperty("子产品id") + private Long subProductId; + + /** 从机地址 */ + @ApiModelProperty("从机地址") + private Integer slaveId; + + /** 创建者 */ + @ApiModelProperty("创建者") + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty("创建时间") + private Date createTime; + + /** 更新者 */ + @ApiModelProperty("更新者") + private String updateBy; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty("更新时间") + private Date updateTime; + + /** 备注 */ + @ApiModelProperty("备注") + private String remark; + + @Setter + @TableField(exist = false) + @ApiModelProperty("请求参数") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public Map getParams(){ + if (params == null){ + params = new HashMap<>(); + } + return params; + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Protocol.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Protocol.java new file mode 100644 index 0000000..9d4874b --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Protocol.java @@ -0,0 +1,60 @@ +package com.maibu.domain; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; + +/** + * 协议管理model + * @author gsb + * @date 2022/10/19 15:35 + */ +@ApiModel(value = "Protocol", description = "协议管理对象 iot_protocol") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Protocol { + + @ApiModelProperty("主键ID") + private Long id; + /*协议编码*/ + @ApiModelProperty("协议编码") + private String protocolCode; + /*协议名称*/ + @ApiModelProperty("协议名称") + private String protocolName; + /*协议jar包,js包 c程序上传地址*/ + @ApiModelProperty("协议jar包,js包 c程序上传地址") + private String protocolFileUrl; + /*协议类型 0:未知 1:jar 2:js 3:C*/ + @ApiModelProperty("协议类型 0:未知 1:jar 2:js 3:C") + private Integer protocolType; + /*协议文件摘要(文件的md5)*/ + @ApiModelProperty("协议文件摘要(文件的md5)") + private String jarSign; + /*创建时间*/ + @ApiModelProperty("创建时间") + private Date createTime; + /*更新时间*/ + @ApiModelProperty("更新时间") + private Date updateTime; + /*0:草稿 1:启用 2:停用*/ + @ApiModelProperty("0:草稿 1:启用 2:停用") + private Integer protocolStatus; + /*'0:正常 1:删除*/ + @ApiModelProperty("'0:正常 1:删除") + private Integer delFlag; + + /** + * 是否显示 + */ + @ApiModelProperty("'0:不显示 1:显示") + private Integer display; + /** + * 协议数据格式 + */ + @ApiModelProperty("协议数据格式") + private String dataFormat; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Scene.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Scene.java new file mode 100644 index 0000000..bfd0db4 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Scene.java @@ -0,0 +1,90 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import lombok.Data; + +import java.util.List; + +/** + * 场景联动对象 iot_scene + * + * @author kerwincui + * @date 2023-12-27 + */ +@Data +public class Scene extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 场景ID */ + private Long sceneId; + + private Long recoverId; + + /** 场景名称 */ + @Excel(name = "场景名称") + private String sceneName; + + /** 规则名称 */ + private String chainName; + + /** 用户ID */ + @Excel(name = "用户ID") + private Long userId; + + /** 用户名称 */ + @Excel(name = "用户名称") + private String userName; + + /** 执行条件(1=或、任一条件,2=且、所有条件,3=非,不满足) */ + @Excel(name = "执行条件", readConverterExp = "1==或、任一条件,2=且、所有条件,3=非,不满足") + private Integer cond; + + /** 静默周期(分钟) */ + @Excel(name = "静默周期", readConverterExp = "分=钟") + private Integer silentPeriod; + + /** 执行方式(1=串行,顺序执行,2=并行,同时执行) */ + @Excel(name = "执行方式", readConverterExp = "1==串行,顺序执行,2=并行,同时执行") + private Integer executeMode; + + /** 延时执行(秒钟) */ + @Excel(name = "延时执行", readConverterExp = "秒=钟") + private Integer executeDelay; + + @Excel(name = "延时匹配", readConverterExp = "秒=钟") + private Integer checkDelay; + + /** 是否包含告警推送(1=包含,2=不包含) */ + @Excel(name = "是否包含告警推送", readConverterExp = "1==包含,2=不包含") + private Integer hasAlert; + + /** 场景状态(1-启动,2-停止) */ + @Excel(name = "场景状态", readConverterExp = "1=-启动,2-停止") + private Integer enable; + + /** 规则数据 */ + @Excel(name = "规则数据") + private String elData; + + /** 应用名称 */ + @Excel(name = "应用名称") + private String applicationName; + + /** 接收的触发器列表 */ + private List triggers; + + /** 接收的执行动作列表 */ + private List actions; + + /** + * 执行动作数量 + */ + private Integer actionCount = 0; + + /** + * 是否是终端用户 1-是;0-否 + */ + private Integer terminalUser; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneDevice.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneDevice.java new file mode 100644 index 0000000..64bf1cd --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneDevice.java @@ -0,0 +1,129 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 场景设备对象 iot_scene_device + * + * @author kerwincui + * @date 2023-12-28 + */ +public class SceneDevice +{ + private static final long serialVersionUID = 1L; + + /** 场景设备ID */ + private Long sceneDeviceId; + + /** 设备编号(产品触发的没有设备编号) */ + @Excel(name = "设备编号", readConverterExp = "产=品触发的没有设备编号") + private String serialNumber; + + /** 产品ID */ + @Excel(name = "产品ID") + private Long productId; + + /** 产品ID */ + @Excel(name = "产品名称") + private String productName; + + /** 场景脚本ID */ + @Excel(name = "场景脚本ID") + private String scriptId; + + /** 场景ID */ + @Excel(name = "场景ID") + private Long sceneId; + + /** 触发源(1=设备触发,3=产品触发) */ + @Excel(name = "触发源", readConverterExp = "1==设备触发,3=产品触发") + private Integer source; + + /** 类型(2=触发器,3=执行动作) */ + private Integer type; + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public void setSceneDeviceId(Long sceneDeviceId) + { + this.sceneDeviceId = sceneDeviceId; + } + + public Long getSceneDeviceId() + { + return sceneDeviceId; + } + public void setSerialNumber(String serialNumber) + { + this.serialNumber = serialNumber; + } + + public String getSerialNumber() + { + return serialNumber; + } + public void setProductId(Long productId) + { + this.productId = productId; + } + + public Long getProductId() + { + return productId; + } + public void setScriptId(String scriptId) + { + this.scriptId = scriptId; + } + + public String getScriptId() + { + return scriptId; + } + public void setSceneId(Long sceneId) + { + this.sceneId = sceneId; + } + + public Long getSceneId() + { + return sceneId; + } + public void setSource(Integer source) + { + this.source = source; + } + + public Integer getSource() + { + return source; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("sceneDeviceId", getSceneDeviceId()) + .append("serialNumber", getSerialNumber()) + .append("productId", getProductId()) + .append("scriptId", getScriptId()) + .append("sceneId", getSceneId()) + .append("source", getSource()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModel.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModel.java new file mode 100644 index 0000000..729124e --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModel.java @@ -0,0 +1,111 @@ +package com.maibu.domain; + +import com.fastbee.common.core.domain.BaseEntity; +import com.fastbee.iot.model.scenemodel.CusDeviceVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.List; + +/** + * 场景管理对象 scene_model + * + * @author kerwincui + * @date 2024-05-20 + */ +@Setter +@Getter +@ApiModel(value = "SceneModel", description = "场景管理") +public class SceneModel extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 场景管理id */ + private Long sceneModelId; + + /** 所属租户id */ + @ApiModelProperty(value = "所属租户id") + private Long tenantId; + + /** 场景管理名称 */ + @ApiModelProperty(value = "场景管理名称") + private String sceneModelName; + + /** 场景状态 0-停用 1-启用 */ + @ApiModelProperty(value = "场景状态 0-停用 1-启用") + private Integer status; + + /** 关联的组态id */ + @ApiModelProperty(value = "关联的组态id") + private String guid; + + /** 场景描述 */ + @ApiModelProperty(value = "场景描述") + private String desc; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** + * 场景图片 + */ + @ApiModelProperty(value = "场景图片") + private String imgUrl; + + /** + * 机构id + */ + private Long deptId; + + /** + * 机构名称 + */ + private String deptName; + + /** + * 关联设备数 + */ + private Integer deviceTotal; + + /** + * 关联设备名称 + */ + private List cusDeviceList; + + /** + * 关联设备类型 + */ + private List sceneModelDeviceList; + /** + * 关联的监控设备 + */ + private List sipRelationList; + + /** + * 组态id + */ + private Long scadaId; + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("sceneModelId", getSceneModelId()) + .append("tenantId", getTenantId()) + .append("sceneModelName", getSceneModelName()) + .append("status", getStatus()) + .append("guid", getGuid()) + .append("desc", getDesc()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .append("imgUrl", getImgUrl()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModelData.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModelData.java new file mode 100644 index 0000000..30652f5 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModelData.java @@ -0,0 +1,70 @@ +package com.maibu.domain; + +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 【请填写功能名称】对象 scene_model_data + * + * @author kerwincui + * @date 2024-05-21 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "SceneModelData", description = "场景变量") +public class SceneModelData extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 主键id */ + private Long id; + + /** 场景管理id */ + @ApiModelProperty(value = "场景管理id") + private Long sceneModelId; + + /** 场景关联数据来源id */ + @ApiModelProperty(value = "场景关联数据来源id") + private Long sceneModelDeviceId; + + /** 来源类型(0设备 1录入型 2运算型) */ + @ApiModelProperty(value = "来源类型(0设备 1录入型 2运算型)") + private Integer variableType; + + /** 数据源id */ + @ApiModelProperty(value = "物模型或变量id") + private Long datasourceId; + + /** 启用(0未启用 1启用) */ + @ApiModelProperty(value = "启用", notes = "0=未启用,1=启用") + private Integer enable; + + /** 删除标志(0代表存在 1代表删除) */ + private String delFlag; + + /** + * 物模型或变量名称 + */ + @ApiModelProperty(value = "变量名称") + private String sourceName; + + /** + * 标识符 + */ + @ApiModelProperty(value = "变量标识符") + private String identifier; + + /** + * 物模型类型 + */ + @ApiModelProperty(value = "物模型类型") + private Integer type; + + /** + * 关联设备名称 + */ + private String sceneModelDeviceName; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModelDevice.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModelDevice.java new file mode 100644 index 0000000..955d955 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModelDevice.java @@ -0,0 +1,67 @@ +package com.maibu.domain; + +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 场景管理关联设备对象 scene_model_device + * + * @author kerwincui + * @date 2024-05-21 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "SceneModelDevice", description = "场景关联设备") +public class SceneModelDevice extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 主键id */ + private Long id; + + /** 场景id */ + @ApiModelProperty(value = "场景id") + private Long sceneModelId; + + /** 关联设备id */ + @ApiModelProperty(value = "关联设备id") + private Long cusDeviceId; + + /** 排序 */ + @ApiModelProperty(value = "排序") + private Integer sort; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 类型(0设备 1录入型 2运算型) */ + @ApiModelProperty(value = "类型", notes = "0=设备,1=录入型,2=运算型") + private Integer variableType; + + /** 全部启用(0否 1是) */ + @ApiModelProperty(value = "全部启用", notes = "0=否,1=是") + private Integer allEnable; + + /** 名称 */ + @ApiModelProperty(value = "名称") + private String name; + + /** + * 设备名称 + */ + private String deviceName; + + /** + * 产品id + */ + private Long productId; + + /** + * 设备编号 + */ + private String serialNumber; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModelTag.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModelTag.java new file mode 100644 index 0000000..252ddca --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneModelTag.java @@ -0,0 +1,125 @@ +package com.maibu.domain; + +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.ArrayList; +import java.util.List; + +/** + * 场景录入型变量对象 scene_model_tag + * + * @author kerwincui + * @date 2024-05-21 + */ +@Getter +@Setter +@ApiModel(value = "SceneModelTag", description = "场景录入运算变量") +public class SceneModelTag extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 主键id */ + private Long id; + + /** 场景id */ + @ApiModelProperty(value = "场景id") + private Long sceneModelId; + + /** 录入型变量名 */ + @ApiModelProperty(value = "录入型变量名") + private String name; + + /** 单位 */ + @ApiModelProperty(value = "单位") + private String unit; + + /** 数据类型 */ + @ApiModelProperty(value = "数据类型") + private String dataType; + + /** 默认值 */ + @ApiModelProperty(value = "默认值") + private String defaultValue; + + /** 是否只读 0-否 1-是 */ + @ApiModelProperty(value = "是否只读 0-否 1-是") + private Integer isReadonly; + + /** 存储方式 0-不存储 1-存储 */ + @ApiModelProperty(value = "存储方式 0-不存储 1-存储") + private Integer storage; + + /** 变量类型 1-运算型变量 2-输入型变量 */ + @ApiModelProperty(value = "变量类型 1-设备物模型 2-运算型变量 3-输入型变量") + private Integer variableType; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 周期执行(0未执行 1执行) */ + @ApiModelProperty(value = "周期执行", notes = "0=未执行,1=执行") + private Integer cycleExecuted; + + /** 计算公式 ${id} + ${id} */ + @ApiModelProperty(value = "计算公式 ${id} + ${id}") + private String formule; + + /** 显示的计算公式 A+B */ + @ApiModelProperty(value = "显示的计算公式 A+B") + private String aliasFormule; + + /** 时间周期方式 1-周期计算 2-自定义时间段 */ + @ApiModelProperty(value = "时间周期方式 1-周期计算 2-自定义时间段") + private Integer cycleType; + + /** 时间周期内容 */ + @ApiModelProperty(value = "时间周期内容") + private String cycle; + + /** + * 场景关联设备id + */ + private Long sceneModelDeviceId; + + /** + * 变量运算 + */ + private List tagPointsList = new ArrayList<>(); + + /** + * 启用 + */ + private Integer enable; + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("sceneModelId", getSceneModelId()) + .append("name", getName()) + .append("unit", getUnit()) + .append("dataType", getDataType()) + .append("defaultValue", getDefaultValue()) + .append("isReadonly", getIsReadonly()) + .append("storage", getStorage()) + .append("variableType", getVariableType()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .append("cycleExecuted", getCycleExecuted()) + .append("formule", getFormule()) + .append("aliasFormule", getAliasFormule()) + .append("cycleType", getCycleType()) + .append("cycle", getCycle()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneScript.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneScript.java new file mode 100644 index 0000000..76a2cc7 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneScript.java @@ -0,0 +1,278 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; + +import java.util.Date; + +/** + * 场景脚本对象 iot_scene_script + * + * @author kerwincui + * @date 2023-12-27 + */ +@ApiModel(value = "SceneScript", description = "场景脚本") +public class SceneScript +{ + private static final long serialVersionUID = 1L; + + /** 场景脚本ID */ + private String scriptId; + + /** 脚本ID */ + @Excel(name = "场景ID") + private Long sceneId; + + /** 触发源(1=设备触发,2=定时触发,3=产品触发,4=执行告警) */ + @Excel(name = "触发源", readConverterExp = "1=设备触发,2=定时触发,3=产品触发,4=执行告警") + private Integer source; + + /** 脚本用途(1=数据流,2=触发器,3=执行动作) */ + private Integer scriptPurpose; + + /** 物模型标识符 */ + private String id; + + /** 物模型名称 */ + @Excel(name = "物模型名称") + private String name; + + /** 物模型值 */ + @Excel(name = "物模型值") + private String value; + + /** 操作符 */ + @Excel(name = "操作符") + private String operator; + + /** 物模型类别(1=属性,2=功能,3=事件,4=设备升级,5=设备上线,6=设备下线) */ + @Excel(name = "物模型类别", readConverterExp = "1==属性,2=功能,3=事件,4=设备升级,5=设备上线,6=设备下线") + private Integer type; + + /** 设备数量 */ + @Excel(name = "设备数量") + private Integer deviceCount; + + /** 任务ID */ + @Excel(name = "任务ID") + private Long jobId; + + /** cron执行表达式 */ + @Excel(name = "cron执行表达式") + private String cronExpression; + + /** 是否详细corn表达式(1=是,0=否) */ + @Excel(name = "是否详细corn表达式", readConverterExp = "1==是,0=否") + private Integer isAdvance; + + /** 父物模id */ + @Excel(name = "父物模id") + private String parentId; + + /** 父物模名称 */ + @Excel(name = "父物模名称") + private String parentName; + + /** 数组索引 */ + @Excel(name = "数组索引") + private String arrayIndex; + + /** 数组索引名称(前端展示使用) */ + @Excel(name = "数组索引名称", readConverterExp = "前=端展示使用") + private String arrayIndexName; + + /** 产品ID*/ + private Long productId; + + /** 产品名称*/ + private String productName; + + /** 设备编号,仅用于传递*/ + private String[] deviceNums; + + /** 创建者 */ + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + public String getScriptId() { + return scriptId; + } + + public void setScriptId(String scriptId) { + this.scriptId = scriptId; + } + + public Long getSceneId() { + return sceneId; + } + + public void setSceneId(Long sceneId) { + this.sceneId = sceneId; + } + + public Integer getSource() { + return source; + } + + public void setSource(Integer source) { + this.source = source; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public Integer getDeviceCount() { + return deviceCount; + } + + public void setDeviceCount(Integer deviceCount) { + this.deviceCount = deviceCount; + } + + public Long getJobId() { + return jobId; + } + + public void setJobId(Long jobId) { + this.jobId = jobId; + } + + public String getCronExpression() { + return cronExpression; + } + + public void setCronExpression(String cronExpression) { + this.cronExpression = cronExpression; + } + + public Integer getIsAdvance() { + return isAdvance; + } + + public void setIsAdvance(Integer isAdvance) { + this.isAdvance = isAdvance; + } + + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } + + public String getParentName() { + return parentName; + } + + public void setParentName(String parentName) { + this.parentName = parentName; + } + + public String getArrayIndex() { + return arrayIndex; + } + + public void setArrayIndex(String arrayIndex) { + this.arrayIndex = arrayIndex; + } + + public String getArrayIndexName() { + return arrayIndexName; + } + + public void setArrayIndexName(String arrayIndexName) { + this.arrayIndexName = arrayIndexName; + } + + public Long getProductId() { + return productId; + } + + public void setProductId(Long productId) { + this.productId = productId; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public String[] getDeviceNums() { + return deviceNums; + } + + public void setDeviceNums(String[] deviceNums) { + this.deviceNums = deviceNums; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Integer getScriptPurpose() { + return scriptPurpose; + } + + public void setScriptPurpose(Integer scriptPurpose) { + this.scriptPurpose = scriptPurpose; + } + + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneTagPoints.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneTagPoints.java new file mode 100644 index 0000000..70cb80a --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SceneTagPoints.java @@ -0,0 +1,80 @@ +package com.maibu.domain; + +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 运算型变量点对象 scene_tag_points + * + * @author kerwincui + * @date 2024-05-21 + */ +@Getter +@Setter +public class SceneTagPoints extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 运算型变量点id */ + private Long id; + + /** 变量点名称 */ + @ApiModelProperty(value = "变量点名称") + private String name; + + /** 点别名,如 A */ + @ApiModelProperty(value = "点别名,如 A") + private String alias; + + /** 关联的变量id */ + @ApiModelProperty(value = "关联的变量id") + private Long tagId; + + /** 统计方式 ,用字典定义,暂时是”原值“ */ + @ApiModelProperty(value = "统计方式 ,用字典定义,暂时是”原值“") + private Integer operation; + + /** 数据来源方式 1-设备物模型 2-录入型变量 3-运算型变量 */ + @ApiModelProperty(value = "数据来源方式 1-设备物模型 2-录入型变量 3-运算型变量") + private Integer variableType; + + /** 场景变量id */ + @ApiModelProperty(value = "场景变量id") + private Long sceneModelDataId; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** + * 场景关联设备id + */ + private Long sceneModelDeviceId; + + /** + * 场景关联设备名称 + */ + private String sceneModelDeviceName; + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("alias", getAlias()) + .append("tagId", getTagId()) + .append("operation", getOperation()) + .append("variableType", getVariableType()) + .append("sceneModelDataId", getSceneModelDataId()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Script.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Script.java new file mode 100644 index 0000000..e9c8a31 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/Script.java @@ -0,0 +1,80 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import lombok.Data; + +/** + * 规则引擎脚本对象 rule_script + * + * @author lizhuangpeng + * @date 2023-07-01 + */ +@Data +public class Script extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 脚本ID */ + @Excel(name = "脚本ID") + private String scriptId; + + /** 用户ID */ + private Long userId; + + /** 用名称 */ + private String userName; + + /** 应用名 */ + @Excel(name = "应用名") + private String applicationName; + + /** 脚本名 */ + @Excel(name = "脚本名") + private String scriptName; + + /** 脚本数据 */ + @Excel(name = "脚本数据") + private String scriptData; + + /** 脚本类型:script=普通脚本,switch_script=选择脚本,boolean_script=条件脚本,for_script=数量循环脚本 */ + @Excel(name = "脚本类型") + private String scriptType; + + /** 场景ID */ + private Long sceneId; + + /** 脚本类型(1=设备上报,2=平台下发,3=设备上线,4=设备离线,5=http桥接数据,6=mqtt桥接数据) */ + private Integer scriptEvent; + + /** 脚本动作(1=消息重发,2=消息通知,3=Http推送,4=Mqtt桥接,5=数据库存储) */ + private Integer scriptAction; + + /** 脚本用途(1=数据流,2=触发器,3=执行动作) */ + private Integer scriptPurpose; + + /** 脚本执行顺序,值越大优先级越高 */ + private Integer scriptOrder; + + /** 脚本语言(groovy | qlexpress | js | python | lua | aviator) */ + @Excel(name = "脚本语言", readConverterExp = "groovy,qlexpress,js,python,lua,aviator") + private String scriptLanguage; + + /** 产品ID */ + private Long productId; + + /** 产品名称 */ + + private String productName; + + /**是否生效*/ + private Integer enable; + + private Long bridgeId; + + private String bridgeName; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SimulateLog.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SimulateLog.java new file mode 100644 index 0000000..de676b9 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SimulateLog.java @@ -0,0 +1,56 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import com.fastbee.common.core.mq.message.MqttBo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 模拟设备日志对象 iot_simulate_log + * + * @author kerwincui + * @date 2023-04-06 + */ +@ApiModel(value = "SimulateLog", description = "模拟设备日志对象 iot_simulate_log") +@EqualsAndHashCode(callSuper = true) +@Data +public class SimulateLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ID */ + @ApiModelProperty("主键ID") + private Long logId; + + /** 云端发送指令 */ + @ApiModelProperty("云端发送指令") + @Excel(name = "云端发送指令") + private String sendData; + + /** 设备回复 */ + @ApiModelProperty("设备回复") + @Excel(name = "设备回复") + private String callbackData; + + /** 设备ID */ + @ApiModelProperty("设备ID") + @Excel(name = "设备ID") + private Long deviceId; + + /** 设备名称 */ + @ApiModelProperty("设备名称") + @Excel(name = "设备名称") + private String deviceName; + + /** 设备编号 */ + @ApiModelProperty("设备编号") + @Excel(name = "设备编号") + private String serialNumber; + + private MqttBo send; + private MqttBo receive; + +} \ No newline at end of file diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SipRelation.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SipRelation.java new file mode 100644 index 0000000..d44861c --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SipRelation.java @@ -0,0 +1,65 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 监控设备关联对象 iot_sip_relation + * + * @author kerwincui + * @date 2024-06-06 + */ +@ApiModel(value = "SipRelation", description = "监控设备关联 iot_sip_relation") +@Data +@EqualsAndHashCode(callSuper = true) +public class SipRelation extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 业务id + */ + private Long id; + + /** + * 监控设备编号 + */ + @Excel(name = "监控设备编号") + @ApiModelProperty("监控设备编号") + private String channelId; + + @ApiModelProperty("通道名称") + @Excel(name = "通道名称") + private String channelName; + + @ApiModelProperty("产品型号") + @Excel(name = "产品型号") + private String model; + + /** + * 关联的设备id + */ + @Excel(name = "关联的设备id") + @ApiModelProperty("关联的设备id") + private Long reDeviceId; + + /** + * 关联的场景id + */ + @Excel(name = "关联的场景id") + @ApiModelProperty("关联的场景id") + private Long reSceneModelId; + + @ApiModelProperty("监控设备id") + private Long deviceId; + + @ApiModelProperty("sip设备编号") + private String deviceSipId; + + @ApiModelProperty("通道状态") + private Integer status; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SocialPlatform.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SocialPlatform.java new file mode 100644 index 0000000..676f1c8 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SocialPlatform.java @@ -0,0 +1,189 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 第三方登录平台控制对象 iot_social_platform + * + * @author kerwincui + * @date 2022-04-11 + */ +@ApiModel(value = "SocialPlatform", description = "第三方登录平台控制对象 iot_social_platform") +public class SocialPlatform extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 第三方登录平台主键 + */ + @ApiModelProperty("第三方登录平台主键") + private Long socialPlatformId; + + /** + * 第三方登录平台 + */ + @ApiModelProperty("第三方登录平台") + @Excel(name = "第三方登录平台") + private String platform; + + /** + * 0、内部上线 1、上线 2、下线 + */ + @ApiModelProperty("0、内部上线 1、上线 2、下线") + @Excel(name = "0、内部上线 1、上线 2、下线") + private String status; + + /** + * 第三方平台申请Id + */ + @ApiModelProperty("第三方平台申请Id") + @Excel(name = "第三方平台申请Id") + private String clientId; + + /** + * 第三方平台密钥 + */ + @ApiModelProperty("第三方平台密钥") + @Excel(name = "第三方平台密钥") + private String secretKey; + + /** + * 用户认证后跳转地址 + */ + @ApiModelProperty("用户认证后跳转地址") + @Excel(name = "用户认证后跳转地址") + private String redirectUri; + + /** + * 删除标记位(0代表存在,2代表删除) + */ + @ApiModelProperty("删除标记位(0代表存在,2代表删除)") + private String delFlag; + + /** + * 绑定注册登录uri + */ + @ApiModelProperty("绑定注册登录uri") + @Excel(name = "绑定注册登录uri") + private String bindUri; + + /** + * 跳转登录uri + */ + @ApiModelProperty("跳转登录uri") + @Excel(name = "跳转登录uri") + private String redirectLoginUri; + + /** + * 错误提示uri + */ + @ApiModelProperty("错误提示uri") + @Excel(name = "错误提示uri") + private String errorMsgUri; + + public Long getSocialPlatformId() { + return socialPlatformId; + } + + public void setSocialPlatformId(Long socialPlatformId) { + this.socialPlatformId = socialPlatformId; + } + + public String getPlatform() { + return platform; + } + + public void setPlatform(String platform) { + this.platform = platform; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public String getRedirectUri() { + return redirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + public String getDelFlag() { + return delFlag; + } + + public void setDelFlag(String delFlag) { + this.delFlag = delFlag; + } + + public String getBindUri() { + return bindUri; + } + + public void setBindUri(String bindUri) { + this.bindUri = bindUri; + } + + public String getRedirectLoginUri() { + return redirectLoginUri; + } + + public void setRedirectLoginUri(String redirectLoginUri) { + this.redirectLoginUri = redirectLoginUri; + } + + public String getErrorMsgUri() { + return errorMsgUri; + } + + public void setErrorMsgUri(String errorMsgUri) { + this.errorMsgUri = errorMsgUri; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("socialPlatformId", getSocialPlatformId()) + .append("platform", getPlatform()) + .append("status", getStatus()) + .append("clientId", getClientId()) + .append("secretKey", getSecretKey()) + .append("redirectUri", getRedirectUri()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateTime", getUpdateTime()) + .append("updateBy", getUpdateBy()) + .append("remark", getRemark()) + .append("bindUri", getBindUri()) + .append("redirectLoginUri", getRedirectLoginUri()) + .append("errorMsgUri", getErrorMsgUri()) + .toString(); + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SocialUser.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SocialUser.java new file mode 100644 index 0000000..4141012 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SocialUser.java @@ -0,0 +1,188 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户第三方用户信息对象 iot_social_user + * + * @author json + * @date 2022-04-18 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "SocialUser", description = "用户第三方用户信息对象 iot_social_user") +@Accessors(chain = true) +@Data +public class SocialUser extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 第三方系统用户表主键 */ + @ApiModelProperty("第三方系统用户表主键") + private Long socialUserId; + + /** 第三方系统的唯一ID */ + @ApiModelProperty("第三方系统的唯一ID") + @Excel(name = "第三方系统的唯一ID") + private String uuid; + + /** 第三方用户来源 */ + @ApiModelProperty("第三方用户来源") + @Excel(name = "第三方用户来源") + private String source; + + /** 用户的授权令牌 */ + @ApiModelProperty("用户的授权令牌") + @Excel(name = "用户的授权令牌") + private String accessToken; + + /** 第三方用户的授权令牌的有效期(部分平台可能没有) */ + @ApiModelProperty(value = "第三方用户的授权令牌的有效期", notes = "(部分平台可能没有)") + @Excel(name = "第三方用户的授权令牌的有效期", readConverterExp = "部=分平台可能没有") + private Long expireIn; + + /** 刷新令牌(部分平台可能没有) */ + @ApiModelProperty(value = "刷新令牌", notes = "(部分平台可能没有)") + @Excel(name = "刷新令牌(部分平台可能没有)") + private String refreshToken; + + /** 第三方用户的 open id(部分平台可能没有) */ + @ApiModelProperty(value = "第三方用户的 open id", notes = "(部分平台可能没有)") + @Excel(name = "第三方用户的 open id", readConverterExp = "部=分平台可能没有") + private String openId; + + /** 第三方用户的 ID(部分平台可能没有) */ + @ApiModelProperty(value = "第三方用户的 ID", notes = "(部分平台可能没有)") + @Excel(name = "第三方用户的 ID(部分平台可能没有)") + private String uid; + + /** 个别平台的授权信息(部分平台可能没有) */ + @ApiModelProperty(value = "个别平台的授权信息", notes = "(部分平台可能没有)") + @Excel(name = "个别平台的授权信息", readConverterExp = "部=分平台可能没有") + private String accessCode; + + /** 第三方用户的 union id(部分平台可能没有) */ + @ApiModelProperty(value = "第三方用户的 union id", notes = "(部分平台可能没有)") + @Excel(name = "第三方用户的 union id(部分平台可能没有)") + private String unionId; + + /** 第三方用户授予的权限(部分平台可能没有) */ + @ApiModelProperty(value = "第三方用户授予的权限", notes = "(部分平台可能没有)") + @Excel(name = "第三方用户授予的权限(部分平台可能没有)") + private String scope; + + /** 个别平台的授权信息(部分平台可能没有) */ + @ApiModelProperty(value = "个别平台的授权信息", notes = "(部分平台可能没有)") + @Excel(name = "个别平台的授权信息", readConverterExp = "部=分平台可能没有") + private String tokenType; + + /** id token(部分平台可能没有) */ + @ApiModelProperty(value = "id token", notes = "(部分平台可能没有)") + @Excel(name = "id token", readConverterExp = "部=分平台可能没有") + private String idToken; + + /** 小米平台用户的附带属性(部分平台可能没有) */ + @ApiModelProperty(value = "小米平台用户的附带属性", notes = "(部分平台可能没有)") + @Excel(name = "小米平台用户的附带属性", readConverterExp = "部=分平台可能没有") + private String macAlgorithm; + + /** 小米平台用户的附带属性(部分平台可能没有) */ + @ApiModelProperty(value = "小米平台用户的附带属性", notes = "(部分平台可能没有) ") + @Excel(name = "小米平台用户的附带属性(部分平台可能没有)") + private String macKey; + + /** 用户的授权code(部分平台可能没有) */ + @ApiModelProperty(value = "用户的授权code", notes = "(部分平台可能没有)") + @Excel(name = "用户的授权code", readConverterExp = "部=分平台可能没有") + private String code; + + /** Twitter平台用户的附带属性(部分平台可能没有) */ + @ApiModelProperty(value = "Twitter平台用户的附带属性", notes = "(部分平台可能没有) ") + @Excel(name = "Twitter平台用户的附带属性(部分平台可能没有)") + private String oauthToken; + + /** Twitter平台用户的附带属性(部分平台可能没有) */ + @ApiModelProperty(value = "Twitter平台用户的附带属性", notes = "(部分平台可能没有)") + @Excel(name = "Twitter平台用户的附带属性(部分平台可能没有)") + private String oauthTokenSecret; + + /** 删除标记位(0代表存在,2代表删除) */ + @ApiModelProperty("删除标记位") + private String delFlag; + + /** 绑定状态(0:未绑定,1:绑定) */ + @ApiModelProperty(value = "绑定状态", notes = "(0:未绑定,1:绑定)") + @Excel(name = "绑定状态(0:未绑定,1:绑定)") + private String status; + + /** 用户ID */ + @ApiModelProperty("用户ID") + @Excel(name = "用户ID") + private Long sysUserId; + + /** 用户名 */ + @ApiModelProperty("用户名") + @Excel(name = "用户名") + private String username; + + /** 用户昵称 */ + @ApiModelProperty("用户昵称") + @Excel(name = "用户昵称") + private String nickname; + + /** 用户头像 */ + @ApiModelProperty("用户头像") + @Excel(name = "用户头像") + private String avatar; + + /** 用户性别 */ + @ApiModelProperty("用户性别") + @Excel(name = "用户性别") + private Integer gender; + /** 三方登录具体来源 */ + @ApiModelProperty("三方登录具体来源") + @Excel(name = "三方登录具体来源") + private String sourceClient; + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("socialUserId", getSocialUserId()) + .append("uuid", getUuid()) + .append("source", getSource()) + .append("accessToken", getAccessToken()) + .append("expireIn", getExpireIn()) + .append("refreshToken", getRefreshToken()) + .append("openId", getOpenId()) + .append("uid", getUid()) + .append("accessCode", getAccessCode()) + .append("unionId", getUnionId()) + .append("scope", getScope()) + .append("tokenType", getTokenType()) + .append("idToken", getIdToken()) + .append("macAlgorithm", getMacAlgorithm()) + .append("macKey", getMacKey()) + .append("code", getCode()) + .append("oauthToken", getOauthToken()) + .append("oauthTokenSecret", getOauthTokenSecret()) + .append("createTime", getCreateTime()) + .append("createBy", getCreateBy()) + .append("updateTime", getUpdateTime()) + .append("updateBy", getUpdateBy()) + .append("delFlag", getDelFlag()) + .append("status", getStatus()) + .append("sysUserId", getSysUserId()) + .append("username", getUsername()) + .append("nickname", getNickname()) + .append("avatar", getAvatar()) + .append("gender", getGender()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SubGateway.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SubGateway.java new file mode 100644 index 0000000..a3cb075 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/SubGateway.java @@ -0,0 +1,47 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 网关与子设备关联对象 iot_gateway + * + * @author gsb + * @date 2024-05-27 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class SubGateway extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 业务id */ + private Long id; + + /** 网关设备id */ + @Excel(name = "网关设备id") + @ApiModelProperty("网关设备id") + private Long gwDeviceId; + + /** 子设备id */ + @Excel(name = "子设备id") + @ApiModelProperty("子设备id") + private Long subDeviceId; + + /** 从机地址 */ + @Excel(name = "从机地址") + @ApiModelProperty("从机地址") + private Integer slaveId; + /** + * 子设备名称 + */ + private String subDeviceName; + /** + * 子设备编号 + */ + private String subDeviceNo; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ThingsModel.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ThingsModel.java new file mode 100644 index 0000000..21bb780 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ThingsModel.java @@ -0,0 +1,136 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * 物模型对象 iot_things_model + * + * @author kerwincui + * @date 2023-01-14 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "ThingsModel", description = "物模型对象 iot_things_model") +@JsonInclude(JsonInclude.Include.NON_NULL) +@Data +public class ThingsModel extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 物模型ID */ + @ApiModelProperty("物模型ID") + private Long modelId; + + /** 物模型名称 */ + @ApiModelProperty("物模型名称") + @Excel(name = "物模型名称" ,prompt = "必填") + private String modelName; + + + /** 物模型名称 */ + @ApiModelProperty("中文物模型名称_中文") + private String modelName_zh_CN; + + /** 物模型名称 */ + @ApiModelProperty("英文物模型名称") + private String modelName_en_US; + + /** 产品ID */ + @ApiModelProperty("产品ID") + private Long productId; + + /** 产品名称 */ + @ApiModelProperty("产品名称") + private String productName; + + /** 租户ID */ + @ApiModelProperty("租户ID") + private Long tenantId; + + /** 租户名称 */ + @ApiModelProperty("租户名称") + private String tenantName; + + /** 标识符,产品下唯一 */ + @ApiModelProperty("标识符,产品下唯一") + @Excel(name = "标识符",prompt = "modbus不填默认为寄存器地址") + private String identifier; + + /** 模型类别(1-属性,2-功能,3-事件) */ + @ApiModelProperty(value = "模型类别", notes = "(1-属性,2-功能,3-事件)") + @Excel(name = "模型类别", readConverterExp = "1=属性,2=功能,3=事件,4=属性和功能", + prompt ="1=属性,2-功能,3-事件") + private Integer type; + + /** 计算公式 */ + @ApiModelProperty("计算公式") + @Excel(name = "计算公式",prompt = "选填,例如:%s*10,%s是占位符") + private String formula; + + /** 数据定义 */ + //@Excel(name = "数据定义") + @ApiModelProperty("数据定义") + private String specs; + + /** 是否图表显示(0-否,1-是) */ + @ApiModelProperty(value = "是否图表显示", notes = "(0-否,1-是)") + @Excel(name = "是否图表显示", readConverterExp = "0=否,1=是") + private Integer isChart; + + /** 是否历史存储(0-否,1-是) */ + @ApiModelProperty(value = "是否历史存储", notes = "(0-否,1-是)") + @Excel(name = "是否历史存储", readConverterExp = "0=否,1=是") + private Integer isHistory; + + /** 是否实时监测(0-否,1-是) */ + @ApiModelProperty(value = "是否实时监测", notes = "(0-否,1-是) ") + @Excel(name = "是否实时监测", readConverterExp = "0=否,1=是") + private Integer isMonitor; + + /** 是否分享设备权限(0-否,1-是) */ + @ApiModelProperty(value = "是否分享设备权限", notes = "(0-否,1-是) ") + private Integer isSharePerm; + + /** 是否分享设备权限(0-否,1-是) */ + @ApiModelProperty(value = "是否分享设备权限", notes = "(0-否,1-是) ") + @Excel(name = "是否分享设备权限", readConverterExp = "0=否,1=是") + private Integer isApp; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志") + private String delFlag; + + @Excel(name = "单位") + private String unit; + + /** 数据类型(integer、decimal、string、bool、array、enum) */ + @ApiModelProperty(value = "数据类型", notes = "(integer、decimal、string、bool、array、enum)") + @Excel(name = "数据类型", prompt = "integer、decimal、string、bool、array、enum") + private String datatype; + + @Excel(name = "有效值范围") + private String limitValue; + + /** 是否只读数据(0-否,1-是) */ + @ApiModelProperty(value = "是否只读数据", notes = "(0-否,1-是)") + @Excel(name = "是否只读", readConverterExp = "0=否,1=是",prompt = "0=否,1=是") + private Integer isReadonly; + + + private Integer modelOrder; + + private ModbusConfig modbusConfig; + + @Deprecated + private String language; + + private List modelIdList; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ThingsModelJsonTemplate.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ThingsModelJsonTemplate.java new file mode 100644 index 0000000..6a8c3f1 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ThingsModelJsonTemplate.java @@ -0,0 +1,68 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 通用物模型对象 iot_things_model_template + * + * @author kerwincui + * @date 2023-01-15 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ThingsModelJsonTemplate extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 物模型ID */ + private Long templateId; + + /** 物模型名称 */ + @Excel(name = "物模型名称",prompt = "必填") + private String templateName; + + /** 标识符,产品下唯一 */ + @Excel(name = "标识符",prompt = "modbus不填,默认为寄存器地址") + private String identifier; + + /** 模型类别(1-属性,2-功能,3-事件) */ + @Excel(name = "模型类别", readConverterExp = "1=属性,2=功能,3=事件",prompt ="1=属性,2=功能,3=事件") + private Integer type; + + /** 数据类型(integer、decimal、string、bool、array、enum) */ + @Excel(name = "数据类型", prompt = "integer、decimal、string、bool、array、enum") + private String datatype; + + /** 计算公式 */ + @Excel(name = "计算公式",prompt = "选填,例如:%s*10,%s是占位符") + private String formula; + + @Excel(name = "有效值范围") + private String limitValue; + + @Excel(name = "单位") + private String unit; + + /** 是否只读数据(0-否,1-是) */ + @Excel(name = "是否只读",readConverterExp = "0=否,1=是",prompt = "0=否,1=是") + private Integer isReadonly; + + /** 是否历史存储(0-否,1-是) */ + @Excel(name = "是否历史存储(0-否,1-是)") + private Integer isHistory; + + /** 是否首页显示(0-否,1-是) */ + @Excel(name = "是否首页显示", readConverterExp = "0=否,1=是") + private Integer isChart; + + /** 是否实时监测(0-否,1-是) */ + @Excel(name = "是否实时监测", readConverterExp = "0=否,1=是") + private Integer isMonitor; + + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ThingsModelTemplate.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ThingsModelTemplate.java new file mode 100644 index 0000000..858ada9 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ThingsModelTemplate.java @@ -0,0 +1,120 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 通用物模型对象 iot_things_model_template + * + * @author kerwincui + * @date 2023-01-15 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "ThingsModelTemplate", description = "通用物模型对象 iot_things_model_template") +@JsonInclude(JsonInclude.Include.NON_NULL) +@Data +public class ThingsModelTemplate extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 物模型ID */ + @ApiModelProperty("物模型ID") + private Long templateId; + + /** 物模型名称 */ + @ApiModelProperty("物模型名称") + @Excel(name = "物模型名称" ,prompt = "必填") + private String templateName; + + /** 租户ID */ + @ApiModelProperty("租户ID") + private Long tenantId; + + /** 租户名称 */ + @ApiModelProperty("租户名称") + private String tenantName; + + /** 标识符,产品下唯一 */ + @ApiModelProperty("标识符,产品下唯一") + @Excel(name = "标识符",prompt = "modbus不填,默认为寄存器地址") + private String identifier; + + /** 模型类别(1-属性,2-功能,3-事件) */ + @ApiModelProperty(value = "模型类别", notes = "(1-属性,2-功能,3-事件)") + @Excel(name = "模型类别", readConverterExp = "1=属性,2=功能,3=事件",prompt ="1=属性,2-功能,3-事件") + private Integer type; + + /** 计算公式 */ + @ApiModelProperty("计算公式") + @Excel(name = "计算公式",prompt = "选填,例如:%s*10,%s是占位符") + private String formula; + + /** 数据定义 */ + @ApiModelProperty("数据定义") + private String specs; + + /** 是否系统通用(0-否,1-是) */ + @ApiModelProperty("是否系统通用(0-否,1-是)") + private Integer isSys; + + + /** 是否图表显示(0-否,1-是) */ + @ApiModelProperty("是否图表显示(0-否,1-是)") + //@Excel(name = "是否图表显示", readConverterExp = "0=否,1=是") + private Integer isChart; + + /** 是否历史存储(0-否,1-是) */ + @ApiModelProperty("是否历史存储(0-否,1-是)") + @Excel(name = "是否历史存储", readConverterExp = "0=否,1=是") + private Integer isHistory; + + /** 是否实时监测(0-否,1-是) */ + @ApiModelProperty("是否实时监测(0-否,1-是)") + private Integer isMonitor; + + /** 是否分享设备权限(0-否,1-是) */ + @ApiModelProperty(value = "是否分享设备权限", notes = "(0-否,1-是) ") + private Integer isSharePerm; + + + /** 是否分享设备权限(0-否,1-是) */ + @ApiModelProperty(value = "是否分享设备权限", notes = "(0-否,1-是) ") + @Excel(name = "是否分享设备权限", readConverterExp = "0=否,1=是") + private Integer isApp; + + /** 删除标志(0代表存在 2代表删除) */ + @ApiModelProperty("删除标志(0代表存在 2代表删除)") + private String delFlag; + + @Excel(name = "单位") + private String unit; + + /** 数据类型(integer、decimal、string、bool、array、enum) */ + @ApiModelProperty(value = "数据类型", notes = "(integer、decimal、string、bool、array、enum)") + @Excel(name = "数据类型", prompt = "integer、decimal、string、bool、array、enum") + private String datatype; + + @ApiModelProperty("有效值范围") + @Excel(name = "有效值范围") + private String limitValue; + + /** 是否只读数据(0-否,1-是) */ + @ApiModelProperty("是否只读数据(0-否,1-是)") + @Excel(name = "是否只读", readConverterExp = "0=否,1=是",prompt = "0=否,1=是") + private Integer isReadonly; + + private Integer modelOrder; + + private String language; + + /** + * 同一租户或用户为true + */ + private Boolean owner; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/UserSocialProfile.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/UserSocialProfile.java new file mode 100644 index 0000000..148e485 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/UserSocialProfile.java @@ -0,0 +1,116 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class UserSocialProfile { + /** + * 第三方系统用户表主键 + */ + private Long socialUserId; + + /** + * 第三方用户来源 + */ + @Excel(name = "第三方用户来源") + private String source; + + /** + * 用户名 + */ + @Excel(name = "用户名") + private String username; + + /** + * 用户昵称 + */ + @Excel(name = "用户昵称") + private String nickname; + + /** + * 用户头像 + */ + @Excel(name = "用户头像") + private String avatar; + + /** + * 绑定状态(0:未绑定,1:绑定) + */ + @Excel(name = "绑定状态(0:未绑定,1:绑定)") + private String status; + + /** + * 第三方具体来源 + */ + private String sourceClient; + + public String getSourceClient() { + return sourceClient; + } + + public void setSourceClient(String sourceClient) { + this.sourceClient = sourceClient; + } + + public Long getSocialUserId() { + return socialUserId; + } + + public void setSocialUserId(Long socialUserId) { + this.socialUserId = socialUserId; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("socialUserId", getSocialUserId()) + .append("source", getSource()) + .append("status", getStatus()) + .append("username", getUsername()) + .append("nickname", getNickname()) + .append("avatar", getAvatar()) + .toString(); + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ViewConfig.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ViewConfig.java new file mode 100644 index 0000000..3fe9f70 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/domain/ViewConfig.java @@ -0,0 +1,125 @@ +package com.maibu.domain; + +import com.fastbee.common.annotation.Excel; +import com.fastbee.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 界面可视化配置对象 iot_view_config + * + * @author kerwincui + * @date 2022-11-15 + */ +public class ViewConfig extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 可视化配置ID */ + private Long viewId; + + /** 可视化配置数据 */ + @Excel(name = "可视化配置数据") + private String viewData; + + /** 产品ID */ + @Excel(name = "产品ID") + private Long productId; + + /** 产品名称 */ + @Excel(name = "产品名称") + private String productName; + + /** 租户ID */ + @Excel(name = "租户ID") + private Long tenantId; + + /** 租户名称 */ + @Excel(name = "租户名称") + private String tenantName; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + public void setViewId(Long viewId) + { + this.viewId = viewId; + } + + public Long getViewId() + { + return viewId; + } + public void setViewData(String viewData) + { + this.viewData = viewData; + } + + public String getViewData() + { + return viewData; + } + public void setProductId(Long productId) + { + this.productId = productId; + } + + public Long getProductId() + { + return productId; + } + public void setProductName(String productName) + { + this.productName = productName; + } + + public String getProductName() + { + return productName; + } + public void setTenantId(Long tenantId) + { + this.tenantId = tenantId; + } + + public Long getTenantId() + { + return tenantId; + } + public void setTenantName(String tenantName) + { + this.tenantName = tenantName; + } + + public String getTenantName() + { + return tenantName; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("viewId", getViewId()) + .append("viewData", getViewData()) + .append("productId", getProductId()) + .append("productName", getProductName()) + .append("tenantId", getTenantId()) + .append("tenantName", getTenantName()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/ConnectType.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/ConnectType.java new file mode 100644 index 0000000..562ea2f --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/ConnectType.java @@ -0,0 +1,16 @@ +package com.maibu.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum ConnectType { + + TCP, + + MQTT, + + HTTP; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/DeviceTaskPlanRepeatType.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/DeviceTaskPlanRepeatType.java new file mode 100644 index 0000000..6a949f5 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/DeviceTaskPlanRepeatType.java @@ -0,0 +1,18 @@ +package com.maibu.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum DeviceTaskPlanRepeatType { + + DAY("DAY","天"), + WEEK("WEEK","周"), + MONTH("MONTH","月"); +// ONCE("ONCE","单次"); + + private final String code; + private final String description; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/DeviceTaskStaus.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/DeviceTaskStaus.java new file mode 100644 index 0000000..96f78b3 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/DeviceTaskStaus.java @@ -0,0 +1,20 @@ +package com.maibu.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum DeviceTaskStaus { + + NEW("NEW","新建"), + EXECUTING("EXECUTING","执行中"), + PAUSE("PAUSE","暂停中"), + FINISH("FINISH","执行成功"), + FAILED("FAILED","执行失败"); + + + private final String code; + private final String description; + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/DeviceType.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/DeviceType.java new file mode 100644 index 0000000..fc4728d --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/enums/DeviceType.java @@ -0,0 +1,42 @@ +package com.maibu.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum DeviceType { + /** + * 未知 + */ + UNKNOWN(0, "未知"), + /** + * 直连设备 + */ + DIRECT_DEVICE(1, "直连设备"), + /** + * 网关设备 + */ + GATEWAY(2, "网关设备"), + /** + * 监控设备 + */ + CAMERA(3, "监控设备"), + /** + * 网关子设备 + */ + SUB_GATEWAY(4,"网关子设备"); + + private int code; + private String desc; + + public static DeviceType transfer(Integer code){ + for (DeviceType value : DeviceType.values()) { + if (value.code == code){ + return value; + } + } + return DeviceType.DIRECT_DEVICE; + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/AlertLogMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/AlertLogMapper.java new file mode 100644 index 0000000..96fc505 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/AlertLogMapper.java @@ -0,0 +1,109 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.AlertLog; +import com.fastbee.iot.model.AlertCountVO; +import com.fastbee.iot.model.DeviceAlertCount; +import com.fastbee.iot.model.param.DataCenterParam; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 设备告警Mapper接口 + * + * @author kerwincui + * @date 2022-01-13 + */ +@Repository +public interface AlertLogMapper +{ + /** + * 查询设备告警 + * + * @param alertLogId 设备告警主键 + * @return 设备告警 + */ + public AlertLog selectAlertLogByAlertLogId(Long alertLogId); + + /** + * 查询设备告警列表 + * + * @param alertLog 设备告警 + * @return 设备告警集合 + */ + public List selectAlertLogList(AlertLog alertLog); + + /** + * 查询设备告警列表总数 + * + * @param alertLog 设备告警 + * @return 设备告警集合 + */ + public Long selectAlertLogListCount(AlertLog alertLog); + + public List selectDeviceAlertCount(); + public DeviceAlertCount selectDeviceAlertCountBySN(String serialNumber); + public List selectSceneAlertCount(); + public DeviceAlertCount selectSceneAlertCountBySceneId(String sceneId); + /** + * 新增设备告警 + * + * @param alertLog 设备告警 + * @return 结果 + */ + public int insertAlertLog(AlertLog alertLog); + + /** + * 新增设备告警 + * + * @param alertLogList 设备告警集合 + * @return 结果 + */ + public int insertAlertLogBatch(List alertLogList); + + /** + * 修改设备告警 + * + * @param alertLog 设备告警 + * @return 结果 + */ + public int updateAlertLog(AlertLog alertLog); + public int updateAlertLogStatus(AlertLog alertLog); + /** + * 删除设备告警 + * + * @param alertLogId 设备告警主键 + * @return 结果 + */ + public int deleteAlertLogByAlertLogId(Long alertLogId); + + /** + * 根据设备编号删除设备告警 + * + * @param serialNumber 设备告警主键 + * @return 结果 + */ + public int deleteAlertLogBySerialNumber(String serialNumber); + + /** + * 批量删除设备告警 + * + * @param alertLogIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteAlertLogByAlertLogIds(Long[] alertLogIds); + + /** + * 统计告警处理信息 + * @param dataCenterParam 传参 + * @return com.fastbee.iot.model.AlertCountVO + */ + List countAlertProcess(DataCenterParam dataCenterParam); + + /** + * 统计告警级别信息 + * @param dataCenterParam 传参 + * @return com.fastbee.iot.model.AlertCountVO + */ + List countAlertLevel(DataCenterParam dataCenterParam); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/AlertMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/AlertMapper.java new file mode 100644 index 0000000..f3798c7 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/AlertMapper.java @@ -0,0 +1,149 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.Alert; +import com.fastbee.iot.domain.AlertNotifyTemplate; +import com.fastbee.iot.domain.AlertScene; +import com.fastbee.iot.domain.Scene; +import com.fastbee.iot.model.AlertSceneSendVO; +import com.fastbee.notify.domain.NotifyTemplate; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 设备告警Mapper接口 + * + * @author kerwincui + * @date 2022-01-13 + */ +@Repository +public interface AlertMapper +{ + /** + * 查询设备告警 + * + * @param alertId 设备告警主键 + * @return 设备告警 + */ + public Alert selectAlertByAlertId(Long alertId); + + /** + * 查询设备告警列表 + * + * @param alert 设备告警 + * @return 设备告警集合 + */ + public List selectAlertList(Alert alert); + + /** + * 获取告警关联的场景列表 + * @param alertId + * @return + */ + public List selectScenesByAlertId(Long alertId); + + /** + * 新增设备告警 + * + * @param alert 设备告警 + * @return 结果 + */ + public int insertAlert(Alert alert); + + /** + * 修改设备告警 + * + * @param alert 设备告警 + * @return 结果 + */ + public int updateAlert(Alert alert); + + /** + * 删除设备告警 + * + * @param alertId 设备告警主键 + * @return 结果 + */ + public int deleteAlertByAlertId(Long alertId); + + /** + * 批量删除设备告警 + * + * @param alertIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteAlertByAlertIds(Long[] alertIds); + + /** + * 修改设备告警状态 + * @param alertId 告警id + * @param status 状态 + * @return 结果 + */ + int updateAlertStatus(@Param("alertId") Long alertId, @Param("status") Integer status); + + /** + * 批量插入告警场景 + * @param alerts + * @return + */ + public int insertAlertSceneList(List alerts); + + /** + * 根据告警ID批量删除告警场景 + * @param alertIds + * @return + */ + public int deleteAlertSceneByAlertIds(Long[] alertIds); + + /** + * 根据场景ID批量删除告警场景 + * @param sceneIds + * @return + */ + public int deleteAlertSceneBySceneIds(Long[] sceneIds); + + /** + * 批量插入告警通知模版 + * @param alertNotifyTemplateList + * @return + */ + public int insertAlertNotifyTemplateList(List alertNotifyTemplateList); + + /** + * 根据告警ID批量删除告警场景 + * @param alertIds + * @return + */ + public int deleteAlertNotifyTemplateByAlertIds(Long[] alertIds); + + /** + * 查询告警通知模版 + * @param alertId 告警id + * @return java.util.List + */ + List selectAlertNotifyTemplateList(Long alertId); + + /** + * 获取告警关联的通知模版列表 + * @param alertId 告警id + * @return + */ + public List selectNotifyTemplateListByAlertId(Long alertId); + + /** + * 获取场景关联的告警列表 + * @param sceneId 场景id + * @return java.util.List + */ + List selectAlertSceneListBySceneId(Long sceneId); + + /** + * 获取场景告警通知参数 + * + * @param sceneId 场景id + * @return 设备告警集合 + */ + List listByAlertIds(Long sceneId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/BridgeMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/BridgeMapper.java new file mode 100644 index 0000000..5c5bd77 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/BridgeMapper.java @@ -0,0 +1,15 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.Bridge; + +/** + * 数据桥接Mapper接口 + * + * @author kerwincui + * @date 2024-08-20 + */ +public interface BridgeMapper extends BaseMapperX +{ + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/CategoryMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/CategoryMapper.java new file mode 100644 index 0000000..0c81502 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/CategoryMapper.java @@ -0,0 +1,81 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.Category; +import com.fastbee.iot.model.IdAndName; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 产品分类Mapper接口 + * + * @author kerwincui + * @date 2021-12-16 + */ +@Repository +public interface CategoryMapper +{ + /** + * 查询产品分类 + * + * @param categoryId 产品分类主键 + * @return 产品分类 + */ + public Category selectCategoryByCategoryId(Long categoryId); + + /** + * 查询产品分类列表 + * + * @param category 产品分类 + * @return 产品分类集合 + */ + public List selectCategoryList(Category category); + + /** + * 查询产品简短分类列表 + * + * @return 产品分类集合 + */ + public List selectCategoryShortList(Category category); + + /** + * 新增产品分类 + * + * @param category 产品分类 + * @return 结果 + */ + public int insertCategory(Category category); + + /** + * 修改产品分类 + * + * @param category 产品分类 + * @return 结果 + */ + public int updateCategory(Category category); + + /** + * 删除产品分类 + * + * @param categoryId 产品分类主键 + * @return 结果 + */ + public int deleteCategoryByCategoryId(Long categoryId); + + /** + * 批量删除产品分类 + * + * @param categoryIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteCategoryByCategoryIds(Long[] categoryIds); + + /** + * 分类下的产品数量 + * + * @param categoryIds 需要删除的数据主键集合 + * @return 结果 + */ + public int productCountInCategorys(Long[] categoryIds); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/CommandPreferencesMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/CommandPreferencesMapper.java new file mode 100644 index 0000000..5dd53ac --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/CommandPreferencesMapper.java @@ -0,0 +1,62 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.CommandPreferences; + +import java.util.List; + +/** + * 指令偏好设置Mapper接口 + * + * @author kerwincui + * @date 2024-06-29 + */ +public interface CommandPreferencesMapper +{ + /** + * 查询指令偏好设置 + * + * @param id 指令偏好设置主键 + * @return 指令偏好设置 + */ + public CommandPreferences selectCommandPreferencesById(Long id); + + /** + * 查询指令偏好设置列表 + * + * @param commandPreferences 指令偏好设置 + * @return 指令偏好设置集合 + */ + public List selectCommandPreferencesList(CommandPreferences commandPreferences); + + /** + * 新增指令偏好设置 + * + * @param commandPreferences 指令偏好设置 + * @return 结果 + */ + public int insertCommandPreferences(CommandPreferences commandPreferences); + + /** + * 修改指令偏好设置 + * + * @param commandPreferences 指令偏好设置 + * @return 结果 + */ + public int updateCommandPreferences(CommandPreferences commandPreferences); + + /** + * 删除指令偏好设置 + * + * @param id 指令偏好设置主键 + * @return 结果 + */ + public int deleteCommandPreferencesById(Long id); + + /** + * 批量删除指令偏好设置 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteCommandPreferencesByIds(Long[] ids); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceAlertUserMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceAlertUserMapper.java new file mode 100644 index 0000000..639232e --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceAlertUserMapper.java @@ -0,0 +1,71 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.DeviceAlertUser; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 设备告警用户Mapper接口 + * + * @author kerwincui + * @date 2024-05-15 + */ +public interface DeviceAlertUserMapper +{ + /** + * 查询设备告警用户 + * + * @param deviceId 设备告警用户主键 + * @return 设备告警用户 + */ + public DeviceAlertUser selectDeviceAlertUserByDeviceId(Long deviceId); + + /** + * 查询设备告警用户列表 + * + * @param deviceAlertUser 设备告警用户 + * @return 设备告警用户集合 + */ + public List selectDeviceAlertUserList(DeviceAlertUser deviceAlertUser); + + /** + * 新增设备告警用户 + * + * @param deviceAlertUser 设备告警用户 + * @return 结果 + */ + public int insertDeviceAlertUser(DeviceAlertUser deviceAlertUser); + + /** + * 修改设备告警用户 + * + * @param deviceAlertUser 设备告警用户 + * @return 结果 + */ + public int updateDeviceAlertUser(DeviceAlertUser deviceAlertUser); + + /** + * 删除设备告警用户 + * + * @param deviceId 设备告警用户主键 + * @return 结果 + */ + public int deleteDeviceAlertUserByDeviceId(Long deviceId); + + /** + * 批量删除设备告警用户 + * + * @param deviceIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteDeviceAlertUserByDeviceIds(Long[] deviceIds); + + /** + * 删除设备告警用户 + * @param deviceId 设备id + * @param: userId 用户id + * @return int + */ + int deleteByDeviceIdAndUserId(@Param("deviceId") Long deviceId, @Param("userId") Long userId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceJobMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceJobMapper.java new file mode 100644 index 0000000..d463ea2 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceJobMapper.java @@ -0,0 +1,140 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.DeviceJob; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 调度任务信息 数据层 + * + * @author kerwincui + */ +@Repository +public interface DeviceJobMapper +{ + /** + * 查询调度任务日志集合 + * + * @param job 调度信息 + * @return 操作日志集合 + */ + public List selectJobList(DeviceJob job); + + /** + * 根据设备Ids查询调度任务日志集合 + * + * @param deviceIds 设备ID数组 + * @return 操作日志集合 + */ + public List selectShortJobListByDeviceIds(Long[] deviceIds); + + /** + * 根据告警Ids查询调度任务日志集合 + * + * @param alertIds 告警ID数组 + * @return 操作日志集合 + */ + public List selectShortJobListByAlertIds(Long[] alertIds); + + /** + * 根据场景Ids查询调度任务日志集合 + * + * @param sceneIds 场景ID数组 + * @return 操作日志集合 + */ + public List selectShortJobListBySceneIds(Long[] sceneIds); + + /** + * 查询所有调度任务 + * + * @return 调度任务列表 + */ + public List selectJobAll(); + + /** + * 通过调度ID查询调度任务信息 + * + * @param jobId 调度ID + * @return 角色对象信息 + */ + public DeviceJob selectJobById(Long jobId); + + /** + * 通过调度ID删除调度任务信息 + * + * @param jobId 调度ID + * @return 结果 + */ + public int deleteJobById(Long jobId); + + /** + * 批量删除调度任务信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteJobByIds(Long[] ids); + + /** + * 根据设备Ids批量删除调度任务信息 + * + * @param deviceIds 需要删除的数据ID + * @return 结果 + */ + public int deleteJobByDeviceIds(Long[] deviceIds); + + /** + * 根据告警Ids批量删除调度任务信息 + * + * @param alertIds 需要删除的告警IDs + * @return 结果 + */ + public int deleteJobByAlertIds(Long[] alertIds); + + /** + * 根据场景联动Ids批量删除调度任务信息 + * + * @param sceneIds 需要删除的数据ID + * @return 结果 + */ + public int deleteJobBySceneIds(Long[] sceneIds); + + /** + * 修改调度任务信息 + * + * @param job 调度任务信息 + * @return 结果 + */ + public int updateJob(DeviceJob job); + + /** + * 新增调度任务信息 + * + * @param job 调度任务信息 + * @return 结果 + */ + public int insertJob(DeviceJob job); + + /** + * 批量查询定时任务 + * @param datasourceIds 源数据id集合 + * @param: jobType 定时任务类型 + * @return java.util.List + */ + List selectListByJobTypeAndDatasourceIds(@Param("datasourceIds") Long[] datasourceIds, @Param("jobType") int jobType); + + /** + * 批量删除定时任务 + * @param datasourceIds 源数据id集合 + * @param: jobType 类型 + * @return int + */ + int deleteJobByJobTypeAndDatasourceIds(@Param("datasourceIds") Long[] datasourceIds, @Param("jobType") int jobType); + + /** + * 根据条件批量删除定时任务 + */ + void deleteJobByJobTypeAndDeviceId(@Param("deviceId") Long deviceId, @Param("jobType") int jobType); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceLogMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceLogMapper.java new file mode 100644 index 0000000..8874895 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceLogMapper.java @@ -0,0 +1,127 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.DeviceLog; +import com.fastbee.iot.model.DeviceStatistic; +import com.fastbee.iot.model.HistoryModel; +import com.fastbee.iot.model.MonitorModel; +import com.fastbee.iot.model.ThingsModelLogCountVO; +import com.fastbee.iot.model.param.DataCenterParam; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 设备日志Mapper接口 + * + * @author kerwincui + * @date 2022-01-13 + */ +@Repository +public interface DeviceLogMapper +{ + /** + * 查询设备日志 + * + * @param logId 设备日志主键 + * @return 设备日志 + */ + public DeviceLog selectDeviceLogByLogId(Long logId); + + /** + * 查询日志分类总数 + * + * @return 设备日志 + */ + public DeviceStatistic selectDeviceLogCount(Long userId); + + /** + * 查询设备日志列表 + * + * @param deviceLog 设备日志 + * @return 设备日志集合 + */ + public List selectDeviceLogList(DeviceLog deviceLog); + + /** + * 查询设备监测数据 + * + * @param deviceLog 设备日志 + * @return 设备日志集合 + */ + public List selectMonitorList(DeviceLog deviceLog); + + /** + * 新增设备日志 + * + * @param deviceLog 设备日志 + * @return 结果 + */ + public int insertDeviceLog(DeviceLog deviceLog); + + /** + * 批量保存图片 + */ + public int saveBatch(@Param("list") List list); + + /** + * 修改设备日志 + * + * @param deviceLog 设备日志 + * @return 结果 + */ + public int updateDeviceLog(DeviceLog deviceLog); + + /** + * 删除设备日志 + * + * @param logId 设备日志主键 + * @return 结果 + */ + public int deleteDeviceLogByLogId(Long logId); + + /** + * 批量删除设备日志 + * + * @param logIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteDeviceLogByLogIds(Long[] logIds); + + /** + * 根据设备Ids批量删除设备日志 + * + * @param deviceNumber 需要删除的数据设备Id + * @return 结果 + */ + public int deleteDeviceLogByDeviceNumber(String deviceNumber); + + /** + * 查询历史数据 + */ + public List selectHistoryList(DeviceLog deviceLog); + + /** + * 查询物模型历史数据 + * @param deviceLog 设备日志 + * @return java.util.List + */ + List listHistory(DeviceLog deviceLog); + + List listhistoryGroupByCreateTime(DeviceLog deviceLog); + + DeviceLog selectLastReport(DeviceLog deviceLog); + /** + * 场景统计变量历史值 + * @param deviceLog 实体类 + * @return java.lang.String + */ + List selectStatsValue(DeviceLog deviceLog); + + /** + * 统计设备物模型指令下发数量 + * @param dataCenterParam 传参 + * @return com.fastbee.common.core.domain.AjaxResult + */ + List countThingsModelInvoke(DataCenterParam dataCenterParam); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceMapper.java new file mode 100644 index 0000000..c41391e --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceMapper.java @@ -0,0 +1,406 @@ +package com.maibu.mapper; + +import com.fastbee.common.core.device.DeviceAndProtocol; +import com.fastbee.common.core.thingsModel.ThingsModelValuesInput; +import com.fastbee.iot.domain.Device; +import com.fastbee.iot.domain.DeviceGroup; +import com.fastbee.iot.model.*; +import com.fastbee.iot.model.ThingsModels.ThingsModelValuesOutput; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Set; + +/** + * 设备Mapper接口 + * + * @author kerwincui + * @date 2021-12-16 + */ +@Repository +public interface DeviceMapper +{ + /** + * 查询设备 + * + * @param deviceId 设备主键 + * @return 设备 + */ + public Device selectDeviceByDeviceId(Long deviceId); + + + /** + * 获取割草机运行信息 + * + * @param deviceId 设备主键 + * @return 设备 + */ + public DeviceRunningStatus selectDeviceStatusByDeviceId(@Param("deviceId") String deviceId); + + + /** + * 添加割草机运行信息 + * + * @return 设备 + */ + public int addDeviceRunningStatusInfo(DeviceRunningStatus deviceRunningStatus); + + /** + * 修改割草机运行信息 + * + * @return 设备 + */ + public int updateDeviceRunningStatusInfo(DeviceRunningStatus deviceRunningStatus); + + /** + * 查询设备和产品总数 + * + * @return 设备 + */ + public DeviceStatistic selectDeviceProductAlertCount(Long deptId); + + /** + * 根据设备编号查询设备 + * + * @param serialNumber 设备主键 + * @return 设备 + */ + public Device selectDeviceBySerialNumber(String serialNumber); + + + /** + * 根据设备编号查询设备数量 + * + * @param serialNumber 设备主键 + * @return 设备 + */ + public int selectDeviceCountBySerialNumber(String serialNumber); + + /** + * 根据设备编号查询简介设备 + * + * @param serialNumber 设备主键 + * @return 设备 + */ + public Device selectShortDeviceBySerialNumber(String serialNumber); + + + /** + * 根据设备编号查询协议编号 + * @param serialNumber 设备编号 + * @return 协议编号 + */ + public ProductCode getProtocolBySerialNumber(String serialNumber); + + /** + * 根据设备编号查询设备认证信息 + * + * @param model 设备编号和产品ID + * @return 设备 + */ + public ProductAuthenticateModel selectProductAuthenticate(AuthenticateInputModel model); + + /** + * 查询设备和运行状态 + * + * @param deviceId 设备主键 + * @return 设备 + */ + public DeviceShortOutput selectDeviceRunningStatusByDeviceId(Long deviceId); + + /** + * 查询设备的物模型值 + * + * @param serialNumber 设备编号 + * @return 设备 + */ + public ThingsModelValuesOutput selectDeviceThingsModelValueBySerialNumber(String serialNumber); + + /** + * 修改设备的物模型值 + * + * @param input 设备ID和物模型值 + * @return 结果 + */ + public int updateDeviceThingsModelValue(ThingsModelValuesInput input); + + + /** + * 查询设备列表 + * + * @param device 设备 + * @return 设备集合 + */ + public List selectDeviceList(Device device); + + /** + * 查询未分配授权码设备列表 + * + * @param device 设备 + * @return 设备集合 + */ + public List selectUnAuthDeviceList(Device device); + + /** + * 查询分组可添加设备分页列表 + * + * @param device 设备 + * @return 设备集合 + */ + public List selectDeviceListByGroup(Device device); + + /** + * 查询设备简短列表 + * + * @param device 设备 + * @return 设备集合 + */ + public List selectDeviceShortList(Device device); + + /** + * 查询所有设备简短列表 + * + * @return 设备集合 + */ + public List selectAllDeviceShortList(Device device); + + /** + * 根据产品ID查询产品下所有设备的编号 + * + * @return 设备集合 + */ + public List selectSerialNumberByProductId(Long productId); + + /** + * 获取产品下面的设备数量 + * + * @param productId 产品 + * @return 结果 + */ + public int selectDeviceCountByProductId(Long productId); + + /** + * 新增设备 + * + * @param device 设备 + * @return 结果 + */ + public int insertDevice(Device device); + + /** + * 修改设备 + * + * @param device 设备 + * @return 结果 + */ + public int updateDevice(Device device); + + /** + * 更新设备状态 + * + * @param device 设备 + * @return 结果 + */ + public int updateDeviceStatus(Device device); + + /** + * 更新固件版本 + * @param device + * @return + */ + public int updateDeviceFirmwareVersion(Device device); + + /** + * 通过设备编号修改设备 + * + * @param device 设备 + * @return 结果 + */ + public int updateDeviceBySerialNumber(Device device); + + /** + * 删除设备 + * + * @param deviceId 设备主键 + * @return 结果 + */ + public int deleteDeviceByDeviceId(Long deviceId); + + /** + * 批量删除设备 + * + * @param deviceIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteDeviceByDeviceIds(Long[] deviceIds); + + /** + * 查询设备序列号的数量 + * @param deviceNum + * @return + */ + public int getDeviceNumCount(String deviceNum); + + /** + * 根据设备IDS删除设备分组 + * @param userDeviceGroupIdModel + * @return + */ + public int deleteDeviceGroupByDeviceId(UserIdDeviceIdModel userDeviceGroupIdModel); + + /** + * 重置设备状态 + * @return 结果 + */ + public int resetDeviceStatus(String deviceNum); + + /** + * 根据设备编号查询协议编码 + * @param serialNumber 设备编号 + * @return + */ + public DeviceAndProtocol selectProtocolBySerialNumber(String serialNumber); + + /** + * 查询产品下所有设备,返回设备编号 + * @param productId 产品id + * @return + */ + public List selectDevicesByProductId(@Param("productId") Long productId,@Param("hasSub") Integer hasSub); + + /** + * 批量更新设备上线 + * @param devices 设备ids + */ + public void batchChangeOnline(List devices); + + /** + * 批量更新设备下线 + * @param devices 设备ids + */ + public void batchChangeOffline(List devices); + + + /** + * 获取设备MQTT连接参数 + * @param deviceId 设备id + * @return + */ + DeviceMqttVO selectMqttConnectData(Long deviceId); + + /** + * 查询告警日志相关联信息 + * @param deviceNumbers 设备编号集合 + * @return + */ + List selectDeviceBySerialNumbers(@Param("deviceNumbers") Set deviceNumbers); + + /** + * 查询告警日志相关联信息 + * @param deviceNumber 设备编号 + * @return + */ + DeviceRelateAlertLogVO selectRelateAlertLogBySerialNumber(String deviceNumber); + + /** + * 根据产品ID获取产品下所有编号 + * @param productId + * @return + */ + public String[] getDeviceNumsByProductId(Long productId); + + /** + * 根据设备编号查询设备状态 + * @param deviceNumbers 设备编号集合 + * @return + */ + public List selectDeviceStatusByNumbers(String[] deviceNumbers); + + + + /** + * 重置设备状态 + */ + public void reSetDeviceStatus(); + + /** + * 获取所有已经激活并不是禁用的设备 + * @return + */ + List selectDeviceActive(); + + /** + * 批量添加设备 + * @param deviceList 设备集合 + * @return void + */ + int insertBatchDevice(@Param("deviceList") List deviceList); + + /** + * 批量校验设备 + * @param serialNumberList + * @return java.util.List + */ + List checkExistBySerialNumbers(@Param("serialNumberList") List serialNumberList); + + /** + * 更新设备绑定机构 + * @param tenantId 机构管理员id + * @param: userName 管理员名称 + * @param: deviceIdList 设备id集合 + * @return int + */ + int updateTenantIdByDeptIds(@Param("tenantId") Long tenantId, @Param("tenantName") String tenantName, @Param("deviceIdList") List deviceIdList); + + /** + * 查询终端用户设备简短列表,主页列表数据 + */ + List listTerminalUser(Device device); + + List listTerminalUserByGroup(Device device); + + /** + * 设备数量 + * @param tenantId + * @return int + */ + int countByTenantId(Long tenantId); + + /** + * @description: + * @param: deviceIdList 设备id集合 + * @return: java.util.List + */ + List selectDeviceListByDeviceIds(@Param("deviceIdList") List deviceIdList); + /** + * 根据监控设备channelId获取设备 + * @param channelId + * @return + */ + Device selectDeviceByChannelId(String channelId); + + /** + * 查询设备状态以及传输协议 + * @param serialNumber + * @return + */ + DeviceStatusVO selectDeviceStatusAndTransportStatus(String serialNumber); + + /** + * 根据分组id集合查询设备分组 + * + * @param groupIds 设备分组主键 + * @return 设备分组 + */ + List listDeviceGroupByGroupIds(List groupIds); + + + /** + * 查询产品下所有设备,返回设备编号 + * @param productId 产品id + * @return + */ + public List selectSerialNumbersByProductId(@Param("productId") Long productId); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DevicePlanMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DevicePlanMapper.java new file mode 100644 index 0000000..1cac7eb --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DevicePlanMapper.java @@ -0,0 +1,13 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.DevicePlan; +import org.springframework.stereotype.Repository; + +/** + * 设备历史状态 + */ +@Repository +public interface DevicePlanMapper extends BaseMapperX { + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DevicePlanTaskMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DevicePlanTaskMapper.java new file mode 100644 index 0000000..d0cf8bb --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DevicePlanTaskMapper.java @@ -0,0 +1,13 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.DevicePlanTask; +import org.springframework.stereotype.Repository; + +/** + * 设备历史状态 + */ +@Repository +public interface DevicePlanTaskMapper extends BaseMapperX { + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceRecordMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceRecordMapper.java new file mode 100644 index 0000000..19d9a59 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceRecordMapper.java @@ -0,0 +1,65 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.DeviceRecord; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 设备记录Mapper接口 + * + * @author zhangzhiyi + * @date 2024-07-16 + */ +@Mapper +public interface DeviceRecordMapper extends BaseMapperX +{ + /** + * 查询设备记录 + * + * @param id 设备记录主键 + * @return 设备记录 + */ + public DeviceRecord selectDeviceRecordById(Long id); + + /** + * 查询设备记录列表 + * + * @param deviceRecord 设备记录 + * @return 设备记录集合 + */ + public List selectDeviceRecordList(DeviceRecord deviceRecord); + + /** + * 新增设备记录 + * + * @param deviceRecord 设备记录 + * @return 结果 + */ + public int insertDeviceRecord(DeviceRecord deviceRecord); + + /** + * 修改设备记录 + * + * @param deviceRecord 设备记录 + * @return 结果 + */ + public int updateDeviceRecord(DeviceRecord deviceRecord); + + /** + * 删除设备记录 + * + * @param id 设备记录主键 + * @return 结果 + */ + public int deleteDeviceRecordById(Long id); + + /** + * 批量删除设备记录 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteDeviceRecordByIds(Long[] ids); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceRunStatisticsMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceRunStatisticsMapper.java new file mode 100644 index 0000000..a0d6a87 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceRunStatisticsMapper.java @@ -0,0 +1,13 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.DeviceRunStatistics; +import org.springframework.stereotype.Repository; + +/** + * 设备历史状态 + */ +@Repository +public interface DeviceRunStatisticsMapper extends BaseMapperX { + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceShareMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceShareMapper.java new file mode 100644 index 0000000..2f32809 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceShareMapper.java @@ -0,0 +1,89 @@ +package com.maibu.mapper; + +import com.fastbee.common.core.domain.entity.SysUser; +import com.fastbee.iot.domain.DeviceShare; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 设备分享Mapper接口 + * + * @author kerwincui + * @date 2024-04-03 + */ +@Repository +public interface DeviceShareMapper +{ + /** + * 根据用户id、设备Id获取分享详情 + * @param deviceId + * @param userId + * @return + */ + DeviceShare selectDeviceShareByDeviceIdAndUserId(@Param("deviceId") Long deviceId, @Param("userId") Long userId); + + /** + * 查询设备分享 + * + * @param deviceId 设备分享主键 + * @return 设备分享 + */ + public List selectDeviceShareByDeviceId(Long deviceId); + + /** + * 查询设备分享列表 + * + * @param deviceShare 设备分享 + * @return 设备分享集合 + */ + public List selectDeviceShareList(DeviceShare deviceShare); + + /** + * 新增设备分享 + * + * @param deviceShare 设备分享 + * @return 结果 + */ + public int insertDeviceShare(DeviceShare deviceShare); + + /** + * 修改设备分享 + * + * @param deviceShare 设备分享 + * @return 结果 + */ + public int updateDeviceShare(DeviceShare deviceShare); + + /** + * 删除设备分享 + * + * @param deviceId 设备分享主键 + * @return 结果 + */ + public int deleteDeviceShareByDeviceId(Long deviceId); + + /** + * 批量删除设备分享 + * + * @param deviceIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteDeviceShareByDeviceIds(Long[] deviceIds); + + /** + * 查询分享设备用户 + * + * @param deviceUser 设备分享 + * @return 设备用户集合 + */ + public SysUser selectShareUser(DeviceShare share); + + /** + * 删除分享设备 + * @param deviceShare + * @return int + */ + int deleteDeviceShareByDeviceIdAndUserId(DeviceShare deviceShare); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceStatusHistoryMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceStatusHistoryMapper.java new file mode 100644 index 0000000..8da31ff --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceStatusHistoryMapper.java @@ -0,0 +1,34 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.DeviceRunningStatusHistory; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 设备历史状态 + */ +@Repository +public interface DeviceStatusHistoryMapper extends BaseMapperX { + + @Select("") + List selectLatestByDeviceIds(@Param("deviceIds") List deviceIds); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceUserMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceUserMapper.java new file mode 100644 index 0000000..2c402e9 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/DeviceUserMapper.java @@ -0,0 +1,96 @@ +package com.maibu.mapper; + +import com.fastbee.common.core.domain.entity.SysUser; +import com.fastbee.iot.domain.DeviceUser; +import com.fastbee.iot.model.UserIdDeviceIdModel; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 设备用户Mapper接口 + * + * @author kerwincui + * @date 2021-12-16 + */ +@Repository +public interface DeviceUserMapper +{ + /** + * 查询设备用户 + * + * @param deviceId 设备用户主键 + * @return 设备用户 + */ + public DeviceUser selectDeviceUserByDeviceId(Long deviceId); + + /** + * 查询设备用户列表 + * + * @param deviceUser 设备用户 + * @return 设备用户集合 + */ + public List selectDeviceUserList(DeviceUser deviceUser); + + /** + * 查询设备分享用户 + * + * @param deviceUser 设备用户 + * @return 设备用户集合 + */ + public SysUser selectShareUser(DeviceUser deviceUser); + + /** + * 新增设备用户 + * + * @param deviceUser 设备用户 + * @return 结果 + */ + public int insertDeviceUser(DeviceUser deviceUser); + + /** + * 修改设备用户 + * + * @param deviceUser 设备用户 + * @return 结果 + */ + public int updateDeviceUser(DeviceUser deviceUser); + + /** + * 删除设备用户 + * + * @param UserIdDeviceIdModel 用户ID和设备ID + * @return 结果 + */ + public int deleteDeviceUserByDeviceId(UserIdDeviceIdModel UserIdDeviceIdModel); + + /** + * 批量删除设备用户 + * + * @param deviceIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteDeviceUserByDeviceIds(Long[] deviceIds); + + /** + * 批量添加设备用户 + * @param deviceUsers 设备用户 + * @return 结果 + */ + public int insertDeviceUserList(List deviceUsers); + + /** + * 根据deviceId 和 userId 查询 + * @param deviceId 设备id + * @param userId 用户id + * @return 结果 + */ + public DeviceUser selectDeviceUserByDeviceIdAndUserId(@Param("deviceId") Long deviceId, @Param("userId") Long userId); + + /** + * 根据deviceId 和 userId 删除设备用户,不包含设备所有者 + */ + public int deleteDeviceUser(DeviceUser deviceUser); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/EventLogMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/EventLogMapper.java new file mode 100644 index 0000000..fbe1c4f --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/EventLogMapper.java @@ -0,0 +1,27 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.EventLog; +import com.fastbee.iot.model.HistoryModel; + +import java.util.List; + +/** + * 事件日志Mapper接口 + * + * @author kerwincui + * @date 2024-08-16 + */ +public interface EventLogMapper extends BaseMapperX +{ + + /** + * 查询物模型历史数据 + * @param eventLog 事件日志 + * @return java.util.List + */ + List listHistory(EventLog eventLog); + + Long selectEventLogCount(Long userId); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FirmwareMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FirmwareMapper.java new file mode 100644 index 0000000..3315140 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FirmwareMapper.java @@ -0,0 +1,34 @@ +package com.maibu.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.fastbee.iot.domain.Firmware; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 产品固件Mapper接口 + * + * @author kerwincui + * @date 2024-08-18 + */ +public interface FirmwareMapper extends BaseMapper +{ + + + /** + * 查询设备最新固件 + * @param deviceId 产品固件主键 + * @param firmwareType 固件类型 + * @return 产品固件 + */ + Firmware selectLatestFirmware(@Param("deviceId") Long deviceId, @Param("firmwareType") Long firmwareType); + + + /** + * 查询待升级固件版本列表 + * @param firmware + * @return + */ + List selectUpGradeVersionList(Firmware firmware); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FirmwareTaskDetailMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FirmwareTaskDetailMapper.java new file mode 100644 index 0000000..46582da --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FirmwareTaskDetailMapper.java @@ -0,0 +1,34 @@ +package com.maibu.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.fastbee.iot.domain.FirmwareTaskDetail; +import com.fastbee.iot.model.FirmwareTaskDetailInput; +import com.fastbee.iot.model.FirmwareTaskDetailOutput; +import com.fastbee.iot.model.FirmwareTaskDeviceStatistic; + +import java.util.List; + +/** + * 固件升级任务详细对象Mapper接口 + * + * @author kerwincui + * @date 2024-08-18 + */ +public interface FirmwareTaskDetailMapper extends BaseMapper +{ + + /** + * 根据固件id查询下属设备列表 + * @param firmwareTaskDetailInput + * @return + */ + public List selectFirmwareTaskDetailListByFirmwareId(FirmwareTaskDetailInput firmwareTaskDetailInput); + + + /** + * 固件升级设备统计 + * @param firmwareTaskDetailInput + * @return + */ + public List deviceStatistic(FirmwareTaskDetailInput firmwareTaskDetailInput); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FirmwareTaskMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FirmwareTaskMapper.java new file mode 100644 index 0000000..7edd927 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FirmwareTaskMapper.java @@ -0,0 +1,24 @@ +package com.maibu.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.fastbee.iot.domain.FirmwareTask; +import org.apache.ibatis.annotations.Param; + +/** + * 固件升级任务对象Mapper接口 + * + * @author kerwincui + * @date 2024-08-18 + */ +public interface FirmwareTaskMapper extends BaseMapper +{ + + + /** + * 根据任务名称查询固件升级任务总数 + * @param firmwareId 固件id + * @param taskName 固件升级任务名称 + * @return 固件升级任务 + */ + public int selectCountFirmwareTaskByTaskName(@Param("firmwareId") Long firmwareId, @Param("taskName") String taskName); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FunctionLogMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FunctionLogMapper.java new file mode 100644 index 0000000..f7eddc8 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/FunctionLogMapper.java @@ -0,0 +1,124 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.FunctionLog; +import com.fastbee.iot.model.HistoryModel; +import com.fastbee.iot.model.ThingsModelLogCountVO; +import com.fastbee.iot.model.param.DataCenterParam; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 设备服务下发日志Mapper接口 + * + * @author kerwincui + * @date 2022-10-22 + */ +@Repository +public interface FunctionLogMapper +{ + /** + * 查询设备服务下发日志 + * + * @param id 设备服务下发日志主键 + * @return 设备服务下发日志 + */ + public FunctionLog selectFunctionLogById(Long id); + + /** + * 查询设备服务下发日志列表 + * + * @param functionLog 设备服务下发日志 + * @return 设备服务下发日志集合 + */ + public List selectFunctionLogList(FunctionLog functionLog); + + /** + * 新增设备服务下发日志 + * + * @param functionLog 设备服务下发日志 + * @return 结果 + */ + public int insertFunctionLog(FunctionLog functionLog); + + /** + * 批量插入数据 + * @param list + */ + public void insertBatch(List list); + + /** + * 修改设备服务下发日志 + * + * @param functionLog 设备服务下发日志 + * @return 结果 + */ + public int updateFunctionLog(FunctionLog functionLog); + + /** + * 删除设备服务下发日志 + * + * @param id 设备服务下发日志主键 + * @return 结果 + */ + public int deleteFunctionLogById(Long id); + + /** + * 根据设备编号删除设备服务下发日志 + * + * @param serialNumber 设备编号 + * @return 结果 + */ + public int deleteFunctionLogBySerialNumber(String serialNumber); + + /** + * 根据标识符前缀和设备编号批量删除日志 + * + * @param + * @return 结果 + */ + public int deleteFunctionLogByPreIdentify(FunctionLog functionLog); + + /** + * 批量删除设备服务下发日志 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteFunctionLogByIds(Long[] ids); + + /** + * 批量更新日志状态值 + * @param log 参数 + */ + public void updateFuncLogBatch(FunctionLog log); + + /** + * 根据消息id更新指令下发状态 + * @param log + */ + public void updateByMessageId(FunctionLog log); + + /** + * 查询物模型历史数据 + * @param functionLog 功能日志 + * @return java.util.List + */ + List listHistory(FunctionLog functionLog); + + /** + * 统计设备物模型指令下发数量 + * @param dataCenterParam 传参 + * @return com.fastbee.common.core.domain.AjaxResult + */ + List countThingsModelInvoke(DataCenterParam dataCenterParam); + + /** + * 根据消息id获取指令日志 + * @param messageId + * @return + */ + FunctionLog selectLogByMessageId(String messageId); + + Long selectFunctionLogCount(Long userId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/GoviewProjectDataMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/GoviewProjectDataMapper.java new file mode 100644 index 0000000..b445351 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/GoviewProjectDataMapper.java @@ -0,0 +1,74 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.GoviewProjectData; +import org.springframework.stereotype.Repository; + +import java.util.LinkedHashMap; +import java.util.List; + +/** + * 项目数据关联Mapper接口 + * + * @author kami + * @date 2022-10-27 + */ +@Repository +public interface GoviewProjectDataMapper +{ + /** + * 查询项目数据关联 + * + * @param id 项目数据关联主键 + * @return 项目数据关联 + */ + public GoviewProjectData selectGoviewProjectDataById(String id); + + /** + * 查询项目数据关联列表 + * + * @param goviewProjectData 项目数据关联 + * @return 项目数据关联集合 + */ + public List selectGoviewProjectDataList(GoviewProjectData goviewProjectData); + + /** + * 新增项目数据关联 + * + * @param goviewProjectData 项目数据关联 + * @return 结果 + */ + public int insertGoviewProjectData(GoviewProjectData goviewProjectData); + + /** + * 修改项目数据关联 + * + * @param goviewProjectData 项目数据关联 + * @return 结果 + */ + public int updateGoviewProjectData(GoviewProjectData goviewProjectData); + + /** + * 删除项目数据关联 + * + * @param id 项目数据关联主键 + * @return 结果 + */ + public int deleteGoviewProjectDataById(String id); + + /** + * 批量删除项目数据关联 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteGoviewProjectDataByIds(String[] ids); + + GoviewProjectData selectGoviewProjectDataByProjectId(String projectId); + + /** + * 根据sql获取组件数据接口 + * @param sql sql + * @return 组件数据 + */ + List executeSql(String sql); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/GoviewProjectMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/GoviewProjectMapper.java new file mode 100644 index 0000000..f249676 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/GoviewProjectMapper.java @@ -0,0 +1,64 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.GoviewProject; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 项目Mapper接口 + * + * @author kami + * @date 2022-10-27 + */ +@Repository +public interface GoviewProjectMapper +{ + /** + * 查询项目 + * + * @param id 项目主键 + * @return 项目 + */ + public GoviewProject selectGoviewProjectById(String id); + + /** + * 查询项目列表 + * + * @param goviewProject 项目 + * @return 项目集合 + */ + public List selectGoviewProjectList(GoviewProject goviewProject); + + /** + * 新增项目 + * + * @param goviewProject 项目 + * @return 结果 + */ + public int insertGoviewProject(GoviewProject goviewProject); + + /** + * 修改项目 + * + * @param goviewProject 项目 + * @return 结果 + */ + public int updateGoviewProject(GoviewProject goviewProject); + + /** + * 删除项目 + * + * @param id 项目主键 + * @return 结果 + */ + public int deleteGoviewProjectById(String id); + + /** + * 批量删除项目 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteGoviewProjectByIds(String[] ids); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/GroupMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/GroupMapper.java new file mode 100644 index 0000000..1c7b6a0 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/GroupMapper.java @@ -0,0 +1,103 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.Group; +import com.fastbee.iot.model.DeviceGroupInput; +import com.fastbee.iot.model.IdOutput; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Set; + +/** + * 设备分组Mapper接口 + * + * @author kerwincui + * @date 2021-12-16 + */ +@Repository +public interface GroupMapper +{ + /** + * 查询设备分组 + * + * @param groupId 设备分组主键 + * @return 设备分组 + */ + public Group selectGroupByGroupId(Long groupId); + + /** + * 通过分组ID查询关联的设备ID数组 + * @param groupId + * @return + */ + public List selectDeviceIdsByGroupId(Long groupId); + + /** + * 查询设备分组列表 + * + * @param group 设备分组 + * @return 设备分组集合 + */ + public List selectGroupList(Group group); + + /** + * 新增设备分组 + * + * @param group 设备分组 + * @return 结果 + */ + public int insertGroup(Group group); + + /** + * 分组下批量增加设备分组 + * @param input + * @return + */ + public int insertDeviceGroups(DeviceGroupInput input); + + /** + * 修改设备分组 + * + * @param group 设备分组 + * @return 结果 + */ + public int updateGroup(Group group); + + /** + * 删除设备分组 + * + * @param groupId 设备分组主键 + * @return 结果 + */ + public int deleteGroupByGroupId(Long groupId); + + /** + * 批量删除分组 + * + * @param groupIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteGroupByGroupIds(Long[] groupIds); + + /** + * 批量删除设备分组 + * @param groupIds + * @return + */ + public int deleteDeviceGroupByGroupIds(Long[] groupIds); + + /** + * 根据用户Id查询分组列表 + * @param userId 用户id + * @return 分组列表 + */ + List selectGroupListByUserId(Long userId); + + /** + * 查询设备分组 根据分组Id + * + * @return 分组列表 + */ + List listAllByIdList(Set groupIds); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/IoTCommonDevicesMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/IoTCommonDevicesMapper.java new file mode 100644 index 0000000..8f3a58e --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/IoTCommonDevicesMapper.java @@ -0,0 +1,13 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.IoTCommonDevice; +import org.springframework.stereotype.Repository; + +/** + * 一般设备 + */ +@Repository +public interface IoTCommonDevicesMapper extends BaseMapperX { + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ModbusConfigMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ModbusConfigMapper.java new file mode 100644 index 0000000..ea8564e --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ModbusConfigMapper.java @@ -0,0 +1,92 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.ModbusConfig; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * modbus配置Mapper接口 + * + * @author kerwincui + * @date 2024-05-22 + */ +public interface ModbusConfigMapper +{ + /** + * 查询modbus配置 + * + * @param id modbus配置主键 + * @return modbus配置 + */ + public ModbusConfig selectModbusConfigById(Long id); + + /** + * 查询modbus配置列表 + * + * @param modbusConfig modbus配置 + * @return modbus配置集合 + */ + public List selectModbusConfigList(ModbusConfig modbusConfig); + + /** + * 新增modbus配置 + * + * @param modbusConfig modbus配置 + * @return 结果 + */ + public int insertModbusConfig(ModbusConfig modbusConfig); + + /** + * 修改modbus配置 + * + * @param modbusConfig modbus配置 + * @return 结果 + */ + public int updateModbusConfig(ModbusConfig modbusConfig); + + /** + * 批量添加modbus配置 + * @param list + * @return + */ + int insertModbusConfigBatch(List list); + + /** + * 批量更新modbus配置 + * @param list + * @return + */ + int updateModbusConfigBatch(List list); + + /** + * 删除modbus配置 + * + * @param id modbus配置主键 + * @return 结果 + */ + public int deleteModbusConfigById(Long id); + + /** + * 批量删除modbus配置 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteModbusConfigByIds(Long[] ids); + + /** + * 根据产品id和标识符获取modbus配置 + * @param productId + * @param identity + * @return + */ + public ModbusConfig selectByIdentify(@Param("productId") Long productId, @Param("identity") String identity); + + /** + * 获取modbus配置简要字段 + * @param config + * @return + */ + public List selectShortListByProductId(ModbusConfig config); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ModbusJobMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ModbusJobMapper.java new file mode 100644 index 0000000..702ba40 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ModbusJobMapper.java @@ -0,0 +1,63 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.ModbusJob; + +import java.util.List; + +/** + * 轮训任务列Mapper接口 + * + * @author kerwincui + * @date 2024-07-05 + */ +public interface ModbusJobMapper +{ + /** + * 查询轮训任务列 + * + * @param taskId 轮训任务列主键 + * @return 轮训任务列 + */ + public ModbusJob selectModbusJobByTaskId(Long taskId); + + /** + * 查询轮训任务列列表 + * + * @param modbusJob 轮训任务列 + * @return 轮训任务列集合 + */ + public List selectModbusJobList(ModbusJob modbusJob); + + /** + * 新增轮训任务列 + * + * @param modbusJob 轮训任务列 + * @return 结果 + */ + public int insertModbusJob(ModbusJob modbusJob); + + /** + * 修改轮训任务列 + * + * @param modbusJob 轮训任务列 + * @return 结果 + */ + public int updateModbusJob(ModbusJob modbusJob); + + /** + * 删除轮训任务列 + * + * @param taskId 轮训任务列主键 + * @return 结果 + */ + public int deleteModbusJobByTaskId(Long taskId); + + /** + * 批量删除轮训任务列 + * + * @param taskIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteModbusJobByTaskIds(Long[] taskIds); + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ModbusParamsMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ModbusParamsMapper.java new file mode 100644 index 0000000..a0f3604 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ModbusParamsMapper.java @@ -0,0 +1,25 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.ModbusParams; + +/** + * 产品modbus配置参数Mapper接口 + * @date 2024-08-20 + */ +public interface ModbusParamsMapper extends BaseMapperX +{ + /** + * 根据产品io获取modbus配置 + * @param productId + * @return + */ + ModbusParams getModbusParamsByProductId(Long productId); + + /** + * 根据设备id获取modbus配置 + * @param deviceId + * @return + */ + ModbusParams getModbusParamsByDeviceId(Long deviceId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/MqttClientMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/MqttClientMapper.java new file mode 100644 index 0000000..990884c --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/MqttClientMapper.java @@ -0,0 +1,62 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.MqttClient; + +import java.util.List; + +/** + * mqtt桥接配置表Mapper接口 + * + * @author gx_ma + * @date 2024-06-03 + */ +public interface MqttClientMapper +{ + /** + * 查询mqtt桥接配置表 + * + * @param id mqtt桥接配置表主键 + * @return mqtt桥接配置表 + */ + public MqttClient selectMqttClientById(Long id); + + /** + * 查询mqtt桥接配置表列表 + * + * @param mqttClient mqtt桥接配置表 + * @return mqtt桥接配置表集合 + */ + public List selectMqttClientList(MqttClient mqttClient); + + /** + * 新增mqtt桥接配置表 + * + * @param mqttClient mqtt桥接配置表 + * @return 结果 + */ + public int insertMqttClient(MqttClient mqttClient); + + /** + * 修改mqtt桥接配置表 + * + * @param mqttClient mqtt桥接配置表 + * @return 结果 + */ + public int updateMqttClient(MqttClient mqttClient); + + /** + * 删除mqtt桥接配置表 + * + * @param id mqtt桥接配置表主键 + * @return 结果 + */ + public int deleteMqttClientById(Long id); + + /** + * 批量删除mqtt桥接配置表 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteMqttClientByIds(Long[] ids); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/NewsCategoryMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/NewsCategoryMapper.java new file mode 100644 index 0000000..2564228 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/NewsCategoryMapper.java @@ -0,0 +1,80 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.NewsCategory; +import com.fastbee.iot.model.IdAndName; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 新闻分类Mapper接口 + * + * @author kerwincui + * @date 2022-04-09 + */ +@Repository +public interface NewsCategoryMapper +{ + /** + * 查询新闻分类 + * + * @param categoryId 新闻分类主键 + * @return 新闻分类 + */ + public NewsCategory selectNewsCategoryByCategoryId(Long categoryId); + + /** + * 查询新闻分类列表 + * + * @param newsCategory 新闻分类 + * @return 新闻分类集合 + */ + public List selectNewsCategoryList(NewsCategory newsCategory); + + /** + * 查询新闻分类简短列表 + * + * @return 新闻分类集合 + */ + public List selectNewsCategoryShortList(); + + /** + * 新增新闻分类 + * + * @param newsCategory 新闻分类 + * @return 结果 + */ + public int insertNewsCategory(NewsCategory newsCategory); + + /** + * 修改新闻分类 + * + * @param newsCategory 新闻分类 + * @return 结果 + */ + public int updateNewsCategory(NewsCategory newsCategory); + + /** + * 删除新闻分类 + * + * @param categoryId 新闻分类主键 + * @return 结果 + */ + public int deleteNewsCategoryByCategoryId(Long categoryId); + + /** + * 批量删除新闻分类 + * + * @param categoryIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteNewsCategoryByCategoryIds(Long[] categoryIds); + + /** + * 分类下的新闻数量 + * + * @param categoryIds 需要删除的数据主键集合 + * @return 结果 + */ + public int newsCountInCategorys(Long[] categoryIds); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/NewsMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/NewsMapper.java new file mode 100644 index 0000000..ee57a7c --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/NewsMapper.java @@ -0,0 +1,71 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.News; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 新闻资讯Mapper接口 + * + * @author kerwincui + * @date 2022-04-09 + */ +@Repository +public interface NewsMapper +{ + /** + * 查询新闻资讯 + * + * @param newsId 新闻资讯主键 + * @return 新闻资讯 + */ + public News selectNewsByNewsId(Long newsId); + + /** + * 查询新闻资讯列表 + * + * @param news 新闻资讯 + * @return 新闻资讯集合 + */ + public List selectNewsList(News news); + + /** + * 查询置顶新闻资讯列表 + * + * @return 新闻资讯集合 + */ + public List selectTopNewsList(); + + /** + * 新增新闻资讯 + * + * @param news 新闻资讯 + * @return 结果 + */ + public int insertNews(News news); + + /** + * 修改新闻资讯 + * + * @param news 新闻资讯 + * @return 结果 + */ + public int updateNews(News news); + + /** + * 删除新闻资讯 + * + * @param newsId 新闻资讯主键 + * @return 结果 + */ + public int deleteNewsByNewsId(Long newsId); + + /** + * 批量删除新闻资讯 + * + * @param newsIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteNewsByNewsIds(Long[] newsIds); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/OrderControlMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/OrderControlMapper.java new file mode 100644 index 0000000..65f5b54 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/OrderControlMapper.java @@ -0,0 +1,70 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.OrderControl; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 指令权限控制Mapper接口 + * + * @author kerwincui + * @date 2024-07-01 + */ +public interface OrderControlMapper +{ + /** + * 查询指令权限控制 + * + * @param id 指令权限控制主键 + * @return 指令权限控制 + */ + public OrderControl selectOrderControlById(Long id); + + /** + * 查询指令权限控制列表 + * + * @param orderControl 指令权限控制 + * @return 指令权限控制集合 + */ + public List selectOrderControlList(OrderControl orderControl); + + /** + * 新增指令权限控制 + * + * @param orderControl 指令权限控制 + * @return 结果 + */ + public int insertOrderControl(OrderControl orderControl); + + /** + * 修改指令权限控制 + * + * @param orderControl 指令权限控制 + * @return 结果 + */ + public int updateOrderControl(OrderControl orderControl); + + /** + * 删除指令权限控制 + * + * @param id 指令权限控制主键 + * @return 结果 + */ + public int deleteOrderControlById(Long id); + + /** + * 批量删除指令权限控制 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteOrderControlByIds(Long[] ids); + + /** + * 根据用户id获取 + * @param userId + * @return + */ + List selectByUserId(@Param("userId") Long userId,@Param("deviceId") Long deviceId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductAuthorizeMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductAuthorizeMapper.java new file mode 100644 index 0000000..a94ae19 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductAuthorizeMapper.java @@ -0,0 +1,93 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.ProductAuthorize; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 产品授权码Mapper接口 + * + * @author kami + * @date 2022-04-11 + */ +@Repository +public interface ProductAuthorizeMapper +{ + /** + * 查询产品授权码 + * + * @param authorizeId 产品授权码主键 + * @return 产品授权码 + */ + public ProductAuthorize selectProductAuthorizeByAuthorizeId(Long authorizeId); + + /** + * 查询产品授权码列表 + * + * @param productAuthorize 产品授权码 + * @return 产品授权码集合 + */ + public List selectProductAuthorizeList(ProductAuthorize productAuthorize); + + /** + * 新增产品授权码 + * + * @param productAuthorize 产品授权码 + * @return 结果 + */ + public int insertProductAuthorize(ProductAuthorize productAuthorize); + + /** + * 修改产品授权码 + * + * @param productAuthorize 产品授权码 + * @return 结果 + */ + public int updateProductAuthorize(ProductAuthorize productAuthorize); + + /** + * 删除产品授权码 + * + * @param authorizeId 产品授权码主键 + * @return 结果 + */ + public int deleteProductAuthorizeByAuthorizeId(Long authorizeId); + + /** + * 批量删除产品授权码 + * + * @param authorizeIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteProductAuthorizeByAuthorizeIds(Long[] authorizeIds); + + /** + * 通过产品ID批量删除产品授权码 + * + * @param productIds 产品ID数组 + * @return 结果 + */ + public int deleteProductAuthorizeByProductIds(Long[] productIds); + + /** + * 批量新增产品授权码 + * @param list + * @return + */ + public int insertBatchAuthorize(List list); + + /** + * 根据授权码查询一条未绑定的授权码 + * @param authorize + * @return + */ + ProductAuthorize selectFirstAuthorizeByAuthorizeCode(ProductAuthorize authorize); + + /** + * 根据产品id查询产品授权码 + * @param productId 产品id + * @return + */ + List selectProductAuthorizeListByProductId(Long productId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductMapper.java new file mode 100644 index 0000000..dd7f3aa --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductMapper.java @@ -0,0 +1,176 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.Product; +import com.fastbee.iot.model.ChangeProductStatusModel; +import com.fastbee.iot.model.IdAndName; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 产品Mapper接口 + * + * @author kerwincui + * @date 2021-12-16 + */ +@Repository +public interface ProductMapper +{ + /** + * 查询产品 + * + * @param productId 产品主键 + * @return 产品 + */ + public Product selectProductByProductId(Long productId); + + /** + * 查询产品列表 + * + * @param product 产品 + * @return 产品集合 + */ + public List selectProductList(Product product); + + /** + * 查询产品简短列表 + * + * @param product 产品 + * @return 产品集合 + */ + public List selectProductShortList(Product product); + + /** + * 新增产品 + * + * @param product 产品 + * @return 结果 + */ + public int insertProduct(Product product); + + /** + * 修改产品 + * + * @param product 产品 + * @return 结果 + */ + public int updateProduct(Product product); + + /** + * 更新产品状态,1-未发布,2-已发布 + * + * @param model + * @return 结果 + */ + public int changeProductStatus(ChangeProductStatusModel model); + + /** + * 修改物模型JSON + * + * @param product 产品 + * @return 结果 + */ + public int updateThingsModelJson(Product product); + + /** + * 删除产品 + * + * @param productId 产品主键 + * @return 结果 + */ + public int deleteProductByProductId(Long productId); + + /** + * 批量删除产品 + * + * @param productIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteProductByProductIds(Long[] productIds); + + /** + * 批量删除产品物模型 + * + * @param productIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteProductThingsModelByProductIds(Long[] productIds); + + /** + * 产品下的固件数量 + * @param productIds 需要删除的数据主键集合 + * @return 结果 + */ + public int firmwareCountInProducts(Long[] productIds); + + /** + * 产品下的设备数量 + * @param productIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deviceCountInProducts(Long[] productIds); + + /** + * 产品下的物模型数量 + * @param productId 需要删除的数据主键集合 + * @return 结果 + */ + public int thingsCountInProduct(Long productId); + + /** + * 产品下的物模型标识符重复数 + * @param productId 需要删除的数据主键集合 + * @return 结果 + */ + public int thingsRepeatCountInProduct(Long productId); + + /** + * 根据产品id获取协议编号 + * @param productId 产品id + * @return 协议编号 + */ + public String getProtocolByProductId(Long productId); + + /** + * 根据模板id查询所有使用的产品 + * @param templeId 模板id + * @return + */ + public List selectByTempleId(Long templeId); + + /** + * 查询产品图片 + * @param productId 产品id + * @return java.lang.String + */ + String selectImgUrlByProductId(Long productId); + + /** + * 查询终端用户产品 + * @param product + * @return java.util.List + */ + List selectTerminalUserProduct(Product product); + + + /** + * 根据产品id获取关联组态guid + * @param productId + * @return guid + */ + String selectGuidByProductId(Long productId); + + /** + * 查询组态信息 + * @param guidList 组态id集合 + * @return java.util.List + */ + List selectListScadaIdByGuidS(@Param("guidList") List guidList); + /** + * @description: + * @param: productIdList 产品id集合 + * @return: java.util.List + */ + List selectProductListByProductIds(@Param("productIdList") List productIdList); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductModbusJobMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductModbusJobMapper.java new file mode 100644 index 0000000..7bca69b --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductModbusJobMapper.java @@ -0,0 +1,15 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.ProductModbusJob; + +/** + * 产品轮训任务列Mapper接口 + * + * @author zhuangpeng.li + * @date 2024-09-04 + */ +public interface ProductModbusJobMapper extends BaseMapperX +{ + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductSubGatewayMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductSubGatewayMapper.java new file mode 100644 index 0000000..65a54f1 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProductSubGatewayMapper.java @@ -0,0 +1,24 @@ +package com.maibu.mapper; + +import com.fastbee.framework.mybatis.mapper.BaseMapperX; +import com.fastbee.iot.domain.ProductSubGateway; +import com.fastbee.iot.model.gateWay.ProductSubGatewayVO; + +import java.util.List; + +/** + * 网关与子产品关联Mapper接口 + * + * @author zhuangpeng.li + * @date 2024-09-04 + */ +public interface ProductSubGatewayMapper extends BaseMapperX +{ + + /** + * @description: 查询网关 + * @param: productSubGateway 网关 + * @return: java.util.List + */ + List selectListVO(ProductSubGateway productSubGateway); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProtocolMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProtocolMapper.java new file mode 100644 index 0000000..9191e09 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ProtocolMapper.java @@ -0,0 +1,80 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.Protocol; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 协议管理Mapper + * @author gsb + * @date 2022/10/19 15:46 + */ +@Repository +public interface ProtocolMapper { + + + /** + * 查询协议 + * + * @param id 协议主键 + * @return 协议 + */ + public Protocol selectProtocolById(Long id); + + /** + * 查询协议列表 + * + * @param protocol 协议 + * @return 协议集合 + */ + public List selectProtocolList(Protocol protocol); + + /** + * 新增协议 + * + * @param protocol 协议 + * @return 结果 + */ + public int insertProtocol(Protocol protocol); + + /** + * 修改协议 + * + * @param protocol 协议 + * @return 结果 + */ + public int updateProtocol(Protocol protocol); + + /** + * 删除协议 + * + * @param id 协议主键 + * @return 结果 + */ + public int deleteProtocolById(Long id); + + /** + * 批量删除协议 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteProtocolByIds(Long[] ids); + + /** + * 获取所有唯一协议 + * @param protocol + * @return + */ + public List selectByUnion(Protocol protocol); + + /** + * 获取所有可用协议 + * @param status + * @param delFlag + * @return + */ + public List selectAll(@Param("status") Integer status, @Param("delFlag") Integer delFlag); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneDeviceMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneDeviceMapper.java new file mode 100644 index 0000000..92f5b6c --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneDeviceMapper.java @@ -0,0 +1,113 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.Scene; +import com.fastbee.iot.domain.SceneDevice; +import com.fastbee.iot.model.SceneDeviceBindVO; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 场景设备Mapper接口 + * + * @author kerwincui + * @date 2023-12-28 + */ +@Repository +public interface SceneDeviceMapper +{ + /** + * 查询场景设备 + * + * @param sceneDeviceId 场景设备主键 + * @return 场景设备 + */ + public SceneDevice selectSceneDeviceBySceneDeviceId(Long sceneDeviceId); + + /** + * 查询场景设备列表 + * + * @param sceneDevice 场景设备 + * @return 场景设备集合 + */ + public List selectSceneDeviceList(SceneDevice sceneDevice); + + /** + * 新增场景设备 + * + * @param sceneDevice 场景设备 + * @return 结果 + */ + public int insertSceneDevice(SceneDevice sceneDevice); + + /** + * 修改场景设备 + * + * @param sceneDevice 场景设备 + * @return 结果 + */ + public int updateSceneDevice(SceneDevice sceneDevice); + + /** + * 删除场景设备 + * + * @param sceneDeviceId 场景设备主键 + * @return 结果 + */ + public int deleteSceneDeviceBySceneDeviceId(Long sceneDeviceId); + + /** + * 批量删除场景设备 + * + * @param sceneDeviceIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSceneDeviceBySceneDeviceIds(Long[] sceneDeviceIds); + + /** + * 批量删除场景设备 + * + * @param sceneIds 需要删除的数据场景ID集合 + * @return 结果 + */ + public int deleteSceneDeviceBySceneIds(Long[] sceneIds); + + /** + * 批量新增场景脚本 + * + * @param sceneDeviceList 场景联动触发器集合 + * @return 结果 + */ + public int insertSceneDeviceList(List sceneDeviceList); + + /** + * 查询设备关联的场景列表 + * + * @param sceneDevice 场景设备 + * @return 场景设备集合 + */ + public List selectTriggerDeviceRelateScenes(SceneDevice sceneDevice); + + /** + * 查询场景联动绑定产品 + * @param productIds 产品id数组 + * @return java.util.List + */ + List listSceneProductBind(Long[] productIds); + + /** + * 查询场景联动绑定设备 + * @param serialNumber 设备编号 + * @return java.util.List + */ + List listSceneDeviceBind(String serialNumber); + + /** + * 查询设备用户对应的场景 + * @param serialNumber 设备编号 + * @param: userIdList + * @return java.lang.Long[] + */ + Long[] listSceneIdByDeviceIdAndUserId(@Param("serialNumber") String serialNumber, @Param("userIdList") List userIdList); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneMapper.java new file mode 100644 index 0000000..54f591f --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneMapper.java @@ -0,0 +1,81 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.Scene; +import com.fastbee.iot.model.SceneTerminalUserVO; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Set; + +/** + * 场景联动Mapper接口 + * + * @author kerwincui + * @date 2022-01-13 + */ +@Repository +public interface SceneMapper +{ + /** + * 查询场景联动 + * + * @param sceneId 场景联动主键 + * @return 场景联动 + */ + public Scene selectSceneBySceneId(Long sceneId); + + /** + * 查询场景联动列表 + * + * @param scene 场景联动 + * @return 场景联动集合 + */ + public List selectSceneList(Scene scene); + + /** + * 新增场景联动 + * + * @param scene 场景联动 + * @return 结果 + */ + public int insertScene(Scene scene); + + + /** + * 修改场景联动 + * + * @param scene 场景联动 + * @return 结果 + */ + public int updateScene(Scene scene); + + /** + * 删除场景联动 + * + * @param sceneId 场景联动主键 + * @return 结果 + */ + public int deleteSceneBySceneId(Long sceneId); + + /** + * 批量删除场景联动 + * + * @param sceneIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSceneBySceneIds(Long[] sceneIds); + + /** + * 根据ids批量查询场景联动 + * @param sceneIds 场景联动id数组 + * @return 集合 + */ + List selectSceneListBySceneIds(Long[] sceneIds); + + /** + * 查询场景用户信息 + * @param sceneIdSet 场景id + * @return java.util.List + */ + List selectTerminalUserBySceneIds(Set sceneIdSet); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelDataMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelDataMapper.java new file mode 100644 index 0000000..09e66d3 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelDataMapper.java @@ -0,0 +1,182 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.SceneModelData; +import com.fastbee.iot.model.scenemodel.SceneDeviceThingsModelVO; +import com.fastbee.iot.model.scenemodel.SceneModelDataDTO; +import com.fastbee.iot.model.scenemodel.SceneModelDeviceVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 【请填写功能名称】Mapper接口 + * + * @author kerwincui + * @date 2024-05-21 + */ +public interface SceneModelDataMapper +{ + /** + * 查询【请填写功能名称】 + * + * @param id 【请填写功能名称】主键 + * @return 【请填写功能名称】 + */ + public SceneModelData selectSceneModelDataById(Long id); + + /** + * 查询【请填写功能名称】列表 + * + * @param sceneModelData 【请填写功能名称】 + * @return 【请填写功能名称】集合 + */ + public List selectSceneModelDataList(SceneModelData sceneModelData); + + /** + * 新增【请填写功能名称】 + * + * @param sceneModelData 【请填写功能名称】 + * @return 结果 + */ + public int insertSceneModelData(SceneModelData sceneModelData); + + /** + * 修改【请填写功能名称】 + * + * @param sceneModelData 【请填写功能名称】 + * @return 结果 + */ + public int updateSceneModelData(SceneModelData sceneModelData); + + /** + * 删除【请填写功能名称】 + * + * @param id 【请填写功能名称】主键 + * @return 结果 + */ + public int deleteSceneModelDataById(Long id); + + /** + * 批量删除【请填写功能名称】 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSceneModelDataByIds(Long[] ids); + + /** + * 查询场景关联设备物模型变量 + * @param datasourceId + * @return + */ + List listBySourceIdAndType(Long datasourceId); + + /** + * 删除场景关联设备物模型变量 + * @param datasourceIds + * @return void + */ + void deleteThingsModelByDatasourceId(Long[] datasourceIds); + + /** + * 批量删除场景变量 + * @param sceneModelIds + * @return void + */ + void deleteBySceneModelIds(Long[] sceneModelIds); + + /** + * 更新关联设备变量所有启用状态 + * @param sceneModelData + * @return int + */ + int editAllEnable(SceneModelData sceneModelData); + + /** + * 删除设备关联变量 + * @param sceneModelDeviceIds 设备关联id + * @return void + */ + void deleteBySceneModelDeviceIds(Long[] sceneModelDeviceIds); + + /** + * 统计统一关联来源未启用 + * @param sceneModelDeviceId + * @return int + */ + int countNoEnableBySceneModelDeviceId(Long sceneModelDeviceId); + + void deleteBySourceIds(Long[] datasourceIds); + + /** + * 批量插入 + * @param sceneModelDataList 变量集合 + * @return int + */ + int insertBatchSceneModelData(@Param("sceneModelDataList") List sceneModelDataList); + + /** + * 查询变量 + * @param datasourceId + * @param: variableType + * @return com.fastbee.iot.domain.SceneModelData + */ + SceneModelData selectNoDeviceBySourceIdAndVariableType(@Param("datasourceId") Long datasourceId, @Param("variableType") Integer variableType); + + /** + * 查询关联设备 + * @param idList 变量id集合 + * @return com.fastbee.iot.model.scenemodel.SceneModelDeviceVO + */ + List selectSceneModelDeviceByDataIdList(@Param("idList") List idList); + + /** + * 查询单个物模型来源 + * @param id 主键 + * @return com.fastbee.iot.model.scenemodel.SceneDeviceThingsModelVO + */ + SceneDeviceThingsModelVO selectDeviceThingsModelById(Long id); + + /** + * 查询录入型变量默认值 + * @param id 主键id + * @return java.lang.String + */ + String selectInputTagDefaultValueById(Long id); + + /** + * 检查是否被应用到计算公式 + * @param datasourceId 数据源id + * @param: type + * @return int + */ + int checkIsApplyAliasFormule(@Param("datasourceId") Long datasourceId, @Param("variableType") Integer variableType); + + /** + * 批量查询 + * @param ids id集合 + * @return java.util.List + */ + List selectSceneModelDataListByIds(@Param("ids") List ids); + + /** + * 查询场景变量完整信息列表 + * @param sceneModelData 场景变量类 + * @return java.util.List + */ + List selectSceneModelDataDTOList(SceneModelData sceneModelData); + + /** + * 查询场景关联设备物模型 + * @param datasourceId 数据源id + * @return java.util.List + */ + List selectSceneDeviceThingsModelList(Long datasourceId); + + /** + * @description: 同步变量 + * @param: updateSceneModelData 变量信息 + * @return: void + */ + void updateSceneModelDataByDatasourceId(SceneModelData updateSceneModelData); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelDeviceMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelDeviceMapper.java new file mode 100644 index 0000000..8bbb069 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelDeviceMapper.java @@ -0,0 +1,105 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.SceneModelDevice; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 场景管理关联设备Mapper接口 + * + * @author kerwincui + * @date 2024-05-21 + */ +public interface SceneModelDeviceMapper +{ + /** + * 查询场景管理关联设备 + * + * @param id 场景管理关联设备主键 + * @return 场景管理关联设备 + */ + public SceneModelDevice selectSceneModelDeviceById(Long id); + + /** + * 查询场景管理关联设备列表 + * + * @param sceneModelDevice 场景管理关联设备 + * @return 场景管理关联设备集合 + */ + public List selectSceneModelDeviceList(SceneModelDevice sceneModelDevice); + + /** + * 新增场景管理关联设备 + * + * @param sceneModelDevice 场景管理关联设备 + * @return 结果 + */ + public int insertSceneModelDevice(SceneModelDevice sceneModelDevice); + + /** + * 修改场景管理关联设备 + * + * @param sceneModelDevice 场景管理关联设备 + * @return 结果 + */ + public int updateSceneModelDevice(SceneModelDevice sceneModelDevice); + + /** + * 删除场景管理关联设备 + * + * @param id 场景管理关联设备主键 + * @return 结果 + */ + public int deleteSceneModelDeviceById(Long id); + + /** + * 批量删除场景管理关联设备 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSceneModelDeviceByIds(Long[] ids); + + /** + * 查询关联未关联设备的设备配置 + * @return + */ + SceneModelDevice selectOneModelDevice(Long sceneModelId); + + /** + * 批量删除场景关联 + * @param sceneModelIds + * @return void + */ + void deleteBySceneModelIds(Long[] sceneModelIds); + + /** + * 更新全部启用状态 + * @param updateSceneModelDevice + * @return int + */ + int updateAllEnable(SceneModelDevice updateSceneModelDevice); + + /** + * 查询关联的录入、运算型 + * @param sceneModelId 场景id + * @param: variableType 类型 + * @return com.fastbee.iot.domain.SceneModelDevice + */ + SceneModelDevice selectOneNoDeviceBySceneModelId(@Param("sceneModelId") Long sceneModelId, @Param("variableType") Integer variableType); + + /** + * 校验是否有使用计算公式 + * @param id 主键 + * @return int + */ + int checkContainAliasFormule(Long id); + + /** + * 查询场景关联设备 + * @param productId 产品id + * @return java.util.List + */ + List listDeviceByProductId(Long productId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelMapper.java new file mode 100644 index 0000000..61ce711 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelMapper.java @@ -0,0 +1,84 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.SceneModel; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 场景管理Mapper接口 + * + * @author kerwincui + * @date 2024-05-20 + */ +public interface SceneModelMapper +{ + /** + * 查询场景管理 + * + * @param sceneModelId 场景管理主键 + * @return 场景管理 + */ + public SceneModel selectSceneModelBySceneModelId(Long sceneModelId); + + /** + * 查询场景管理列表 + * + * @param sceneModel 场景管理 + * @return 场景管理集合 + */ + public List selectSceneModelList(SceneModel sceneModel); + + /** + * 新增场景管理 + * + * @param sceneModel 场景管理 + * @return 结果 + */ + public int insertSceneModel(SceneModel sceneModel); + + /** + * 修改场景管理 + * + * @param sceneModel 场景管理 + * @return 结果 + */ + public int updateSceneModel(SceneModel sceneModel); + + /** + * 删除场景管理 + * + * @param sceneModelId 场景管理主键 + * @return 结果 + */ + public int deleteSceneModelBySceneModelId(Long sceneModelId); + + /** + * 批量删除场景管理 + * + * @param sceneModelIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSceneModelBySceneModelIds(Long[] sceneModelIds); + + /** + * 根据监控设备id获取场景 + * @param channelId + * @return + */ + SceneModel selectSceneModelByChannelId(String channelId); + + /** + * 查询组态信息 + * @param guidList 组态id集合 + * @return java.util.List + */ + List selectListScadaIdByGuidS(@Param("guidList") List guidList); + + /** + * 查询场景信息 + * @param sceneModelId 场景id + * @return com.fastbee.iot.domain.SceneModel + */ + SceneModel selectBySceneModelId(Long sceneModelId); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelTagMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelTagMapper.java new file mode 100644 index 0000000..4f91f48 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneModelTagMapper.java @@ -0,0 +1,84 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.SceneModelTag; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 场景录入型变量Mapper接口 + * + * @author kerwincui + * @date 2024-05-21 + */ +public interface SceneModelTagMapper +{ + /** + * 查询场景录入型变量 + * + * @param id 场景录入型变量主键 + * @return 场景录入型变量 + */ + public SceneModelTag selectSceneModelTagById(Long id); + + /** + * 查询场景录入型变量列表 + * + * @param sceneModelTag 场景录入型变量 + * @return 场景录入型变量集合 + */ + public List selectSceneModelTagList(SceneModelTag sceneModelTag); + + /** + * 新增场景录入型变量 + * + * @param sceneModelTag 场景录入型变量 + * @return 结果 + */ + public int insertSceneModelTag(SceneModelTag sceneModelTag); + + /** + * 修改场景录入型变量 + * + * @param sceneModelTag 场景录入型变量 + * @return 结果 + */ + public int updateSceneModelTag(SceneModelTag sceneModelTag); + + /** + * 删除场景录入型变量 + * + * @param id 场景录入型变量主键 + * @return 结果 + */ + public int deleteSceneModelTagById(Long id); + + /** + * 批量删除场景录入型变量 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSceneModelTagByIds(Long[] ids); + + /** + * 查询场景联动相关变量 + * @param idList id + * @return java.util.List + */ + List listSceneModelDataByIds(@Param("idList") List idList); + + /** + * 批量删除场景变量 + * @param sceneModelIds + * @return void + */ + void deleteBySceneModelIds(Long[] sceneModelIds); + + /** + * 校验变量名称唯一 + * @param sceneModelTag 场景变量 + * @return com.fastbee.iot.domain.SceneModelTag + */ + SceneModelTag checkName(SceneModelTag sceneModelTag); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneScriptMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneScriptMapper.java new file mode 100644 index 0000000..61debb6 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneScriptMapper.java @@ -0,0 +1,89 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.SceneScript; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 场景脚本Mapper接口 + * + * @author kerwincui + * @date 2023-12-27 + */ +@Repository +public interface SceneScriptMapper +{ + /** + * 查询场景脚本 + * + * @param scriptId 场景脚本主键 + * @return 场景脚本 + */ + public SceneScript selectSceneScriptBySceneScriptId(String scriptId); + + /** + * 查询场景脚本列表 + * + * @param sceneScript 场景脚本 + * @return 场景脚本集合 + */ + public List selectSceneScriptList(SceneScript sceneScript); + + /** + * 新增场景脚本 + * + * @param sceneScript 场景脚本 + * @return 结果 + */ + public int insertSceneScript(SceneScript sceneScript); + + /** + * 修改场景脚本 + * + * @param sceneScript 场景脚本 + * @return 结果 + */ + public int updateSceneScript(SceneScript sceneScript); + + /** + * 删除场景脚本 + * + * @param scriptId 场景脚本主键 + * @return 结果 + */ + public int deleteSceneScriptBySceneScriptId(String scriptId); + + /** + * 批量删除场景脚本 + * + * @param scriptIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSceneScriptBySceneScriptIds(String[] scriptIds); + + /** + * 批量删除场景联动脚本 + * + * @param sceneIds 需要删除的数据场景ID集合 + * @return 结果 + */ + public int deleteSceneScriptBySceneIds(Long[] sceneIds); + + /** + * 批量新增场景脚本 + * + * @param sceneScriptList 场景联动触发器集合 + * @return 结果 + */ + public int insertSceneScriptList(List sceneScriptList); + + /** + * 通过脚本用途批量查询 + * @param sceneIdList 场景id + * @param: scriptPurpose 脚本用途 + * @return java.util.List + */ + List listSceneScriptByPurpose(@Param("sceneIdList") List sceneIdList, @Param("scriptPurpose") Integer scriptPurpose); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneTagPointsMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneTagPointsMapper.java new file mode 100644 index 0000000..25502f8 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/SceneTagPointsMapper.java @@ -0,0 +1,82 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.SceneTagPoints; + +import java.util.List; + +/** + * 运算型变量点Mapper接口 + * + * @author kerwincui + * @date 2024-05-21 + */ +public interface SceneTagPointsMapper +{ + /** + * 查询运算型变量点 + * + * @param id 运算型变量点主键 + * @return 运算型变量点 + */ + public SceneTagPoints selectSceneTagPointsById(Long id); + + /** + * 查询运算型变量点列表 + * + * @param sceneTagPoints 运算型变量点 + * @return 运算型变量点集合 + */ + public List selectSceneTagPointsList(SceneTagPoints sceneTagPoints); + + /** + * 新增运算型变量点 + * + * @param sceneTagPoints 运算型变量点 + * @return 结果 + */ + public int insertSceneTagPoints(SceneTagPoints sceneTagPoints); + + /** + * 修改运算型变量点 + * + * @param sceneTagPoints 运算型变量点 + * @return 结果 + */ + public int updateSceneTagPoints(SceneTagPoints sceneTagPoints); + + /** + * 删除运算型变量点 + * + * @param id 运算型变量点主键 + * @return 结果 + */ + public int deleteSceneTagPointsById(Long id); + + /** + * 批量删除运算型变量点 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSceneTagPointsByIds(Long[] ids); + + /** + * 批量删除场景变量运算 + * @param sceneModelIds + * @return void + */ + void deleteBySceneModelIds(Long[] sceneModelIds); + + /** + * 批量删除场景变量运算 + * @param tagIds + */ + void deleteByTagIds(Long[] tagIds); + + /** + * 查询变量运算列表 + * @param id + * @return java.util.List + */ + List selectListByTagId(Long id); +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ScriptMapper.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ScriptMapper.java new file mode 100644 index 0000000..fd0e1ac --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/mapper/ScriptMapper.java @@ -0,0 +1,102 @@ +package com.maibu.mapper; + +import com.fastbee.iot.domain.Script; +import com.fastbee.iot.model.ScriptCondition; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 规则引擎脚本Mapper接口 + * + * @author lizhuangpeng + * @date 2023-07-01 + */ +@Repository +public interface ScriptMapper +{ + /** + * 查询规则引擎脚本 + * + * @param scriptId 规则引擎脚本主键 + * @return 规则引擎脚本 + */ + public Script selectRuleScriptById(String scriptId); + + /** + * 查询规则引擎脚本列表 + * + * @param ruleScript 规则引擎脚本 + * @return 规则引擎脚本集合 + */ + public List