diff --git a/iot-auth-server/pom.xml b/iot-auth-server/pom.xml deleted file mode 100755 index 98fc008a..00000000 --- a/iot-auth-server/pom.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - iotkit-parent - cc.iotkit - ${revision} - - 4.0.0 - - iot-auth-server - - 此模块为认证服务,提供oauth2认证界面和接口 - - - - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - - cn.dev33 - sa-token-oauth2 - - - - cn.dev33 - sa-token-spring-boot-starter - - - - cn.dev33 - sa-token-dao-redis-jackson - - - - com.ejlchina - okhttps - - - - org.projectlombok - lombok - - - - junit - junit - test - - - - cc.iotkit - iot-data-service - - - - - \ No newline at end of file diff --git a/iot-auth-server/src/main/java/cc/iotkit/oauth/controller/AuthClientController.java b/iot-auth-server/src/main/java/cc/iotkit/oauth/controller/AuthClientController.java deleted file mode 100755 index b7588b69..00000000 --- a/iot-auth-server/src/main/java/cc/iotkit/oauth/controller/AuthClientController.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.oauth.controller; - -import cc.iotkit.common.Constants; -import cc.iotkit.common.utils.CodecUtil; -import cc.iotkit.common.utils.ReflectUtil; -import cc.iotkit.data.IOauthClientData; -import cc.iotkit.data.IUserInfoData; -import cc.iotkit.model.OauthClient; -import cc.iotkit.model.UserInfo; -import cc.iotkit.oauth.vo.UserInfoVo; -import cc.iotkit.utils.SoMap; -import cn.dev33.satoken.stp.SaLoginConfig; -import cn.dev33.satoken.stp.StpUtil; -import cn.dev33.satoken.util.SaResult; -import com.ejlchina.okhttps.OkHttps; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.cglib.beans.BeanMap; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.view.RedirectView; - -import java.util.HashMap; -import java.util.Map; - - -@Slf4j -@RestController -@RequestMapping("/oauth2") -public class AuthClientController { - - @Value("${oauth2.auth-server-url}") - private String serverUrl; - - @Autowired - @Qualifier("oauthClientDataCache") - private IOauthClientData oauthClientData; - @Autowired - @Qualifier("userInfoDataCache") - private IUserInfoData userInfoData; - - /** - * 根据Code码进行登录,获取 Access-Token 和 用户信息 - */ - @RequestMapping("/codeLogin") - public SaResult codeLogin(String code, String clientId) { - OauthClient oauthClient = oauthClientData.findByClientId(clientId); - if (oauthClient == null) { - return SaResult.error("clientId does not exist"); - } - String clientSecret = oauthClient.getClientSecret(); - - // 调用Server端接口,获取 Access-Token 以及其他信息 - String str = OkHttps.sync(serverUrl + "/oauth2/token") - .addBodyPara("grant_type", "authorization_code") - .addBodyPara("code", code) - .addBodyPara("client_id", clientId) - .addBodyPara("client_secret", clientSecret) - .post() - .getBody() - .toString(); - SoMap so = SoMap.getSoMap().setJsonString(str); - log.info("get token by code result:{}", so); - // 存在code,不是token结构 - if (so.getInt("code") != 0) { - return SaResult.error(so.getString("msg")); - } - - // 根据openid获取其对应的userId - String uid = getUserIdByOpenid(so.getString("openid")); - String access_token = so.getString("access_token"); - UserInfoVo userVo = getUserInfo(uid); - BeanMap beanMap = BeanMap.create(userVo); - Map data = new HashMap<>(); - beanMap.forEach((key, value) -> { - data.put(key.toString(), value); - }); - data.put("access_token", access_token); - - // 返回相关参数 - StpUtil.login(uid, SaLoginConfig.setToken(access_token)); - return SaResult.data(data); - } - - /** - * 注销登录 - */ - @RequestMapping("/logout") - public RedirectView logout(String accessToken, String redirect_uri) { - //先注销client中cookie的token - StpUtil.logout(); - //再注销web页面使用的token - StpUtil.logoutByTokenValue(accessToken); - - return new RedirectView(redirect_uri); - } - - /** - * 登录验证 - */ - @GetMapping("/checkLogin") - public SaResult checkLogin() { - try { - String uid = StpUtil.getLoginId().toString(); - UserInfoVo userVo = getUserInfo(uid); - return SaResult.ok().setData(userVo); - } catch (Throwable e) { - return SaResult.error("no login"); - } - } - - @SneakyThrows - private String getUserIdByOpenid(String openid) { - String clientIdLoginId = CodecUtil.aesDecrypt(openid, Constants.ACCOUNT_SECRET); - return clientIdLoginId.split(":")[1]; - } - - private UserInfoVo getUserInfo(String uid) { - UserInfo userInfo = userInfoData.findById(uid); - UserInfoVo userVo = new UserInfoVo(); - ReflectUtil.copyNoNulls(userInfo, userVo); - return userVo; - } - -} diff --git a/iot-auth-server/src/main/java/cc/iotkit/oauth/controller/AuthServerController.java b/iot-auth-server/src/main/java/cc/iotkit/oauth/controller/AuthServerController.java deleted file mode 100755 index e94caa95..00000000 --- a/iot-auth-server/src/main/java/cc/iotkit/oauth/controller/AuthServerController.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.oauth.controller; - -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.data.IUserInfoData; -import cc.iotkit.model.UserInfo; -import cc.iotkit.oauth.service.TokenRequestHandler; -import cc.iotkit.utils.AuthUtil; -import cn.dev33.satoken.oauth2.config.SaOAuth2Config; -import cn.dev33.satoken.stp.StpUtil; -import cn.dev33.satoken.util.SaResult; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.http.HttpServletRequest; -import java.util.HashMap; -import java.util.Map; - -@Slf4j -@RestController -public class AuthServerController { - - @Autowired - private IUserInfoData userInfoData; - - /** - * 处理所有OAuth相关请求 - */ - @RequestMapping("/oauth2/*") - public Object request(HttpServletRequest request) { - Object result = TokenRequestHandler.serverRequest(); - log.info("oauth path:{},result:{}", request.getRequestURI(), JsonUtil.toJsonString(result)); - return result; - } - - /** - * Sa-OAuth2 自定义配置 - */ - @Autowired - public void setSaOAuth2Config(SaOAuth2Config cfg) { - cfg. - // 未登录的视图 - setNotLoginView(() -> new ModelAndView("login.html")). - // 登录处理函数 - setDoLoginHandle((name, pwd) -> { - try { - UserInfo userInfo = userInfoData.findByUid(name); - if (userInfo != null) { - String secret = userInfo.getSecret(); - if (AuthUtil.checkPwd(pwd, secret)) { - StpUtil.login(userInfo.getId(), "PC"); - return SaResult.ok(); - } - } - } catch (Throwable e) { - return SaResult.error("账号名或密码错误"); - } - return SaResult.error("账号名或密码错误"); - }). - // 授权确认视图 - setConfirmView((clientId, scope) -> { - Map map = new HashMap<>(); - map.put("clientId", clientId); - map.put("scope", scope); - return new ModelAndView("confirm.html", map); - }) - ; - - //开启密码授权、刷新token和client授权模式 - cfg.setIsPassword(true); - cfg.setIsNewRefresh(true); - cfg.setIsClient(true); - } - - // 全局异常拦截 - @ExceptionHandler - public SaResult handlerException(Exception e) { - e.printStackTrace(); - return SaResult.error(e.getMessage()); - } - - @RequestMapping("/oauth2/userinfo") - public SaResult userinfo() { - return SaResult.ok(); - } - -} diff --git a/iot-auth-server/src/main/java/cc/iotkit/oauth/service/SaOAuth2TemplateImpl.java b/iot-auth-server/src/main/java/cc/iotkit/oauth/service/SaOAuth2TemplateImpl.java deleted file mode 100755 index 7524bb25..00000000 --- a/iot-auth-server/src/main/java/cc/iotkit/oauth/service/SaOAuth2TemplateImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.oauth.service; - -import cc.iotkit.common.Constants; -import cc.iotkit.common.utils.CodecUtil; -import cc.iotkit.data.IOauthClientData; -import cc.iotkit.model.OauthClient; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Template; -import cn.dev33.satoken.oauth2.model.SaClientModel; -import cn.dev33.satoken.stp.StpUtil; -import lombok.SneakyThrows; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - -@Component -public class SaOAuth2TemplateImpl extends SaOAuth2Template { - - @Autowired - @Qualifier("oauthClientDataCache") - private IOauthClientData oauthClientData; - - // 根据 id 获取 Client 信息 - @Override - public SaClientModel getClientModel(String clientId) { - OauthClient client = oauthClientData.findByClientId(clientId); - if (client == null) { - return null; - } - - return new SaClientModel() - .setClientId(client.getClientId()) - .setClientSecret(client.getClientSecret()) - .setAllowUrl(client.getAllowUrl()) - .setContractScope("userinfo") - .setIsAutoMode(true); - } - - // 根据ClientId 和 LoginId 获取openid - @SneakyThrows - @Override - public String getOpenid(String clientId, Object loginId) { - // 此为模拟数据,真实环境需要从数据库查询 - return CodecUtil.aesEncrypt(clientId + ":" + loginId, Constants.ACCOUNT_SECRET); - } - - @Override - public String randomAccessToken(String clientId, Object loginId, String scope) { - return StpUtil.createLoginSession(loginId); - } - - -} diff --git a/iot-auth-server/src/main/java/cc/iotkit/oauth/service/StpInterfaceImpl.java b/iot-auth-server/src/main/java/cc/iotkit/oauth/service/StpInterfaceImpl.java deleted file mode 100755 index b3e350fb..00000000 --- a/iot-auth-server/src/main/java/cc/iotkit/oauth/service/StpInterfaceImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.oauth.service; - -import cc.iotkit.data.IUserInfoData; -import cc.iotkit.model.UserInfo; -import cn.dev33.satoken.stp.StpInterface; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -public class StpInterfaceImpl implements StpInterface { - - @Autowired - @Qualifier("userInfoDataCache") - private IUserInfoData userInfoData; - - /** - * 返回一个账号所拥有的权限码集合 - */ - @Override - public List getPermissionList(Object loginId, String loginType) { - UserInfo userInfo = userInfoData.findById(loginId.toString()); - return userInfo.getPermissions(); - } - - /** - * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验) - */ - @Override - public List getRoleList(Object loginId, String loginType) { - UserInfo userInfo = userInfoData.findById(loginId.toString()); - return userInfo.getRoles(); - } - -} \ No newline at end of file diff --git a/iot-auth-server/src/main/java/cc/iotkit/oauth/service/TokenRequestHandler.java b/iot-auth-server/src/main/java/cc/iotkit/oauth/service/TokenRequestHandler.java deleted file mode 100755 index a9d73d98..00000000 --- a/iot-auth-server/src/main/java/cc/iotkit/oauth/service/TokenRequestHandler.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.oauth.service; - -import cn.dev33.satoken.context.SaHolder; -import cn.dev33.satoken.context.model.SaRequest; -import cn.dev33.satoken.context.model.SaResponse; -import cn.dev33.satoken.oauth2.SaOAuth2Manager; -import cn.dev33.satoken.oauth2.config.SaOAuth2Config; -import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Handle; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Util; -import cn.dev33.satoken.oauth2.model.AccessTokenModel; -import cn.dev33.satoken.oauth2.model.ClientTokenModel; -import cn.dev33.satoken.oauth2.model.RequestAuthModel; -import cn.dev33.satoken.oauth2.model.SaClientModel; -import cn.dev33.satoken.stp.StpUtil; - -public class TokenRequestHandler { - - public static Object serverRequest() { - SaRequest req = SaHolder.getRequest(); - SaResponse res = SaHolder.getResponse(); - SaOAuth2Config cfg = SaOAuth2Manager.getConfig(); - SaClientModel cm; - if (req.isPath(SaOAuth2Consts.Api.authorize) && req.isParam(SaOAuth2Consts.Param.response_type, SaOAuth2Consts.ResponseType.code)) { - cm = SaOAuth2Handle.currClientModel(); - if (!cfg.getIsCode() || !cm.isCode && !cm.isAutoMode) { - throw new SaOAuth2Exception("暂未开放的授权模式"); - } else { - return SaOAuth2Handle.authorize(req, res, cfg); - } - } else if (req.isPath(SaOAuth2Consts.Api.token) && req.isParam(SaOAuth2Consts.Param.grant_type, SaOAuth2Consts.GrantType.authorization_code)) { - return token(req, res, cfg); - } else if (req.isPath(SaOAuth2Consts.Api.token) && req.isParam(SaOAuth2Consts.Param.grant_type, SaOAuth2Consts.GrantType.refresh_token)) { - return refreshToken(req); - } else if (req.isPath(SaOAuth2Consts.Api.revoke)) { - return SaOAuth2Handle.revokeToken(req); - } else if (req.isPath(SaOAuth2Consts.Api.doLogin)) { - return SaOAuth2Handle.doLogin(req, res, cfg); - } else if (req.isPath(SaOAuth2Consts.Api.doConfirm)) { - return SaOAuth2Handle.doConfirm(req); - } else if (req.isPath(SaOAuth2Consts.Api.authorize) && req.isParam(SaOAuth2Consts.Param.response_type, SaOAuth2Consts.ResponseType.token)) { - cm = SaOAuth2Handle.currClientModel(); - if (!cfg.getIsImplicit() || !cm.isImplicit && !cm.isAutoMode) { - throw new SaOAuth2Exception("暂未开放的授权模式"); - } else { - return SaOAuth2Handle.authorize(req, res, cfg); - } - } else if (req.isPath(SaOAuth2Consts.Api.token) && req.isParam(SaOAuth2Consts.Param.grant_type, SaOAuth2Consts.GrantType.password)) { - cm = SaOAuth2Handle.currClientModel(); - if (!cfg.getIsPassword() || !cm.isPassword && !cm.isAutoMode) { - throw new SaOAuth2Exception("暂未开放的授权模式"); - } else { - return password(req, res, cfg); - } - } else if (req.isPath(SaOAuth2Consts.Api.token) && req.isParam(SaOAuth2Consts.Param.grant_type, SaOAuth2Consts.GrantType.client_credentials)) { - cm = SaOAuth2Handle.currClientModel(); - if (!cfg.getIsClient() || !cm.isClient && !cm.isAutoMode) { - throw new SaOAuth2Exception("暂未开放的授权模式"); - } else { - return clientToken(req, res, cfg); - } - } else { - return "{\"msg\": \"not handle\"}"; - } - } - - public static Object token(SaRequest req, SaResponse res, SaOAuth2Config cfg) { - String code = req.getParamNotNull(SaOAuth2Consts.Param.code); - String clientId = req.getParamNotNull(SaOAuth2Consts.Param.client_id); - String clientSecret = req.getParamNotNull(SaOAuth2Consts.Param.client_secret); - String redirectUri = req.getParam(SaOAuth2Consts.Param.redirect_uri); - SaOAuth2Util.checkGainTokenParam(code, clientId, clientSecret, redirectUri); - AccessTokenModel token = SaOAuth2Util.generateAccessToken(code); - return token.toLineMap(); - } - - public static Object refreshToken(SaRequest req) { - String clientId = req.getParamNotNull(SaOAuth2Consts.Param.client_id); - String clientSecret = req.getParamNotNull(SaOAuth2Consts.Param.client_secret); - String refreshToken = req.getParamNotNull(SaOAuth2Consts.Param.refresh_token); - SaOAuth2Util.checkRefreshTokenParam(clientId, clientSecret, refreshToken); - return SaOAuth2Util.refreshAccessToken(refreshToken).toLineMap(); - } - - public static Object password(SaRequest req, SaResponse res, SaOAuth2Config cfg) { - String username = req.getParamNotNull(SaOAuth2Consts.Param.username); - String password = req.getParamNotNull(SaOAuth2Consts.Param.password); - String clientId = req.getParamNotNull(SaOAuth2Consts.Param.client_id); - String scope = req.getParam(SaOAuth2Consts.Param.scope, ""); - SaOAuth2Util.checkContract(clientId, scope); - SaHolder.getStorage().set(StpUtil.stpLogic.splicingKeyJustCreatedSave(), "no-token"); - Object retObj = cfg.getDoLoginHandle().apply(username, password); - if (!StpUtil.isLogin()) { - return retObj; - } else { - RequestAuthModel ra = new RequestAuthModel(); - ra.clientId = clientId; - ra.loginId = StpUtil.getLoginId(); - ra.scope = scope; - AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra, true); - return at.toLineMap(); - } - } - - public static Object clientToken(SaRequest req, SaResponse res, SaOAuth2Config cfg) { - String clientId = req.getParamNotNull(SaOAuth2Consts.Param.client_id); - String clientSecret = req.getParamNotNull(SaOAuth2Consts.Param.client_secret); - String scope = req.getParam(SaOAuth2Consts.Param.scope); - SaOAuth2Util.checkContract(clientId, scope); - SaOAuth2Util.checkClientSecret(clientId, clientSecret); - ClientTokenModel ct = SaOAuth2Util.generateClientToken(clientId, scope); - return ct.toLineMap(); - } -} diff --git a/iot-auth-server/src/main/java/cc/iotkit/oauth/vo/UserInfoVo.java b/iot-auth-server/src/main/java/cc/iotkit/oauth/vo/UserInfoVo.java deleted file mode 100755 index 547090e4..00000000 --- a/iot-auth-server/src/main/java/cc/iotkit/oauth/vo/UserInfoVo.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.oauth.vo; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.ArrayList; -import java.util.List; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class UserInfoVo { - - /** - * 用户账号 - */ - private String uid; - - /** - * 用户昵称 - */ - private String nickName; - - /** - * 性别 0-未知 1-male,2-female - */ - private Integer gender; - - /** - * 头像地址 - */ - private String avatarUrl; - - private String email; - - private String address; - - /** - * 当前家庭Id - */ - private String currHomeId; - - /** - * 用户类型 - * 0:平台用户 - * 1:终端用户 - */ - private Integer type; - - /** - * 角色 - */ - private List roles = new ArrayList<>(); - - /** - * 权限 - */ - private List permissions = new ArrayList<>(); - - /** - * 用户使用的平台 - * 见:Constants.THIRD_PLATFORM - */ - private List usePlatforms = new ArrayList<>(); - - -} diff --git a/iot-auth-server/src/main/java/cc/iotkit/utils/AuthUtil.java b/iot-auth-server/src/main/java/cc/iotkit/utils/AuthUtil.java deleted file mode 100755 index 7fe916ae..00000000 --- a/iot-auth-server/src/main/java/cc/iotkit/utils/AuthUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.utils; - -import cc.iotkit.common.Constants; -import cc.iotkit.common.utils.CodecUtil; -import cn.dev33.satoken.stp.StpUtil; -import org.apache.commons.lang3.RandomUtils; - -import java.util.List; - -public class AuthUtil { - - public static String getUserId() { - return StpUtil.getLoginId().toString(); - } - - public static List getUserRoles() { - return StpUtil.getRoleList(); - } - - public static boolean isAdmin() { - return AuthUtil.getUserRoles().contains(Constants.ROLE_ADMIN); - } - - public static boolean isClientUser() { - return AuthUtil.getUserRoles().contains(Constants.ROLE_CLIENT); - } - - public static boolean hasWriteRole() { - return AuthUtil.getUserRoles().contains(Constants.ROLE_WRITE); - } - - public static String enCryptPwd(String pwd) throws Exception { - return CodecUtil.aesEncrypt(CodecUtil.md5Str(pwd) + ":" - + RandomUtils.nextInt(1000, 9999), Constants.ACCOUNT_SECRET); - } - - public static boolean checkPwd(String pwd, String secret) throws Exception { - String code = CodecUtil.aesDecrypt(secret, Constants.ACCOUNT_SECRET); - String[] arr = code.split(":"); - return arr.length > 0 && CodecUtil.md5Str(pwd).equals(arr[0]); - } -} diff --git a/iot-auth-server/src/main/java/cc/iotkit/utils/SoMap.java b/iot-auth-server/src/main/java/cc/iotkit/utils/SoMap.java deleted file mode 100755 index e37d480c..00000000 --- a/iot-auth-server/src/main/java/cc/iotkit/utils/SoMap.java +++ /dev/null @@ -1,837 +0,0 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.utils; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import javax.servlet.http.HttpServletRequest; - -import cc.iotkit.common.utils.JsonUtil; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -/** - * Map< String, Object> 是最常用的一种Map类型,但是它写着麻烦 - *

所以特封装此类,继承Map,进行一些扩展,可以让Map更灵活使用 - *

最新:2020-12-10 新增部分构造方法 - * - * @author kong - */ -public class SoMap extends LinkedHashMap { - - private static final long serialVersionUID = 1L; - - public SoMap() { - } - - /** - * 以下元素会在isNull函数中被判定为Null, - */ - public static final Object[] NULL_ELEMENT_ARRAY = {null, ""}; - public static final List NULL_ELEMENT_LIST; - - static { - NULL_ELEMENT_LIST = Arrays.asList(NULL_ELEMENT_ARRAY); - } - - // ============================= 读值 ============================= - - /** - * 获取一个值 - */ - @Override - public Object get(Object key) { - if ("this".equals(key)) { - return this; - } - return super.get(key); - } - - /** - * 如果为空,则返回默认值 - */ - public Object get(Object key, Object defaultValue) { - Object value = get(key); - if (valueIsNull(value)) { - return defaultValue; - } - return value; - } - - /** - * 转为String并返回 - */ - public String getString(String key) { - Object value = get(key); - if (value == null) { - return null; - } - return String.valueOf(value); - } - - /** - * 如果为空,则返回默认值 - */ - public String getString(String key, String defaultValue) { - Object value = get(key); - if (valueIsNull(value)) { - return defaultValue; - } - return String.valueOf(value); - } - - /** - * 转为int并返回 - */ - public int getInt(String key) { - Object value = get(key); - if (valueIsNull(value)) { - return 0; - } - return Integer.parseInt(String.valueOf(value)); - } - - /** - * 转为int并返回,同时指定默认值 - */ - public int getInt(String key, int defaultValue) { - Object value = get(key); - if (valueIsNull(value)) { - return defaultValue; - } - return Integer.parseInt(String.valueOf(value)); - } - - /** - * 转为long并返回 - */ - public long getLong(String key) { - Object value = get(key); - if (valueIsNull(value)) { - return 0; - } - return Long.parseLong(String.valueOf(value)); - } - - /** - * 转为double并返回 - */ - public double getDouble(String key) { - Object value = get(key); - if (valueIsNull(value)) { - return 0.0; - } - return Double.parseDouble(String.valueOf(value)); - } - - /** - * 转为boolean并返回 - */ - public boolean getBoolean(String key) { - Object value = get(key); - if (valueIsNull(value)) { - return false; - } - return Boolean.parseBoolean(String.valueOf(value)); - } - - /** - * 转为Date并返回,根据自定义格式 - */ - public Date getDateByFormat(String key, String format) { - try { - return new SimpleDateFormat(format).parse(getString(key)); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * 转为Date并返回,根据格式: yyyy-MM-dd - */ - public Date getDate(String key) { - return getDateByFormat(key, "yyyy-MM-dd"); - } - - /** - * 转为Date并返回,根据格式: yyyy-MM-dd HH:mm:ss - */ - public Date getDateTime(String key) { - return getDateByFormat(key, "yyyy-MM-dd HH:mm:ss"); - } - - /** - * 转为Map并返回 - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - public SoMap getMap(String key) { - Object value = get(key); - if (value == null) { - return SoMap.getSoMap(); - } - if (value instanceof Map) { - return SoMap.getSoMap((Map) value); - } - if (value instanceof String) { - return SoMap.getSoMap().setJsonString((String) value); - } - throw new RuntimeException("值无法转化为SoMap: " + value); - } - - /** - * 获取集合(必须原先就是个集合,否则会创建个新集合并返回) - */ - @SuppressWarnings("unchecked") - public List getList(String key) { - Object value = get(key); - List list; - if (value == null || value.equals("")) { - list = new ArrayList<>(); - } else if (value instanceof List) { - list = (List) value; - } else { - list = new ArrayList<>(); - list.add(value); - } - return list; - } - - /** - * 获取集合 (指定泛型类型) - */ - public List getList(String key, Class cs) { - List list = getList(key); - List list2 = new ArrayList(); - for (Object obj : list) { - T objC = getValueByClass(obj, cs); - list2.add(objC); - } - return list2; - } - - /** - * 获取集合(逗号分隔式),(指定类型) - */ - public List getListByComma(String key, Class cs) { - String listStr = getString(key); - if (listStr == null || listStr.equals("")) { - return new ArrayList<>(); - } - // 开始转化 - String[] arr = listStr.split(","); - List list = new ArrayList(); - for (String str : arr) { - if (cs == int.class || cs == Integer.class || cs == long.class || cs == Long.class) { - str = str.trim(); - } - T objC = getValueByClass(str, cs); - list.add(objC); - } - return list; - } - - - /** - * 根据指定类型从map中取值,返回实体对象 - */ - public T getModel(Class cs) { - try { - return getModelByObject(cs.newInstance()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * 从map中取值,塞到一个对象中 - */ - public T getModelByObject(T obj) { - // 获取类型 - Class cs = obj.getClass(); - // 循环复制 - for (Field field : cs.getDeclaredFields()) { - try { - // 获取对象 - Object value = this.get(field.getName()); - if (value == null) { - continue; - } - field.setAccessible(true); - Object valueConvert = getValueByClass(value, field.getType()); - field.set(obj, valueConvert); - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new RuntimeException("属性取值出错:" + field.getName(), e); - } - } - return obj; - } - - - /** - * 将指定值转化为指定类型并返回 - * - * @param obj - * @param cs - * @param - * @return - */ - @SuppressWarnings("unchecked") - public static T getValueByClass(Object obj, Class cs) { - String obj2 = String.valueOf(obj); - Object obj3; - if (cs.equals(String.class)) { - obj3 = obj2; - } else if (cs.equals(int.class) || cs.equals(Integer.class)) { - obj3 = Integer.valueOf(obj2); - } else if (cs.equals(long.class) || cs.equals(Long.class)) { - obj3 = Long.valueOf(obj2); - } else if (cs.equals(short.class) || cs.equals(Short.class)) { - obj3 = Short.valueOf(obj2); - } else if (cs.equals(byte.class) || cs.equals(Byte.class)) { - obj3 = Byte.valueOf(obj2); - } else if (cs.equals(float.class) || cs.equals(Float.class)) { - obj3 = Float.valueOf(obj2); - } else if (cs.equals(double.class) || cs.equals(Double.class)) { - obj3 = Double.valueOf(obj2); - } else if (cs.equals(boolean.class) || cs.equals(Boolean.class)) { - obj3 = Boolean.valueOf(obj2); - } else { - obj3 = (T) obj; - } - return (T) obj3; - } - - - // ============================= 写值 ============================= - - /** - * 给指定key添加一个默认值(只有在这个key原来无值的情况先才会set进去) - */ - public void setDefaultValue(String key, Object defaultValue) { - if (isNull(key)) { - set(key, defaultValue); - } - } - - /** - * set一个值,连缀风格 - */ - public SoMap set(String key, Object value) { - // 防止敏感key - if (key.toLowerCase().equals("this")) { - return this; - } - put(key, value); - return this; - } - - /** - * 将一个Map塞进SoMap - */ - public SoMap setMap(Map map) { - if (map != null) { - for (String key : map.keySet()) { - this.set(key, map.get(key)); - } - } - return this; - } - - /** - * 将一个对象解析塞进SoMap - */ - public SoMap setModel(Object model) { - if (model == null) { - return this; - } - Field[] fields = model.getClass().getDeclaredFields(); - for (Field field : fields) { - try { - field.setAccessible(true); - boolean isStatic = Modifier.isStatic(field.getModifiers()); - if (!isStatic) { - this.set(field.getName(), field.get(model)); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - return this; - } - - /** - * 将json字符串解析后塞进SoMap - */ - public SoMap setJsonString(String jsonString) { - return this.setMap(JsonUtil.parse(jsonString, Map.class)); - } - - - // ============================= 删值 ============================= - - /** - * delete一个值,连缀风格 - */ - public SoMap delete(String key) { - remove(key); - return this; - } - - /** - * 清理所有value为null的字段 - */ - public SoMap clearNull() { - Iterator iterator = this.keySet().iterator(); - while (iterator.hasNext()) { - String key = iterator.next(); - if (this.isNull(key)) { - iterator.remove(); - this.remove(key); - } - - } - return this; - } - - /** - * 清理指定key - */ - public SoMap clearIn(String... keys) { - List keys2 = Arrays.asList(keys); - Iterator iterator = this.keySet().iterator(); - while (iterator.hasNext()) { - String key = iterator.next(); - if (keys2.contains(key)) { - iterator.remove(); - this.remove(key); - } - } - return this; - } - - /** - * 清理掉不在列表中的key - */ - public SoMap clearNotIn(String... keys) { - List keys2 = Arrays.asList(keys); - Iterator iterator = this.keySet().iterator(); - while (iterator.hasNext()) { - String key = iterator.next(); - if (!keys2.contains(key)) { - iterator.remove(); - this.remove(key); - } - - } - return this; - } - - /** - * 清理掉所有key - */ - public SoMap clearAll() { - clear(); - return this; - } - - - // ============================= 快速构建 ============================= - - /** - * 构建一个SoMap并返回 - */ - public static SoMap getSoMap() { - return new SoMap(); - } - - /** - * 构建一个SoMap并返回 - */ - public static SoMap getSoMap(String key, Object value) { - return new SoMap().set(key, value); - } - - /** - * 构建一个SoMap并返回 - */ - public static SoMap getSoMap(Map map) { - return new SoMap().setMap(map); - } - - /** - * 将一个对象集合解析成为SoMap - */ - public static SoMap getSoMapByModel(Object model) { - return SoMap.getSoMap().setModel(model); - } - - /** - * 将一个对象集合解析成为SoMap集合 - */ - public static List getSoMapByList(List list) { - List listMap = new ArrayList<>(); - for (Object model : list) { - listMap.add(getSoMapByModel(model)); - } - return listMap; - } - - /** - * 克隆指定key,返回一个新的SoMap - */ - public SoMap cloneKeys(String... keys) { - SoMap so = new SoMap(); - for (String key : keys) { - so.set(key, this.get(key)); - } - return so; - } - - /** - * 克隆所有key,返回一个新的SoMap - */ - public SoMap cloneSoMap() { - SoMap so = new SoMap(); - for (String key : this.keySet()) { - so.set(key, this.get(key)); - } - return so; - } - - /** - * 将所有key转为大写 - */ - public SoMap toUpperCase() { - SoMap so = new SoMap(); - for (String key : this.keySet()) { - so.set(key.toUpperCase(), this.get(key)); - } - this.clearAll().setMap(so); - return this; - } - - /** - * 将所有key转为小写 - */ - public SoMap toLowerCase() { - SoMap so = new SoMap(); - for (String key : this.keySet()) { - so.set(key.toLowerCase(), this.get(key)); - } - this.clearAll().setMap(so); - return this; - } - - /** - * 将所有key中下划线转为中划线模式 (kebab-case风格) - */ - public SoMap toKebabCase() { - SoMap so = new SoMap(); - for (String key : this.keySet()) { - so.set(wordEachKebabCase(key), this.get(key)); - } - this.clearAll().setMap(so); - return this; - } - - /** - * 将所有key中下划线转为小驼峰模式 - */ - public SoMap toHumpCase() { - SoMap so = new SoMap(); - for (String key : this.keySet()) { - so.set(wordEachBigFs(key), this.get(key)); - } - this.clearAll().setMap(so); - return this; - } - - /** - * 将所有key中小驼峰转为下划线模式 - */ - public SoMap humpToLineCase() { - SoMap so = new SoMap(); - for (String key : this.keySet()) { - so.set(wordHumpToLine(key), this.get(key)); - } - this.clearAll().setMap(so); - return this; - } - - - // ============================= 辅助方法 ============================= - - - /** - * 指定key是否为null,判定标准为 NULL_ELEMENT_ARRAY 中的元素 - */ - public boolean isNull(String key) { - return valueIsNull(get(key)); - } - - /** - * 指定key列表中是否包含value为null的元素,只要有一个为null,就会返回true - */ - public boolean isContainNull(String... keys) { - for (String key : keys) { - if (this.isNull(key)) { - return true; - } - } - return false; - } - - /** - * 与isNull()相反 - */ - public boolean isNotNull(String key) { - return !isNull(key); - } - - /** - * 指定key的value是否为null,作用同isNotNull() - */ - public boolean has(String key) { - return !isNull(key); - } - - /** - * 指定value在此SoMap的判断标准中是否为null - */ - public boolean valueIsNull(Object value) { - return NULL_ELEMENT_LIST.contains(value); - } - - /** - * 验证指定key不为空,为空则抛出异常 - */ - public SoMap checkNull(String... keys) { - for (String key : keys) { - if (this.isNull(key)) { - throw new RuntimeException("参数" + key + "不能为空"); - } - } - return this; - } - - static Pattern patternNumber = Pattern.compile("[0-9]*"); - - /** - * 指定key是否为数字 - */ - public boolean isNumber(String key) { - String value = getString(key); - if (value == null) { - return false; - } - return patternNumber.matcher(value).matches(); - } - - - /** - * 转为JSON字符串 - */ - public String toJsonString() { - return JsonUtil.toJsonString(this); - } - - // ============================= web辅助 ============================= - - /** - * 返回当前request请求的的所有参数 - * - * @return - */ - public static SoMap getRequestSoMap() { - // 大善人SpringMVC提供的封装 - ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - if (servletRequestAttributes == null) { - throw new RuntimeException("当前线程非JavaWeb环境"); - } - // 当前request - HttpServletRequest request = servletRequestAttributes.getRequest(); - if (request.getAttribute("currentSoMap") == null || !(request.getAttribute("currentSoMap") instanceof SoMap)) { - initRequestSoMap(request); - } - return (SoMap) request.getAttribute("currentSoMap"); - } - - /** - * 初始化当前request的 SoMap - */ - private static void initRequestSoMap(HttpServletRequest request) { - SoMap soMap = new SoMap(); - Map parameterMap = request.getParameterMap(); // 获取所有参数 - for (String key : parameterMap.keySet()) { - try { - String[] values = parameterMap.get(key); // 获得values - if (values.length == 1) { - soMap.set(key, values[0]); - } else { - soMap.set(key, Arrays.asList(values)); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - request.setAttribute("currentSoMap", soMap); - } - - /** - * 验证返回当前线程是否为JavaWeb环境 - * - * @return - */ - public static boolean isJavaWeb() { - ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();// 大善人SpringMVC提供的封装 - if (servletRequestAttributes == null) { - return false; - } - return true; - } - - - // ============================= 常见key (以下key经常用,所以封装以下,方便写代码) ============================= - - /** - * get 当前页 - */ - public int getKeyPageNo() { - int pageNo = getInt("pageNo", 1); - if (pageNo <= 0) { - pageNo = 1; - } - return pageNo; - } - - /** - * get 页大小 - */ - public int getKeyPageSize() { - int pageSize = getInt("pageSize", 10); - if (pageSize <= 0 || pageSize > 1000) { - pageSize = 10; - } - return pageSize; - } - - /** - * get 排序方式 - */ - public int getKeySortType() { - return getInt("sortType"); - } - - - // ============================= 工具方法 ============================= - - - /** - * 将一个一维集合转换为树形集合 - * - * @param list 集合 - * @param idKey id标识key - * @param parentIdKey 父id标识key - * @param childListKey 子节点标识key - * @return 转换后的tree集合 - */ - public static List listToTree(List list, String idKey, String parentIdKey, String childListKey) { - // 声明新的集合,存储tree形数据 - List newTreeList = new ArrayList<>(); - // 声明hash-Map,方便查找数据 - SoMap hash = new SoMap(); - // 将数组转为Object的形式,key为数组中的id - for (SoMap json : list) { - hash.put(json.getString(idKey), json); - } - // 遍历结果集 - for (SoMap soMap : list) { - // 单条记录 - // 在hash中取出key为单条记录中pid的值 - SoMap hashVp = (SoMap) hash.get(soMap.get(parentIdKey, "").toString()); - // 如果记录的pid存在,则说明它有父节点,将她添加到孩子节点的集合中 - if (hashVp != null) { - // 检查是否有child属性,有则添加,没有则新建 - if (hashVp.get(childListKey) != null) { - @SuppressWarnings("unchecked") - List ch = (List) hashVp.get(childListKey); - ch.add(soMap); - hashVp.put(childListKey, ch); - } else { - List ch = new ArrayList(); - ch.add(soMap); - hashVp.put(childListKey, ch); - } - } else { - newTreeList.add(soMap); - } - } - return newTreeList; - } - - - /** - * 指定字符串的字符串下划线转大写模式 - */ - private static String wordEachBig(String str) { - StringBuilder newStr = new StringBuilder(); - for (String s : str.split("_")) { - newStr.append(wordFirstBig(s)); - } - return newStr.toString(); - } - - /** - * 返回下划线转小驼峰形式 - */ - private static String wordEachBigFs(String str) { - return wordFirstSmall(wordEachBig(str)); - } - - /** - * 将指定单词首字母大写 - */ - private static String wordFirstBig(String str) { - return str.substring(0, 1).toUpperCase() + str.substring(1); - } - - /** - * 将指定单词首字母小写 - */ - private static String wordFirstSmall(String str) { - return str.substring(0, 1).toLowerCase() + str.substring(1); - } - - /** - * 下划线转中划线 - */ - private static String wordEachKebabCase(String str) { - return str.replaceAll("_", "-"); - } - - /** - * 驼峰转下划线 - */ - private static String wordHumpToLine(String str) { - return str.replaceAll("[A-Z]", "_$0").toLowerCase(); - } - - -} diff --git a/iot-auth-server/src/main/resources/templates/confirm.html b/iot-auth-server/src/main/resources/templates/confirm.html deleted file mode 100755 index d84103fc..00000000 --- a/iot-auth-server/src/main/resources/templates/confirm.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - 奇特物联认证授权 - - - -
-
©奇特物联
- -
- - - - - - diff --git a/iot-auth-server/src/main/resources/templates/login.html b/iot-auth-server/src/main/resources/templates/login.html deleted file mode 100755 index 60033bab..00000000 --- a/iot-auth-server/src/main/resources/templates/login.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - 奇特物联登录授权 - - - -
-
©奇特物联
- -
- - - - - - diff --git a/iot-auth-server/src/test/java/GenPwdSecret.java b/iot-auth-server/src/test/java/GenPwdSecret.java deleted file mode 100755 index c18b9404..00000000 --- a/iot-auth-server/src/test/java/GenPwdSecret.java +++ /dev/null @@ -1,13 +0,0 @@ -import cc.iotkit.utils.AuthUtil; -import org.junit.Test; - -public class GenPwdSecret { - - @Test - public void gen() throws Exception { - //生成密码加密内容 - String secret = AuthUtil.enCryptPwd("iotkitadmin"); - System.out.println(secret); - System.out.println(AuthUtil.checkPwd("guest123", secret)); - } -} diff --git a/iot-common/iot-common-core/pom.xml b/iot-common/iot-common-core/pom.xml index 1d35ffa9..cb84280c 100644 --- a/iot-common/iot-common-core/pom.xml +++ b/iot-common/iot-common-core/pom.xml @@ -16,12 +16,6 @@ - - - org.apache.commons - commons-lang3 - - commons-codec commons-codec @@ -47,12 +41,89 @@ commons-beanutils + + + org.springframework + spring-context-support + + + + + org.springframework + spring-web + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.apache.commons + commons-lang3 + + + + cn.hutool + hutool-core + + + + cn.hutool + hutool-http + + + + cn.hutool + hutool-extra + + + + cn.hutool + hutool-json + provided + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + io.github.linpeilie + mapstruct-plus-spring-boot-starter + + + + jakarta.servlet + jakarta.servlet-api + + + + jakarta.validation + jakarta.validation-api + + org.projectlombok lombok - true + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/PageRequest.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/PageRequest.java index a7724bc7..9242d037 100644 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/PageRequest.java +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/PageRequest.java @@ -1,5 +1,8 @@ package cc.iotkit.common.api; +import lombok.Data; +import lombok.EqualsAndHashCode; + import java.io.Serializable; /** @@ -8,26 +11,38 @@ import java.io.Serializable; * @date:created in 2023/5/10 23:15 * @modificed by: */ +@EqualsAndHashCode(callSuper = true) +@Data public class PageRequest extends Request implements Serializable { - private Integer pageNo = 1; - private Integer pageSize = 20; - public PageRequest() { - } + /** + * 分页大小 + */ + private Integer pageSize; - public Integer getPageNo() { - return this.pageNo; - } + /** + * 当前页数 + */ + private Integer pageNum; - public Integer getPageSize() { - return this.pageSize; - } + /** + * 排序列 + */ + private String orderByColumn; - public void setPageNo(Integer pageNo) { - this.pageNo = pageNo; - } + /** + * 排序的方向desc或者asc + */ + private String isAsc; + + /** + * 当前记录起始索引 默认值 + */ + public static final int DEFAULT_PAGE_NUM = 1; + + /** + * 每页显示记录数 默认值 默认查全部 + */ + public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE; - public void setPageSize(Integer pageSize) { - this.pageSize = pageSize; - } } diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/PageRequestEmpty.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/PageRequestEmpty.java index 4b44c1da..c2ce71b2 100644 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/PageRequestEmpty.java +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/PageRequestEmpty.java @@ -1,31 +1,15 @@ package cc.iotkit.common.api; +import lombok.Data; + /** * @author: Longjun.Tu * @description: * @date:created in 2023/5/10 23:16 * @modificed by: */ +@Data public class PageRequestEmpty { - private Integer pageNo = 1; - private Integer pageSize = 20; - - public PageRequestEmpty() { - } - - public Integer getPageNo() { - return this.pageNo; - } - - public Integer getPageSize() { - return this.pageSize; - } - - public void setPageNo(Integer pageNo) { - this.pageNo = pageNo; - } - - public void setPageSize(Integer pageSize) { - this.pageSize = pageSize; - } + private Integer page = 1; + private Integer size = 20; } diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/Request.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/Request.java index 38ab5e02..db50282d 100644 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/Request.java +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/Request.java @@ -1,5 +1,7 @@ package cc.iotkit.common.api; +import lombok.Data; + import java.io.Serializable; import java.util.UUID; @@ -9,20 +11,10 @@ import java.util.UUID; * @date:created in 2023/5/10 23:14 * @modificed by: */ +@Data public class Request extends RequestEmpty implements Serializable { private T data; - public Request() { - } - - public T getData() { - return this.data; - } - - public void setData(T data) { - this.data = data; - } - public static Request of(T data) { Request request = new Request(); request.setData(data); diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/RequestEmpty.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/RequestEmpty.java index 132b667c..ee919b4b 100644 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/RequestEmpty.java +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/RequestEmpty.java @@ -1,5 +1,7 @@ package cc.iotkit.common.api; +import lombok.Data; + import java.io.Serializable; import java.util.UUID; @@ -9,34 +11,14 @@ import java.util.UUID; * @date:created in 2023/5/10 23:12 * @modificed by: */ +@Data public class RequestEmpty implements Serializable { - private String language; - @Deprecated private String requestId; - public RequestEmpty() { - } - - public String getLanguage() { - return this.language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public String getRequestId() { - return this.requestId; - } - - public void setRequestId(String requestId) { - this.requestId = requestId; - } - public static RequestEmpty of() { RequestEmpty request = new RequestEmpty(); request.setRequestId(UUID.randomUUID().toString()); diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/Response.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/Response.java new file mode 100644 index 00000000..ad915510 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/api/Response.java @@ -0,0 +1,15 @@ +package cc.iotkit.common.api; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Response { + private int code; + private String message; + private Object data; + private long timestamp; +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/config/BigNumberSerializer.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/config/BigNumberSerializer.java new file mode 100644 index 00000000..fd40186d --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/config/BigNumberSerializer.java @@ -0,0 +1,42 @@ +package cc.iotkit.common.config; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; +import com.fasterxml.jackson.databind.ser.std.NumberSerializer; + +import java.io.IOException; + +/** + * 超出 JS 最大最小值 处理 + * + * @author Lion Li + */ +@JacksonStdImpl +public class BigNumberSerializer extends NumberSerializer { + + /** + * 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来 + */ + private static final long MAX_SAFE_INTEGER = 9007199254740991L; + private static final long MIN_SAFE_INTEGER = -9007199254740991L; + + /** + * 提供实例 + */ + public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class); + + public BigNumberSerializer(Class rawType) { + super(rawType); + } + + @Override + public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { + // 超出范围 序列化位字符串 + if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) { + super.serialize(value, gen, provider); + } else { + gen.writeString(value.toString()); + } + } +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/config/JacksonConfig.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/config/JacksonConfig.java new file mode 100644 index 00000000..846f413f --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/config/JacksonConfig.java @@ -0,0 +1,46 @@ +package cc.iotkit.common.config; + +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +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 org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.context.annotation.Bean; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.TimeZone; + +/** + * jackson 配置 + * + * @author Lion Li + */ +@Slf4j +@AutoConfiguration(before = JacksonAutoConfiguration.class) +public class JacksonConfig { + + @Bean + public Jackson2ObjectMapperBuilderCustomizer customizer() { + return builder -> { + // 全局配置序列化返回 JSON 处理 + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE); + javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE); + javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE); + javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter)); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter)); + builder.modules(javaTimeModule); + builder.timeZone(TimeZone.getDefault()); + log.info("初始化 jackson 配置"); + }; + } + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/CacheConstants.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/CacheConstants.java new file mode 100644 index 00000000..c6d8fea9 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/CacheConstants.java @@ -0,0 +1,25 @@ +package cc.iotkit.common.constant; + +/** + * 缓存的key 常量 + * + * @author Lion Li + */ +public interface CacheConstants { + + /** + * 在线用户 redis key + */ + String ONLINE_TOKEN_KEY = "online_tokens:"; + + /** + * 参数管理 cache key + */ + String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 字典管理 cache key + */ + String SYS_DICT_KEY = "sys_dict:"; + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/CacheNames.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/CacheNames.java new file mode 100644 index 00000000..de593f7d --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/CacheNames.java @@ -0,0 +1,63 @@ +package cc.iotkit.common.constant; + +/** + * 缓存组名称常量 + *

+ * key 格式为 cacheNames#ttl#maxIdleTime#maxSize + *

+ * ttl 过期时间 如果设置为0则不过期 默认为0 + * maxIdleTime 最大空闲时间 根据LRU算法清理空闲数据 如果设置为0则不检测 默认为0 + * maxSize 组最大长度 根据LRU算法清理溢出数据 如果设置为0则无限长 默认为0 + *

+ * 例子: test#60s、test#0#60s、test#0#1m#1000、test#1h#0#500 + * + * @author Lion Li + */ +public interface CacheNames { + + /** + * 演示案例 + */ + String DEMO_CACHE = "demo:cache#60s#10m#20"; + + /** + * 系统配置 + */ + String SYS_CONFIG = "sys_config"; + + /** + * 数据字典 + */ + String SYS_DICT = "sys_dict"; + + /** + * 租户 + */ + String SYS_TENANT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_tenant#30d"; + + /** + * 用户账户 + */ + String SYS_USER_NAME = "sys_user_name#30d"; + + /** + * 部门 + */ + String SYS_DEPT = "sys_dept#30d"; + + /** + * OSS内容 + */ + String SYS_OSS = "sys_oss#30d"; + + /** + * OSS配置 + */ + String SYS_OSS_CONFIG = "sys_oss_config"; + + /** + * 在线用户 + */ + String ONLINE_TOKEN = "online_tokens"; + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/Constants.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/Constants.java similarity index 81% rename from iot-common/iot-common-core/src/main/java/cc/iotkit/common/Constants.java rename to iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/Constants.java index fdcd4f9e..b10e3ace 100644 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/Constants.java +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/Constants.java @@ -1,16 +1,83 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.common; +package cc.iotkit.common.constant; +/** + * 通用常量信息 + * + * @author ruoyi + */ public interface Constants { + /** + * UTF-8 字符集 + */ + String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + String GBK = "GBK"; + + /** + * www主域 + */ + String WWW = "www."; + + /** + * http请求 + */ + String HTTP = "http://"; + + /** + * https请求 + */ + String HTTPS = "https://"; + + /** + * 通用成功标识 + */ + String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + String FAIL = "1"; + + /** + * 登录成功 + */ + String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + String LOGOUT = "Logout"; + + /** + * 注册 + */ + String REGISTER = "Register"; + + /** + * 登录失败 + */ + String LOGIN_FAIL = "Error"; + + /** + * 验证码有效期(分钟) + */ + Integer CAPTCHA_EXPIRATION = 2; + + /** + * 令牌 + */ + String TOKEN = "token"; + + /** + * 顶级部门id + */ + Long TOP_PARENT_ID = 0L; + + String PRODUCT_SECRET = "xdkKUymrEGSCYWswqCvSPyRSFvH5j7CU"; String ACCOUNT_SECRET = "3n1z33kzvpgz1foijpkepyd3e8tw84us"; @@ -224,3 +291,4 @@ public interface Constants { String DEVICE_SUBSCRIBE_TOPIC = "^/sys/.+/.+/c/#$"; } } + diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/GlobalConstants.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/GlobalConstants.java new file mode 100644 index 00000000..d48c886a --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/GlobalConstants.java @@ -0,0 +1,34 @@ +package cc.iotkit.common.constant; + +/** + * 全局的key常量 (业务无关的key) + * + * @author Lion Li + */ +public interface GlobalConstants { + + /** + * 全局 redis key (业务无关的key) + */ + String GLOBAL_REDIS_KEY = "global:"; + + /** + * 验证码 redis key + */ + String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:"; + + /** + * 防重提交 redis key + */ + String REPEAT_SUBMIT_KEY = GLOBAL_REDIS_KEY + "repeat_submit:"; + + /** + * 限流 redis key + */ + String RATE_LIMIT_KEY = GLOBAL_REDIS_KEY + "rate_limit:"; + + /** + * 登录账户密码错误次数 redis key + */ + String PWD_ERR_CNT_KEY = GLOBAL_REDIS_KEY + "pwd_err_cnt:"; +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/HttpStatus.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/HttpStatus.java new file mode 100644 index 00000000..24cbcaba --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/HttpStatus.java @@ -0,0 +1,93 @@ +package cc.iotkit.common.constant; + +/** + * 返回状态码 + * + * @author Lion Li + */ +public interface HttpStatus { + /** + * 操作成功 + */ + int SUCCESS = 200; + + /** + * 对象创建成功 + */ + int CREATED = 201; + + /** + * 请求已经被接受 + */ + int ACCEPTED = 202; + + /** + * 操作已经执行成功,但是没有返回数据 + */ + int NO_CONTENT = 204; + + /** + * 资源已被移除 + */ + int MOVED_PERM = 301; + + /** + * 重定向 + */ + int SEE_OTHER = 303; + + /** + * 资源没有被修改 + */ + int NOT_MODIFIED = 304; + + /** + * 参数列表错误(缺少,格式不匹配) + */ + int BAD_REQUEST = 400; + + /** + * 未授权 + */ + int UNAUTHORIZED = 401; + + /** + * 访问受限,授权过期 + */ + int FORBIDDEN = 403; + + /** + * 资源,服务未找到 + */ + int NOT_FOUND = 404; + + /** + * 不允许的http方法 + */ + int BAD_METHOD = 405; + + /** + * 资源冲突,或者资源被锁 + */ + int CONFLICT = 409; + + /** + * 不支持的数据,媒体类型 + */ + int UNSUPPORTED_TYPE = 415; + + /** + * 系统内部错误 + */ + int ERROR = 500; + + /** + * 接口未实现 + */ + int NOT_IMPLEMENTED = 501; + + /** + * 系统警告消息 + */ + int WARN = 601; +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/TenantConstants.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/TenantConstants.java new file mode 100644 index 00000000..f22fbf85 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/TenantConstants.java @@ -0,0 +1,45 @@ +package cc.iotkit.common.constant; + +/** + * 租户常量信息 + * + * @author Lion Li + */ +public interface TenantConstants { + + /** + * 租户正常状态 + */ + String NORMAL = "0"; + + /** + * 租户封禁状态 + */ + String DISABLE = "1"; + + /** + * 超级管理员ID + */ + Long SUPER_ADMIN_ID = 1L; + + /** + * 超级管理员角色 roleKey + */ + String SUPER_ADMIN_ROLE_KEY = "superadmin"; + + /** + * 租户管理员角色 roleKey + */ + String TENANT_ADMIN_ROLE_KEY = "admin"; + + /** + * 租户管理员角色名称 + */ + String TENANT_ADMIN_ROLE_NAME = "管理员"; + + /** + * 默认租户ID + */ + String DEFAULT_TENANT_ID = "000000"; + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/UserConstants.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/UserConstants.java new file mode 100644 index 00000000..699c09bd --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/constant/UserConstants.java @@ -0,0 +1,132 @@ +package cc.iotkit.common.constant; + +/** + * 用户常量信息 + * + * @author ruoyi + */ +public interface UserConstants { + + /** + * 平台内系统用户的唯一标志 + */ + String SYS_USER = "SYS_USER"; + + /** + * 正常状态 + */ + String NORMAL = "0"; + + /** + * 异常状态 + */ + String EXCEPTION = "1"; + + /** + * 用户正常状态 + */ + String USER_NORMAL = "0"; + + /** + * 用户封禁状态 + */ + String USER_DISABLE = "1"; + + /** + * 角色正常状态 + */ + String ROLE_NORMAL = "0"; + + /** + * 角色封禁状态 + */ + String ROLE_DISABLE = "1"; + + /** + * 部门正常状态 + */ + String DEPT_NORMAL = "0"; + + /** + * 部门停用状态 + */ + String DEPT_DISABLE = "1"; + + /** + * 字典正常状态 + */ + String DICT_NORMAL = "0"; + + /** + * 是否为系统默认(是) + */ + String YES = "Y"; + + /** + * 是否菜单外链(是) + */ + String YES_FRAME = "0"; + + /** + * 是否菜单外链(否) + */ + String NO_FRAME = "1"; + + /** + * 菜单正常状态 + */ + String MENU_NORMAL = "0"; + + /** + * 菜单停用状态 + */ + String MENU_DISABLE = "1"; + + /** + * 菜单类型(目录) + */ + String TYPE_DIR = "M"; + + /** + * 菜单类型(菜单) + */ + String TYPE_MENU = "C"; + + /** + * 菜单类型(按钮) + */ + String TYPE_BUTTON = "F"; + + /** + * Layout组件标识 + */ + String LAYOUT = "Layout"; + + /** + * ParentView组件标识 + */ + String PARENT_VIEW = "ParentView"; + + /** + * InnerLink组件标识 + */ + String INNER_LINK = "InnerLink"; + + /** + * 用户名长度限制 + */ + int USERNAME_MIN_LENGTH = 2; + int USERNAME_MAX_LENGTH = 20; + + /** + * 密码长度限制 + */ + int PASSWORD_MIN_LENGTH = 5; + int PASSWORD_MAX_LENGTH = 20; + + /** + * 超级管理员ID + */ + Long SUPER_ADMIN_ID = 1L; + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/BaseEntity.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/BaseEntity.java new file mode 100644 index 00000000..6101bd66 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/BaseEntity.java @@ -0,0 +1,40 @@ +package cc.iotkit.common.domain.model; + +import lombok.Data; + +import java.util.Date; + +/** + * Entity基类 + * + * @author Lion Li + */ +@Data +public class BaseEntity { + + /** + * 创建部门 + */ + private Long createDept; + + /** + * 创建者 + */ + private Long createBy; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新者 + */ + private Long updateBy; + + /** + * 更新时间 + */ + private Date updateTime; + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/LoginBody.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/LoginBody.java new file mode 100644 index 00000000..83f2253e --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/LoginBody.java @@ -0,0 +1,47 @@ +package cc.iotkit.common.domain.model; + +import cc.iotkit.common.constant.UserConstants; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 用户登录对象 + * + * @author Lion Li + */ + +@Data +public class LoginBody { + + /** + * 租户ID + */ + @NotBlank(message = "{tenant.number.not.blank}") + private String tenantId; + + /** + * 用户名 + */ + @NotBlank(message = "{user.username.not.blank}") + @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}") + private String username; + + /** + * 用户密码 + */ + @NotBlank(message = "{user.password.not.blank}") + @Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}") + private String password; + + /** + * 验证码 + */ + private String code; + + /** + * 唯一标识 + */ + private String uuid; + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/LoginUser.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/LoginUser.java new file mode 100644 index 00000000..2fce3380 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/LoginUser.java @@ -0,0 +1,123 @@ +package cc.iotkit.common.domain.model; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dromara.common.core.domain.dto.RoleDTO; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +/** + * 登录用户身份权限 + * + * @author Lion Li + */ + +@Data +@NoArgsConstructor +public class LoginUser implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 用户ID + */ + private Long userId; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 部门名 + */ + private String deptName; + + /** + * 用户唯一标识 + */ + private String token; + + /** + * 用户类型 + */ + private String userType; + + /** + * 登录时间 + */ + private Long loginTime; + + /** + * 过期时间 + */ + private Long expireTime; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 菜单权限 + */ + private Set menuPermission; + + /** + * 角色权限 + */ + private Set rolePermission; + + /** + * 用户名 + */ + private String username; + + /** + * 角色对象 + */ + private List roles; + + /** + * 数据权限 当前角色ID + */ + private Long roleId; + + /** + * 获取登录id + */ + public String getLoginId() { + if (userType == null) { + throw new IllegalArgumentException("用户类型不能为空"); + } + if (userId == null) { + throw new IllegalArgumentException("用户ID不能为空"); + } + return userType + ":" + userId; + } + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/RegisterBody.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/RegisterBody.java new file mode 100644 index 00000000..f0e4a83b --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/model/RegisterBody.java @@ -0,0 +1,17 @@ +package cc.iotkit.common.domain.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 用户注册对象 + * + * @author Lion Li + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class RegisterBody extends LoginBody { + + private String userType; + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/vo/PagedDataVo.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/vo/PagedDataVo.java new file mode 100644 index 00000000..efcb7c1c --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/domain/vo/PagedDataVo.java @@ -0,0 +1,25 @@ +package cc.iotkit.common.domain.vo; + +import lombok.Data; + +import java.util.List; + +/** + * 分页数据包装类 + * @author sjg + */ +@Data +public class PagedDataVo { + + /** + * 总记录数 + */ + private long total; + + /** + * 列表数据 + */ + private List rows; + + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/DeviceType.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/DeviceType.java new file mode 100644 index 00000000..829175bc --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/DeviceType.java @@ -0,0 +1,32 @@ +package cc.iotkit.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 设备类型 + * 针对一套 用户体系 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum DeviceType { + + /** + * pc端 + */ + PC("pc"), + + /** + * app端 + */ + APP("app"), + + /** + * 小程序端 + */ + XCX("xcx"); + + private final String device; +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java index 396ba745..f5ff907d 100644 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java @@ -3,25 +3,23 @@ package cc.iotkit.common.enums; /** * @author :tfd * 异常枚举类 - * */ -public enum ErrCode implements IEnum{ +public enum ErrCode implements IEnum { /** * 系统通用异常段 - * */ - PARAMS_EXCEPTION(00000000, "参数异常"), - SYSTEM_EXCEPTION(00000000, "系统异常"), - UNKNOWN_EXCEPTION(00000000, "未知异常"), - SYSTEM_ERROR(00000000, "服务器内部错误"), - METHOD_NOT_ALLOWED(00000000, "请求方法不支持"), - NOT_FOUND(00000000, "请求资源不存在"), - FORBIDDEN(00000000, "请求被拒绝"), - UNAUTHORIZED_EXCEPTION(00000000, "未授权访问"), - + */ + PARAMS_EXCEPTION(10000001, "参数异常"), + SYSTEM_EXCEPTION(10000002, "系统异常"), + UNKNOWN_EXCEPTION(10000003, "未知异常"), + SYSTEM_ERROR(10000004, "服务器内部错误"), + METHOD_NOT_ALLOWED(10000005, "请求方法不支持"), + NOT_FOUND(10000006, "请求资源不存在"), + FORBIDDEN(10000007, "请求被拒绝"), + UNAUTHORIZED_EXCEPTION(10000008, "未授权访问"), /** * 组件通用异常段 - * */ + */ GET_COMPONENT_INSTANCE_ERROR(00000000, "获取通讯组件实例失败"), GET_COMPONENT_SCRIPT_ERROR(00000000, "获取通讯组件脚本失败"), GET_CONVERT_ERROR(00000000, "获取转换器失败"), @@ -49,7 +47,7 @@ public enum ErrCode implements IEnum{ /** * 业务通用异常段 - * */ + */ TASK_NOT_SUPPORT_RENEW(00000000, "任务不支持续订"), GROUP_ALREADY(00000000, "分组已经存在"), GROUP_NOT_FOUND(00000000, "分组不存在"), diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java new file mode 100644 index 00000000..b3a2c761 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java @@ -0,0 +1,37 @@ +package cc.iotkit.common.enums; + +import cc.iotkit.common.utils.StringUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 设备类型 + * 针对多套 用户体系 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum UserType { + + /** + * pc端 + */ + SYS_USER("sys_user"), + + /** + * app端 + */ + APP_USER("app_user"); + + private final String userType; + + public static UserType getUserType(String str) { + for (UserType value : values()) { + if (StringUtils.contains(str, value.getUserType())) { + return value; + } + } + throw new RuntimeException("'UserType' not found By " + str); + } +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/exception/BizException.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/exception/BizException.java index 132a21ed..bcd34e9d 100644 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/exception/BizException.java +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/exception/BizException.java @@ -10,42 +10,54 @@ package cc.iotkit.common.exception; import cc.iotkit.common.enums.ErrCode; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; -public class BizException extends RuntimeException{ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BizException extends RuntimeException { - private int code; + /** + * 所属模块 + */ + private String module; + + /** + * 错误码 + */ + private String code; + + /** + * 错误消息 + */ private String message; - public BizException() { - } - public BizException(String message) { super(message); + this.code = ErrCode.SYSTEM_EXCEPTION.getValue(); } /** * 统一异常消息处理 * - * @param ErrCode 异常枚举值 + * @param errCode 异常枚举值 */ - public BizException(ErrCode ErrCode) { - this.message = ErrCode.getValue(); + public BizException(ErrCode errCode) { + this.message = errCode.getValue(); } - public BizException(ErrCode ErrCode, Throwable cause) { + public BizException(ErrCode errCode, Throwable cause) { super(cause); - this.message = ErrCode.getValue(); + this.message = errCode.getValue(); } - /** - * 自定义异常消息处理 - * - * @param code - * @param message - */ - public BizException(int code, String message) { - this.code = code; + public BizException(ErrCode errCode, String message) { this.message = message; + this.code = errCode.getValue(); } public BizException(String message, Throwable cause) { @@ -56,20 +68,4 @@ public class BizException extends RuntimeException{ super(cause); } - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - @Override - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } } diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/exception/ViewException.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/exception/ViewException.java new file mode 100644 index 00000000..5a0def1d --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/exception/ViewException.java @@ -0,0 +1,40 @@ +package cc.iotkit.common.exception; + + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 视图异常 + * + * @author sjg + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ViewException extends RuntimeException { + + public static final int CODE_FAILED = 0; + public static final int CODE_WARN = 1; + + private int code; + private String message; + private Object data; + + public ViewException() { + } + + public ViewException(String message) { + super(message); + } + + public ViewException(int code, String message) { + this.code = code; + this.message = message; + } + + public ViewException(int code, String message, Object data) { + this.code = code; + this.message = message; + this.data = data; + } +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/ConfigService.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/ConfigService.java new file mode 100644 index 00000000..910acc40 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/ConfigService.java @@ -0,0 +1,18 @@ +package cc.iotkit.common.service; + +/** + * 通用 参数配置服务 + * + * @author Lion Li + */ +public interface ConfigService { + + /** + * 根据参数 key 获取参数值 + * + * @param configKey 参数 key + * @return 参数值 + */ + String getConfigValue(String configKey); + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/DeptService.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/DeptService.java new file mode 100644 index 00000000..53e4993e --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/DeptService.java @@ -0,0 +1,18 @@ +package cc.iotkit.common.service; + +/** + * 通用 部门服务 + * + * @author Lion Li + */ +public interface DeptService { + + /** + * 通过部门ID查询部门名称 + * + * @param deptIds 部门ID串逗号分隔 + * @return 部门名称串逗号分隔 + */ + String selectDeptNameByIds(String deptIds); + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/DictService.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/DictService.java new file mode 100644 index 00000000..6ab10828 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/DictService.java @@ -0,0 +1,57 @@ +package cc.iotkit.common.service; + +/** + * 通用 字典服务 + * + * @author Lion Li + */ +public interface DictService { + + /** + * 分隔符 + */ + String SEPARATOR = ","; + + /** + * 根据字典类型和字典值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @return 字典标签 + */ + default String getDictLabel(String dictType, String dictValue) { + return getDictLabel(dictType, dictValue, SEPARATOR); + } + + /** + * 根据字典类型和字典标签获取字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @return 字典值 + */ + default String getDictValue(String dictType, String dictLabel) { + return getDictValue(dictType, dictLabel, SEPARATOR); + } + + /** + * 根据字典类型和字典值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @param separator 分隔符 + * @return 字典标签 + */ + String getDictLabel(String dictType, String dictValue, String separator); + + /** + * 根据字典类型和字典标签获取字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @param separator 分隔符 + * @return 字典值 + */ + String getDictValue(String dictType, String dictLabel, String separator); + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/OssService.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/OssService.java new file mode 100644 index 00000000..0ac5f8fb --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/OssService.java @@ -0,0 +1,18 @@ +package cc.iotkit.common.service; + +/** + * 通用 OSS服务 + * + * @author Lion Li + */ +public interface OssService { + + /** + * 通过ossId查询对应的url + * + * @param ossIds ossId串逗号分隔 + * @return url串逗号分隔 + */ + String selectUrlByIds(String ossIds); + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/UserService.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/UserService.java new file mode 100644 index 00000000..5b57e390 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/service/UserService.java @@ -0,0 +1,18 @@ +package cc.iotkit.common.service; + +/** + * 通用 用户服务 + * + * @author Lion Li + */ +public interface UserService { + + /** + * 通过用户ID查询用户账户 + * + * @param userId 用户ID + * @return 用户账户 + */ + String selectUserNameById(Long userId); + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/JsonUtil.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/JsonUtil.java deleted file mode 100644 index cde8dde6..00000000 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/JsonUtil.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * +---------------------------------------------------------------------- - * | Copyright (c) 奇特物联 2021-2022 All rights reserved. - * +---------------------------------------------------------------------- - * | Licensed 未经许可不能去掉「奇特物联」相关版权 - * +---------------------------------------------------------------------- - * | Author: xw2sy@163.com - * +---------------------------------------------------------------------- - */ -package cc.iotkit.common.utils; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import lombok.SneakyThrows; - -public final class JsonUtil { - - private final static ObjectMapper MAPPER = new ObjectMapper() - .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - - @SneakyThrows - public static String toJsonString(Object obj) { - return MAPPER.writeValueAsString(obj); - } - - @SneakyThrows - public static T parse(String json, Class cls) { - return MAPPER.readValue(json, cls); - } - - @SneakyThrows - public static T parse(String json, TypeReference type) { - return MAPPER.readValue(json, type); - } - - @SneakyThrows - public static JsonNode parse(String json) { - return MAPPER.readTree(json); - } -} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/JsonUtils.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/JsonUtils.java new file mode 100644 index 00000000..a0bbd3dd --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/JsonUtils.java @@ -0,0 +1,109 @@ +package cc.iotkit.common.utils; + +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.MismatchedInputException; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * JSON 工具类 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class JsonUtils { + + private static final ObjectMapper OBJECT_MAPPER = SpringUtils.getBean(ObjectMapper.class); + + public static ObjectMapper getObjectMapper() { + return OBJECT_MAPPER; + } + + public static String toJsonString(Object object) { + if (ObjectUtil.isNull(object)) { + return null; + } + try { + return OBJECT_MAPPER.writeValueAsString(object); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(String text, Class clazz) { + if (StringUtils.isEmpty(text)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(text, clazz); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(byte[] bytes, Class clazz) { + if (ArrayUtil.isEmpty(bytes)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(bytes, clazz); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(String text, TypeReference typeReference) { + if (StringUtils.isBlank(text)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(text, typeReference); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static Dict parseMap(String text) { + if (StringUtils.isBlank(text)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructType(Dict.class)); + } catch (MismatchedInputException e) { + // 类型不匹配说明不是json + return null; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static List parseArrayMap(String text) { + if (StringUtils.isBlank(text)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, Dict.class)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static List parseArray(String text, Class clazz) { + if (StringUtils.isEmpty(text)) { + return new ArrayList<>(); + } + try { + return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, clazz)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/MapstructUtils.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/MapstructUtils.java new file mode 100644 index 00000000..8258f456 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/MapstructUtils.java @@ -0,0 +1,92 @@ +package cc.iotkit.common.utils; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; +import io.github.linpeilie.Converter; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +/** + * Mapstruct 工具类 + *

参考文档:mapstruct-plus

+ * + * @author Michelle.Chung + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class MapstructUtils { + + private final static Converter CONVERTER = SpringUtils.getBean(Converter.class); + + /** + * 将 T 类型对象,转换为 desc 类型的对象并返回 + * + * @param source 数据来源实体 + * @param desc 描述对象 转换后的对象 + * @return desc + */ + public static V convert(T source, Class desc) { + if (ObjectUtil.isNull(source)) { + return null; + } + if (ObjectUtil.isNull(desc)) { + return null; + } + return CONVERTER.convert(source, desc); + } + + /** + * 将 T 类型对象,按照配置的映射字段规则,给 desc 类型的对象赋值并返回 desc 对象 + * + * @param source 数据来源实体 + * @param desc 转换后的对象 + * @return desc + */ + public static V convert(T source, V desc) { + if (ObjectUtil.isNull(source)) { + return null; + } + if (ObjectUtil.isNull(desc)) { + return null; + } + return CONVERTER.convert(source, desc); + } + + /** + * 将 T 类型的集合,转换为 desc 类型的集合并返回 + * + * @param sourceList 数据来源实体列表 + * @param desc 描述对象 转换后的对象 + * @return desc + */ + public static List convert(List sourceList, Class desc) { + if (ObjectUtil.isNull(sourceList)) { + return null; + } + if (CollUtil.isEmpty(sourceList)) { + return CollUtil.newArrayList(); + } + return CONVERTER.convert(sourceList, desc); + } + + /** + * 将 Map 转换为 beanClass 类型的集合并返回 + * + * @param map 数据来源 + * @param beanClass bean类 + * @return bean对象 + */ + public static T convert(Map map, Class beanClass) { + if (MapUtil.isEmpty(map)) { + return null; + } + if (ObjectUtil.isNull(beanClass)) { + return null; + } + return CONVERTER.convert(map, beanClass); + } + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/ServletUtils.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/ServletUtils.java new file mode 100644 index 00000000..c620a79d --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/ServletUtils.java @@ -0,0 +1,193 @@ +package cc.iotkit.common.utils; + +import cn.hutool.core.convert.Convert; +import cn.hutool.extra.servlet.JakartaServletUtil; +import cn.hutool.http.HttpStatus; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.io.IOException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * 客户端工具类 + * + * @author ruoyi + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ServletUtils extends JakartaServletUtil { + + /** + * 获取String参数 + */ + public static String getParameter(String name) { + return getRequest().getParameter(name); + } + + /** + * 获取String参数 + */ + public static String getParameter(String name, String defaultValue) { + return Convert.toStr(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name) { + return Convert.toInt(getRequest().getParameter(name)); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name, Integer defaultValue) { + return Convert.toInt(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name) { + return Convert.toBool(getRequest().getParameter(name)); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name, Boolean defaultValue) { + return Convert.toBool(getRequest().getParameter(name), defaultValue); + } + + /** + * 获得所有请求参数 + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParams(ServletRequest request) { + final Map map = request.getParameterMap(); + return Collections.unmodifiableMap(map); + } + + /** + * 获得所有请求参数 + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParamMap(ServletRequest request) { + Map params = new HashMap<>(); + for (Map.Entry entry : getParams(request).entrySet()) { + params.put(entry.getKey(), StringUtils.join(entry.getValue(), StringUtils.SEPARATOR)); + } + return params; + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() { + return getRequestAttributes().getRequest(); + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() { + return getRequestAttributes().getResponse(); + } + + /** + * 获取session + */ + public static HttpSession getSession() { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 将字符串渲染到客户端 + * + * @param response 渲染对象 + * @param string 待渲染的字符串 + */ + public static void renderString(HttpServletResponse response, String string) { + try { + response.setStatus(HttpStatus.HTTP_OK); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding(StandardCharsets.UTF_8.toString()); + response.getWriter().print(string); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) { + + String accept = request.getHeader("accept"); + if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) { + return true; + } + + String uri = request.getRequestURI(); + if (StringUtils.equalsAnyIgnoreCase(uri, ".json", ".xml")) { + return true; + } + + String ajax = request.getParameter("__ajax"); + return StringUtils.equalsAnyIgnoreCase(ajax, "json", "xml"); + } + + public static String getClientIP() { + return getClientIP((HttpServletRequest)getRequest()); + } + + /** + * 内容编码 + * + * @param str 内容 + * @return 编码后的内容 + */ + public static String urlEncode(String str) { + return URLEncoder.encode(str, StandardCharsets.UTF_8); + } + + /** + * 内容解码 + * + * @param str 内容 + * @return 解码后的内容 + */ + public static String urlDecode(String str) { + return URLDecoder.decode(str, StandardCharsets.UTF_8); + } + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/SpringUtils.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/SpringUtils.java new file mode 100644 index 00000000..80c10817 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/SpringUtils.java @@ -0,0 +1,62 @@ +package cc.iotkit.common.utils; + +import cn.hutool.extra.spring.SpringUtil; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +/** + * spring工具类 + * + * @author Lion Li + */ +@Component +public final class SpringUtils extends SpringUtil { + + /** + * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true + */ + public static boolean containsBean(String name) { + return getBeanFactory().containsBean(name); + } + + /** + * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 + * 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { + return getBeanFactory().isSingleton(name); + } + + /** + * @return Class 注册对象的类型 + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException { + return getBeanFactory().getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { + return getBeanFactory().getAliases(name); + } + + /** + * 获取aop代理对象 + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) { + return (T) AopContext.currentProxy(); + } + + + /** + * 获取spring上下文 + */ + public static ApplicationContext context() { + return getApplicationContext(); + } + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/StreamUtils.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/StreamUtils.java new file mode 100644 index 00000000..eeab4e8c --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/StreamUtils.java @@ -0,0 +1,254 @@ +package cc.iotkit.common.utils; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * stream 流工具类 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class StreamUtils { + + /** + * 将collection过滤 + * + * @param collection 需要转化的集合 + * @param function 过滤方法 + * @return 过滤后的list + */ + public static List filter(Collection collection, Predicate function) { + if (CollUtil.isEmpty(collection)) { + return CollUtil.newArrayList(); + } + // 注意此处不要使用 .toList() 新语法 因为返回的是不可变List 会导致序列化问题 + return collection.stream().filter(function).collect(Collectors.toList()); + } + + /** + * 将collection拼接 + * + * @param collection 需要转化的集合 + * @param function 拼接方法 + * @return 拼接后的list + */ + public static String join(Collection collection, Function function) { + return join(collection, function, StringUtils.SEPARATOR); + } + + /** + * 将collection拼接 + * + * @param collection 需要转化的集合 + * @param function 拼接方法 + * @param delimiter 拼接符 + * @return 拼接后的list + */ + public static String join(Collection collection, Function function, CharSequence delimiter) { + if (CollUtil.isEmpty(collection)) { + return StringUtils.EMPTY; + } + return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter)); + } + + /** + * 将collection排序 + * + * @param collection 需要转化的集合 + * @param comparing 排序方法 + * @return 排序后的list + */ + public static List sorted(Collection collection, Comparator comparing) { + if (CollUtil.isEmpty(collection)) { + return CollUtil.newArrayList(); + } + // 注意此处不要使用 .toList() 新语法 因为返回的是不可变List 会导致序列化问题 + return collection.stream().sorted(comparing).collect(Collectors.toList()); + } + + /** + * 将collection转化为类型不变的map
+ * {@code Collection ----> Map} + * + * @param collection 需要转化的集合 + * @param key V类型转化为K类型的lambda方法 + * @param collection中的泛型 + * @param map中的key类型 + * @return 转化后的map + */ + public static Map toIdentityMap(Collection collection, Function key) { + if (CollUtil.isEmpty(collection)) { + return MapUtil.newHashMap(); + } + return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l)); + } + + /** + * 将Collection转化为map(value类型与collection的泛型不同)
+ * {@code Collection -----> Map } + * + * @param collection 需要转化的集合 + * @param key E类型转化为K类型的lambda方法 + * @param value E类型转化为V类型的lambda方法 + * @param collection中的泛型 + * @param map中的key类型 + * @param map中的value类型 + * @return 转化后的map + */ + public static Map toMap(Collection collection, Function key, Function value) { + if (CollUtil.isEmpty(collection)) { + return MapUtil.newHashMap(); + } + return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l)); + } + + /** + * 将collection按照规则(比如有相同的班级id)分类成map
+ * {@code Collection -------> Map> } + * + * @param collection 需要分类的集合 + * @param key 分类的规则 + * @param collection中的泛型 + * @param map中的key类型 + * @return 分类后的map + */ + public static Map> groupByKey(Collection collection, Function key) { + if (CollUtil.isEmpty(collection)) { + return MapUtil.newHashMap(); + } + return collection + .stream() + .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList())); + } + + /** + * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map
+ * {@code Collection ---> Map>> } + * + * @param collection 需要分类的集合 + * @param key1 第一个分类的规则 + * @param key2 第二个分类的规则 + * @param 集合元素类型 + * @param 第一个map中的key类型 + * @param 第二个map中的key类型 + * @return 分类后的map + */ + public static Map>> groupBy2Key(Collection collection, Function key1, Function key2) { + if (CollUtil.isEmpty(collection)) { + return MapUtil.newHashMap(); + } + return collection + .stream() + .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList()))); + } + + /** + * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map
+ * {@code Collection ---> Map> } + * + * @param collection 需要分类的集合 + * @param key1 第一个分类的规则 + * @param key2 第二个分类的规则 + * @param 第一个map中的key类型 + * @param 第二个map中的key类型 + * @param collection中的泛型 + * @return 分类后的map + */ + public static Map> group2Map(Collection collection, Function key1, Function key2) { + if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) { + return MapUtil.newHashMap(); + } + return collection + .stream() + .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l))); + } + + /** + * 将collection转化为List集合,但是两者的泛型不同
+ * {@code Collection ------> List } + * + * @param collection 需要转化的集合 + * @param function collection中的泛型转化为list泛型的lambda表达式 + * @param collection中的泛型 + * @param List中的泛型 + * @return 转化后的list + */ + public static List toList(Collection collection, Function function) { + if (CollUtil.isEmpty(collection)) { + return CollUtil.newArrayList(); + } + return collection + .stream() + .map(function) + .filter(Objects::nonNull) + // 注意此处不要使用 .toList() 新语法 因为返回的是不可变List 会导致序列化问题 + .collect(Collectors.toList()); + } + + /** + * 将collection转化为Set集合,但是两者的泛型不同
+ * {@code Collection ------> Set } + * + * @param collection 需要转化的集合 + * @param function collection中的泛型转化为set泛型的lambda表达式 + * @param collection中的泛型 + * @param Set中的泛型 + * @return 转化后的Set + */ + public static Set toSet(Collection collection, Function function) { + if (CollUtil.isEmpty(collection) || function == null) { + return CollUtil.newHashSet(); + } + return collection + .stream() + .map(function) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } + + + /** + * 合并两个相同key类型的map + * + * @param map1 第一个需要合并的 map + * @param map2 第二个需要合并的 map + * @param merge 合并的lambda,将key value1 value2合并成最终的类型,注意value可能为空的情况 + * @param map中的key类型 + * @param 第一个 map的value类型 + * @param 第二个 map的value类型 + * @param 最终map的value类型 + * @return 合并后的map + */ + public static Map merge(Map map1, Map map2, BiFunction merge) { + if (MapUtil.isEmpty(map1) && MapUtil.isEmpty(map2)) { + return MapUtil.newHashMap(); + } else if (MapUtil.isEmpty(map1)) { + map1 = MapUtil.newHashMap(); + } else if (MapUtil.isEmpty(map2)) { + map2 = MapUtil.newHashMap(); + } + Set key = new HashSet<>(); + key.addAll(map1.keySet()); + key.addAll(map2.keySet()); + Map map = new HashMap<>(); + for (K t : key) { + X x = map1.get(t); + Y y = map2.get(t); + V z = merge.apply(x, y); + if (z != null) { + map.put(t, z); + } + } + return map; + } + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/StringUtils.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/StringUtils.java new file mode 100644 index 00000000..96b4b5c3 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/StringUtils.java @@ -0,0 +1,321 @@ +package cc.iotkit.common.utils; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Validator; +import cn.hutool.core.util.StrUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.util.AntPathMatcher; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 字符串工具类 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class StringUtils extends org.apache.commons.lang3.StringUtils { + + public static final String SEPARATOR = ","; + + /** + * 获取参数不为空值 + * + * @param str defaultValue 要判断的value + * @return value 返回值 + */ + public static String blankToDefault(String str, String defaultValue) { + return StrUtil.blankToDefault(str, defaultValue); + } + + /** + * * 判断一个字符串是否为空串 + * + * @param str String + * @return true:为空 false:非空 + */ + public static boolean isEmpty(String str) { + return StrUtil.isEmpty(str); + } + + /** + * * 判断一个字符串是否为非空串 + * + * @param str String + * @return true:非空串 false:空串 + */ + public static boolean isNotEmpty(String str) { + return !isEmpty(str); + } + + /** + * 去空格 + */ + public static String trim(String str) { + return StrUtil.trim(str); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @return 结果 + */ + public static String substring(final String str, int start) { + return substring(str, start, str.length()); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end 结束 + * @return 结果 + */ + public static String substring(final String str, int start, int end) { + return StrUtil.sub(str, start, end); + } + + /** + * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is {} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param template 文本模板,被替换的部分用 {} 表示 + * @param params 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... params) { + return StrUtil.format(template, params); + } + + /** + * 是否为http(s)://开头 + * + * @param link 链接 + * @return 结果 + */ + public static boolean ishttp(String link) { + return Validator.isUrl(link); + } + + /** + * 字符串转set + * + * @param str 字符串 + * @param sep 分隔符 + * @return set集合 + */ + public static Set str2Set(String str, String sep) { + return new HashSet<>(str2List(str, sep, true, false)); + } + + /** + * 字符串转list + * + * @param str 字符串 + * @param sep 分隔符 + * @param filterBlank 过滤纯空白 + * @param trim 去掉首尾空白 + * @return list集合 + */ + public static List str2List(String str, String sep, boolean filterBlank, boolean trim) { + List list = new ArrayList<>(); + if (isEmpty(str)) { + return list; + } + + // 过滤空白字符串 + if (filterBlank && isBlank(str)) { + return list; + } + String[] split = str.split(sep); + for (String string : split) { + if (filterBlank && isBlank(string)) { + continue; + } + if (trim) { + string = trim(string); + } + list.add(string); + } + + return list; + } + + /** + * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 + * + * @param cs 指定字符串 + * @param searchCharSequences 需要检查的字符串数组 + * @return 是否包含任意一个字符串 + */ + public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) { + return StrUtil.containsAnyIgnoreCase(cs, searchCharSequences); + } + + /** + * 驼峰转下划线命名 + */ + public static String toUnderScoreCase(String str) { + return StrUtil.toUnderlineCase(str); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) { + return StrUtil.equalsAnyIgnoreCase(str, strs); + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) { + return StrUtil.upperFirst(StrUtil.toCamelCase(name)); + } + + /** + * 驼峰式命名法 例如:user_name->userName + */ + public static String toCamelCase(String s) { + return StrUtil.toCamelCase(s); + } + + /** + * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, List strs) { + if (isEmpty(str) || CollUtil.isEmpty(strs)) { + return false; + } + for (String pattern : strs) { + if (isMatch(pattern, str)) { + return true; + } + } + return false; + } + + /** + * 判断url是否与规则配置: + * ? 表示单个字符; + * * 表示一层路径内的任意字符串,不可跨层级; + * ** 表示任意层路径; + * + * @param pattern 匹配规则 + * @param url 需要匹配的url + */ + public static boolean isMatch(String pattern, String url) { + AntPathMatcher matcher = new AntPathMatcher(); + return matcher.match(pattern, url); + } + + /** + * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 + * + * @param num 数字对象 + * @param size 字符串指定长度 + * @return 返回数字的字符串格式,该字符串为指定长度。 + */ + public static String padl(final Number num, final int size) { + return padl(num.toString(), size, '0'); + } + + /** + * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 + * + * @param s 原始字符串 + * @param size 字符串指定长度 + * @param c 用于补齐的字符 + * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 + */ + public static String padl(final String s, final int size, final char c) { + final StringBuilder sb = new StringBuilder(size); + if (s != null) { + final int len = s.length(); + if (s.length() <= size) { + sb.append(String.valueOf(c).repeat(size - len)); + sb.append(s); + } else { + return s.substring(len - size, len); + } + } else { + sb.append(String.valueOf(c).repeat(Math.max(0, size))); + } + return sb.toString(); + } + + /** + * 切分字符串(分隔符默认逗号) + * + * @param str 被切分的字符串 + * @return 分割后的数据列表 + */ + public static List splitList(String str) { + return splitTo(str, Convert::toStr); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符 + * @return 分割后的数据列表 + */ + public static List splitList(String str, String separator) { + return splitTo(str, separator, Convert::toStr); + } + + /** + * 切分字符串自定义转换(分隔符默认逗号) + * + * @param str 被切分的字符串 + * @param mapper 自定义转换 + * @return 分割后的数据列表 + */ + public static List splitTo(String str, Function mapper) { + return splitTo(str, SEPARATOR, mapper); + } + + /** + * 切分字符串自定义转换 + * + * @param str 被切分的字符串 + * @param separator 分隔符 + * @param mapper 自定义转换 + * @return 分割后的数据列表 + */ + public static List splitTo(String str, String separator, Function mapper) { + if (isBlank(str)) { + return new ArrayList<>(0); + } + return StrUtil.split(str, separator) + .stream() + .filter(Objects::nonNull) + .map(mapper) + .collect(Collectors.toList()); + } + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/ValidatorUtils.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/ValidatorUtils.java new file mode 100644 index 00000000..2e7a370f --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/ValidatorUtils.java @@ -0,0 +1,28 @@ +package cc.iotkit.common.utils; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; +import jakarta.validation.Validator; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.Set; + +/** + * Validator 校验框架工具 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ValidatorUtils { + + private static final Validator VALID = SpringUtils.getBean(Validator.class); + + public static void validate(T object, Class... groups) { + Set> validate = VALID.validate(object, groups); + if (!validate.isEmpty()) { + throw new ConstraintViolationException("参数校验异常", validate); + } + } + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/file/FileUtils.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/file/FileUtils.java new file mode 100644 index 00000000..df978517 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/file/FileUtils.java @@ -0,0 +1,43 @@ +package cc.iotkit.common.utils.file; + +import cn.hutool.core.io.FileUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import javax.servlet.http.HttpServletResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * 文件处理工具类 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class FileUtils extends FileUtil { + + /** + * 下载文件名重新编码 + * + * @param response 响应对象 + * @param realFileName 真实文件名 + */ + public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) { + String percentEncodedFileName = percentEncode(realFileName); + String contentDispositionValue = String.format("attachment; filename=%s;filename*=utf-8''%s", percentEncodedFileName, percentEncodedFileName); + response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename"); + response.setHeader("Content-disposition", contentDispositionValue); + response.setHeader("download-filename", percentEncodedFileName); + } + + /** + * 百分号编码工具方法 + * + * @param s 需要百分号编码的字符串 + * @return 百分号编码后的字符串 + */ + public static String percentEncode(String s) { + String encode = URLEncoder.encode(s, StandardCharsets.UTF_8); + return encode.replaceAll("\\+", "%20"); + } +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/file/MimeTypeUtils.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/file/MimeTypeUtils.java new file mode 100644 index 00000000..2f24e720 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/utils/file/MimeTypeUtils.java @@ -0,0 +1,40 @@ +package cc.iotkit.common.utils.file; + +/** + * 媒体类型工具类 + * + * @author ruoyi + */ +public class MimeTypeUtils { + public static final String IMAGE_PNG = "image/png"; + + public static final String IMAGE_JPG = "image/jpg"; + + public static final String IMAGE_JPEG = "image/jpeg"; + + public static final String IMAGE_BMP = "image/bmp"; + + public static final String IMAGE_GIF = "image/gif"; + + public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"}; + + public static final String[] FLASH_EXTENSION = {"swf", "flv"}; + + public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", + "asf", "rm", "rmvb"}; + + public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"}; + + public static final String[] DEFAULT_ALLOWED_EXTENSION = { + // 图片 + "bmp", "gif", "jpg", "jpeg", "png", + // word excel powerpoint + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", + // 压缩文件 + "rar", "zip", "gz", "bz2", + // 视频格式 + "mp4", "avi", "rmvb", + // pdf + "pdf"}; + +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/validate/AddGroup.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/validate/AddGroup.java new file mode 100644 index 00000000..1537625c --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/validate/AddGroup.java @@ -0,0 +1,9 @@ +package cc.iotkit.common.validate; + +/** + * 校验分组 add + * + * @author Lion Li + */ +public interface AddGroup { +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/validate/EditGroup.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/validate/EditGroup.java new file mode 100644 index 00000000..8fe56f4f --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/validate/EditGroup.java @@ -0,0 +1,9 @@ +package cc.iotkit.common.validate; + +/** + * 校验分组 edit + * + * @author Lion Li + */ +public interface EditGroup { +} diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/validate/QueryGroup.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/validate/QueryGroup.java new file mode 100644 index 00000000..f3f1d091 --- /dev/null +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/validate/QueryGroup.java @@ -0,0 +1,9 @@ +package cc.iotkit.common.validate; + +/** + * 校验分组 query + * + * @author Lion Li + */ +public interface QueryGroup { +} diff --git a/iot-components/iot-component-swagger/pom.xml b/iot-common/iot-common-doc/pom.xml similarity index 76% rename from iot-components/iot-component-swagger/pom.xml rename to iot-common/iot-common-doc/pom.xml index 0c04949a..f9679b9c 100644 --- a/iot-components/iot-component-swagger/pom.xml +++ b/iot-common/iot-common-doc/pom.xml @@ -2,14 +2,14 @@ - - iot-components + + iot-common cc.iotkit ${revision} 4.0.0 - iot-component-swagger + iot-common-doc @@ -50,4 +50,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-components/iot-component-swagger/src/main/java/cc/iotkit/swagger/annotation/EnableIotKitSwagger2.java b/iot-common/iot-common-doc/src/main/java/cc/iotkit/swagger/annotation/EnableIotKitSwagger2.java similarity index 100% rename from iot-components/iot-component-swagger/src/main/java/cc/iotkit/swagger/annotation/EnableIotKitSwagger2.java rename to iot-common/iot-common-doc/src/main/java/cc/iotkit/swagger/annotation/EnableIotKitSwagger2.java diff --git a/iot-components/iot-component-swagger/src/main/java/cc/iotkit/swagger/config/SwaggerAutoConfiguration.java b/iot-common/iot-common-doc/src/main/java/cc/iotkit/swagger/config/SwaggerAutoConfiguration.java similarity index 98% rename from iot-components/iot-component-swagger/src/main/java/cc/iotkit/swagger/config/SwaggerAutoConfiguration.java rename to iot-common/iot-common-doc/src/main/java/cc/iotkit/swagger/config/SwaggerAutoConfiguration.java index ec9e87ce..86dff023 100644 --- a/iot-components/iot-component-swagger/src/main/java/cc/iotkit/swagger/config/SwaggerAutoConfiguration.java +++ b/iot-common/iot-common-doc/src/main/java/cc/iotkit/swagger/config/SwaggerAutoConfiguration.java @@ -9,8 +9,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; -import springfox.documentation.builders.*; -import springfox.documentation.service.*; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.ApiSelectorBuilder; import springfox.documentation.spring.web.plugins.Docket; diff --git a/iot-components/iot-component-swagger/src/main/java/cc/iotkit/swagger/config/SwaggerProperties.java b/iot-common/iot-common-doc/src/main/java/cc/iotkit/swagger/config/SwaggerProperties.java similarity index 100% rename from iot-components/iot-component-swagger/src/main/java/cc/iotkit/swagger/config/SwaggerProperties.java rename to iot-common/iot-common-doc/src/main/java/cc/iotkit/swagger/config/SwaggerProperties.java diff --git a/iot-components/iot-component-swagger/src/main/java/cc/iotkit/swagger/config/SwaggerWebConfiguration.java b/iot-common/iot-common-doc/src/main/java/cc/iotkit/swagger/config/SwaggerWebConfiguration.java similarity index 100% rename from iot-components/iot-component-swagger/src/main/java/cc/iotkit/swagger/config/SwaggerWebConfiguration.java rename to iot-common/iot-common-doc/src/main/java/cc/iotkit/swagger/config/SwaggerWebConfiguration.java diff --git a/iot-components/iot-component-swagger/src/main/resources/META-INF/spring.factories b/iot-common/iot-common-doc/src/main/resources/META-INF/spring.factories similarity index 100% rename from iot-components/iot-component-swagger/src/main/resources/META-INF/spring.factories rename to iot-common/iot-common-doc/src/main/resources/META-INF/spring.factories diff --git a/iot-common/iot-common-excel/pom.xml b/iot-common/iot-common-excel/pom.xml new file mode 100644 index 00000000..7d453b7d --- /dev/null +++ b/iot-common/iot-common-excel/pom.xml @@ -0,0 +1,46 @@ + + + + iot-common + cc.iotkit + ${revision} + + 4.0.0 + + iot-common-excel + + + + + com.alibaba + easyexcel + + + + jakarta.servlet + jakarta.servlet-api + + + + cc.iotkit + iot-common-core + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/annotation/CellMerge.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/annotation/CellMerge.java new file mode 100644 index 00000000..82bd3329 --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/annotation/CellMerge.java @@ -0,0 +1,23 @@ +package cc.iotkit.common.excel.annotation; + + +import java.lang.annotation.*; + +/** + * excel 列单元格合并(合并列相同项) + * + * 需搭配 {@link CellMergeStrategy} 策略使用 + * + * @author Lion Li + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface CellMerge { + + /** + * col index + */ + int index() default -1; + +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/annotation/ExcelDictFormat.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/annotation/ExcelDictFormat.java new file mode 100644 index 00000000..3c695511 --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/annotation/ExcelDictFormat.java @@ -0,0 +1,33 @@ +package cc.iotkit.common.excel.annotation; + + +import cc.iotkit.common.utils.StringUtils; + +import java.lang.annotation.*; + +/** + * 字典格式化 + * + * @author Lion Li + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface ExcelDictFormat { + + /** + * 如果是字典类型,请设置字典的type值 (如: sys_user_sex) + */ + String dictType() default ""; + + /** + * 读取内容转表达式 (如: 0=男,1=女,2=未知) + */ + String readConverterExp() default ""; + + /** + * 分隔符,读取字符串组内容 + */ + String separator() default StringUtils.SEPARATOR; + +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/annotation/ExcelEnumFormat.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/annotation/ExcelEnumFormat.java new file mode 100644 index 00000000..5a39c1a3 --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/annotation/ExcelEnumFormat.java @@ -0,0 +1,30 @@ +package cc.iotkit.common.excel.annotation; + +import java.lang.annotation.*; + +/** + * 枚举格式化 + * + * @author Liang + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface ExcelEnumFormat { + + /** + * 字典枚举类型 + */ + Class> enumClass(); + + /** + * 字典枚举类中对应的code属性名称,默认为code + */ + String codeField() default "code"; + + /** + * 字典枚举类中对应的text属性名称,默认为text + */ + String textField() default "text"; + +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/convert/ExcelBigNumberConvert.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/convert/ExcelBigNumberConvert.java new file mode 100644 index 00000000..15d47dff --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/convert/ExcelBigNumberConvert.java @@ -0,0 +1,52 @@ +package cc.iotkit.common.excel.convert; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import lombok.extern.slf4j.Slf4j; + +import java.math.BigDecimal; + +/** + * 大数值转换 + * Excel 数值长度位15位 大于15位的数值转换位字符串 + * + * @author Lion Li + */ +@Slf4j +public class ExcelBigNumberConvert implements Converter { + + @Override + public Class supportJavaTypeKey() { + return Long.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public Long convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + return Convert.toLong(cellData.getData()); + } + + @Override + public WriteCellData convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if (ObjectUtil.isNotNull(object)) { + String str = Convert.toStr(object); + if (str.length() > 15) { + return new WriteCellData<>(str); + } + } + WriteCellData cellData = new WriteCellData<>(new BigDecimal(object)); + cellData.setType(CellDataTypeEnum.NUMBER); + return cellData; + } + +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/convert/ExcelDictConvert.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/convert/ExcelDictConvert.java new file mode 100644 index 00000000..ae383017 --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/convert/ExcelDictConvert.java @@ -0,0 +1,73 @@ +package cc.iotkit.common.excel.convert; + +import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.service.DictService; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.utils.ExcelUtil; + +import java.lang.reflect.Field; + +/** + * 字典格式化转换处理 + * + * @author Lion Li + */ +@Slf4j +public class ExcelDictConvert implements Converter { + + @Override + public Class supportJavaTypeKey() { + return Object.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return null; + } + + @Override + public Object convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + ExcelDictFormat anno = getAnnotation(contentProperty.getField()); + String type = anno.dictType(); + String label = cellData.getStringValue(); + String value; + if (StringUtils.isBlank(type)) { + value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator()); + } else { + value = SpringUtils.getBean(DictService.class).getDictValue(type, label, anno.separator()); + } + return Convert.convert(contentProperty.getField().getType(), value); + } + + @Override + public WriteCellData convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if (ObjectUtil.isNull(object)) { + return new WriteCellData<>(""); + } + ExcelDictFormat anno = getAnnotation(contentProperty.getField()); + String type = anno.dictType(); + String value = Convert.toStr(object); + String label; + if (StringUtils.isBlank(type)) { + label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator()); + } else { + label = SpringUtils.getBean(DictService.class).getDictLabel(type, value, anno.separator()); + } + return new WriteCellData<>(label); + } + + private ExcelDictFormat getAnnotation(Field field) { + return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class); + } +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/convert/ExcelEnumConvert.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/convert/ExcelEnumConvert.java new file mode 100644 index 00000000..281c5b96 --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/convert/ExcelEnumConvert.java @@ -0,0 +1,75 @@ +package cc.iotkit.common.excel.convert; + +import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.utils.reflect.ReflectUtils; +import org.dromara.common.excel.annotation.ExcelEnumFormat; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * 枚举格式化转换处理 + * + * @author Liang + */ +@Slf4j +public class ExcelEnumConvert implements Converter { + + @Override + public Class supportJavaTypeKey() { + return Object.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return null; + } + + @Override + public Object convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + Object codeValue = cellData.getData(); + // 如果是空值 + if (ObjectUtil.isNull(codeValue)) { + return null; + } + Map enumValueMap = beforeConvert(contentProperty); + String textValue = enumValueMap.get(codeValue); + return Convert.convert(contentProperty.getField().getType(), textValue); + } + + @Override + public WriteCellData convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if (ObjectUtil.isNull(object)) { + return new WriteCellData<>(""); + } + Map enumValueMap = beforeConvert(contentProperty); + String value = Convert.toStr(enumValueMap.get(object), ""); + return new WriteCellData<>(value); + } + + private Map beforeConvert(ExcelContentProperty contentProperty) { + ExcelEnumFormat anno = getAnnotation(contentProperty.getField()); + Map enumValueMap = new HashMap<>(); + Enum[] enumConstants = anno.enumClass().getEnumConstants(); + for (Enum enumConstant : enumConstants) { + Object codeValue = ReflectUtils.invokeGetter(enumConstant, anno.codeField()); + String textValue = ReflectUtils.invokeGetter(enumConstant, anno.textField()); + enumValueMap.put(codeValue, textValue); + } + return enumValueMap; + } + + private ExcelEnumFormat getAnnotation(Field field) { + return AnnotationUtil.getAnnotation(field, ExcelEnumFormat.class); + } +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/CellMergeStrategy.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/CellMergeStrategy.java new file mode 100644 index 00000000..2b2c278f --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/CellMergeStrategy.java @@ -0,0 +1,122 @@ +package cc.iotkit.common.excel.core; + +import cn.hutool.core.collection.CollUtil; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.write.merge.AbstractMergeStrategy; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; +import org.dromara.common.core.utils.reflect.ReflectUtils; +import org.dromara.common.excel.annotation.CellMerge; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 列值重复合并策略 + * + * @author Lion Li + */ +@Slf4j +public class CellMergeStrategy extends AbstractMergeStrategy { + + private final List list; + private final boolean hasTitle; + private int rowIndex; + + public CellMergeStrategy(List list, boolean hasTitle) { + this.list = list; + this.hasTitle = hasTitle; + // 行合并开始下标 + this.rowIndex = hasTitle ? 1 : 0; + } + + @Override + protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { + List cellList = handle(list, hasTitle); + // judge the list is not null + if (CollUtil.isNotEmpty(cellList)) { + // the judge is necessary + if (cell.getRowIndex() == rowIndex && cell.getColumnIndex() == 0) { + for (CellRangeAddress item : cellList) { + sheet.addMergedRegion(item); + } + } + } + } + + @SneakyThrows + private List handle(List list, boolean hasTitle) { + List cellList = new ArrayList<>(); + if (CollUtil.isEmpty(list)) { + return cellList; + } + Field[] fields = ReflectUtils.getFields(list.get(0).getClass(), field -> !"serialVersionUID".equals(field.getName())); + + // 有注解的字段 + List mergeFields = new ArrayList<>(); + List mergeFieldsIndex = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + if (field.isAnnotationPresent(CellMerge.class)) { + CellMerge cm = field.getAnnotation(CellMerge.class); + mergeFields.add(field); + mergeFieldsIndex.add(cm.index() == -1 ? i : cm.index()); + if (hasTitle) { + ExcelProperty property = field.getAnnotation(ExcelProperty.class); + rowIndex = Math.max(rowIndex, property.value().length); + } + } + } + + Map map = new HashMap<>(); + // 生成两两合并单元格 + for (int i = 0; i < list.size(); i++) { + for (int j = 0; j < mergeFields.size(); j++) { + Field field = mergeFields.get(j); + Object val = ReflectUtils.invokeGetter(list.get(i), field.getName()); + + int colNum = mergeFieldsIndex.get(j); + if (!map.containsKey(field)) { + map.put(field, new RepeatCell(val, i)); + } else { + RepeatCell repeatCell = map.get(field); + Object cellValue = repeatCell.getValue(); + if (cellValue == null || "".equals(cellValue)) { + // 空值跳过不合并 + continue; + } + if (!cellValue.equals(val)) { + if (i - repeatCell.getCurrent() > 1) { + cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum)); + } + map.put(field, new RepeatCell(val, i)); + } else if (i == list.size() - 1) { + if (i > repeatCell.getCurrent()) { + cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum)); + } + } + } + } + } + return cellList; + } + + @Data + @AllArgsConstructor + static class RepeatCell { + + private Object value; + + private int current; + + } +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/DefaultExcelListener.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/DefaultExcelListener.java new file mode 100644 index 00000000..224a49da --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/DefaultExcelListener.java @@ -0,0 +1,106 @@ +package cc.iotkit.common.excel.core; + +import cc.iotkit.common.utils.JsonUtils; +import cc.iotkit.common.utils.StreamUtils; +import cc.iotkit.common.utils.ValidatorUtils; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.exception.ExcelAnalysisException; +import com.alibaba.excel.exception.ExcelDataConvertException; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; +import java.util.Set; + +/** + * Excel 导入监听 + * + * @author Yjoioooo + * @author Lion Li + */ +@Slf4j +@NoArgsConstructor +public class DefaultExcelListener extends AnalysisEventListener implements ExcelListener { + + /** + * 是否Validator检验,默认为是 + */ + private Boolean isValidate = Boolean.TRUE; + + /** + * excel 表头数据 + */ + private Map headMap; + + /** + * 导入回执 + */ + private ExcelResult excelResult; + + public DefaultExcelListener(boolean isValidate) { + this.excelResult = new DefaultExcelResult<>(); + this.isValidate = isValidate; + } + + /** + * 处理异常 + * + * @param exception ExcelDataConvertException + * @param context Excel 上下文 + */ + @Override + public void onException(Exception exception, AnalysisContext context) throws Exception { + String errMsg = null; + if (exception instanceof ExcelDataConvertException) { + ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception; + // 如果是某一个单元格的转换异常 能获取到具体行号 + Integer rowIndex = excelDataConvertException.getRowIndex(); + Integer columnIndex = excelDataConvertException.getColumnIndex(); + errMsg = StrUtil.format("第{}行-第{}列-表头{}: 解析异常
", + rowIndex + 1, columnIndex + 1, headMap.get(columnIndex)); + if (log.isDebugEnabled()) { + log.error(errMsg); + } + } + if (exception instanceof ConstraintViolationException) { + ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception; + Set> constraintViolations = constraintViolationException.getConstraintViolations(); + String constraintViolationsMsg = StreamUtils.join(constraintViolations, ConstraintViolation::getMessage, ", "); + errMsg = StrUtil.format("第{}行数据校验异常: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg); + if (log.isDebugEnabled()) { + log.error(errMsg); + } + } + excelResult.getErrorList().add(errMsg); + throw new ExcelAnalysisException(errMsg); + } + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + this.headMap = headMap; + log.debug("解析到一条表头数据: {}", JsonUtils.toJsonString(headMap)); + } + + @Override + public void invoke(T data, AnalysisContext context) { + if (isValidate) { + ValidatorUtils.validate(data); + } + excelResult.getList().add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + log.debug("所有数据解析完成!"); + } + + @Override + public ExcelResult getExcelResult() { + return excelResult; + } + +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/DefaultExcelResult.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/DefaultExcelResult.java new file mode 100644 index 00000000..de88ff29 --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/DefaultExcelResult.java @@ -0,0 +1,73 @@ +package cc.iotkit.common.excel.core; + +import cn.hutool.core.util.StrUtil; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +/** + * 默认excel返回对象 + * + * @author Yjoioooo + * @author Lion Li + */ +public class DefaultExcelResult implements ExcelResult { + + /** + * 数据对象list + */ + @Setter + private List list; + + /** + * 错误信息列表 + */ + @Setter + private List errorList; + + public DefaultExcelResult() { + this.list = new ArrayList<>(); + this.errorList = new ArrayList<>(); + } + + public DefaultExcelResult(List list, List errorList) { + this.list = list; + this.errorList = errorList; + } + + public DefaultExcelResult(ExcelResult excelResult) { + this.list = excelResult.getList(); + this.errorList = excelResult.getErrorList(); + } + + @Override + public List getList() { + return list; + } + + @Override + public List getErrorList() { + return errorList; + } + + /** + * 获取导入回执 + * + * @return 导入回执 + */ + @Override + public String getAnalysis() { + int successCount = list.size(); + int errorCount = errorList.size(); + if (successCount == 0) { + return "读取失败,未解析到数据"; + } else { + if (errorCount == 0) { + return StrUtil.format("恭喜您,全部读取成功!共{}条", successCount); + } else { + return ""; + } + } + } +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/ExcelListener.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/ExcelListener.java new file mode 100644 index 00000000..cf12a666 --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/ExcelListener.java @@ -0,0 +1,14 @@ +package cc.iotkit.common.excel.core; + +import com.alibaba.excel.read.listener.ReadListener; + +/** + * Excel 导入监听 + * + * @author Lion Li + */ +public interface ExcelListener extends ReadListener { + + ExcelResult getExcelResult(); + +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/ExcelResult.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/ExcelResult.java new file mode 100644 index 00000000..fc4c7729 --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/core/ExcelResult.java @@ -0,0 +1,26 @@ +package cc.iotkit.common.excel.core; + +import java.util.List; + +/** + * excel返回对象 + * + * @author Lion Li + */ +public interface ExcelResult { + + /** + * 对象列表 + */ + List getList(); + + /** + * 错误列表 + */ + List getErrorList(); + + /** + * 导入回执 + */ + String getAnalysis(); +} diff --git a/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/utils/ExcelUtil.java b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/utils/ExcelUtil.java new file mode 100644 index 00000000..0d9b13b7 --- /dev/null +++ b/iot-common/iot-common-excel/src/main/java/cc/iotkit/common/excel/utils/ExcelUtil.java @@ -0,0 +1,327 @@ +package cc.iotkit.common.excel.utils; + +import cc.iotkit.common.excel.convert.ExcelBigNumberConvert; +import cc.iotkit.common.excel.core.CellMergeStrategy; +import cc.iotkit.common.excel.core.DefaultExcelListener; +import cc.iotkit.common.excel.core.ExcelListener; +import cc.iotkit.common.excel.core.ExcelResult; +import cc.iotkit.common.utils.StringUtils; +import cc.iotkit.common.utils.file.FileUtils; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.resource.ClassPathResource; +import cn.hutool.core.util.IdUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.fill.FillConfig; +import com.alibaba.excel.write.metadata.fill.FillWrapper; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * Excel相关处理 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ExcelUtil { + + /** + * 同步导入(适用于小数据量) + * + * @param is 输入流 + * @return 转换后集合 + */ + public static List importExcel(InputStream is, Class clazz) { + return EasyExcel.read(is).head(clazz).autoCloseStream(false).sheet().doReadSync(); + } + + + /** + * 使用校验监听器 异步导入 同步返回 + * + * @param is 输入流 + * @param clazz 对象类型 + * @param isValidate 是否 Validator 检验 默认为是 + * @return 转换后集合 + */ + public static ExcelResult importExcel(InputStream is, Class clazz, boolean isValidate) { + DefaultExcelListener listener = new DefaultExcelListener<>(isValidate); + EasyExcel.read(is, clazz, listener).sheet().doRead(); + return listener.getExcelResult(); + } + + /** + * 使用自定义监听器 异步导入 自定义返回 + * + * @param is 输入流 + * @param clazz 对象类型 + * @param listener 自定义监听器 + * @return 转换后集合 + */ + public static ExcelResult importExcel(InputStream is, Class clazz, ExcelListener listener) { + EasyExcel.read(is, clazz, listener).sheet().doRead(); + return listener.getExcelResult(); + } + + /** + * 导出excel + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param clazz 实体类 + * @param response 响应体 + */ + public static void exportExcel(List list, String sheetName, Class clazz, HttpServletResponse response) { + try { + resetResponse(sheetName, response); + ServletOutputStream os = response.getOutputStream(); + exportExcel(list, sheetName, clazz, false, os); + } catch (IOException e) { + throw new RuntimeException("导出Excel异常"); + } + } + + /** + * 导出excel + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param clazz 实体类 + * @param merge 是否合并单元格 + * @param response 响应体 + */ + public static void exportExcel(List list, String sheetName, Class clazz, boolean merge, HttpServletResponse response) { + try { + resetResponse(sheetName, response); + ServletOutputStream os = response.getOutputStream(); + exportExcel(list, sheetName, clazz, merge, os); + } catch (IOException e) { + throw new RuntimeException("导出Excel异常"); + } + } + + /** + * 导出excel + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param clazz 实体类 + * @param os 输出流 + */ + public static void exportExcel(List list, String sheetName, Class clazz, OutputStream os) { + exportExcel(list, sheetName, clazz, false, os); + } + + /** + * 导出excel + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param clazz 实体类 + * @param merge 是否合并单元格 + * @param os 输出流 + */ + public static void exportExcel(List list, String sheetName, Class clazz, boolean merge, OutputStream os) { + ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz) + .autoCloseStream(false) + // 自动适配 + .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) + // 大数值自动转换 防止失真 + .registerConverter(new ExcelBigNumberConvert()) + .sheet(sheetName); + if (merge) { + // 合并处理器 + builder.registerWriteHandler(new CellMergeStrategy(list, true)); + } + builder.doWrite(list); + } + + /** + * 单表多数据模板导出 模板格式为 {.属性} + * + * @param filename 文件名 + * @param templatePath 模板路径 resource 目录下的路径包括模板文件名 + * 例如: excel/temp.xlsx + * 重点: 模板文件必须放置到启动类对应的 resource 目录下 + * @param data 模板需要的数据 + * @param response 响应体 + */ + public static void exportTemplate(List data, String filename, String templatePath, HttpServletResponse response) { + try { + resetResponse(filename, response); + ServletOutputStream os = response.getOutputStream(); + exportTemplate(data, templatePath, os); + } catch (IOException e) { + throw new RuntimeException("导出Excel异常"); + } + } + + /** + * 单表多数据模板导出 模板格式为 {.属性} + * + * @param templatePath 模板路径 resource 目录下的路径包括模板文件名 + * 例如: excel/temp.xlsx + * 重点: 模板文件必须放置到启动类对应的 resource 目录下 + * @param data 模板需要的数据 + * @param os 输出流 + */ + public static void exportTemplate(List data, String templatePath, OutputStream os) { + ClassPathResource templateResource = new ClassPathResource(templatePath); + ExcelWriter excelWriter = EasyExcel.write(os) + .withTemplate(templateResource.getStream()) + .autoCloseStream(false) + // 大数值自动转换 防止失真 + .registerConverter(new ExcelBigNumberConvert()) + .build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } + // 单表多数据导出 模板格式为 {.属性} + for (Object d : data) { + excelWriter.fill(d, writeSheet); + } + excelWriter.finish(); + } + + /** + * 多表多数据模板导出 模板格式为 {key.属性} + * + * @param filename 文件名 + * @param templatePath 模板路径 resource 目录下的路径包括模板文件名 + * 例如: excel/temp.xlsx + * 重点: 模板文件必须放置到启动类对应的 resource 目录下 + * @param data 模板需要的数据 + * @param response 响应体 + */ + public static void exportTemplateMultiList(Map data, String filename, String templatePath, HttpServletResponse response) { + try { + resetResponse(filename, response); + ServletOutputStream os = response.getOutputStream(); + exportTemplateMultiList(data, templatePath, os); + } catch (IOException e) { + throw new RuntimeException("导出Excel异常"); + } + } + + /** + * 多表多数据模板导出 模板格式为 {key.属性} + * + * @param templatePath 模板路径 resource 目录下的路径包括模板文件名 + * 例如: excel/temp.xlsx + * 重点: 模板文件必须放置到启动类对应的 resource 目录下 + * @param data 模板需要的数据 + * @param os 输出流 + */ + public static void exportTemplateMultiList(Map data, String templatePath, OutputStream os) { + ClassPathResource templateResource = new ClassPathResource(templatePath); + ExcelWriter excelWriter = EasyExcel.write(os) + .withTemplate(templateResource.getStream()) + .autoCloseStream(false) + // 大数值自动转换 防止失真 + .registerConverter(new ExcelBigNumberConvert()) + .build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } + for (Map.Entry map : data.entrySet()) { + // 设置列表后续还有数据 + FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); + if (map.getValue() instanceof Collection) { + // 多表导出必须使用 FillWrapper + excelWriter.fill(new FillWrapper(map.getKey(), (Collection) map.getValue()), fillConfig, writeSheet); + } else { + excelWriter.fill(map.getValue(), writeSheet); + } + } + excelWriter.finish(); + } + + /** + * 重置响应体 + */ + private static void resetResponse(String sheetName, HttpServletResponse response) { + String filename = encodingFilename(sheetName); + FileUtils.setAttachmentResponseHeader(response, filename); + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); + } + + /** + * 解析导出值 0=男,1=女,2=未知 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String convertByExp(String propertyValue, String converterExp, String separator) { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(StringUtils.SEPARATOR); + for (String item : convertSource) { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(propertyValue, separator)) { + for (String value : propertyValue.split(separator)) { + if (itemArray[0].equals(value)) { + propertyString.append(itemArray[1]).append(separator); + break; + } + } + } else { + if (itemArray[0].equals(propertyValue)) { + return itemArray[1]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 反向解析值 男=0,女=1,未知=2 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String reverseByExp(String propertyValue, String converterExp, String separator) { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(StringUtils.SEPARATOR); + for (String item : convertSource) { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(propertyValue, separator)) { + for (String value : propertyValue.split(separator)) { + if (itemArray[1].equals(value)) { + propertyString.append(itemArray[0]).append(separator); + break; + } + } + } else { + if (itemArray[1].equals(propertyValue)) { + return itemArray[0]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 编码文件名 + */ + public static String encodingFilename(String filename) { + return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx"; + } + +} diff --git a/iot-common/iot-common-log/pom.xml b/iot-common/iot-common-log/pom.xml new file mode 100644 index 00000000..00fac737 --- /dev/null +++ b/iot-common/iot-common-log/pom.xml @@ -0,0 +1,61 @@ + + + + iot-common + cc.iotkit + ${revision} + + 4.0.0 + + iot-common-log + + + + + org.aspectj + aspectjweaver + + + + org.springframework.boot + spring-boot-autoconfigure + + + + com.alibaba + transmittable-thread-local + + + + org.projectlombok + lombok + + + + cc.iotkit + iot-common-core + + + + cc.iotkit + iot-common-security + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-common/iot-common-oss/pom.xml b/iot-common/iot-common-oss/pom.xml new file mode 100644 index 00000000..38135837 --- /dev/null +++ b/iot-common/iot-common-oss/pom.xml @@ -0,0 +1,27 @@ + + + + iot-common + cc.iotkit + ${revision} + + 4.0.0 + + iot-common-oss + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-common/iot-common-redis/pom.xml b/iot-common/iot-common-redis/pom.xml new file mode 100644 index 00000000..b887d202 --- /dev/null +++ b/iot-common/iot-common-redis/pom.xml @@ -0,0 +1,48 @@ + + + + iot-common + cc.iotkit + ${revision} + + 4.0.0 + + iot-common-redis + + + + + + cc.iotkit + iot-common-core + + + + + org.redisson + redisson-spring-boot-starter + + + + com.baomidou + lock4j-redisson-spring-boot-starter + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/config/RedisConfig.java b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/config/RedisConfig.java new file mode 100644 index 00000000..ee82e63f --- /dev/null +++ b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/config/RedisConfig.java @@ -0,0 +1,130 @@ +package cc.iotkit.common.redis.config; + +import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.dromara.common.redis.config.properties.RedissonProperties; +import org.dromara.common.redis.handler.KeyPrefixHandler; +import org.dromara.common.redis.manager.PlusSpringCacheManager; +import lombok.extern.slf4j.Slf4j; +import org.redisson.codec.JsonJacksonCodec; +import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; + +/** + * redis配置 + * + * @author Lion Li + */ +@Slf4j +@AutoConfiguration +@EnableCaching +@EnableConfigurationProperties(RedissonProperties.class) +public class RedisConfig { + + @Autowired + private RedissonProperties redissonProperties; + + @Autowired + private ObjectMapper objectMapper; + + @Bean + public RedissonAutoConfigurationCustomizer redissonCustomizer() { + return config -> { + config.setThreads(redissonProperties.getThreads()) + .setNettyThreads(redissonProperties.getNettyThreads()) + .setCodec(new JsonJacksonCodec(objectMapper)); + 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 配置"); + }; + } + + /** + * 自定义缓存管理器 整合spring-cache + */ + @Bean + public CacheManager cacheManager() { + return new PlusSpringCacheManager(); + } + + /** + * redis集群配置 yml + * + * --- # redis 集群配置(单机与集群只能开启一个另一个需要注释掉) + * spring: + * redis: + * cluster: + * nodes: + * - 192.168.0.100:6379 + * - 192.168.0.101:6379 + * - 192.168.0.102:6379 + * # 密码 + * password: + * # 连接超时时间 + * timeout: 10s + * # 是否开启ssl + * ssl: false + * + * redisson: + * # 线程池数量 + * threads: 16 + * # Netty线程池数量 + * nettyThreads: 32 + * # 集群配置 + * clusterServersConfig: + * # 客户端名称 + * clientName: ${ruoyi.name} + * # master最小空闲连接数 + * masterConnectionMinimumIdleSize: 32 + * # master连接池大小 + * masterConnectionPoolSize: 64 + * # slave最小空闲连接数 + * slaveConnectionMinimumIdleSize: 32 + * # slave连接池大小 + * slaveConnectionPoolSize: 64 + * # 连接空闲超时,单位:毫秒 + * idleConnectionTimeout: 10000 + * # 命令等待超时,单位:毫秒 + * timeout: 3000 + * # 发布和订阅连接池大小 + * subscriptionConnectionPoolSize: 50 + * # 读取模式 + * readMode: "SLAVE" + * # 订阅模式 + * subscriptionMode: "MASTER" + */ + +} diff --git a/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/config/properties/RedissonProperties.java b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/config/properties/RedissonProperties.java new file mode 100644 index 00000000..af7a6067 --- /dev/null +++ b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/config/properties/RedissonProperties.java @@ -0,0 +1,135 @@ +package cc.iotkit.common.redis.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 配置属性 + * + * @author Lion Li + */ +@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/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/handler/KeyPrefixHandler.java b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/handler/KeyPrefixHandler.java new file mode 100644 index 00000000..7f57f53f --- /dev/null +++ b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/handler/KeyPrefixHandler.java @@ -0,0 +1,50 @@ +package cc.iotkit.common.redis.handler; + +import org.dromara.common.core.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/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/manager/PlusSpringCacheManager.java b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/manager/PlusSpringCacheManager.java new file mode 100644 index 00000000..33d65034 --- /dev/null +++ b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/manager/PlusSpringCacheManager.java @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2013-2021 Nikita Koksharov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cc.iotkit.common.redis.manager; + +import org.dromara.common.redis.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 org.springframework.cache.CacheManager} implementation + * backed by Redisson instance. + *

+ * 修改 RedissonSpringCacheManager 源码 + * 重写 cacheName 处理方法 支持多参数 + * + * @author Nikita Koksharov + * + */ +@SuppressWarnings("unchecked") +public class PlusSpringCacheManager implements CacheManager { + + private boolean dynamic = true; + + private boolean allowNullValues = true; + + private boolean transactionAware = true; + + Map configMap = new ConcurrentHashMap<>(); + ConcurrentMap instanceMap = new ConcurrentHashMap<>(); + + /** + * Creates CacheManager supplied by Redisson instance + */ + public PlusSpringCacheManager() { + } + + + /** + * 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) { + 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); + } + + // 重写 cacheName 支持多参数 + String[] array = StringUtils.delimitedListToStringArray(name, "#"); + name = array[0]; + 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 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 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/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/utils/CacheUtils.java b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/utils/CacheUtils.java new file mode 100644 index 00000000..51817842 --- /dev/null +++ b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/utils/CacheUtils.java @@ -0,0 +1,75 @@ +package cc.iotkit.common.redis.utils; + +import org.dromara.common.core.utils.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/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/utils/QueueUtils.java b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/utils/QueueUtils.java new file mode 100644 index 00000000..4e3b1fad --- /dev/null +++ b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/utils/QueueUtils.java @@ -0,0 +1,180 @@ +package cc.iotkit.common.redis.utils; + +import org.dromara.common.core.utils.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); + } + + /** + * 尝试设置 有界队列 容量 用于限制数量 + * + * @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); + } + + /** + * 订阅阻塞队列(可订阅所有实现类 例如: 延迟 优先 有界 等) + */ + public static void subscribeBlockingQueue(String queueName, Consumer consumer) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + queue.subscribeOnElements(consumer); + } + +} diff --git a/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/utils/RedisUtils.java b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/utils/RedisUtils.java new file mode 100644 index 00000000..b6171c6a --- /dev/null +++ b/iot-common/iot-common-redis/src/main/java/cc/iotkit/common/redis/utils/RedisUtils.java @@ -0,0 +1,462 @@ +package cc.iotkit.common.redis.utils; + +import cc.iotkit.common.utils.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); + } + + 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(); + 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(); + } + + /** + * 注册对象监听器 + *

+ * 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监听器 + *

+ * 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(); + } + + /** + * 缓存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监听器 + *

+ * 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键集合 + * @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/iot-common/iot-common-redis/src/main/resources/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iot-common/iot-common-redis/src/main/resources/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..cdda9835 --- /dev/null +++ b/iot-common/iot-common-redis/src/main/resources/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cc.iotkit.common.redis.config.RedisConfig diff --git a/iot-common/iot-common-security/pom.xml b/iot-common/iot-common-security/pom.xml new file mode 100644 index 00000000..557ebaaf --- /dev/null +++ b/iot-common/iot-common-security/pom.xml @@ -0,0 +1,53 @@ + + + + iot-common + cc.iotkit + ${revision} + + 4.0.0 + + iot-common-security + + + + + + cn.dev33 + sa-token-spring-boot3-starter + + + + + cn.dev33 + sa-token-jwt + + + + cc.iotkit + iot-common-core + + + + cc.iotkit + iot-common-redis + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/config/SaTokenConfig.java b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/config/SaTokenConfig.java new file mode 100644 index 00000000..1482b56e --- /dev/null +++ b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/config/SaTokenConfig.java @@ -0,0 +1,43 @@ +package cc.iotkit.common.satoken.config; + +import cc.iotkit.common.satoken.core.dao.PlusSaTokenDao; +import cc.iotkit.common.satoken.core.service.SaPermissionImpl; +import cn.dev33.satoken.dao.SaTokenDao; +import cn.dev33.satoken.jwt.StpLogicJwtForSimple; +import cn.dev33.satoken.stp.StpInterface; +import cn.dev33.satoken.stp.StpLogic; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * sa-token 配置 + * + * @author Lion Li + */ +@AutoConfiguration +public class SaTokenConfig implements WebMvcConfigurer { + + @Bean + public StpLogic getStpLogicJwt() { + // Sa-Token 整合 jwt (简单模式) + return new StpLogicJwtForSimple(); + } + + /** + * 权限接口实现(使用bean注入方便用户替换) + */ + @Bean + public StpInterface stpInterface() { + return new SaPermissionImpl(); + } + + /** + * 自定义dao层存储 + */ + @Bean + public SaTokenDao saTokenDao() { + return new PlusSaTokenDao(); + } + +} diff --git a/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/core/dao/PlusSaTokenDao.java b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/core/dao/PlusSaTokenDao.java new file mode 100644 index 00000000..d35ce393 --- /dev/null +++ b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/core/dao/PlusSaTokenDao.java @@ -0,0 +1,176 @@ +package cc.iotkit.common.satoken.core.dao; + +import cc.iotkit.common.redis.utils.RedisUtils; +import cn.dev33.satoken.dao.SaTokenDao; +import cn.dev33.satoken.util.SaFoxUtil; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Sa-Token持久层接口(使用框架自带RedisUtils实现 协议统一) + * + * @author Lion Li + */ +public class PlusSaTokenDao implements SaTokenDao { + + /** + * 获取Value,如无返空 + */ + @Override + public String get(String key) { + return RedisUtils.getCacheObject(key); + } + + /** + * 写入Value,并设定存活时间 (单位: 秒) + */ + @Override + public void set(String key, String value, long timeout) { + if (timeout == 0 || timeout <= NOT_VALUE_EXPIRE) { + return; + } + // 判断是否为永不过期 + if (timeout == NEVER_EXPIRE) { + RedisUtils.setCacheObject(key, value); + } else { + RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); + } + } + + /** + * 修修改指定key-value键值对 (过期时间不变) + */ + @Override + public void update(String key, String value) { + long expire = getTimeout(key); + // -2 = 无此键 + if (expire == NOT_VALUE_EXPIRE) { + return; + } + this.set(key, value, expire); + } + + /** + * 删除Value + */ + @Override + public void delete(String key) { + RedisUtils.deleteObject(key); + } + + /** + * 获取Value的剩余存活时间 (单位: 秒) + */ + @Override + public long getTimeout(String key) { + long timeout = RedisUtils.getTimeToLive(key); + return timeout < 0 ? timeout : timeout / 1000; + } + + /** + * 修改Value的剩余存活时间 (单位: 秒) + */ + @Override + public void updateTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == NEVER_EXPIRE) { + long expire = getTimeout(key); + if (expire == NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.set(key, this.get(key), timeout); + } + return; + } + RedisUtils.expire(key, Duration.ofSeconds(timeout)); + } + + + /** + * 获取Object,如无返空 + */ + @Override + public Object getObject(String key) { + return RedisUtils.getCacheObject(key); + } + + /** + * 写入Object,并设定存活时间 (单位: 秒) + */ + @Override + public void setObject(String key, Object object, long timeout) { + if (timeout == 0 || timeout <= NOT_VALUE_EXPIRE) { + return; + } + // 判断是否为永不过期 + if (timeout == NEVER_EXPIRE) { + RedisUtils.setCacheObject(key, object); + } else { + RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); + } + } + + /** + * 更新Object (过期时间不变) + */ + @Override + public void updateObject(String key, Object object) { + long expire = getObjectTimeout(key); + // -2 = 无此键 + if (expire == NOT_VALUE_EXPIRE) { + return; + } + this.setObject(key, object, expire); + } + + /** + * 删除Object + */ + @Override + public void deleteObject(String key) { + RedisUtils.deleteObject(key); + } + + /** + * 获取Object的剩余存活时间 (单位: 秒) + */ + @Override + public long getObjectTimeout(String key) { + long timeout = RedisUtils.getTimeToLive(key); + return timeout < 0 ? timeout : timeout / 1000; + } + + /** + * 修改Object的剩余存活时间 (单位: 秒) + */ + @Override + public void updateObjectTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == NEVER_EXPIRE) { + long expire = getObjectTimeout(key); + if (expire == NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.setObject(key, this.getObject(key), timeout); + } + return; + } + RedisUtils.expire(key, Duration.ofSeconds(timeout)); + } + + + /** + * 搜索数据 + */ + @Override + public List searchData(String prefix, String keyword, int start, int size, boolean sortType) { + Collection keys = RedisUtils.keys(prefix + "*" + keyword + "*"); + List list = new ArrayList<>(keys); + return SaFoxUtil.searchList(list, start, size, sortType); + } +} diff --git a/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/core/service/SaPermissionImpl.java b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/core/service/SaPermissionImpl.java new file mode 100644 index 00000000..0a00cdb1 --- /dev/null +++ b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/core/service/SaPermissionImpl.java @@ -0,0 +1,47 @@ +package cc.iotkit.common.satoken.core.service; + +import cc.iotkit.common.domain.model.LoginUser; +import cc.iotkit.common.enums.UserType; +import cc.iotkit.common.satoken.utils.LoginHelper; +import cn.dev33.satoken.stp.StpInterface; + +import java.util.ArrayList; +import java.util.List; + +/** + * sa-token 权限管理实现类 + * + * @author Lion Li + */ +public class SaPermissionImpl implements StpInterface { + + /** + * 获取菜单权限列表 + */ + @Override + public List getPermissionList(Object loginId, String loginType) { + LoginUser loginUser = LoginHelper.getLoginUser(); + UserType userType = UserType.getUserType(loginUser.getUserType()); + if (userType == UserType.SYS_USER) { + return new ArrayList<>(loginUser.getMenuPermission()); + } else if (userType == UserType.APP_USER) { + // 其他端 自行根据业务编写 + } + return new ArrayList<>(); + } + + /** + * 获取角色权限列表 + */ + @Override + public List getRoleList(Object loginId, String loginType) { + LoginUser loginUser = LoginHelper.getLoginUser(); + UserType userType = UserType.getUserType(loginUser.getUserType()); + if (userType == UserType.SYS_USER) { + return new ArrayList<>(loginUser.getRolePermission()); + } else if (userType == UserType.APP_USER) { + // 其他端 自行根据业务编写 + } + return new ArrayList<>(); + } +} diff --git a/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/listener/UserActionListener.java b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/listener/UserActionListener.java new file mode 100644 index 00000000..b21b0f53 --- /dev/null +++ b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/listener/UserActionListener.java @@ -0,0 +1,139 @@ +package cc.iotkit.common.satoken.listener; + +import cn.dev33.satoken.config.SaTokenConfig; +import cn.dev33.satoken.listener.SaTokenListener; +import cn.dev33.satoken.stp.SaLoginModel; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.constant.CacheConstants; +import org.dromara.common.core.domain.dto.UserOnlineDTO; +import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.common.core.enums.UserType; +import org.dromara.common.core.utils.ServletUtils; +import org.dromara.common.core.utils.ip.AddressUtils; +import org.dromara.common.redis.utils.RedisUtils; +import org.dromara.common.satoken.utils.LoginHelper; +import org.springframework.stereotype.Component; + +import java.time.Duration; + +/** + * 用户行为 侦听器的实现 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Component +@Slf4j +public class UserActionListener implements SaTokenListener { + + private final SaTokenConfig tokenConfig; + + /** + * 每次登录时触发 + */ + @Override + public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) { + UserType userType = UserType.getUserType(loginId.toString()); + if (userType == UserType.SYS_USER) { + UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = ServletUtils.getClientIP(); + LoginUser user = LoginHelper.getLoginUser(); + UserOnlineDTO dto = new UserOnlineDTO(); + dto.setIpaddr(ip); + dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); + dto.setBrowser(userAgent.getBrowser().getName()); + dto.setOs(userAgent.getOs().getName()); + dto.setLoginTime(System.currentTimeMillis()); + dto.setTokenId(tokenValue); + dto.setUserName(user.getUsername()); + dto.setDeptName(user.getDeptName()); + if(tokenConfig.getTimeout() == -1) { + RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto); + } else { + RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout())); + } + log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue); + } else if (userType == UserType.APP_USER) { + // app端 自行根据业务编写 + } + } + + /** + * 每次注销时触发 + */ + @Override + public void doLogout(String loginType, Object loginId, String tokenValue) { + RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); + log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue); + } + + /** + * 每次被踢下线时触发 + */ + @Override + public void doKickout(String loginType, Object loginId, String tokenValue) { + RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); + log.info("user doKickout, userId:{}, token:{}", loginId, tokenValue); + } + + /** + * 每次被顶下线时触发 + */ + @Override + public void doReplaced(String loginType, Object loginId, String tokenValue) { + RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); + log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue); + } + + /** + * 每次被封禁时触发 + */ + @Override + public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) { + } + + /** + * 每次被解封时触发 + */ + @Override + public void doUntieDisable(String loginType, Object loginId, String service) { + } + + /** + * 每次打开二级认证时触发 + */ + @Override + public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) { + } + + /** + * 每次创建Session时触发 + */ + @Override + public void doCloseSafe(String loginType, String tokenValue, String service) { + } + + /** + * 每次创建Session时触发 + */ + @Override + public void doCreateSession(String id) { + } + + /** + * 每次注销Session时触发 + */ + @Override + public void doLogoutSession(String id) { + } + + /** + * 每次Token续期时触发 + */ + @Override + public void doRenewTimeout(String tokenValue, Object loginId, long timeout) { + } +} diff --git a/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/utils/LoginHelper.java b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/utils/LoginHelper.java new file mode 100644 index 00000000..db820b39 --- /dev/null +++ b/iot-common/iot-common-security/src/main/java/cc/iotkit/common/satoken/utils/LoginHelper.java @@ -0,0 +1,172 @@ +package cc.iotkit.common.satoken.utils; + +import cc.iotkit.common.constant.TenantConstants; +import cc.iotkit.common.constant.UserConstants; +import cc.iotkit.common.domain.model.LoginUser; +import cc.iotkit.common.enums.DeviceType; +import cc.iotkit.common.enums.UserType; +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.context.model.SaStorage; +import cn.dev33.satoken.stp.SaLoginModel; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.Set; + +/** + * 登录鉴权助手 + *

+ * user_type 为 用户类型 同一个用户表 可以有多种用户类型 例如 pc,app + * deivce 为 设备类型 同一个用户类型 可以有 多种设备类型 例如 web,ios + * 可以组成 用户类型与设备类型多对多的 权限灵活控制 + *

+ * 多用户体系 针对 多种用户类型 但权限控制不一致 + * 可以组成 多用户类型表与多设备类型 分别控制权限 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class LoginHelper { + + public static final String LOGIN_USER_KEY = "loginUser"; + public static final String TENANT_KEY = "tenantId"; + public static final String USER_KEY = "userId"; + + /** + * 登录系统 + * + * @param loginUser 登录用户信息 + */ + public static void login(LoginUser loginUser) { + loginByDevice(loginUser, null); + } + + /** + * 登录系统 基于 设备类型 + * 针对相同用户体系不同设备 + * + * @param loginUser 登录用户信息 + */ + public static void loginByDevice(LoginUser loginUser, DeviceType deviceType) { + SaStorage storage = SaHolder.getStorage(); + storage.set(LOGIN_USER_KEY, loginUser); + storage.set(TENANT_KEY, loginUser.getTenantId()); + storage.set(USER_KEY, loginUser.getUserId()); + SaLoginModel model = new SaLoginModel(); + if (ObjectUtil.isNotNull(deviceType)) { + model.setDevice(deviceType.getDevice()); + } + StpUtil.login(loginUser.getLoginId(), + model.setExtra(TENANT_KEY, loginUser.getTenantId()) + .setExtra(USER_KEY, loginUser.getUserId())); + StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser); + } + + /** + * 获取用户(多级缓存) + */ + public static LoginUser getLoginUser() { + LoginUser loginUser = (LoginUser) SaHolder.getStorage().get(LOGIN_USER_KEY); + if (loginUser != null) { + return loginUser; + } + loginUser = (LoginUser) StpUtil.getTokenSession().get(LOGIN_USER_KEY); + SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser); + return loginUser; + } + + /** + * 获取用户基于token + */ + public static LoginUser getLoginUser(String token) { + return (LoginUser) StpUtil.getTokenSessionByToken(token).get(LOGIN_USER_KEY); + } + + /** + * 获取用户id + */ + public static Long getUserId() { + Long userId; + try { + userId = Convert.toLong(SaHolder.getStorage().get(USER_KEY)); + if (ObjectUtil.isNull(userId)) { + userId = Convert.toLong(StpUtil.getExtra(USER_KEY)); + SaHolder.getStorage().set(USER_KEY, userId); + } + } catch (Exception e) { + return null; + } + return userId; + } + + /** + * 获取租户ID + */ + public static String getTenantId() { + String tenantId; + try { + tenantId = (String) SaHolder.getStorage().get(TENANT_KEY); + if (ObjectUtil.isNull(tenantId)) { + tenantId = (String) StpUtil.getExtra(TENANT_KEY); + SaHolder.getStorage().set(TENANT_KEY, tenantId); + } + } catch (Exception e) { + return null; + } + return tenantId; + } + + /** + * 获取部门ID + */ + public static Long getDeptId() { + return getLoginUser().getDeptId(); + } + + /** + * 获取用户账户 + */ + public static String getUsername() { + return getLoginUser().getUsername(); + } + + /** + * 获取用户类型 + */ + public static UserType getUserType() { + String loginId = StpUtil.getLoginIdAsString(); + return UserType.getUserType(loginId); + } + + /** + * 是否为超级管理员 + * + * @param userId 用户ID + * @return 结果 + */ + public static boolean isSuperAdmin(Long userId) { + return UserConstants.SUPER_ADMIN_ID.equals(userId); + } + + public static boolean isSuperAdmin() { + return isSuperAdmin(getUserId()); + } + + /** + * 是否为超级管理员 + * + * @param rolePermission 角色权限标识组 + * @return 结果 + */ + public static boolean isTenantAdmin(Set rolePermission) { + return rolePermission.contains(TenantConstants.TENANT_ADMIN_ROLE_KEY); + } + + public static boolean isTenantAdmin() { + return isTenantAdmin(getLoginUser().getRolePermission()); + } + +} diff --git a/iot-common/iot-common-tenant/pom.xml b/iot-common/iot-common-tenant/pom.xml new file mode 100644 index 00000000..ffcfc25f --- /dev/null +++ b/iot-common/iot-common-tenant/pom.xml @@ -0,0 +1,41 @@ + + + + iot-common + cc.iotkit + ${revision} + + 4.0.0 + + iot-common-tenant + + + + + cc.iotkit + iot-common-core + + + + cc.iotkit + iot-common-redis + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/config/TenantConfig.java b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/config/TenantConfig.java new file mode 100644 index 00000000..18f3612d --- /dev/null +++ b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/config/TenantConfig.java @@ -0,0 +1,100 @@ +package cc.iotkit.common.tenant.config; + +import cn.dev33.satoken.dao.SaTokenDao; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; +import org.dromara.common.core.utils.reflect.ReflectUtils; +import org.dromara.common.mybatis.config.MybatisPlusConfig; +import org.dromara.common.redis.config.RedisConfig; +import org.dromara.common.redis.config.properties.RedissonProperties; +import org.dromara.common.tenant.core.TenantSaTokenDao; +import org.dromara.common.tenant.handle.PlusTenantLineHandler; +import org.dromara.common.tenant.handle.TenantKeyPrefixHandler; +import org.dromara.common.tenant.manager.TenantSpringCacheManager; +import org.dromara.common.tenant.properties.TenantProperties; +import org.redisson.config.ClusterServersConfig; +import org.redisson.config.SingleServerConfig; +import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +import java.util.ArrayList; +import java.util.List; + +/** + * 租户配置类 + * + * @author Lion Li + */ +@EnableConfigurationProperties(TenantProperties.class) +@AutoConfiguration(after = {RedisConfig.class, MybatisPlusConfig.class}) +@ConditionalOnProperty(value = "tenant.enable", havingValue = "true") +public class TenantConfig { + + /** + * 初始化租户配置 + */ + @Bean + public boolean tenantInit(MybatisPlusInterceptor mybatisPlusInterceptor, + TenantProperties tenantProperties) { + List interceptors = new ArrayList<>(); + // 多租户插件 必须放到第一位 + interceptors.add(tenantLineInnerInterceptor(tenantProperties)); + interceptors.addAll(mybatisPlusInterceptor.getInterceptors()); + mybatisPlusInterceptor.setInterceptors(interceptors); + return true; + } + + /** + * 多租户插件 + */ + public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) { + return new TenantLineInnerInterceptor(new PlusTenantLineHandler(tenantProperties)); + } + + @Bean + public RedissonAutoConfigurationCustomizer tenantRedissonCustomizer(RedissonProperties redissonProperties) { + return config -> { + TenantKeyPrefixHandler nameMapper = new TenantKeyPrefixHandler(redissonProperties.getKeyPrefix()); + SingleServerConfig singleServerConfig = ReflectUtils.invokeGetter(config, "singleServerConfig"); + if (ObjectUtil.isNotNull(singleServerConfig)) { + // 使用单机模式 + // 设置多租户 redis key前缀 + singleServerConfig.setNameMapper(nameMapper); + ReflectUtils.invokeSetter(config, "singleServerConfig", singleServerConfig); + } + ClusterServersConfig clusterServersConfig = ReflectUtils.invokeGetter(config, "clusterServersConfig"); + // 集群配置方式 参考下方注释 + if (ObjectUtil.isNotNull(clusterServersConfig)) { + // 设置多租户 redis key前缀 + clusterServersConfig.setNameMapper(nameMapper); + ReflectUtils.invokeSetter(config, "clusterServersConfig", clusterServersConfig); + } + }; + } + + /** + * 多租户缓存管理器 + */ + @Primary + @Bean + public CacheManager tenantCacheManager() { + return new TenantSpringCacheManager(); + } + + /** + * 多租户鉴权dao实现 + */ + @Primary + @Bean + public SaTokenDao tenantSaTokenDao() { + return new TenantSaTokenDao(); + } + +} diff --git a/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/core/TenantEntity.java b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/core/TenantEntity.java new file mode 100644 index 00000000..2fe74c80 --- /dev/null +++ b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/core/TenantEntity.java @@ -0,0 +1,21 @@ +package cc.iotkit.common.tenant.core; + +import cc.iotkit.common.domain.model.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 租户基类 + * + * @author Michelle.Chung + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class TenantEntity extends BaseEntity { + + /** + * 租户编号 + */ + private String tenantId; + +} diff --git a/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/core/TenantSaTokenDao.java b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/core/TenantSaTokenDao.java new file mode 100644 index 00000000..3667f38d --- /dev/null +++ b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/core/TenantSaTokenDao.java @@ -0,0 +1,148 @@ +package cc.iotkit.common.tenant.core; + +import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.redis.utils.RedisUtils; +import org.dromara.common.satoken.core.dao.PlusSaTokenDao; + +import java.time.Duration; +import java.util.List; + +/** + * SaToken 认证数据持久层 适配多租户 + * + * @author Lion Li + */ +public class TenantSaTokenDao extends PlusSaTokenDao { + + @Override + public String get(String key) { + return super.get(GlobalConstants.GLOBAL_REDIS_KEY + key); + } + + @Override + public void set(String key, String value, long timeout) { + super.set(GlobalConstants.GLOBAL_REDIS_KEY + key, value, timeout); + } + + /** + * 修修改指定key-value键值对 (过期时间不变) + */ + @Override + public void update(String key, String value) { + long expire = getTimeout(key); + // -2 = 无此键 + if (expire == NOT_VALUE_EXPIRE) { + return; + } + this.set(key, value, expire); + } + + /** + * 删除Value + */ + @Override + public void delete(String key) { + super.delete(GlobalConstants.GLOBAL_REDIS_KEY + key); + } + + /** + * 获取Value的剩余存活时间 (单位: 秒) + */ + @Override + public long getTimeout(String key) { + return super.getTimeout(GlobalConstants.GLOBAL_REDIS_KEY + key); + } + + /** + * 修改Value的剩余存活时间 (单位: 秒) + */ + @Override + public void updateTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == NEVER_EXPIRE) { + long expire = getTimeout(key); + if (expire == NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.set(key, this.get(key), timeout); + } + return; + } + RedisUtils.expire(GlobalConstants.GLOBAL_REDIS_KEY + key, Duration.ofSeconds(timeout)); + } + + + /** + * 获取Object,如无返空 + */ + @Override + public Object getObject(String key) { + return super.getObject(GlobalConstants.GLOBAL_REDIS_KEY + key); + } + + /** + * 写入Object,并设定存活时间 (单位: 秒) + */ + @Override + public void setObject(String key, Object object, long timeout) { + super.setObject(GlobalConstants.GLOBAL_REDIS_KEY + key, object, timeout); + } + + /** + * 更新Object (过期时间不变) + */ + @Override + public void updateObject(String key, Object object) { + long expire = getObjectTimeout(key); + // -2 = 无此键 + if (expire == NOT_VALUE_EXPIRE) { + return; + } + this.setObject(key, object, expire); + } + + /** + * 删除Object + */ + @Override + public void deleteObject(String key) { + super.deleteObject(GlobalConstants.GLOBAL_REDIS_KEY + key); + } + + /** + * 获取Object的剩余存活时间 (单位: 秒) + */ + @Override + public long getObjectTimeout(String key) { + return super.getObjectTimeout(GlobalConstants.GLOBAL_REDIS_KEY + key); + } + + /** + * 修改Object的剩余存活时间 (单位: 秒) + */ + @Override + public void updateObjectTimeout(String key, long timeout) { + // 判断是否想要设置为永久 + if (timeout == NEVER_EXPIRE) { + long expire = getObjectTimeout(key); + if (expire == NEVER_EXPIRE) { + // 如果其已经被设置为永久,则不作任何处理 + } else { + // 如果尚未被设置为永久,那么再次set一次 + this.setObject(key, this.getObject(key), timeout); + } + return; + } + RedisUtils.expire(GlobalConstants.GLOBAL_REDIS_KEY + key, Duration.ofSeconds(timeout)); + } + + + /** + * 搜索数据 + */ + @Override + public List searchData(String prefix, String keyword, int start, int size, boolean sortType) { + return super.searchData(GlobalConstants.GLOBAL_REDIS_KEY + prefix, keyword, start, size, sortType); + } +} diff --git a/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/exception/TenantException.java b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/exception/TenantException.java new file mode 100644 index 00000000..45a5af4b --- /dev/null +++ b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/exception/TenantException.java @@ -0,0 +1,20 @@ +package cc.iotkit.common.tenant.exception; + + +import cc.iotkit.common.exception.BizException; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 租户异常类 + * + * @author Lion Li + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class TenantException extends BizException { + + public TenantException(String code, String message) { + super("tenant", code, message); + } +} diff --git a/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/handle/PlusTenantLineHandler.java b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/handle/PlusTenantLineHandler.java new file mode 100644 index 00000000..bf65d6e7 --- /dev/null +++ b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/handle/PlusTenantLineHandler.java @@ -0,0 +1,59 @@ +package cc.iotkit.common.tenant.handle; + +import cn.hutool.core.collection.ListUtil; +import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; +import lombok.AllArgsConstructor; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.NullValue; +import net.sf.jsqlparser.expression.StringValue; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.tenant.helper.TenantHelper; +import org.dromara.common.tenant.properties.TenantProperties; + +import java.util.List; + +/** + * 自定义租户处理器 + * + * @author Lion Li + */ +@AllArgsConstructor +public class PlusTenantLineHandler implements TenantLineHandler { + + private final TenantProperties tenantProperties; + + @Override + public Expression getTenantId() { + String tenantId = LoginHelper.getTenantId(); + if (StringUtils.isBlank(tenantId)) { + return new NullValue(); + } + String dynamicTenantId = TenantHelper.getDynamic(); + if (StringUtils.isNotBlank(dynamicTenantId)) { + // 返回动态租户 + return new StringValue(dynamicTenantId); + } + // 返回固定租户 + return new StringValue(tenantId); + } + + @Override + public boolean ignoreTable(String tableName) { + String tenantId = LoginHelper.getTenantId(); + // 判断是否有租户 + if (StringUtils.isNotBlank(tenantId)) { + // 不需要过滤租户的表 + List excludes = tenantProperties.getExcludes(); + // 非业务表 + List tables = ListUtil.toList( + "gen_table", + "gen_table_column" + ); + tables.addAll(excludes); + return tables.contains(tableName); + } + return true; + } + +} diff --git a/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/handle/TenantKeyPrefixHandler.java b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/handle/TenantKeyPrefixHandler.java new file mode 100644 index 00000000..b0632ab3 --- /dev/null +++ b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/handle/TenantKeyPrefixHandler.java @@ -0,0 +1,58 @@ +package cc.iotkit.common.tenant.handle; + +import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.redis.handler.KeyPrefixHandler; +import org.dromara.common.tenant.helper.TenantHelper; + +/** + * 多租户redis缓存key前缀处理 + * + * @author Lion Li + */ +public class TenantKeyPrefixHandler extends KeyPrefixHandler { + + public TenantKeyPrefixHandler(String keyPrefix) { + super(keyPrefix); + } + + /** + * 增加前缀 + */ + @Override + public String map(String name) { + if (StringUtils.isBlank(name)) { + return null; + } + if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { + return super.map(name); + } + String tenantId = TenantHelper.getTenantId(); + if (StringUtils.startsWith(name, tenantId)) { + // 如果存在则直接返回 + return super.map(name); + } + return super.map(tenantId + ":" + name); + } + + /** + * 去除前缀 + */ + @Override + public String unmap(String name) { + String unmap = super.unmap(name); + if (StringUtils.isBlank(unmap)) { + return null; + } + if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { + return super.unmap(name); + } + String tenantId = TenantHelper.getTenantId(); + if (StringUtils.startsWith(unmap, tenantId)) { + // 如果存在则删除 + return unmap.substring((tenantId + ":").length()); + } + return unmap; + } + +} diff --git a/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/helper/TenantHelper.java b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/helper/TenantHelper.java new file mode 100644 index 00000000..3917d542 --- /dev/null +++ b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/helper/TenantHelper.java @@ -0,0 +1,140 @@ +package cc.iotkit.common.tenant.helper; + +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.spring.SpringMVCUtil; +import cn.hutool.core.convert.Convert; +import com.alibaba.ttl.TransmittableThreadLocal; +import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy; +import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.redis.utils.RedisUtils; +import org.dromara.common.satoken.utils.LoginHelper; + +import java.util.function.Supplier; + +/** + * 租户助手 + * + * @author Lion Li + */ +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class TenantHelper { + + private static final String DYNAMIC_TENANT_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "dynamicTenant"; + + private static final ThreadLocal TEMP_DYNAMIC_TENANT = new TransmittableThreadLocal<>(); + + /** + * 租户功能是否启用 + */ + public static boolean isEnable() { + return Convert.toBool(SpringUtils.getProperty("tenant.enable"), false); + } + + /** + * 开启忽略租户(开启后需手动调用 {@link #disableIgnore()} 关闭) + */ + public static void enableIgnore() { + InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build()); + } + + /** + * 关闭忽略租户 + */ + public static void disableIgnore() { + InterceptorIgnoreHelper.clearIgnoreStrategy(); + } + + /** + * 在忽略租户中执行 + * + * @param handle 处理执行方法 + */ + public static void ignore(Runnable handle) { + enableIgnore(); + try { + handle.run(); + } finally { + disableIgnore(); + } + } + + /** + * 在忽略租户中执行 + * + * @param handle 处理执行方法 + */ + public static T ignore(Supplier handle) { + enableIgnore(); + try { + return handle.get(); + } finally { + disableIgnore(); + } + } + + /** + * 设置动态租户(一直有效 需要手动清理) + *

+ * 如果为非web环境 那么只在当前线程内生效 + */ + public static void setDynamic(String tenantId) { + if (!SpringMVCUtil.isWeb()) { + TEMP_DYNAMIC_TENANT.set(tenantId); + return; + } + String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); + RedisUtils.setCacheObject(cacheKey, tenantId); + SaHolder.getStorage().set(cacheKey, tenantId); + } + + /** + * 获取动态租户(一直有效 需要手动清理) + *

+ * 如果为非web环境 那么只在当前线程内生效 + */ + public static String getDynamic() { + if (!SpringMVCUtil.isWeb()) { + return TEMP_DYNAMIC_TENANT.get(); + } + String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); + String tenantId = (String) SaHolder.getStorage().get(cacheKey); + if (StringUtils.isNotBlank(tenantId)) { + return tenantId; + } + tenantId = RedisUtils.getCacheObject(cacheKey); + SaHolder.getStorage().set(cacheKey, tenantId); + return tenantId; + } + + /** + * 清除动态租户 + */ + public static void clearDynamic() { + if (!SpringMVCUtil.isWeb()) { + TEMP_DYNAMIC_TENANT.remove(); + return; + } + String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); + RedisUtils.deleteObject(cacheKey); + SaHolder.getStorage().delete(cacheKey); + } + + /** + * 获取当前租户id(动态租户优先) + */ + public static String getTenantId() { + String tenantId = TenantHelper.getDynamic(); + if (StringUtils.isBlank(tenantId)) { + tenantId = LoginHelper.getTenantId(); + } + return tenantId; + } + +} diff --git a/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/manager/TenantSpringCacheManager.java b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/manager/TenantSpringCacheManager.java new file mode 100644 index 00000000..9e8a2d5c --- /dev/null +++ b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/manager/TenantSpringCacheManager.java @@ -0,0 +1,32 @@ +package cc.iotkit.common.tenant.manager; + +import cc.iotkit.common.constant.GlobalConstants; +import cc.iotkit.common.redis.manager.PlusSpringCacheManager; +import cc.iotkit.common.tenant.helper.TenantHelper; +import cc.iotkit.common.utils.StringUtils; +import org.springframework.cache.Cache; + +/** + * 重写 cacheName 处理方法 支持多租户 + * + * @author Lion Li + */ +public class TenantSpringCacheManager extends PlusSpringCacheManager { + + public TenantSpringCacheManager() { + } + + @Override + public Cache getCache(String name) { + if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { + return super.getCache(name); + } + String tenantId = TenantHelper.getTenantId(); + if (StringUtils.startsWith(name, tenantId)) { + // 如果存在则直接返回 + return super.getCache(name); + } + return super.getCache(tenantId + ":" + name); + } + +} diff --git a/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/properties/TenantProperties.java b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/properties/TenantProperties.java new file mode 100644 index 00000000..1aea06f3 --- /dev/null +++ b/iot-common/iot-common-tenant/src/main/java/cc/iotkit/common/tenant/properties/TenantProperties.java @@ -0,0 +1,27 @@ +package cc.iotkit.common.tenant.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +/** + * 租户 配置属性 + * + * @author Lion Li + */ +@Data +@ConfigurationProperties(prefix = "tenant") +public class TenantProperties { + + /** + * 是否启用 + */ + private Boolean enable; + + /** + * 排除表 + */ + private List excludes; + +} diff --git a/iot-common/iot-common-web/pom.xml b/iot-common/iot-common-web/pom.xml new file mode 100644 index 00000000..f82b248b --- /dev/null +++ b/iot-common/iot-common-web/pom.xml @@ -0,0 +1,63 @@ + + + + iot-common + cc.iotkit + ${revision} + + 4.0.0 + + iot-common-web + + + + + + org.springframework.boot + spring-boot-starter-web + + + spring-boot-starter-tomcat + org.springframework.boot + + + + + + org.springframework.boot + spring-boot-starter-undertow + + + + cn.hutool + hutool-captcha + + + + org.projectlombok + lombok + + + + cc.iotkit + iot-common-core + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/CaptchaConfig.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/CaptchaConfig.java new file mode 100644 index 00000000..b37b7e8e --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/CaptchaConfig.java @@ -0,0 +1,65 @@ +package cc.iotkit.common.web.config; + +import cc.iotkit.common.web.config.properties.CaptchaProperties; +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.CircleCaptcha; +import cn.hutool.captcha.LineCaptcha; +import cn.hutool.captcha.ShearCaptcha; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; + +import java.awt.*; + +/** + * 验证码配置 + * + * @author Lion Li + */ +@AutoConfiguration +@EnableConfigurationProperties(CaptchaProperties.class) +public class CaptchaConfig { + + private static final int WIDTH = 160; + private static final int HEIGHT = 60; + private static final Color BACKGROUND = Color.PINK; + private static final Font FONT = new Font("Arial", Font.BOLD, 48); + + /** + * 圆圈干扰验证码 + */ + @Lazy + @Bean + public CircleCaptcha circleCaptcha() { + CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(WIDTH, HEIGHT); + captcha.setBackground(BACKGROUND); + captcha.setFont(FONT); + return captcha; + } + + /** + * 线段干扰的验证码 + */ + @Lazy + @Bean + public LineCaptcha lineCaptcha() { + LineCaptcha captcha = CaptchaUtil.createLineCaptcha(WIDTH, HEIGHT); + captcha.setBackground(BACKGROUND); + captcha.setFont(FONT); + return captcha; + } + + /** + * 扭曲干扰验证码 + */ + @Lazy + @Bean + public ShearCaptcha shearCaptcha() { + ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(WIDTH, HEIGHT); + captcha.setBackground(BACKGROUND); + captcha.setFont(FONT); + return captcha; + } + +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/FilterConfig.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/FilterConfig.java new file mode 100644 index 00000000..cfe7e743 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/FilterConfig.java @@ -0,0 +1,53 @@ +package cc.iotkit.common.web.config; + +import jakarta.servlet.DispatcherType; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.web.config.properties.XssProperties; +import org.dromara.common.web.filter.RepeatableFilter; +import org.dromara.common.web.filter.XssFilter; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; + +import java.util.HashMap; +import java.util.Map; + +/** + * Filter配置 + * + * @author Lion Li + */ +@AutoConfiguration +@EnableConfigurationProperties(XssProperties.class) +public class FilterConfig { + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Bean + @ConditionalOnProperty(value = "xss.enabled", havingValue = "true") + public FilterRegistrationBean xssFilterRegistration(XssProperties xssProperties) { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setDispatcherTypes(DispatcherType.REQUEST); + registration.setFilter(new XssFilter()); + registration.addUrlPatterns(StringUtils.split(xssProperties.getUrlPatterns(), StringUtils.SEPARATOR)); + registration.setName("xssFilter"); + registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); + Map initParameters = new HashMap<>(); + initParameters.put("excludes", xssProperties.getExcludes()); + 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/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/ResourcesConfig.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/ResourcesConfig.java new file mode 100644 index 00000000..fe34a808 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/ResourcesConfig.java @@ -0,0 +1,52 @@ +package cc.iotkit.common.web.config; + +import cc.iotkit.common.web.interceptor.PlusWebInvokeTimeInterceptor; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; +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; + +/** + * 通用配置 + * + * @author Lion Li + */ +@AutoConfiguration +public class ResourcesConfig implements WebMvcConfigurer { + + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 全局访问性能拦截 + registry.addInterceptor(new PlusWebInvokeTimeInterceptor()); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + } + + /** + * 跨域配置 + */ + @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); + } +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/UndertowConfig.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/UndertowConfig.java new file mode 100644 index 00000000..83f4efd9 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/UndertowConfig.java @@ -0,0 +1,30 @@ +package cc.iotkit.common.web.config; + +import io.undertow.server.DefaultByteBufferPool; +import io.undertow.websockets.jsr.WebSocketDeploymentInfo; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; + +/** + * Undertow 自定义配置 + * + * @author Lion Li + */ +@AutoConfiguration +public class UndertowConfig implements WebServerFactoryCustomizer { + + /** + * 设置 Undertow 的 websocket 缓冲池 + */ + @Override + public void customize(UndertowServletWebServerFactory factory) { + // 默认不直接分配内存 如果项目中使用了 websocket 建议直接分配 + factory.addDeploymentInfoCustomizers(deploymentInfo -> { + WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo(); + webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, 512)); + deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo); + }); + } + +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/properties/CaptchaProperties.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/properties/CaptchaProperties.java new file mode 100644 index 00000000..26ad96a7 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/properties/CaptchaProperties.java @@ -0,0 +1,38 @@ +package cc.iotkit.common.web.config.properties; + +import cc.iotkit.common.web.enums.CaptchaCategory; +import cc.iotkit.common.web.enums.CaptchaType; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * 验证码 配置属性 + * + * @author Lion Li + */ +@Data +@ConfigurationProperties(prefix = "captcha") +public class CaptchaProperties { + + private Boolean enable; + + /** + * 验证码类型 + */ + private CaptchaType type; + + /** + * 验证码类别 + */ + private CaptchaCategory category; + + /** + * 数字验证码位数 + */ + private Integer numberLength; + + /** + * 字符验证码长度 + */ + private Integer charLength; +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/properties/XssProperties.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/properties/XssProperties.java new file mode 100644 index 00000000..4f8e9a08 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/config/properties/XssProperties.java @@ -0,0 +1,30 @@ +package cc.iotkit.common.web.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * xss过滤 配置属性 + * + * @author Lion Li + */ +@Data +@ConfigurationProperties(prefix = "xss") +public class XssProperties { + + /** + * 过滤开关 + */ + private String enabled; + + /** + * 排除链接(多个用逗号分隔) + */ + private String excludes; + + /** + * 匹配链接 + */ + private String urlPatterns; + +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/core/BaseController.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/core/BaseController.java new file mode 100644 index 00000000..1495d35c --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/core/BaseController.java @@ -0,0 +1,56 @@ +package cc.iotkit.common.web.core; + + +import cc.iotkit.common.exception.ViewException; +import cc.iotkit.common.utils.StringUtils; + +/** + * web层通用数据处理 + * + * @author Lion Li + */ +public class BaseController { + + public static void fail() { + throw new ViewException("操作失败"); + } + + public static void fail(String msg) { + throw new ViewException(msg); + } + + public static void fail(T data) { + throw new ViewException(ViewException.CODE_FAILED, "操作失败", data); + } + + public static void fail(String msg, T data) { + throw new ViewException(ViewException.CODE_FAILED, msg, data); + } + + /** + * 返回警告消息 + * + * @param msg 返回内容 + */ + public static void warn(String msg) { + throw new ViewException(ViewException.CODE_WARN, msg); + } + + /** + * 返回警告消息 + * + * @param msg 返回内容 + * @param data 数据对象 + */ + public static void warn(String msg, T data) { + throw new ViewException(ViewException.CODE_WARN, msg, data); + } + + /** + * 页面跳转 + */ + public String redirect(String url) { + return StringUtils.format("redirect:{}", url); + } + +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/enums/CaptchaCategory.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/enums/CaptchaCategory.java new file mode 100644 index 00000000..ca5bddd3 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/enums/CaptchaCategory.java @@ -0,0 +1,35 @@ +package cc.iotkit.common.web.enums; + +import cn.hutool.captcha.AbstractCaptcha; +import cn.hutool.captcha.CircleCaptcha; +import cn.hutool.captcha.LineCaptcha; +import cn.hutool.captcha.ShearCaptcha; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 验证码类别 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum CaptchaCategory { + + /** + * 线段干扰 + */ + LINE(LineCaptcha.class), + + /** + * 圆圈干扰 + */ + CIRCLE(CircleCaptcha.class), + + /** + * 扭曲干扰 + */ + SHEAR(ShearCaptcha.class); + + private final Class clazz; +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/enums/CaptchaType.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/enums/CaptchaType.java new file mode 100644 index 00000000..df83608b --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/enums/CaptchaType.java @@ -0,0 +1,29 @@ +package cc.iotkit.common.web.enums; + +import cn.hutool.captcha.generator.CodeGenerator; +import cn.hutool.captcha.generator.RandomGenerator; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.dromara.common.web.utils.UnsignedMathGenerator; + +/** + * 验证码类型 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum CaptchaType { + + /** + * 数字 + */ + MATH(UnsignedMathGenerator.class), + + /** + * 字符 + */ + CHAR(RandomGenerator.class); + + private final Class clazz; +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/RepeatableFilter.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/RepeatableFilter.java new file mode 100644 index 00000000..c75310e5 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/RepeatableFilter.java @@ -0,0 +1,40 @@ +package cc.iotkit.common.web.filter; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import org.dromara.common.core.utils.StringUtils; +import org.springframework.http.MediaType; + +import java.io.IOException; + +/** + * Repeatable 过滤器 + * + * @author ruoyi + */ +public class RepeatableFilter implements Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + ServletRequest requestWrapper = null; + if (request instanceof HttpServletRequest + && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) { + requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); + } + if (null == requestWrapper) { + chain.doFilter(request, response); + } else { + chain.doFilter(requestWrapper, response); + } + } + + @Override + public void destroy() { + + } +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/RepeatedlyRequestWrapper.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/RepeatedlyRequestWrapper.java new file mode 100644 index 00000000..d9c00232 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/RepeatedlyRequestWrapper.java @@ -0,0 +1,67 @@ +package cc.iotkit.common.web.filter; + +import cn.hutool.core.io.IoUtil; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import org.dromara.common.core.constant.Constants; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * 构建可重复读取inputStream的request + * + * @author ruoyi + */ +public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper { + private final byte[] body; + + public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException { + super(request); + request.setCharacterEncoding(Constants.UTF8); + response.setCharacterEncoding(Constants.UTF8); + + body = IoUtil.readBytes(request.getInputStream(), false); + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream bais = new ByteArrayInputStream(body); + return new ServletInputStream() { + @Override + public int read() throws IOException { + return bais.read(); + } + + @Override + public int available() throws IOException { + return body.length; + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + }; + } +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/XssFilter.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/XssFilter.java new file mode 100644 index 00000000..152216d5 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/XssFilter.java @@ -0,0 +1,62 @@ +package cc.iotkit.common.web.filter; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.dromara.common.core.utils.StringUtils; +import org.springframework.http.HttpMethod; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * 防止XSS攻击的过滤器 + * + * @author ruoyi + */ +public class XssFilter implements Filter { + /** + * 排除链接 + */ + public List excludes = new ArrayList<>(); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + String tempExcludes = filterConfig.getInitParameter("excludes"); + if (StringUtils.isNotEmpty(tempExcludes)) { + String[] url = tempExcludes.split(StringUtils.SEPARATOR); + for (int i = 0; url != null && i < url.length; i++) { + excludes.add(url[i]); + } + } + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + if (handleExcludeURL(req, resp)) { + chain.doFilter(request, response); + return; + } + XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); + chain.doFilter(xssRequest, response); + } + + private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) { + String url = request.getServletPath(); + String method = request.getMethod(); + // GET DELETE 不过滤 + if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method)) { + return true; + } + return StringUtils.matches(url, excludes); + } + + @Override + public void destroy() { + + } +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/XssHttpServletRequestWrapper.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/XssHttpServletRequestWrapper.java new file mode 100644 index 00000000..c8b44c59 --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/filter/XssHttpServletRequestWrapper.java @@ -0,0 +1,97 @@ +package cc.iotkit.common.web.filter; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HtmlUtil; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import org.dromara.common.core.utils.StringUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +/** + * XSS过滤处理 + * + * @author ruoyi + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + /** + * @param request + */ + public XssHttpServletRequestWrapper(HttpServletRequest request) { + super(request); + } + + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (values != null) { + int length = values.length; + String[] escapseValues = new String[length]; + for (int i = 0; i < length; i++) { + // 防xss攻击和过滤前后空格 + escapseValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim(); + } + return escapseValues; + } + return super.getParameterValues(name); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + // 非json类型,直接返回 + if (!isJsonRequest()) { + return super.getInputStream(); + } + + // 为空,直接返回 + String json = StrUtil.str(IoUtil.readBytes(super.getInputStream(), false), StandardCharsets.UTF_8); + if (StringUtils.isEmpty(json)) { + return super.getInputStream(); + } + + // xss过滤 + json = HtmlUtil.cleanHtmlTag(json).trim(); + byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8); + final ByteArrayInputStream bis = IoUtil.toStream(jsonBytes); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public int available() throws IOException { + return jsonBytes.length; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + + @Override + public int read() throws IOException { + return bis.read(); + } + }; + } + + /** + * 是否是Json请求 + */ + public boolean isJsonRequest() { + String header = super.getHeader(HttpHeaders.CONTENT_TYPE); + return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); + } +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/interceptor/PlusWebInvokeTimeInterceptor.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/interceptor/PlusWebInvokeTimeInterceptor.java new file mode 100644 index 00000000..93277f2f --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/interceptor/PlusWebInvokeTimeInterceptor.java @@ -0,0 +1,94 @@ +package cc.iotkit.common.web.interceptor; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.map.MapUtil; +import com.alibaba.ttl.TransmittableThreadLocal; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.time.StopWatch; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.json.utils.JsonUtils; +import org.dromara.common.web.filter.RepeatedlyRequestWrapper; +import org.springframework.http.MediaType; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import java.io.BufferedReader; +import java.util.Map; + +/** + * web的调用时间统计拦截器 + * dev环境有效 + * + * @author Lion Li + * @since 3.3.0 + */ +@Slf4j +public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor { + + private final String prodProfile = "prod"; + + private final TransmittableThreadLocal invokeTimeTL = new TransmittableThreadLocal<>(); + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if (!prodProfile.equals(SpringUtils.getActiveProfile())) { + String url = request.getMethod() + " " + request.getRequestURI(); + + // 打印请求参数 + if (isJsonRequest(request)) { + String jsonParam = ""; + if (request instanceof RepeatedlyRequestWrapper) { + BufferedReader reader = request.getReader(); + jsonParam = IoUtil.read(reader); + } + log.debug("[PLUS]开始请求 => URL[{}],参数类型[json],参数:[{}]", url, jsonParam); + } else { + Map parameterMap = request.getParameterMap(); + if (MapUtil.isNotEmpty(parameterMap)) { + String parameters = JsonUtils.toJsonString(parameterMap); + log.debug("[PLUS]开始请求 => URL[{}],参数类型[param],参数:[{}]", url, parameters); + } else { + log.debug("[PLUS]开始请求 => URL[{}],无参数", url); + } + } + + StopWatch stopWatch = new StopWatch(); + invokeTimeTL.set(stopWatch); + stopWatch.start(); + } + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + if (!prodProfile.equals(SpringUtils.getActiveProfile())) { + StopWatch stopWatch = invokeTimeTL.get(); + stopWatch.stop(); + log.debug("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime()); + invokeTimeTL.remove(); + } + } + + /** + * 判断本次请求的数据类型是否为json + * + * @param request request + * @return boolean + */ + private boolean isJsonRequest(HttpServletRequest request) { + String contentType = request.getContentType(); + if (contentType != null) { + return StringUtils.startsWithIgnoreCase(contentType, MediaType.APPLICATION_JSON_VALUE); + } + return false; + } + +} diff --git a/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/utils/UnsignedMathGenerator.java b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/utils/UnsignedMathGenerator.java new file mode 100644 index 00000000..3942644f --- /dev/null +++ b/iot-common/iot-common-web/src/main/java/cc/iotkit/common/web/utils/UnsignedMathGenerator.java @@ -0,0 +1,88 @@ +package cc.iotkit.common.web.utils; + +import cn.hutool.captcha.generator.CodeGenerator; +import cn.hutool.core.math.Calculator; +import cn.hutool.core.util.CharUtil; +import cn.hutool.core.util.RandomUtil; +import org.dromara.common.core.utils.StringUtils; + +import java.io.Serial; + +/** + * 无符号计算生成器 + * + * @author Lion Li + */ +public class UnsignedMathGenerator implements CodeGenerator { + + @Serial + private static final long serialVersionUID = -5514819971774091076L; + + private static final String OPERATORS = "+-*"; + + /** + * 参与计算数字最大长度 + */ + private final int numberLength; + + /** + * 构造 + */ + public UnsignedMathGenerator() { + this(2); + } + + /** + * 构造 + * + * @param numberLength 参与计算最大数字位数 + */ + public UnsignedMathGenerator(int numberLength) { + this.numberLength = numberLength; + } + + @Override + public String generate() { + final int limit = getLimit(); + int a = RandomUtil.randomInt(limit); + int b = RandomUtil.randomInt(limit); + String max = Integer.toString(Math.max(a,b)); + String min = Integer.toString(Math.min(a,b)); + max = StringUtils.rightPad(max, this.numberLength, CharUtil.SPACE); + min = StringUtils.rightPad(min, this.numberLength, CharUtil.SPACE); + + return max + RandomUtil.randomChar(OPERATORS) + min + '='; + } + + @Override + public boolean verify(String code, String userInputCode) { + int result; + try { + result = Integer.parseInt(userInputCode); + } catch (NumberFormatException e) { + // 用户输入非数字 + return false; + } + + final int calculateResult = (int) Calculator.conversion(code); + return result == calculateResult; + } + + /** + * 获取验证码长度 + * + * @return 验证码长度 + */ + public int getLength() { + return this.numberLength * 2 + 2; + } + + /** + * 根据长度获取参与计算数字最大值 + * + * @return 最大值 + */ + private int getLimit() { + return Integer.parseInt("1" + StringUtils.repeat('0', this.numberLength)); + } +} diff --git a/iot-common/iot-common-web/src/main/resources/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iot-common/iot-common-web/src/main/resources/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..52054e08 --- /dev/null +++ b/iot-common/iot-common-web/src/main/resources/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,4 @@ +cc.iotkit.common.web.config.CaptchaConfig +cc.iotkit.common.web.config.FilterConfig +cc.iotkit.common.web.config.ResourcesConfig +cc.iotkit.common.web.config.UndertowConfig diff --git a/iot-common/iot-common-websocket/pom.xml b/iot-common/iot-common-websocket/pom.xml new file mode 100644 index 00000000..fde5c097 --- /dev/null +++ b/iot-common/iot-common-websocket/pom.xml @@ -0,0 +1,27 @@ + + + + iot-common + cc.iotkit + ${revision} + + 4.0.0 + + iot-common-websocket + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-common/iot-message-bus/iot-message-core/pom.xml b/iot-common/iot-message-bus/iot-message-core/pom.xml index dab4a34b..a77cb686 100644 --- a/iot-common/iot-message-bus/iot-message-core/pom.xml +++ b/iot-common/iot-message-bus/iot-message-core/pom.xml @@ -11,5 +11,17 @@ iot-message-core + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + \ No newline at end of file diff --git a/iot-common/iot-message-bus/iot-message-rocketmq/pom.xml b/iot-common/iot-message-bus/iot-message-rocketmq/pom.xml index 911ece5f..d1cbef8e 100644 --- a/iot-common/iot-message-bus/iot-message-rocketmq/pom.xml +++ b/iot-common/iot-message-bus/iot-message-rocketmq/pom.xml @@ -36,4 +36,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-common/iot-message-bus/iot-vertx-event-bus/pom.xml b/iot-common/iot-message-bus/iot-vertx-event-bus/pom.xml index 08923bbf..507885cf 100644 --- a/iot-common/iot-message-bus/iot-vertx-event-bus/pom.xml +++ b/iot-common/iot-message-bus/iot-vertx-event-bus/pom.xml @@ -30,4 +30,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-common/iot-message-notify/pom.xml b/iot-common/iot-message-notify/pom.xml index e3c16f94..c9370daf 100644 --- a/iot-common/iot-message-notify/pom.xml +++ b/iot-common/iot-message-notify/pom.xml @@ -38,4 +38,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-common/iot-script-engine/pom.xml b/iot-common/iot-script-engine/pom.xml index 6ad250b1..33c26cc3 100644 --- a/iot-common/iot-script-engine/pom.xml +++ b/iot-common/iot-script-engine/pom.xml @@ -67,4 +67,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-common/iot-script-engine/src/main/java/cc/iotkit/script/ProcessStringToJsonExample.java b/iot-common/iot-script-engine/src/main/java/cc/iotkit/script/ProcessStringToJsonExample.java deleted file mode 100644 index 98f751fa..00000000 --- a/iot-common/iot-script-engine/src/main/java/cc/iotkit/script/ProcessStringToJsonExample.java +++ /dev/null @@ -1,30 +0,0 @@ -package cc.iotkit.script; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class ProcessStringToJsonExample { - public static void main(String[] args) { - String input = "{type: \"register\", data: {productKey: \"hbtgIA0SuVw9lxjB\", deviceName: \"TEST:GW:000003\", model: \"GW01\"}}"; -// String input = "{type: \"ack\", content: \"{\\\"productKey\\\":\\\"hbtgIA0SuVw9lxjB\\\",\\\"deviceName\\\":\\\"TEST:GW:000001\\\",\\\"mid\\\":\\\"0\\\",\\\"content\\\":{\\\"topic\\\":\\\"/sys/hbtgIA0SuVw9lxjB/TEST:GW:000001/c/register_reply\\\",\\\"payload\\\":\\\"{\\\\\\\"id\\\\\\\":\\\\\\\"0\\\\\\\",\\\\\\\"code\\\\\\\":0,\\\\\\\"data\\\\\\\":{\\\\\\\"productKey\\\\\\\":\\\\\\\"cGCrkK7Ex4FESAwe\\\\\\\",\\\\\\\"deviceName\\\\\\\":\\\\\\\"TEST_SC_000001\\\\\\\"}}\\\"}}\"}"; - - // 使用正则表达式匹配所有键名,并在两端加上双引号 - Pattern pattern = Pattern.compile("[^\":/](\\b\\w+\\b)\\s*:"); - Matcher matcher = pattern.matcher(input); - - StringBuilder jsonBuilder = new StringBuilder(input); - int offset = 0; - while (matcher.find()) { - int start = matcher.start(1) + offset; - int end = matcher.end(1) + offset; - if (jsonBuilder.charAt(start - 1) != '\"' || jsonBuilder.charAt(end) != '\"') { - jsonBuilder.insert(start, '\"'); - jsonBuilder.insert(end + 1, '\"'); - offset += 2; - } - } - - String output = jsonBuilder.toString(); - System.out.println(output); - } -} diff --git a/iot-common/pom.xml b/iot-common/pom.xml index 70263d8a..d3bef4b2 100644 --- a/iot-common/pom.xml +++ b/iot-common/pom.xml @@ -22,13 +22,32 @@ iot-script-engine iot-message-bus iot-message-notify + iot-common-doc + iot-common-excel + iot-common-log + iot-common-oss + iot-common-redis + iot-common-security + iot-common-tenant + iot-common-web + iot-common-websocket - - 11 - 11 UTF-8 - + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-components/iot-component-base/pom.xml b/iot-components/iot-component-base/pom.xml index ec3794fd..bf46346e 100755 --- a/iot-components/iot-component-base/pom.xml +++ b/iot-components/iot-component-base/pom.xml @@ -30,4 +30,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-components/iot-component-converter/pom.xml b/iot-components/iot-component-converter/pom.xml index 554d0d52..30d65053 100755 --- a/iot-components/iot-component-converter/pom.xml +++ b/iot-components/iot-component-converter/pom.xml @@ -55,4 +55,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-components/iot-component-server/pom.xml b/iot-components/iot-component-server/pom.xml index f8c341c8..9cbec709 100755 --- a/iot-components/iot-component-server/pom.xml +++ b/iot-components/iot-component-server/pom.xml @@ -104,4 +104,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-components/iot-component-swagger/readme.txt b/iot-components/iot-component-swagger/readme.txt deleted file mode 100644 index 539c28cd..00000000 --- a/iot-components/iot-component-swagger/readme.txt +++ /dev/null @@ -1 +0,0 @@ -此模块为通用业务逻辑或工具类 diff --git a/iot-components/iot-component-tcp/pom.xml b/iot-components/iot-component-tcp/pom.xml index 7c08c507..388e6ce3 100644 --- a/iot-components/iot-component-tcp/pom.xml +++ b/iot-components/iot-component-tcp/pom.xml @@ -11,10 +11,6 @@ iot-component-tcp - - 11 - 11 - junit @@ -88,8 +84,8 @@ org.apache.maven.plugins maven-compiler-plugin - 11 - 11 + ${java.version} + ${java.version} true false diff --git a/iot-components/iot-emqx-component/pom.xml b/iot-components/iot-emqx-component/pom.xml index 4d0f9586..7d8f2876 100755 --- a/iot-components/iot-emqx-component/pom.xml +++ b/iot-components/iot-emqx-component/pom.xml @@ -110,8 +110,8 @@ org.apache.maven.plugins maven-compiler-plugin - 11 - 11 + ${java.version} + ${java.version} true false diff --git a/iot-components/iot-http-biz-component/pom.xml b/iot-components/iot-http-biz-component/pom.xml index cf82e266..38e644df 100755 --- a/iot-components/iot-http-biz-component/pom.xml +++ b/iot-components/iot-http-biz-component/pom.xml @@ -66,8 +66,8 @@ org.apache.maven.plugins maven-compiler-plugin - 11 - 11 + ${java.version} + ${java.version} diff --git a/iot-components/iot-mqtt-component/pom.xml b/iot-components/iot-mqtt-component/pom.xml index a3799454..9b0b6c18 100755 --- a/iot-components/iot-mqtt-component/pom.xml +++ b/iot-components/iot-mqtt-component/pom.xml @@ -94,8 +94,8 @@ org.apache.maven.plugins maven-compiler-plugin - 11 - 11 + ${java.version} + ${java.version} true false diff --git a/iot-components/iot-websocket-component/pom.xml b/iot-components/iot-websocket-component/pom.xml index dc4060c9..a2545f9f 100644 --- a/iot-components/iot-websocket-component/pom.xml +++ b/iot-components/iot-websocket-component/pom.xml @@ -67,8 +67,8 @@ org.apache.maven.plugins maven-compiler-plugin - 11 - 11 + ${java.version} + ${java.version} true false diff --git a/iot-components/pom.xml b/iot-components/pom.xml index 7fbc7820..92cdb595 100755 --- a/iot-components/pom.xml +++ b/iot-components/pom.xml @@ -14,7 +14,6 @@ iot-component-server iot-component-converter - iot-component-swagger iot-mqtt-component iot-emqx-component iot-component-base diff --git a/iot-data/iot-data-cache/pom.xml b/iot-data/iot-data-cache/pom.xml index 45fb25be..618617f3 100755 --- a/iot-data/iot-data-cache/pom.xml +++ b/iot-data/iot-data-cache/pom.xml @@ -45,4 +45,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/CategoryCacheEvict.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/CategoryCacheEvict.java index c5492988..517363ee 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/CategoryCacheEvict.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/CategoryCacheEvict.java @@ -1,6 +1,6 @@ package cc.iotkit.data.cache; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/DeviceInfoCacheEvict.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/DeviceInfoCacheEvict.java index dd8a90ea..8e7ec3c0 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/DeviceInfoCacheEvict.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/DeviceInfoCacheEvict.java @@ -9,7 +9,7 @@ */ package cc.iotkit.data.cache; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/DeviceInfoCachePut.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/DeviceInfoCachePut.java index bac41eca..109fc2aa 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/DeviceInfoCachePut.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/DeviceInfoCachePut.java @@ -9,7 +9,7 @@ */ package cc.iotkit.data.cache; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import cc.iotkit.model.device.DeviceInfo; import org.springframework.cache.annotation.CachePut; import org.springframework.stereotype.Component; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/OauthClientCacheEvict.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/OauthClientCacheEvict.java index 4d66eabe..6f6ddb29 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/OauthClientCacheEvict.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/OauthClientCacheEvict.java @@ -1,6 +1,6 @@ package cc.iotkit.data.cache; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ProductCacheEvict.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ProductCacheEvict.java index a145b65d..914039d0 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ProductCacheEvict.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ProductCacheEvict.java @@ -1,6 +1,6 @@ package cc.iotkit.data.cache; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ProductModelCacheEvict.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ProductModelCacheEvict.java index 3a786f59..65e5d995 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ProductModelCacheEvict.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ProductModelCacheEvict.java @@ -1,6 +1,6 @@ package cc.iotkit.data.cache; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/SpaceCacheEvict.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/SpaceCacheEvict.java index 9f361621..7178bd14 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/SpaceCacheEvict.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/SpaceCacheEvict.java @@ -1,6 +1,6 @@ package cc.iotkit.data.cache; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ThingModelCacheEvict.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ThingModelCacheEvict.java index 8c900ed3..db8838ca 100644 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ThingModelCacheEvict.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/ThingModelCacheEvict.java @@ -1,6 +1,6 @@ package cc.iotkit.data.cache; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/UserInfoCacheEvict.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/UserInfoCacheEvict.java index c6e9d9bf..17abe75c 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/UserInfoCacheEvict.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/cache/UserInfoCacheEvict.java @@ -1,6 +1,6 @@ package cc.iotkit.data.cache; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/config/CacheConfig.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/config/CacheConfig.java index d561ec81..0ead6733 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/config/CacheConfig.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/config/CacheConfig.java @@ -9,7 +9,7 @@ */ package cc.iotkit.data.config; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/CategoryDataCache.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/CategoryDataCache.java index 1de7704e..1fe9372f 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/CategoryDataCache.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/CategoryDataCache.java @@ -1,6 +1,6 @@ package cc.iotkit.data.service; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import cc.iotkit.data.ICategoryData; import cc.iotkit.data.cache.CategoryCacheEvict; import cc.iotkit.model.Paging; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/DeviceInfoDataCache.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/DeviceInfoDataCache.java index 7780bb55..b3434446 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/DeviceInfoDataCache.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/DeviceInfoDataCache.java @@ -9,8 +9,8 @@ */ package cc.iotkit.data.service; -import cc.iotkit.common.Constants; -import cc.iotkit.common.utils.JsonUtil; +import cc.iotkit.common.constant.Constants; +import cc.iotkit.common.utils.JsonUtils; import cc.iotkit.data.IDeviceInfoData; import cc.iotkit.data.cache.DeviceInfoCacheEvict; import cc.iotkit.data.cache.DeviceInfoCachePut; @@ -88,7 +88,7 @@ public class DeviceInfoDataCache implements IDeviceInfoData, SmartInitializingSi public void saveProperties(String deviceId, Map properties) { Map old = getProperties(deviceId); old.putAll(properties); - redisTemplate.opsForValue().set(getPropertyCacheKey(deviceId), JsonUtil.toJsonString(old)); + redisTemplate.opsForValue().set(getPropertyCacheKey(deviceId), JsonUtils.toJsonString(old)); } /** @@ -104,7 +104,7 @@ public class DeviceInfoDataCache implements IDeviceInfoData, SmartInitializingSi if (StringUtils.isBlank(json)) { return new HashMap<>(); } - return JsonUtil.parse(json, Map.class); + return JsonUtils.parseObject(json, Map.class); } @Override diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/OauthClientDataCache.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/OauthClientDataCache.java index cda05523..af00e863 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/OauthClientDataCache.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/OauthClientDataCache.java @@ -9,7 +9,7 @@ */ package cc.iotkit.data.service; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import cc.iotkit.data.IOauthClientData; import cc.iotkit.data.cache.OauthClientCacheEvict; import cc.iotkit.model.OauthClient; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ProductDataCache.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ProductDataCache.java index 9637766b..22dd62fa 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ProductDataCache.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ProductDataCache.java @@ -1,6 +1,6 @@ package cc.iotkit.data.service; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import cc.iotkit.data.IProductData; import cc.iotkit.data.cache.ProductCacheEvict; import cc.iotkit.model.Paging; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ProductModelDataCache.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ProductModelDataCache.java index 7febdb4c..4f91511d 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ProductModelDataCache.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ProductModelDataCache.java @@ -1,6 +1,6 @@ package cc.iotkit.data.service; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import cc.iotkit.data.IProductModelData; import cc.iotkit.data.cache.ProductModelCacheEvict; import cc.iotkit.model.Paging; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/SpaceDataCache.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/SpaceDataCache.java index 5aefab4e..4577447a 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/SpaceDataCache.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/SpaceDataCache.java @@ -1,6 +1,6 @@ package cc.iotkit.data.service; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import cc.iotkit.data.ISpaceData; import cc.iotkit.data.cache.SpaceCacheEvict; import cc.iotkit.model.Paging; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ThingModelDataCache.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ThingModelDataCache.java index efd5ef8d..a13d17b8 100644 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ThingModelDataCache.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/ThingModelDataCache.java @@ -1,6 +1,6 @@ package cc.iotkit.data.service; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import cc.iotkit.data.IThingModelData; import cc.iotkit.data.cache.ThingModelCacheEvict; import cc.iotkit.model.Paging; diff --git a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/UserInfoDataCache.java b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/UserInfoDataCache.java index 4bc609cd..14885f22 100755 --- a/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/UserInfoDataCache.java +++ b/iot-data/iot-data-cache/src/main/java/cc/iotkit/data/service/UserInfoDataCache.java @@ -1,6 +1,6 @@ package cc.iotkit.data.service; -import cc.iotkit.common.Constants; +import cc.iotkit.common.constant.Constants; import cc.iotkit.data.IUserInfoData; import cc.iotkit.data.cache.UserInfoCacheEvict; import cc.iotkit.model.Paging; diff --git a/iot-data/iot-data-service/pom.xml b/iot-data/iot-data-service/pom.xml index fa25d7cc..05f97978 100755 --- a/iot-data/iot-data-service/pom.xml +++ b/iot-data/iot-data-service/pom.xml @@ -19,4 +19,18 @@ + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysConfigData.java b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysConfigData.java new file mode 100644 index 00000000..164743f8 --- /dev/null +++ b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysConfigData.java @@ -0,0 +1,8 @@ +package cc.iotkit.data.system; + +/** + * 系统配置数据接口 + * @author sjg + */ +public interface ISysConfigData { +} diff --git a/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysDeptData.java b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysDeptData.java new file mode 100644 index 00000000..69ff1d6f --- /dev/null +++ b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysDeptData.java @@ -0,0 +1,10 @@ +package cc.iotkit.data.system; + + +/** + * 部门数据接口 + * + * @author sjg + */ +public interface ISysDeptData { +} diff --git a/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysDictData.java b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysDictData.java new file mode 100644 index 00000000..e675d695 --- /dev/null +++ b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysDictData.java @@ -0,0 +1,9 @@ +package cc.iotkit.data.system; + +/** + * 字典数据接口 + * + * @author sjg + */ +public interface ISysDictData { +} diff --git a/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysDictTypeData.java b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysDictTypeData.java new file mode 100644 index 00000000..745f59fd --- /dev/null +++ b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysDictTypeData.java @@ -0,0 +1,9 @@ +package cc.iotkit.data.system; + +/** + * 字典类型数据接口 + * + * @author sjg + */ +public interface ISysDictTypeData { +} diff --git a/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysLogininforData.java b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysLogininforData.java new file mode 100644 index 00000000..eb468c25 --- /dev/null +++ b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysLogininforData.java @@ -0,0 +1,9 @@ +package cc.iotkit.data.system; + +/** + * 登录记录数据接口 + * + * @author sjg + */ +public interface ISysLogininforData { +} diff --git a/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysMenuData.java b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysMenuData.java new file mode 100644 index 00000000..41ff9514 --- /dev/null +++ b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysMenuData.java @@ -0,0 +1,9 @@ +package cc.iotkit.data.system; + +/** + * 菜单数据接口 + * + * @author sjg + */ +public interface ISysMenuData { +} diff --git a/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysNoticeData.java b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysNoticeData.java new file mode 100644 index 00000000..4bc85f2d --- /dev/null +++ b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysNoticeData.java @@ -0,0 +1,9 @@ +package cc.iotkit.data.system; + +/** + * 通知数据接口 + * + * @author sjg + */ +public interface ISysNoticeData { +} diff --git a/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysOperLogData.java b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysOperLogData.java new file mode 100644 index 00000000..3494f9be --- /dev/null +++ b/iot-data/iot-data-service/src/main/java/cc/iotkit/data/system/ISysOperLogData.java @@ -0,0 +1,9 @@ +package cc.iotkit.data.system; + +/** + * 操作日志数据接口 + * + * @author sjg + */ +public interface ISysOperLogData { +} diff --git a/iot-data/iot-es-temporal-service/pom.xml b/iot-data/iot-es-temporal-service/pom.xml index f1d57e8c..7a56ec04 100755 --- a/iot-data/iot-es-temporal-service/pom.xml +++ b/iot-data/iot-es-temporal-service/pom.xml @@ -53,8 +53,8 @@ maven-compiler-plugin 3.8.1 - 11 - 11 + ${java.version} + ${java.version} org.projectlombok diff --git a/iot-data/iot-model/pom.xml b/iot-data/iot-model/pom.xml index 52ae0d66..ebd207e6 100755 --- a/iot-data/iot-model/pom.xml +++ b/iot-data/iot-model/pom.xml @@ -31,4 +31,18 @@ + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysConfig.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysConfig.java new file mode 100644 index 00000000..fa3843ad --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysConfig.java @@ -0,0 +1,54 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + + +/** + * 参数配置视图对象 sys_config + * + * @author Michelle.Chung + */ +@Data +public class SysConfig implements Id, Serializable { + private static final long serialVersionUID = 1L; + + /** + * 参数主键 + */ + private Long id; + + /** + * 参数名称 + */ + private String configName; + + /** + * 参数键名 + */ + private String configKey; + + /** + * 参数键值 + */ + private String configValue; + + /** + * 系统内置(Y是 N否) + */ + private String configType; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysDept.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysDept.java new file mode 100644 index 00000000..4b853b91 --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysDept.java @@ -0,0 +1,73 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 部门视图对象 sys_dept + * + * @author Michelle.Chung + */ +@Data +public class SysDept implements Id, Serializable { + private static final long serialVersionUID = 1L; + + /** + * 部门id + */ + private Long id; + + /** + * 父部门id + */ + private Long parentId; + + /** + * 父部门名称 + */ + private String parentName; + + /** + * 祖级列表 + */ + private String ancestors; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 显示顺序 + */ + private Integer orderNum; + + /** + * 负责人 + */ + private String leader; + + /** + * 联系电话 + */ + private String phone; + + /** + * 邮箱 + */ + private String email; + + /** + * 部门状态(0正常 1停用) + */ + private String status; + + /** + * 创建时间 + */ + private Date createTime; + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysDictData.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysDictData.java new file mode 100644 index 00000000..59131c4b --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysDictData.java @@ -0,0 +1,73 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + + +/** + * 字典数据视图对象 sys_dict_data + * + * @author Michelle.Chung + */ +@Data +public class SysDictData implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 字典编码 + */ + private Long id; + + /** + * 字典排序 + */ + private Integer dictSort; + + /** + * 字典标签 + */ + private String dictLabel; + + /** + * 字典键值 + */ + private String dictValue; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 样式属性(其他样式扩展) + */ + private String cssClass; + + /** + * 表格回显样式 + */ + private String listClass; + + /** + * 是否默认(Y是 N否) + */ + private String isDefault; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysDictType.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysDictType.java new file mode 100644 index 00000000..2a04b47d --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysDictType.java @@ -0,0 +1,48 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + + +/** + * 字典类型视图对象 sys_dict_type + * + * @author Michelle.Chung + */ +@Data +public class SysDictType implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 字典主键 + */ + private Long id; + + /** + * 字典名称 + */ + private String dictName; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysLogininfor.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysLogininfor.java new file mode 100644 index 00000000..a08bb910 --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysLogininfor.java @@ -0,0 +1,73 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + + +/** + * 系统访问记录视图对象 sys_logininfor + * + * @author Michelle.Chung + * @date 2023-02-07 + */ +@Data +@AutoMapper(target = SysLogininfor.class) +public class SysLogininfor implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 访问ID + */ + private Long id; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 用户账号 + */ + private String userName; + + /** + * 登录状态(0成功 1失败) + */ + private String status; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + + /** + * 提示消息 + */ + private String msg; + + /** + * 访问时间 + */ + private Date loginTime; + + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysMenu.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysMenu.java new file mode 100644 index 00000000..05680ffe --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysMenu.java @@ -0,0 +1,111 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + + +/** + * 菜单权限视图对象 sys_menu + * + * @author Michelle.Chung + */ +@Data +public class SysMenu implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 菜单ID + */ + private Long id; + + /** + * 菜单名称 + */ + private String menuName; + + /** + * 父菜单ID + */ + private Long parentId; + + /** + * 显示顺序 + */ + private Integer orderNum; + + /** + * 路由地址 + */ + private String path; + + /** + * 组件路径 + */ + private String component; + + /** + * 路由参数 + */ + private String queryParam; + + /** + * 是否为外链(0是 1否) + */ + private String isFrame; + + /** + * 是否缓存(0缓存 1不缓存) + */ + private String isCache; + + /** + * 菜单类型(M目录 C菜单 F按钮) + */ + private String menuType; + + /** + * 显示状态(0显示 1隐藏) + */ + private String visible; + + /** + * 菜单状态(0正常 1停用) + */ + private String status; + + /** + * 权限标识 + */ + private String perms; + + /** + * 菜单图标 + */ + private String icon; + + /** + * 创建部门 + */ + private SysDept createDept; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 子菜单 + */ + private List children = new ArrayList<>(); + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysNotice.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysNotice.java new file mode 100644 index 00000000..2a4b7b91 --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysNotice.java @@ -0,0 +1,63 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + + +/** + * 通知公告视图对象 sys_notice + * + * @author Michelle.Chung + */ +@Data +public class SysNotice implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 公告ID + */ + private Long id; + + /** + * 公告标题 + */ + private String noticeTitle; + + /** + * 公告类型(1通知 2公告) + */ + private String noticeType; + + /** + * 公告内容 + */ + private String noticeContent; + + /** + * 公告状态(0正常 1关闭) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 创建者 + */ + private Long createBy; + + /** + * 创建人名称 + */ + private String createByName; + + /** + * 创建时间 + */ + private Date createTime; + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysOperLog.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysOperLog.java new file mode 100644 index 00000000..ae5ebef2 --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysOperLog.java @@ -0,0 +1,114 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + + +/** + * 操作日志记录视图对象 sys_oper_log + * + * @author Michelle.Chung + * @date 2023-02-07 + */ +@Data +public class SysOperLog implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 日志主键 + */ + private Long id; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 模块标题 + */ + private String title; + + /** + * 业务类型(0其它 1新增 2修改 3删除) + */ + private Integer businessType; + + /** + * 业务类型数组 + */ + private Integer[] businessTypes; + + /** + * 方法名称 + */ + private String method; + + /** + * 请求方式 + */ + private String requestMethod; + + /** + * 操作类别(0其它 1后台用户 2手机端用户) + */ + private Integer operatorType; + + /** + * 操作人员 + */ + private String operName; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 请求URL + */ + private String operUrl; + + /** + * 主机地址 + */ + private String operIp; + + /** + * 操作地点 + */ + private String operLocation; + + /** + * 请求参数 + */ + private String operParam; + + /** + * 返回参数 + */ + private String jsonResult; + + /** + * 操作状态(0正常 1异常) + */ + private Integer status; + + /** + * 错误消息 + */ + private String errorMsg; + + /** + * 操作时间 + */ + private Date operTime; + + /** + * 消耗时间 + */ + private Long costTime; +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysOss.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysOss.java new file mode 100644 index 00000000..b8c28cfb --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysOss.java @@ -0,0 +1,64 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * OSS对象存储视图对象 sys_oss + * + * @author Lion Li + */ +@Data +public class SysOss implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 对象存储主键 + */ + private Long id; + + /** + * 文件名 + */ + private String fileName; + + /** + * 原名 + */ + private String originalName; + + /** + * 文件后缀名 + */ + private String fileSuffix; + + /** + * URL地址 + */ + private String url; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 上传人 + */ + private Long createBy; + + /** + * 上传人名称 + */ + private String createByName; + + /** + * 服务商 + */ + private String service; + + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysOssConfig.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysOssConfig.java new file mode 100644 index 00000000..ce696689 --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysOssConfig.java @@ -0,0 +1,90 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; + + +/** + * 对象存储配置视图对象 sys_oss_config + * + * @author Lion Li + * @author 孤舟烟雨 + * @date 2021-08-13 + */ +@Data +public class SysOssConfig implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 主建 + */ + private Long id; + + /** + * 配置key + */ + private String configKey; + + /** + * accessKey + */ + private String accessKey; + + /** + * 秘钥 + */ + private String secretKey; + + /** + * 桶名称 + */ + private String bucketName; + + /** + * 前缀 + */ + private String prefix; + + /** + * 访问站点 + */ + private String endpoint; + + /** + * 自定义域名 + */ + private String domain; + + /** + * 是否https(Y=是,N=否) + */ + private String isHttps; + + /** + * 域 + */ + private String region; + + /** + * 是否默认(0=是,1=否) + */ + private String status; + + /** + * 扩展字段 + */ + private String ext1; + + /** + * 备注 + */ + private String remark; + + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysPost.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysPost.java new file mode 100644 index 00000000..1beff4cc --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysPost.java @@ -0,0 +1,54 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + + +/** + * 岗位信息视图对象 sys_post + * + * @author Michelle.Chung + */ +@Data +public class SysPost implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 岗位ID + */ + private Long id; + + /** + * 岗位编码 + */ + private String postCode; + + /** + * 岗位名称 + */ + private String postName; + + /** + * 显示顺序 + */ + private Integer postSort; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysRole.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysRole.java new file mode 100644 index 00000000..32c765f9 --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysRole.java @@ -0,0 +1,78 @@ +package cc.iotkit.model.system; + +import cc.iotkit.common.constant.UserConstants; +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 角色信息视图对象 sys_role + * + * @author Michelle.Chung + */ +@Data +public class SysRole implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 角色ID + */ + private Long id; + + /** + * 角色名称 + */ + private String roleName; + + /** + * 角色权限字符串 + */ + private String roleKey; + + /** + * 显示顺序 + */ + private Integer roleSort; + + /** + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) + */ + private String dataScope; + + /** + * 菜单树选择项是否关联显示 + */ + private Boolean menuCheckStrictly; + + /** + * 部门树选择项是否关联显示 + */ + private Boolean deptCheckStrictly; + + /** + * 角色状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 用户是否存在此角色标识 默认不存在 + */ + private boolean flag = false; + + public boolean isSuperAdmin() { + return UserConstants.SUPER_ADMIN_ID.equals(this.id); + } + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysTenant.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysTenant.java new file mode 100644 index 00000000..06587b97 --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysTenant.java @@ -0,0 +1,89 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + + +/** + * 租户视图对象 sys_tenant + * + * @author Michelle.Chung + */ +@Data +public class SysTenant implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * id + */ + private Long id; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 联系人 + */ + private String contactUserName; + + /** + * 联系电话 + */ + private String contactPhone; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 统一社会信用代码 + */ + private String licenseNumber; + + /** + * 地址 + */ + private String address; + + /** + * 域名 + */ + private String domain; + + /** + * 企业简介 + */ + private String intro; + + /** + * 备注 + */ + private String remark; + + /** + * 租户套餐编号 + */ + private Long packageId; + + /** + * 过期时间 + */ + private Date expireTime; + + /** + * 用户数量(-1不限制) + */ + private Long accountCount; + + /** + * 租户状态(0正常 1停用) + */ + private String status; + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysTenantPackage.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysTenantPackage.java new file mode 100644 index 00000000..dabba265 --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysTenantPackage.java @@ -0,0 +1,49 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; + + +/** + * 租户套餐视图对象 sys_tenant_package + * + * @author Michelle.Chung + */ +@Data +public class SysTenantPackage implements Id,Serializable { + private static final long serialVersionUID = 1L; + + /** + * 租户套餐id + */ + private Long id; + + /** + * 套餐名称 + */ + private String packageName; + + /** + * 关联菜单id + */ + private String menuIds; + + /** + * 备注 + */ + private String remark; + + /** + * 菜单树选择项是否关联显示 + */ + private Boolean menuCheckStrictly; + + /** + * 状态(0正常 1停用) + */ + private String status; + + +} diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysUser.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysUser.java new file mode 100644 index 00000000..47df3dca --- /dev/null +++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/system/SysUser.java @@ -0,0 +1,125 @@ +package cc.iotkit.model.system; + +import cc.iotkit.model.Id; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + + +/** + * 用户信息视图对象 sys_user + * + * @author Michelle.Chung + */ +@Data +public class SysUser implements Id, Serializable { + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + private Long id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户账号 + */ + private String userName; + + /** + * 用户昵称 + */ + private String nickName; + + /** + * 用户类型(sys_user系统用户) + */ + private String userType; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String phonenumber; + + /** + * 用户性别(0男 1女 2未知) + */ + private String sex; + + /** + * 头像地址 + */ + private Long avatar; + + /** + * 密码 + */ + private String password; + + /** + * 帐号状态(0正常 1停用) + */ + private String status; + + /** + * 最后登录IP + */ + private String loginIp; + + /** + * 最后登录时间 + */ + private Date loginDate; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 部门对象 + */ + private SysDept dept; + + /** + * 角色对象 + */ + private List roles; + + /** + * 角色组 + */ + private Long[] roleIds; + + /** + * 岗位组 + */ + private Long[] postIds; + + /** + * 数据权限 当前角色ID + */ + private Long roleId; + +} diff --git a/iot-data/iot-rdb-data-service/pom.xml b/iot-data/iot-rdb-data-service/pom.xml index e7281f82..5a07ab45 100755 --- a/iot-data/iot-rdb-data-service/pom.xml +++ b/iot-data/iot-rdb-data-service/pom.xml @@ -28,10 +28,10 @@ h2 - - mysql - mysql-connector-java - + + + + commons-io @@ -54,6 +54,11 @@ provided + + cc.iotkit + iot-common-core + + cc.iotkit iot-data-service @@ -68,8 +73,8 @@ maven-compiler-plugin 3.8.1 - 11 - 11 + ${java.version} + ${java.version} org.projectlombok diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/AlertConfigMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/AlertConfigMapper.java similarity index 87% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/AlertConfigMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/AlertConfigMapper.java index b8d09940..6c647818 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/AlertConfigMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/AlertConfigMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbAlertConfig; import cc.iotkit.model.alert.AlertConfig; import java.util.List; import java.util.stream.Collectors; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/AlertRecordMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/AlertRecordMapper.java similarity index 87% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/AlertRecordMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/AlertRecordMapper.java index f197c1c9..51ae186e 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/AlertRecordMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/AlertRecordMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbAlertRecord; import cc.iotkit.model.alert.AlertRecord; import java.util.List; import java.util.stream.Collectors; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/CategoryMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/CategoryMapper.java old mode 100755 new mode 100644 similarity index 80% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/CategoryMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/CategoryMapper.java index 041eaabb..329680cc --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/CategoryMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/CategoryMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbCategory; import cc.iotkit.model.product.Category; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ChannelConfigMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ChannelConfigMapper.java similarity index 83% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ChannelConfigMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ChannelConfigMapper.java index 40f8c2ba..711cc85b 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ChannelConfigMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ChannelConfigMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbChannelConfig; import cc.iotkit.model.notify.ChannelConfig; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ChannelMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ChannelMapper.java similarity index 83% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ChannelMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ChannelMapper.java index 2e1f993b..f5558039 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ChannelMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ChannelMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbChannel; import cc.iotkit.model.notify.Channel; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ChannelTemplateMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ChannelTemplateMapper.java similarity index 84% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ChannelTemplateMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ChannelTemplateMapper.java index e6be76e0..c1cc4a20 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ChannelTemplateMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ChannelTemplateMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbChannelTemplate; import cc.iotkit.model.notify.ChannelTemplate; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/DeviceConfigMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/DeviceConfigMapper.java old mode 100755 new mode 100644 similarity index 91% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/DeviceConfigMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/DeviceConfigMapper.java index 5bbf04ab..aa94ca81 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/DeviceConfigMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/DeviceConfigMapper.java @@ -7,8 +7,9 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbDeviceConfig; import cc.iotkit.model.device.DeviceConfig; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/DeviceGroupMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/DeviceGroupMapper.java old mode 100755 new mode 100644 similarity index 80% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/DeviceGroupMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/DeviceGroupMapper.java index c9a19d24..6b79102f --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/DeviceGroupMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/DeviceGroupMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbDeviceGroup; import cc.iotkit.model.device.DeviceGroup; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/DeviceInfoMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/DeviceInfoMapper.java old mode 100755 new mode 100644 similarity index 92% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/DeviceInfoMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/DeviceInfoMapper.java index 1e61bc69..3f793fe3 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/DeviceInfoMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/DeviceInfoMapper.java @@ -7,8 +7,9 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbDeviceInfo; import cc.iotkit.model.device.DeviceInfo; import org.mapstruct.Mapper; import org.mapstruct.Mapping; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/HomeMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/HomeMapper.java similarity index 86% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/HomeMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/HomeMapper.java index ab5e99cb..3f61e20f 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/HomeMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/HomeMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbHome; import cc.iotkit.model.space.Home; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/OauthClientMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/OauthClientMapper.java old mode 100755 new mode 100644 similarity index 91% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/OauthClientMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/OauthClientMapper.java index e7d7387e..195121b3 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/OauthClientMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/OauthClientMapper.java @@ -7,8 +7,9 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbOauthClient; import cc.iotkit.model.OauthClient; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProductMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProductMapper.java old mode 100755 new mode 100644 similarity index 87% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProductMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProductMapper.java index 296f18cb..05cca81f --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProductMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProductMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbProduct; import cc.iotkit.model.product.Product; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProductModelMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProductModelMapper.java old mode 100755 new mode 100644 similarity index 87% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProductModelMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProductModelMapper.java index b917a0a5..a308f059 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProductModelMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProductModelMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbProductModel; import cc.iotkit.model.product.ProductModel; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProtocolComponentMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProtocolComponentMapper.java old mode 100755 new mode 100644 similarity index 87% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProtocolComponentMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProtocolComponentMapper.java index 54e0cb25..71e7797a --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProtocolComponentMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProtocolComponentMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbProtocolComponent; import cc.iotkit.model.protocol.ProtocolComponent; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProtocolConverterMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProtocolConverterMapper.java old mode 100755 new mode 100644 similarity index 87% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProtocolConverterMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProtocolConverterMapper.java index 96b9ceef..7a389bdb --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ProtocolConverterMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ProtocolConverterMapper.java @@ -1,5 +1,6 @@ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbProtocolConverter; import cc.iotkit.model.protocol.ProtocolConverter; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/RuleInfoMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/RuleInfoMapper.java old mode 100755 new mode 100644 similarity index 96% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/RuleInfoMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/RuleInfoMapper.java index 41d80ed0..9fe90205 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/RuleInfoMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/RuleInfoMapper.java @@ -7,9 +7,10 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; import cc.iotkit.common.utils.JsonUtil; +import cc.iotkit.data.model.TbRuleInfo; import cc.iotkit.model.rule.RuleInfo; import com.fasterxml.jackson.core.type.TypeReference; import org.mapstruct.Mapper; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/SpaceDeviceMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/SpaceDeviceMapper.java old mode 100755 new mode 100644 similarity index 92% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/SpaceDeviceMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/SpaceDeviceMapper.java index 051de8e7..0f6783bb --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/SpaceDeviceMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/SpaceDeviceMapper.java @@ -7,8 +7,9 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbSpaceDevice; import cc.iotkit.model.space.SpaceDevice; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/SpaceMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/SpaceMapper.java old mode 100755 new mode 100644 similarity index 93% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/SpaceMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/SpaceMapper.java index 67f21221..ab7a03ab --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/SpaceMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/SpaceMapper.java @@ -7,8 +7,9 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbSpace; import cc.iotkit.model.space.Space; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/TaskInfoMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/TaskInfoMapper.java old mode 100755 new mode 100644 similarity index 95% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/TaskInfoMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/TaskInfoMapper.java index 164a3c16..f7ae399a --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/TaskInfoMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/TaskInfoMapper.java @@ -7,9 +7,10 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; import cc.iotkit.common.utils.JsonUtil; +import cc.iotkit.data.model.TbTaskInfo; import cc.iotkit.model.rule.TaskInfo; import com.fasterxml.jackson.core.type.TypeReference; import org.mapstruct.Mapper; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ThingModelMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ThingModelMapper.java old mode 100755 new mode 100644 similarity index 95% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ThingModelMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ThingModelMapper.java index d109fd07..9469b0fe --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/ThingModelMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/ThingModelMapper.java @@ -7,9 +7,10 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; import cc.iotkit.common.utils.JsonUtil; +import cc.iotkit.data.model.TbThingModel; import cc.iotkit.model.product.ThingModel; import org.apache.commons.lang3.StringUtils; import org.mapstruct.Mapper; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/UserInfoMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/UserInfoMapper.java old mode 100755 new mode 100644 similarity index 97% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/UserInfoMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/UserInfoMapper.java index 3d80ffa7..dde9454f --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/UserInfoMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/UserInfoMapper.java @@ -7,8 +7,9 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbUserInfo; import cc.iotkit.model.UserInfo; import org.apache.commons.lang3.StringUtils; import org.mapstruct.Mapper; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/VirtualDeviceMapper.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/VirtualDeviceMapper.java old mode 100755 new mode 100644 similarity index 93% rename from iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/VirtualDeviceMapper.java rename to iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/VirtualDeviceMapper.java index 56a23dd0..7a2665f1 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/VirtualDeviceMapper.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/convert/VirtualDeviceMapper.java @@ -7,8 +7,9 @@ * | Author: xw2sy@163.com * +---------------------------------------------------------------------- */ -package cc.iotkit.data.model; +package cc.iotkit.data.convert; +import cc.iotkit.data.model.TbVirtualDevice; import cc.iotkit.model.device.VirtualDevice; import org.mapstruct.Mapper; import org.mapstruct.Mapping; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/BaseEntity.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/BaseEntity.java new file mode 100644 index 00000000..53230eef --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/BaseEntity.java @@ -0,0 +1,58 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import java.util.Date; + +/** + * Entity基类 + * + * @author Lion Li + */ +@Data +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public class BaseEntity { + + /** + * 创建部门 + */ + private Long createDept; + + /** + * 创建者 + */ + @CreatedBy + @Column(name = "create_by", updatable = false) + private Long createBy; + + /** + * 创建时间 + */ + @CreatedDate + @Column(name = "create_time", updatable = false) + private Date createTime; + + /** + * 更新者 + */ + @LastModifiedBy + @Column(name = "update_by") + private Long updateBy; + + /** + * 更新时间 + */ + @LastModifiedDate + @Column(name = "update_time") + private Date updateTime; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysConfig.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysConfig.java new file mode 100644 index 00000000..30701dad --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysConfig.java @@ -0,0 +1,58 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 参数配置表 sys_config + * + * @author Lion Li + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_config") +public class TbSysConfig extends BaseEntity { + + /** + * 参数主键 + */ + @Id + private Long configId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 参数名称 + */ + private String configName; + + /** + * 参数键名 + */ + private String configKey; + + /** + * 参数键值 + */ + private String configValue; + + /** + * 系统内置(Y是 N否) + */ + private String configType; + + /** + * 备注 + */ + private String remark; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysDept.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysDept.java new file mode 100644 index 00000000..33864695 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysDept.java @@ -0,0 +1,79 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 部门表 sys_dept + * + * @author Lion Li + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_dept") +public class TbSysDept extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 部门ID + */ + @Id + private Long deptId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 父部门ID + */ + private Long parentId; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 显示顺序 + */ + private Integer orderNum; + + /** + * 负责人 + */ + private String leader; + + /** + * 联系电话 + */ + private String phone; + + /** + * 邮箱 + */ + private String email; + + /** + * 部门状态:0正常,1停用 + */ + private String status; + + /** + * 删除标志(0代表存在 2代表删除) + */ + private String delFlag; + + /** + * 祖级列表 + */ + private String ancestors; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysDictData.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysDictData.java new file mode 100644 index 00000000..12d340b4 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysDictData.java @@ -0,0 +1,77 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 字典数据表 sys_dict_data + * + * @author Lion Li + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_dict_data") +public class TbSysDictData extends BaseEntity { + + /** + * 字典编码 + */ + @Id + private Long dictCode; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 字典排序 + */ + private Integer dictSort; + + /** + * 字典标签 + */ + private String dictLabel; + + /** + * 字典键值 + */ + private String dictValue; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 样式属性(其他样式扩展) + */ + private String cssClass; + + /** + * 表格字典样式 + */ + private String listClass; + + /** + * 是否默认(Y是 N否) + */ + private String isDefault; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysDictType.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysDictType.java new file mode 100644 index 00000000..f249aed8 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysDictType.java @@ -0,0 +1,53 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 字典类型表 sys_dict_type + * + * @author Lion Li + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_dict_type") +public class TbSysDictType extends BaseEntity { + + /** + * 字典主键 + */ + @Id + private Long dictId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 字典名称 + */ + private String dictName; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysLogininfor.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysLogininfor.java new file mode 100644 index 00000000..aa1c9361 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysLogininfor.java @@ -0,0 +1,74 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.io.Serializable; +import java.util.Date; + +/** + * 系统访问记录表 sys_logininfor + * + * @author Lion Li + */ + +@Data +@Entity +@Table(name = "sys_logininfor") +public class TbSysLogininfor implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Id + private Long infoId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 用户账号 + */ + private String userName; + + /** + * 登录状态 0成功 1失败 + */ + private String status; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 提示消息 + */ + private String msg; + + /** + * 访问时间 + */ + private Date loginTime; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysMenu.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysMenu.java new file mode 100644 index 00000000..8f1b08f8 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysMenu.java @@ -0,0 +1,99 @@ +package cc.iotkit.data.model.system; + +import cc.iotkit.common.domain.model.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 菜单权限表 sys_menu + * + * @author Lion Li + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_menu") +public class TbSysMenu extends BaseEntity { + + /** + * 菜单ID + */ + @Id + private Long menuId; + + /** + * 父菜单ID + */ + private Long parentId; + + /** + * 菜单名称 + */ + private String menuName; + + /** + * 显示顺序 + */ + private Integer orderNum; + + /** + * 路由地址 + */ + private String path; + + /** + * 组件路径 + */ + private String component; + + /** + * 路由参数 + */ + private String queryParam; + + /** + * 是否为外链(0是 1否) + */ + private String isFrame; + + /** + * 是否缓存(0缓存 1不缓存) + */ + private String isCache; + + /** + * 类型(M目录 C菜单 F按钮) + */ + private String menuType; + + /** + * 显示状态(0显示 1隐藏) + */ + private String visible; + + /** + * 菜单状态(0正常 1停用) + */ + private String status; + + /** + * 权限字符串 + */ + private String perms; + + /** + * 菜单图标 + */ + private String icon; + + /** + * 备注 + */ + private String remark; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysNotice.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysNotice.java new file mode 100644 index 00000000..ddcc48d2 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysNotice.java @@ -0,0 +1,57 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 通知公告表 sys_notice + * + * @author Lion Li + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_notice") +public class TbSysNotice extends BaseEntity { + + /** + * 公告ID + */ + @Id + private Long noticeId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 公告标题 + */ + private String noticeTitle; + + /** + * 公告类型(1通知 2公告) + */ + private String noticeType; + + /** + * 公告内容 + */ + private String noticeContent; + + /** + * 公告状态(0正常 1关闭) + */ + private String status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysOperLog.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysOperLog.java new file mode 100644 index 00000000..e300fc62 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysOperLog.java @@ -0,0 +1,113 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.io.Serializable; +import java.util.Date; + +/** + * 操作日志记录表 oper_log + * + * @author Lion Li + */ +@Data +@Entity +@Table(name = "oper_log") +public class TbSysOperLog implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 日志主键 + */ + @Id + private Long operId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 操作模块 + */ + private String title; + + /** + * 业务类型(0其它 1新增 2修改 3删除) + */ + private Integer businessType; + + /** + * 请求方法 + */ + private String method; + + /** + * 请求方式 + */ + private String requestMethod; + + /** + * 操作类别(0其它 1后台用户 2手机端用户) + */ + private Integer operatorType; + + /** + * 操作人员 + */ + private String operName; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 请求url + */ + private String operUrl; + + /** + * 操作地址 + */ + private String operIp; + + /** + * 操作地点 + */ + private String operLocation; + + /** + * 请求参数 + */ + private String operParam; + + /** + * 返回参数 + */ + private String jsonResult; + + /** + * 操作状态(0正常 1异常) + */ + private Integer status; + + /** + * 错误消息 + */ + private String errorMsg; + + /** + * 操作时间 + */ + private Date operTime; + + /** + * 消耗时间 + */ + private Long costTime; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysOss.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysOss.java new file mode 100644 index 00000000..4baf0a0e --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysOss.java @@ -0,0 +1,57 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * OSS对象存储对象 + * + * @author Lion Li + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_oss") +public class TbSysOss extends BaseEntity { + + /** + * 对象存储主键 + */ + @Id + private Long ossId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 文件名 + */ + private String fileName; + + /** + * 原名 + */ + private String originalName; + + /** + * 文件后缀名 + */ + private String fileSuffix; + + /** + * URL地址 + */ + private String url; + + /** + * 服务商 + */ + private String service; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysOssConfig.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysOssConfig.java new file mode 100644 index 00000000..180f1fbc --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysOssConfig.java @@ -0,0 +1,96 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 对象存储配置对象 sys_oss_config + * + * @author Lion Li + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_oss_config") +public class TbSysOssConfig extends BaseEntity { + + /** + * 主建 + */ + @Id + private Long ossConfigId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 配置key + */ + private String configKey; + + /** + * accessKey + */ + private String accessKey; + + /** + * 秘钥 + */ + private String secretKey; + + /** + * 桶名称 + */ + private String bucketName; + + /** + * 前缀 + */ + private String prefix; + + /** + * 访问站点 + */ + private String endpoint; + + /** + * 自定义域名 + */ + private String domain; + + /** + * 是否https(0否 1是) + */ + private String isHttps; + + /** + * 域 + */ + private String region; + + /** + * 是否默认(0=是,1=否) + */ + private String status; + + /** + * 扩展字段 + */ + private String ext1; + + /** + * 备注 + */ + private String remark; + + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysPost.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysPost.java new file mode 100644 index 00000000..e0470608 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysPost.java @@ -0,0 +1,58 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 岗位表 sys_post + * + * @author Lion Li + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_post") +public class TbSysPost extends BaseEntity { + + /** + * 岗位序号 + */ + @Id + private Long postId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 岗位编码 + */ + private String postCode; + + /** + * 岗位名称 + */ + private String postName; + + /** + * 岗位排序 + */ + private Integer postSort; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysRole.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysRole.java new file mode 100644 index 00000000..cbe7f135 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysRole.java @@ -0,0 +1,84 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 角色表 sys_role + * + * @author Lion Li + */ + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_role") +public class TbSysRole extends BaseEntity { + + /** + * 角色ID + */ + @Id + private Long roleId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 角色名称 + */ + private String roleName; + + /** + * 角色权限 + */ + private String roleKey; + + /** + * 角色排序 + */ + private Integer roleSort; + + /** + * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) + */ + private String dataScope; + + /** + * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) + */ + private Boolean menuCheckStrictly; + + /** + * 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) + */ + private Boolean deptCheckStrictly; + + /** + * 角色状态(0正常 1停用) + */ + private String status; + + /** + * 删除标志(0代表存在 2代表删除) + */ + private String delFlag; + + /** + * 备注 + */ + private String remark; + + public TbSysRole(Long roleId) { + this.roleId = roleId; + } + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysRoleDept.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysRoleDept.java new file mode 100644 index 00000000..4d1a7d43 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysRoleDept.java @@ -0,0 +1,33 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 角色和部门关联 sys_role_dept + * + * @author Lion Li + */ + +@Data +@Entity +@Table(name = "sys_role_dept") +public class TbSysRoleDept { + + @Id + private Long id; + + /** + * 角色ID + */ + private Long roleId; + + /** + * 部门ID + */ + private Long deptId; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysRoleMenu.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysRoleMenu.java new file mode 100644 index 00000000..eb341cdd --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysRoleMenu.java @@ -0,0 +1,33 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 角色和菜单关联 sys_role_menu + * + * @author Lion Li + */ + +@Data +@Entity +@Table(name = "sys_role_menu") +public class TbSysRoleMenu { + + @Id + private Long id; + + /** + * 角色ID + */ + private Long roleId; + + /** + * 菜单ID + */ + private Long menuId; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysTenant.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysTenant.java new file mode 100644 index 00000000..8f426fd7 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysTenant.java @@ -0,0 +1,100 @@ +package cc.iotkit.data.model.system; + +import cc.iotkit.common.domain.model.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Date; + +/** + * 租户对象 sys_tenant + * + * @author Michelle.Chung + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_tenant") +public class TbSysTenant extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * id + */ + @Id + private Long id; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 联系人 + */ + private String contactUserName; + + /** + * 联系电话 + */ + private String contactPhone; + + /** + * 企业名称 + */ + private String companyName; + + /** + * 统一社会信用代码 + */ + private String licenseNumber; + + /** + * 地址 + */ + private String address; + + /** + * 域名 + */ + private String domain; + + /** + * 企业简介 + */ + private String intro; + + /** + * 备注 + */ + private String remark; + + /** + * 租户套餐编号 + */ + private Long packageId; + + /** + * 过期时间 + */ + private Date expireTime; + + /** + * 用户数量(-1不限制) + */ + private Long accountCount; + + /** + * 租户状态(0正常 1停用) + */ + private String status; + + /** + * 删除标志(0代表存在 2代表删除) + */ + private String delFlag; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysTenantPackage.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysTenantPackage.java new file mode 100644 index 00000000..617f3d7b --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysTenantPackage.java @@ -0,0 +1,53 @@ +package cc.iotkit.data.model.system; + +import cc.iotkit.common.domain.model.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 租户套餐对象 sys_tenant_package + * + * @author Michelle.Chung + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_tenant_package") +public class TbSysTenantPackage extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 租户套餐id + */ + @Id + private Long packageId; + /** + * 套餐名称 + */ + private String packageName; + /** + * 关联菜单id + */ + private String menuIds; + /** + * 备注 + */ + private String remark; + /** + * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) + */ + private Boolean menuCheckStrictly; + /** + * 状态(0正常 1停用) + */ + private String status; + /** + * 删除标志(0代表存在 2代表删除) + */ + private String delFlag; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysUser.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysUser.java new file mode 100644 index 00000000..df00a3cd --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysUser.java @@ -0,0 +1,110 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Date; + +/** + * 用户对象 sys_user + * + * @author Lion Li + */ + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "sys_user") +public class TbSysUser extends BaseEntity { + + /** + * 用户ID + */ + @Id + private Long userId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户账号 + */ + private String userName; + + /** + * 用户昵称 + */ + private String nickName; + + /** + * 用户类型(sys_user系统用户) + */ + private String userType; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String phonenumber; + + /** + * 用户性别 + */ + private String sex; + + /** + * 用户头像 + */ + private Long avatar; + + /** + * 密码 + */ + private String password; + + /** + * 帐号状态(0正常 1停用) + */ + private String status; + + /** + * 删除标志(0代表存在 2代表删除) + */ + private String delFlag; + + /** + * 最后登录IP + */ + private String loginIp; + + /** + * 最后登录时间 + */ + private Date loginDate; + + /** + * 备注 + */ + private String remark; + + public TbSysUser(Long userId) { + this.userId = userId; + } + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysUserPost.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysUserPost.java new file mode 100644 index 00000000..88d51b14 --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysUserPost.java @@ -0,0 +1,33 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 用户和岗位关联 sys_user_post + * + * @author Lion Li + */ + +@Data +@Entity +@Table(name = "sys_user_post") +public class TbSysUserPost { + + @Id + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 岗位ID + */ + private Long postId; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysUserRole.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysUserRole.java new file mode 100644 index 00000000..c0e7e5fb --- /dev/null +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/system/TbSysUserRole.java @@ -0,0 +1,33 @@ +package cc.iotkit.data.model.system; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 用户和角色关联 sys_user_role + * + * @author Lion Li + */ + +@Data +@Entity +@Table(name = "sys_user_role") +public class TbSysUserRole { + + @Id + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 角色ID + */ + private Long roleId; + +} diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/AlertConfigDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/AlertConfigDataImpl.java index 18cd9d51..468663c4 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/AlertConfigDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/AlertConfigDataImpl.java @@ -3,7 +3,7 @@ package cc.iotkit.data.service; import cc.iotkit.common.api.PageRequest; import cc.iotkit.data.IAlertConfigData; import cc.iotkit.data.dao.AlertConfigRepository; -import cc.iotkit.data.model.AlertConfigMapper; +import cc.iotkit.data.convert.AlertConfigMapper; import cc.iotkit.data.model.TbAlertConfig; import cc.iotkit.model.Paging; import cc.iotkit.model.alert.AlertConfig; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/AlertRecordDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/AlertRecordDataImpl.java index 6721c8ae..a988a930 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/AlertRecordDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/AlertRecordDataImpl.java @@ -2,26 +2,18 @@ package cc.iotkit.data.service; import cc.iotkit.common.api.PageRequest; import cc.iotkit.data.IAlertRecordData; -import cc.iotkit.data.IHomeData; import cc.iotkit.data.dao.AlertRecordRepository; -import cc.iotkit.data.dao.HomeRepository; -import cc.iotkit.data.model.AlertConfigMapper; -import cc.iotkit.data.model.AlertRecordMapper; -import cc.iotkit.data.model.HomeMapper; -import cc.iotkit.data.model.TbAlertConfig; +import cc.iotkit.data.convert.AlertRecordMapper; import cc.iotkit.data.model.TbAlertRecord; import cc.iotkit.model.Paging; import cc.iotkit.model.alert.AlertRecord; -import cc.iotkit.model.space.Home; + import java.util.List; -import java.util.UUID; -import org.apache.commons.lang3.StringUtils; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Primary; -import org.springframework.data.domain.Example; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; @Primary diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/CategoryDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/CategoryDataImpl.java index 0c25963a..668c3164 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/CategoryDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/CategoryDataImpl.java @@ -11,7 +11,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.ICategoryData; import cc.iotkit.data.dao.CategoryRepository; -import cc.iotkit.data.model.CategoryMapper; +import cc.iotkit.data.convert.CategoryMapper; import cc.iotkit.data.model.TbCategory; import cc.iotkit.model.Paging; import cc.iotkit.model.product.Category; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelConfigDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelConfigDataImpl.java index 0180a601..cfe1c1bb 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelConfigDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelConfigDataImpl.java @@ -2,7 +2,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IChannelConfigData; import cc.iotkit.data.dao.ChannelConfigRepository; -import cc.iotkit.data.model.ChannelConfigMapper; +import cc.iotkit.data.convert.ChannelConfigMapper; import cc.iotkit.data.model.TbChannelConfig; import cc.iotkit.model.Paging; import cc.iotkit.model.notify.ChannelConfig; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelDataImpl.java index e2efa258..695ca6a6 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelDataImpl.java @@ -2,7 +2,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IChannelData; import cc.iotkit.data.dao.ChannelRepository; -import cc.iotkit.data.model.ChannelMapper; +import cc.iotkit.data.convert.ChannelMapper; import cc.iotkit.data.model.TbChannel; import cc.iotkit.model.Paging; import cc.iotkit.model.notify.Channel; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelTemplateDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelTemplateDataImpl.java index 80803650..477a13e8 100644 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelTemplateDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ChannelTemplateDataImpl.java @@ -2,7 +2,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IChannelTemplateData; import cc.iotkit.data.dao.ChannelTemplateRepository; -import cc.iotkit.data.model.ChannelTemplateMapper; +import cc.iotkit.data.convert.ChannelTemplateMapper; import cc.iotkit.data.model.TbChannelTemplate; import cc.iotkit.model.Paging; import cc.iotkit.model.notify.ChannelTemplate; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceConfigDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceConfigDataImpl.java index 1aa44a00..fa1bf366 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceConfigDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceConfigDataImpl.java @@ -11,7 +11,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IDeviceConfigData; import cc.iotkit.data.dao.DeviceConfigRepository; -import cc.iotkit.data.model.DeviceConfigMapper; +import cc.iotkit.data.convert.DeviceConfigMapper; import cc.iotkit.data.model.TbDeviceConfig; import cc.iotkit.model.Paging; import cc.iotkit.model.device.DeviceConfig; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceGroupDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceGroupDataImpl.java index 74822ec2..bca13cc1 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceGroupDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceGroupDataImpl.java @@ -2,7 +2,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IDeviceGroupData; import cc.iotkit.data.dao.DeviceGroupRepository; -import cc.iotkit.data.model.DeviceGroupMapper; +import cc.iotkit.data.convert.DeviceGroupMapper; import cc.iotkit.data.model.TbDeviceGroup; import cc.iotkit.model.Paging; import cc.iotkit.model.device.DeviceGroup; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java index 8057b41a..cb08facf 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java @@ -4,6 +4,7 @@ import cc.iotkit.common.utils.ReflectUtil; import cc.iotkit.data.ICategoryData; import cc.iotkit.data.IDeviceInfoData; import cc.iotkit.data.IProductData; +import cc.iotkit.data.convert.DeviceInfoMapper; import cc.iotkit.data.dao.*; import cc.iotkit.data.model.*; import cc.iotkit.model.Paging; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/HomeDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/HomeDataImpl.java index 57564520..eec60742 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/HomeDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/HomeDataImpl.java @@ -2,7 +2,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IHomeData; import cc.iotkit.data.dao.HomeRepository; -import cc.iotkit.data.model.HomeMapper; +import cc.iotkit.data.convert.HomeMapper; import cc.iotkit.model.Paging; import cc.iotkit.model.space.Home; import org.apache.commons.lang3.StringUtils; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/OauthClientDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/OauthClientDataImpl.java index 822aa184..ce9386f9 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/OauthClientDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/OauthClientDataImpl.java @@ -11,7 +11,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IOauthClientData; import cc.iotkit.data.dao.OauthClientRepository; -import cc.iotkit.data.model.OauthClientMapper; +import cc.iotkit.data.convert.OauthClientMapper; import cc.iotkit.model.OauthClient; import cc.iotkit.model.Paging; import org.apache.commons.lang3.StringUtils; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProductDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProductDataImpl.java index b14224c8..e54f31ff 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProductDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProductDataImpl.java @@ -2,11 +2,10 @@ package cc.iotkit.data.service; import cc.iotkit.data.IProductData; import cc.iotkit.data.dao.ProductRepository; -import cc.iotkit.data.model.ProductMapper; +import cc.iotkit.data.convert.ProductMapper; import cc.iotkit.data.model.TbProduct; import cc.iotkit.model.Paging; import cc.iotkit.model.product.Product; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Primary; import org.springframework.data.domain.Page; @@ -14,7 +13,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.List; -import java.util.UUID; @Primary @Service diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProductModelDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProductModelDataImpl.java index 41dd4ae6..5d121c64 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProductModelDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProductModelDataImpl.java @@ -2,7 +2,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IProductModelData; import cc.iotkit.data.dao.ProductModelRepository; -import cc.iotkit.data.model.ProductModelMapper; +import cc.iotkit.data.convert.ProductModelMapper; import cc.iotkit.model.Paging; import cc.iotkit.model.product.ProductModel; import org.apache.commons.lang3.StringUtils; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProtocolComponentDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProtocolComponentDataImpl.java index 56671c2e..df1d5f06 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProtocolComponentDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProtocolComponentDataImpl.java @@ -2,7 +2,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IProtocolComponentData; import cc.iotkit.data.dao.ProtocolComponentRepository; -import cc.iotkit.data.model.ProtocolComponentMapper; +import cc.iotkit.data.convert.ProtocolComponentMapper; import cc.iotkit.data.model.TbProtocolComponent; import cc.iotkit.model.Paging; import cc.iotkit.model.protocol.ProtocolComponent; @@ -13,7 +13,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import java.util.ArrayList; import java.util.List; import java.util.UUID; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProtocolConverterDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProtocolConverterDataImpl.java index 335cd831..53611c97 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProtocolConverterDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ProtocolConverterDataImpl.java @@ -11,7 +11,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IProtocolConverterData; import cc.iotkit.data.dao.ProtocolConverterRepository; -import cc.iotkit.data.model.ProtocolConverterMapper; +import cc.iotkit.data.convert.ProtocolConverterMapper; import cc.iotkit.data.model.TbProtocolConverter; import cc.iotkit.model.Paging; import cc.iotkit.model.protocol.ProtocolConverter; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/RuleInfoDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/RuleInfoDataImpl.java index feadaeda..e0d4b625 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/RuleInfoDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/RuleInfoDataImpl.java @@ -11,7 +11,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IRuleInfoData; import cc.iotkit.data.dao.RuleInfoRepository; -import cc.iotkit.data.model.RuleInfoMapper; +import cc.iotkit.data.convert.RuleInfoMapper; import cc.iotkit.data.model.TbRuleInfo; import cc.iotkit.model.Paging; import cc.iotkit.model.rule.RuleInfo; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/SpaceDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/SpaceDataImpl.java index 53294f94..cf11c07e 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/SpaceDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/SpaceDataImpl.java @@ -2,7 +2,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.ISpaceData; import cc.iotkit.data.dao.SpaceRepository; -import cc.iotkit.data.model.SpaceMapper; +import cc.iotkit.data.convert.SpaceMapper; import cc.iotkit.data.model.TbSpace; import cc.iotkit.model.Paging; import cc.iotkit.model.space.Space; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/SpaceDeviceDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/SpaceDeviceDataImpl.java index d1321307..500a0622 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/SpaceDeviceDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/SpaceDeviceDataImpl.java @@ -11,7 +11,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.ISpaceDeviceData; import cc.iotkit.data.dao.SpaceDeviceRepository; -import cc.iotkit.data.model.SpaceDeviceMapper; +import cc.iotkit.data.convert.SpaceDeviceMapper; import cc.iotkit.model.Paging; import cc.iotkit.model.space.SpaceDevice; import org.apache.commons.lang3.StringUtils; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/TaskInfoDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/TaskInfoDataImpl.java index 06cddbea..579f2eed 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/TaskInfoDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/TaskInfoDataImpl.java @@ -11,7 +11,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.ITaskInfoData; import cc.iotkit.data.dao.TaskInfoRepository; -import cc.iotkit.data.model.TaskInfoMapper; +import cc.iotkit.data.convert.TaskInfoMapper; import cc.iotkit.data.model.TbTaskInfo; import cc.iotkit.model.Paging; import cc.iotkit.model.rule.TaskInfo; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ThingModelDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ThingModelDataImpl.java index 15b11a89..14cc90e1 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ThingModelDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/ThingModelDataImpl.java @@ -11,7 +11,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IThingModelData; import cc.iotkit.data.dao.ThingModelRepository; -import cc.iotkit.data.model.ThingModelMapper; +import cc.iotkit.data.convert.ThingModelMapper; import cc.iotkit.model.Paging; import cc.iotkit.model.product.ThingModel; import org.apache.commons.lang3.StringUtils; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/UserInfoDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/UserInfoDataImpl.java index 777f314c..83e2edde 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/UserInfoDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/UserInfoDataImpl.java @@ -12,7 +12,7 @@ package cc.iotkit.data.service; import cc.iotkit.data.IUserInfoData; import cc.iotkit.data.dao.UserInfoRepository; import cc.iotkit.data.model.TbUserInfo; -import cc.iotkit.data.model.UserInfoMapper; +import cc.iotkit.data.convert.UserInfoMapper; import cc.iotkit.model.Paging; import cc.iotkit.model.UserInfo; import org.apache.commons.lang3.StringUtils; diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/VirtualDeviceDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/VirtualDeviceDataImpl.java index 92cd4663..52fad900 100755 --- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/VirtualDeviceDataImpl.java +++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/VirtualDeviceDataImpl.java @@ -14,7 +14,7 @@ import cc.iotkit.data.dao.VirtualDeviceMappingRepository; import cc.iotkit.data.dao.VirtualDeviceRepository; import cc.iotkit.data.model.TbVirtualDevice; import cc.iotkit.data.model.TbVirtualDeviceMapping; -import cc.iotkit.data.model.VirtualDeviceMapper; +import cc.iotkit.data.convert.VirtualDeviceMapper; import cc.iotkit.model.Paging; import cc.iotkit.model.device.VirtualDevice; import cn.hutool.core.util.IdUtil; diff --git a/iot-data/iot-td-temporal-service/pom.xml b/iot-data/iot-td-temporal-service/pom.xml index a39f5834..d9615c8a 100644 --- a/iot-data/iot-td-temporal-service/pom.xml +++ b/iot-data/iot-td-temporal-service/pom.xml @@ -69,4 +69,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-data/iot-temporal-service/pom.xml b/iot-data/iot-temporal-service/pom.xml index c294eb36..e7c14b2a 100755 --- a/iot-data/iot-temporal-service/pom.xml +++ b/iot-data/iot-temporal-service/pom.xml @@ -20,4 +20,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-data/iot-ts-temporal-service/pom.xml b/iot-data/iot-ts-temporal-service/pom.xml index 18ac3af7..1e031f8b 100644 --- a/iot-data/iot-ts-temporal-service/pom.xml +++ b/iot-data/iot-ts-temporal-service/pom.xml @@ -100,4 +100,18 @@ + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-module/iot-manager/pom.xml b/iot-module/iot-manager/pom.xml new file mode 100644 index 00000000..0da51ded --- /dev/null +++ b/iot-module/iot-manager/pom.xml @@ -0,0 +1,28 @@ + + + + iot-module + cc.iotkit + ${revision} + + 4.0.0 + + iot-manager + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-rule-engine/.DS_Store b/iot-module/iot-rule-engine/.DS_Store old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/.DS_Store rename to iot-module/iot-rule-engine/.DS_Store diff --git a/iot-rule-engine/pom.xml b/iot-module/iot-rule-engine/pom.xml old mode 100755 new mode 100644 similarity index 85% rename from iot-rule-engine/pom.xml rename to iot-module/iot-rule-engine/pom.xml index 421d8c4d..f97c4324 --- a/iot-rule-engine/pom.xml +++ b/iot-module/iot-rule-engine/pom.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - iotkit-parent + iot-module cc.iotkit ${revision} @@ -14,8 +14,6 @@ 规则引擎模块,包含场景引擎、数据流转等 - - @@ -95,4 +93,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/Action.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/Action.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/Action.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/Action.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/ScriptService.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/ScriptService.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/ScriptService.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/ScriptService.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/alert/AlertAction.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/alert/AlertAction.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/alert/AlertAction.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/alert/AlertAction.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/alert/AlertService.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/alert/AlertService.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/alert/AlertService.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/alert/AlertService.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/device/DeviceAction.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/device/DeviceAction.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/device/DeviceAction.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/device/DeviceAction.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/device/DeviceActionService.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/device/DeviceActionService.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/device/DeviceActionService.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/device/DeviceActionService.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/http/HttpAction.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/http/HttpAction.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/http/HttpAction.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/http/HttpAction.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/http/HttpService.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/http/HttpService.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/http/HttpService.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/http/HttpService.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaAction.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaAction.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaAction.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaAction.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaService.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaService.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaService.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaService.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttAction.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttAction.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttAction.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttAction.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttService.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttService.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttService.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttService.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpAction.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpAction.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpAction.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpAction.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpService.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpService.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpService.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpService.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/Alerter.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/Alerter.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/Alerter.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/Alerter.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/DingdRobotAlerter.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/DingdRobotAlerter.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/DingdRobotAlerter.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/DingdRobotAlerter.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/EmailAlerter.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/EmailAlerter.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/EmailAlerter.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/alert/EmailAlerter.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/JobFactory.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/JobFactory.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/JobFactory.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/JobFactory.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/QuartzConfiguration.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/QuartzConfiguration.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/QuartzConfiguration.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/QuartzConfiguration.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/RuleConfiguration.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/RuleConfiguration.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/RuleConfiguration.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/config/RuleConfiguration.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/BaseComparator.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/BaseComparator.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/BaseComparator.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/BaseComparator.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/Comparator.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/Comparator.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/Comparator.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/Comparator.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/EqComparator.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/EqComparator.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/EqComparator.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/EqComparator.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/Expression.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/Expression.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/Expression.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/Expression.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/GtComparator.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/GtComparator.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/GtComparator.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/GtComparator.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/LtComparator.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/LtComparator.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/LtComparator.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/LtComparator.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/NeqComparator.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/NeqComparator.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/NeqComparator.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/expression/NeqComparator.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceCondition.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceCondition.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceCondition.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceCondition.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceFilter.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceFilter.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceFilter.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceFilter.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/Filter.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/Filter.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/Filter.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/filter/Filter.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/handler/DeviceMessageHandler.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/handler/DeviceMessageHandler.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/handler/DeviceMessageHandler.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/handler/DeviceMessageHandler.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/handler/RuleDeviceConsumer.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/handler/RuleDeviceConsumer.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/handler/RuleDeviceConsumer.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/handler/RuleDeviceConsumer.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/BaseSinkLink.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/BaseSinkLink.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/BaseSinkLink.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/BaseSinkLink.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/LinkFactory.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/LinkFactory.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/LinkFactory.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/LinkFactory.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/LinkService.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/LinkService.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/LinkService.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/LinkService.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/KafkaLink.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/KafkaLink.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/KafkaLink.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/KafkaLink.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/MqttClientLink.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/MqttClientLink.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/MqttClientLink.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/MqttClientLink.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/TcpClientLink.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/TcpClientLink.java similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/TcpClientLink.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/link/impl/TcpClientLink.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/DeviceCondition.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/DeviceCondition.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/DeviceCondition.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/DeviceCondition.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/DeviceListener.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/DeviceListener.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/DeviceListener.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/DeviceListener.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/Listener.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/Listener.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/Listener.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/listener/Listener.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/Rule.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/Rule.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/Rule.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/Rule.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleExecutor.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleExecutor.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleExecutor.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleExecutor.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleManager.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleManager.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleManager.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleManager.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleMessageHandler.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleMessageHandler.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleMessageHandler.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/rule/RuleMessageHandler.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/ActionExecutor.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/ActionExecutor.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/ActionExecutor.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/ActionExecutor.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/ActionExecutorManager.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/ActionExecutorManager.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/ActionExecutorManager.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/ActionExecutorManager.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/CommonJob.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/CommonJob.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/CommonJob.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/CommonJob.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/DeviceActionExecutor.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/DeviceActionExecutor.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/DeviceActionExecutor.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/DeviceActionExecutor.java diff --git a/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/TaskManager.java b/iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/TaskManager.java old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/TaskManager.java rename to iot-module/iot-rule-engine/src/main/java/cc/iotkit/ruleengine/task/TaskManager.java diff --git a/iot-rule-engine/src/main/resources/spring.factories b/iot-module/iot-rule-engine/src/main/resources/spring.factories old mode 100755 new mode 100644 similarity index 100% rename from iot-rule-engine/src/main/resources/spring.factories rename to iot-module/iot-rule-engine/src/main/resources/spring.factories diff --git a/iot-module/iot-system/pom.xml b/iot-module/iot-system/pom.xml new file mode 100644 index 00000000..9a4def5d --- /dev/null +++ b/iot-module/iot-system/pom.xml @@ -0,0 +1,66 @@ + + + + iot-module + cc.iotkit + ${revision} + + 4.0.0 + + iot-system + + + + + cc.iotkit + iot-common-core + + + + cc.iotkit + iot-common-web + + + + cc.iotkit + iot-common-security + + + + cc.iotkit + iot-common-log + + + + cc.iotkit + iot-common-excel + + + + cc.iotkit + iot-common-tenant + + + + cc.iotkit + iot-model + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysConfigController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysConfigController.java new file mode 100644 index 00000000..09ff066a --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysConfigController.java @@ -0,0 +1,131 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.excel.utils.ExcelUtil; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysConfigBo; +import cc.iotkit.system.domain.vo.SysConfigVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cc.iotkit.system.service.ISysConfigService; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 参数配置 信息操作处理 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/config") +public class SysConfigController extends BaseController { + + private final ISysConfigService configService; + + /** + * 获取参数配置列表 + */ + @SaCheckPermission("system:config:list") + @GetMapping("/list") + public PagedDataVo list(SysConfigBo config, PageRequest query) { + return configService.selectPageConfigList(config, query); + } + + /** + * 导出参数配置列表 + */ + @Log(title = "参数管理", businessType = BusinessType.EXPORT) + @SaCheckPermission("system:config:export") + @PostMapping("/export") + public void export(SysConfigBo config, HttpServletResponse response) { + List list = configService.selectConfigList(config); + ExcelUtil.exportExcel(list, "参数数据", SysConfigVo.class, response); + } + + /** + * 根据参数编号获取详细信息 + * + * @param configId 参数ID + */ + @SaCheckPermission("system:config:query") + @GetMapping(value = "/{configId}") + public SysConfigVo getInfo(@PathVariable Long configId) { + return configService.selectConfigById(configId); + } + + /** + * 根据参数键名查询参数值 + * + * @param configKey 参数Key + */ + @GetMapping(value = "/configKey/{configKey}") + public void getConfigKey(@PathVariable String configKey) { + configService.selectConfigByKey(configKey); + } + + /** + * 新增参数配置 + */ + @SaCheckPermission("system:config:add") + @Log(title = "参数管理", businessType = BusinessType.INSERT) + @PostMapping + public void add(@Validated @RequestBody SysConfigBo config) { + if (!configService.checkConfigKeyUnique(config)) { + fail("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + configService.insertConfig(config); + } + + /** + * 修改参数配置 + */ + @SaCheckPermission("system:config:edit") + @Log(title = "参数管理", businessType = BusinessType.UPDATE) + @PutMapping + public void edit(@Validated @RequestBody SysConfigBo config) { + if (!configService.checkConfigKeyUnique(config)) { + fail("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + configService.updateConfig(config); + } + + /** + * 根据参数键名修改参数配置 + */ + @SaCheckPermission("system:config:edit") + @Log(title = "参数管理", businessType = BusinessType.UPDATE) + @PutMapping("/updateByKey") + public void updateByKey(@RequestBody SysConfigBo config) { + configService.updateConfig(config); + } + + /** + * 删除参数配置 + * + * @param configIds 参数ID串 + */ + @SaCheckPermission("system:config:remove") + @Log(title = "参数管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{configIds}") + public void remove(@PathVariable Long[] configIds) { + configService.deleteConfigByIds(configIds); + } + + /** + * 刷新参数缓存 + */ + @SaCheckPermission("system:config:remove") + @Log(title = "参数管理", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public void refreshCache() { + configService.resetConfigCache(); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysDeptController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysDeptController.java new file mode 100644 index 00000000..b84a1517 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysDeptController.java @@ -0,0 +1,118 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.constant.UserConstants; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.utils.StringUtils; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysDeptBo; +import cc.iotkit.system.domain.vo.SysDeptVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.convert.Convert; +import cc.iotkit.system.service.ISysDeptService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 部门信息 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/dept") +public class SysDeptController extends BaseController { + + private final ISysDeptService deptService; + + /** + * 获取部门列表 + */ + @SaCheckPermission("system:dept:list") + @GetMapping("/list") + public List list(SysDeptBo dept) { + return deptService.selectDeptList(dept); + } + + /** + * 查询部门列表(排除节点) + * + * @param deptId 部门ID + */ + @SaCheckPermission("system:dept:list") + @GetMapping("/list/exclude/{deptId}") + public List excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) { + List depts = deptService.selectDeptList(new SysDeptBo()); + depts.removeIf(d -> d.getDeptId().equals(deptId) + || StringUtils.splitList(d.getAncestors()).contains(Convert.toStr(deptId))); + return depts; + } + + /** + * 根据部门编号获取详细信息 + * + * @param deptId 部门ID + */ + @SaCheckPermission("system:dept:query") + @GetMapping(value = "/{deptId}") + public SysDeptVo getInfo(@PathVariable Long deptId) { + deptService.checkDeptDataScope(deptId); + return deptService.selectDeptById(deptId); + } + + /** + * 新增部门 + */ + @SaCheckPermission("system:dept:add") + @Log(title = "部门管理", businessType = BusinessType.INSERT) + @PostMapping + public void add(@Validated @RequestBody SysDeptBo dept) { + if (!deptService.checkDeptNameUnique(dept)) { + fail("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + deptService.insertDept(dept); + } + + /** + * 修改部门 + */ + @SaCheckPermission("system:dept:edit") + @Log(title = "部门管理", businessType = BusinessType.UPDATE) + @PutMapping + public void edit(@Validated @RequestBody SysDeptBo dept) { + Long deptId = dept.getDeptId(); + deptService.checkDeptDataScope(deptId); + if (!deptService.checkDeptNameUnique(dept)) { + fail("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } else if (dept.getParentId().equals(deptId)) { + fail("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); + } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) + && deptService.selectNormalChildrenDeptById(deptId) > 0) { + fail("该部门包含未停用的子部门!"); + } + deptService.updateDept(dept); + } + + /** + * 删除部门 + * + * @param deptId 部门ID + */ + @SaCheckPermission("system:dept:remove") + @Log(title = "部门管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{deptId}") + public void remove(@PathVariable Long deptId) { + if (deptService.hasChildByDeptId(deptId)) { + warn("存在下级部门,不允许删除"); + } + if (deptService.checkDeptExistUser(deptId)) { + warn("部门存在用户,不允许删除"); + } + deptService.checkDeptDataScope(deptId); + deptService.deleteDeptById(deptId); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysDictDataController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysDictDataController.java new file mode 100644 index 00000000..6bf47cdc --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysDictDataController.java @@ -0,0 +1,112 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.excel.utils.ExcelUtil; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.system.domain.bo.SysDictDataBo; +import cc.iotkit.system.domain.vo.SysDictDataVo; +import cc.iotkit.system.service.ISysDictDataService; +import cc.iotkit.system.service.ISysDictTypeService; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.ObjectUtil; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * 数据字典信息 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/dict/data") +public class SysDictDataController { + + private final ISysDictDataService dictDataService; + private final ISysDictTypeService dictTypeService; + + /** + * 查询字典数据列表 + */ + @SaCheckPermission("system:dict:list") + @GetMapping("/list") + public PagedDataVo list(SysDictDataBo dictData, PageRequest query) { + return dictDataService.selectPageDictDataList(dictData, query); + } + + /** + * 导出字典数据列表 + */ + @Log(title = "字典数据", businessType = BusinessType.EXPORT) + @SaCheckPermission("system:dict:export") + @PostMapping("/export") + public void export(SysDictDataBo dictData, HttpServletResponse response) { + List list = dictDataService.selectDictDataList(dictData); + ExcelUtil.exportExcel(list, "字典数据", SysDictDataVo.class, response); + } + + /** + * 查询字典数据详细 + * + * @param dictCode 字典code + */ + @SaCheckPermission("system:dict:query") + @GetMapping(value = "/{dictCode}") + public SysDictDataVo getInfo(@PathVariable Long dictCode) { + return dictDataService.selectDictDataById(dictCode); + } + + /** + * 根据字典类型查询字典数据信息 + * + * @param dictType 字典类型 + */ + @GetMapping(value = "/type/{dictType}") + public List dictType(@PathVariable String dictType) { + List data = dictTypeService.selectDictDataByType(dictType); + if (ObjectUtil.isNull(data)) { + data = new ArrayList(); + } + return data; + } + + /** + * 新增字典类型 + */ + @SaCheckPermission("system:dict:add") + @Log(title = "字典数据", businessType = BusinessType.INSERT) + @PostMapping + public void add(@Validated @RequestBody SysDictDataBo dict) { + dictDataService.insertDictData(dict); + } + + /** + * 修改保存字典类型 + */ + @SaCheckPermission("system:dict:edit") + @Log(title = "字典数据", businessType = BusinessType.UPDATE) + @PutMapping + public void edit(@Validated @RequestBody SysDictDataBo dict) { + dictDataService.updateDictData(dict); + } + + /** + * 删除字典类型 + * + * @param dictCodes 字典code串 + */ + @SaCheckPermission("system:dict:remove") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictCodes}") + public void remove(@PathVariable Long[] dictCodes) { + dictDataService.deleteDictDataByIds(dictCodes); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysDictTypeController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysDictTypeController.java new file mode 100644 index 00000000..ccbad46d --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysDictTypeController.java @@ -0,0 +1,119 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.excel.utils.ExcelUtil; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysDictTypeBo; +import cc.iotkit.system.domain.vo.SysDictTypeVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cc.iotkit.system.service.ISysDictTypeService; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 数据字典信息 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/dict/type") +public class SysDictTypeController extends BaseController { + + private final ISysDictTypeService dictTypeService; + + /** + * 查询字典类型列表 + */ + @SaCheckPermission("system:dict:list") + @GetMapping("/list") + public PagedDataVo list(SysDictTypeBo dictType, PageRequest query) { + return dictTypeService.selectPageDictTypeList(dictType, query); + } + + /** + * 导出字典类型列表 + */ + @Log(title = "字典类型", businessType = BusinessType.EXPORT) + @SaCheckPermission("system:dict:export") + @PostMapping("/export") + public void export(SysDictTypeBo dictType, HttpServletResponse response) { + List list = dictTypeService.selectDictTypeList(dictType); + ExcelUtil.exportExcel(list, "字典类型", SysDictTypeVo.class, response); + } + + /** + * 查询字典类型详细 + * + * @param dictId 字典ID + */ + @SaCheckPermission("system:dict:query") + @GetMapping(value = "/{dictId}") + public SysDictTypeVo getInfo(@PathVariable Long dictId) { + return dictTypeService.selectDictTypeById(dictId); + } + + /** + * 新增字典类型 + */ + @SaCheckPermission("system:dict:add") + @Log(title = "字典类型", businessType = BusinessType.INSERT) + @PostMapping + public void add(@Validated @RequestBody SysDictTypeBo dict) { + if (!dictTypeService.checkDictTypeUnique(dict)) { + fail("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dictTypeService.insertDictType(dict); + } + + /** + * 修改字典类型 + */ + @SaCheckPermission("system:dict:edit") + @Log(title = "字典类型", businessType = BusinessType.UPDATE) + @PutMapping + public void edit(@Validated @RequestBody SysDictTypeBo dict) { + if (!dictTypeService.checkDictTypeUnique(dict)) { + fail("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dictTypeService.updateDictType(dict); + } + + /** + * 删除字典类型 + * + * @param dictIds 字典ID串 + */ + @SaCheckPermission("system:dict:remove") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictIds}") + public void remove(@PathVariable Long[] dictIds) { + dictTypeService.deleteDictTypeByIds(dictIds); + } + + /** + * 刷新字典缓存 + */ + @SaCheckPermission("system:dict:remove") + @Log(title = "字典类型", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public void refreshCache() { + dictTypeService.resetDictCache(); + } + + /** + * 获取字典选择框列表 + */ + @GetMapping("/optionselect") + public List optionselect() { + return dictTypeService.selectDictTypeAll(); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysMenuController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysMenuController.java new file mode 100644 index 00000000..006c4aae --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysMenuController.java @@ -0,0 +1,181 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.constant.TenantConstants; +import cc.iotkit.common.constant.UserConstants; +import cc.iotkit.common.exception.BizException; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.satoken.utils.LoginHelper; +import cc.iotkit.common.utils.StringUtils; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.SysMenu; +import cc.iotkit.system.domain.bo.SysMenuBo; +import cc.iotkit.system.domain.vo.MenuTreeSelectVo; +import cc.iotkit.system.domain.vo.RouterVo; +import cc.iotkit.system.domain.vo.SysMenuVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaCheckRole; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.lang.tree.Tree; +import cc.iotkit.system.service.ISysMenuService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 菜单信息 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/menu") +public class SysMenuController extends BaseController { + + private final ISysMenuService menuService; + + /** + * 获取路由信息 + * + * @return 路由信息 + */ + @GetMapping("/getRouters") + public List getRouters() { + List menus = menuService.selectMenuTreeByUserId(LoginHelper.getUserId()); + return menuService.buildMenus(menus); + } + + /** + * 获取菜单列表 + */ + @SaCheckRole(value = { + TenantConstants.SUPER_ADMIN_ROLE_KEY, + TenantConstants.TENANT_ADMIN_ROLE_KEY + }, mode = SaMode.OR) + @SaCheckPermission("system:menu:list") + @GetMapping("/list") + public List list(SysMenuBo menu) { + return menuService.selectMenuList(menu, LoginHelper.getUserId()); + } + + /** + * 根据菜单编号获取详细信息 + * + * @param menuId 菜单ID + */ + @SaCheckRole(value = { + TenantConstants.SUPER_ADMIN_ROLE_KEY, + TenantConstants.TENANT_ADMIN_ROLE_KEY + }, mode = SaMode.OR) + @SaCheckPermission("system:menu:query") + @GetMapping(value = "/{menuId}") + public SysMenuVo getInfo(@PathVariable Long menuId) { + return menuService.selectMenuById(menuId); + } + + /** + * 获取菜单下拉树列表 + */ + @SaCheckRole(value = { + TenantConstants.SUPER_ADMIN_ROLE_KEY, + TenantConstants.TENANT_ADMIN_ROLE_KEY + }, mode = SaMode.OR) + @SaCheckPermission("system:menu:query") + @GetMapping("/treeselect") + public List> treeselect(SysMenuBo menu) { + List menus = menuService.selectMenuList(menu, LoginHelper.getUserId()); + return menuService.buildMenuTreeSelect(menus); + } + + /** + * 加载对应角色菜单列表树 + * + * @param roleId 角色ID + */ + @SaCheckRole(value = { + TenantConstants.SUPER_ADMIN_ROLE_KEY, + TenantConstants.TENANT_ADMIN_ROLE_KEY + }, mode = SaMode.OR) + @SaCheckPermission("system:menu:query") + @GetMapping(value = "/roleMenuTreeselect/{roleId}") + public MenuTreeSelectVo roleMenuTreeselect(@PathVariable("roleId") Long roleId) { + List menus = menuService.selectMenuList(LoginHelper.getUserId()); + MenuTreeSelectVo selectVo = new MenuTreeSelectVo(); + selectVo.setCheckedKeys(menuService.selectMenuListByRoleId(roleId)); + selectVo.setMenus(menuService.buildMenuTreeSelect(menus)); + return selectVo; + } + + /** + * 加载对应租户套餐菜单列表树 + * + * @param packageId 租户套餐ID + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:menu:query") + @GetMapping(value = "/tenantPackageMenuTreeselect/{packageId}") + public MenuTreeSelectVo tenantPackageMenuTreeselect(@PathVariable("packageId") Long packageId) { + List menus = menuService.selectMenuList(LoginHelper.getUserId()); + MenuTreeSelectVo selectVo = new MenuTreeSelectVo(); + selectVo.setCheckedKeys(menuService.selectMenuListByPackageId(packageId)); + selectVo.setMenus(menuService.buildMenuTreeSelect(menus)); + return selectVo; + } + + /** + * 新增菜单 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:menu:add") + @Log(title = "菜单管理", businessType = BusinessType.INSERT) + @PostMapping + public void add(@Validated @RequestBody SysMenuBo menu) { + if (!menuService.checkMenuNameUnique(menu)) { + fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { + fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } + menuService.insertMenu(menu); + } + + /** + * 修改菜单 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:menu:edit") + @Log(title = "菜单管理", businessType = BusinessType.UPDATE) + @PutMapping + public void edit(@Validated @RequestBody SysMenuBo menu) { + if (!menuService.checkMenuNameUnique(menu)) { + fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { + fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } else if (menu.getMenuId().equals(menu.getParentId())) { + fail("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); + } + menuService.updateMenu(menu); + } + + /** + * 删除菜单 + * + * @param menuId 菜单ID + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:menu:remove") + @Log(title = "菜单管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{menuId}") + public void remove(@PathVariable("menuId") Long menuId) { + if (menuService.hasChildByMenuId(menuId)) { + warn("存在子菜单,不允许删除"); + } + if (menuService.checkMenuExistRole(menuId)) { + warn("菜单已分配,不允许删除"); + } + menuService.deleteMenuById(menuId); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysNoticeController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysNoticeController.java new file mode 100644 index 00000000..f3ae3e5c --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysNoticeController.java @@ -0,0 +1,80 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysNoticeBo; +import cc.iotkit.system.domain.vo.SysNoticeVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cc.iotkit.system.service.ISysNoticeService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 公告 信息操作处理 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/notice") +public class SysNoticeController extends BaseController { + + private final ISysNoticeService noticeService; + + /** + * 获取通知公告列表 + */ + @SaCheckPermission("system:notice:list") + @GetMapping("/list") + public PagedDataVo list(SysNoticeBo notice, PageRequest query) { + return noticeService.selectPageNoticeList(notice, query); + } + + /** + * 根据通知公告编号获取详细信息 + * + * @param noticeId 公告ID + */ + @SaCheckPermission("system:notice:query") + @GetMapping(value = "/{noticeId}") + public SysNoticeVo getInfo(@PathVariable Long noticeId) { + return noticeService.selectNoticeById(noticeId); + } + + /** + * 新增通知公告 + */ + @SaCheckPermission("system:notice:add") + @Log(title = "通知公告", businessType = BusinessType.INSERT) + @PostMapping + public void add(@Validated @RequestBody SysNoticeBo notice) { + noticeService.insertNotice(notice); + } + + /** + * 修改通知公告 + */ + @SaCheckPermission("system:notice:edit") + @Log(title = "通知公告", businessType = BusinessType.UPDATE) + @PutMapping + public void edit(@Validated @RequestBody SysNoticeBo notice) { + noticeService.updateNotice(notice); + } + + /** + * 删除通知公告 + * + * @param noticeIds 公告ID串 + */ + @SaCheckPermission("system:notice:remove") + @Log(title = "通知公告", businessType = BusinessType.DELETE) + @DeleteMapping("/{noticeIds}") + public void remove(@PathVariable Long[] noticeIds) { + noticeService.deleteNoticeByIds(noticeIds); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysOssConfigController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysOssConfigController.java new file mode 100644 index 00000000..73e3274f --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysOssConfigController.java @@ -0,0 +1,101 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.common.validate.QueryGroup; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysOssConfigBo; +import cc.iotkit.system.domain.vo.SysOssConfigVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cc.iotkit.system.service.ISysOssConfigService; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 对象存储配置 + * + * @author Lion Li + * @author 孤舟烟雨 + * @date 2021-08-13 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/resource/oss/config") +public class SysOssConfigController extends BaseController { + + private final ISysOssConfigService ossConfigService; + + /** + * 查询对象存储配置列表 + */ + @SaCheckPermission("system:oss:list") + @GetMapping("/list") + public PagedDataVo list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageRequest query) { + return ossConfigService.queryPageList(bo, query); + } + + /** + * 获取对象存储配置详细信息 + * + * @param ossConfigId OSS配置ID + */ + @SaCheckPermission("system:oss:query") + @GetMapping("/{ossConfigId}") + public SysOssConfigVo getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long ossConfigId) { + return ossConfigService.queryById(ossConfigId); + } + + /** + * 新增对象存储配置 + */ + @SaCheckPermission("system:oss:add") + @Log(title = "对象存储配置", businessType = BusinessType.INSERT) + @PostMapping() + public void add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) { + ossConfigService.insertByBo(bo); + } + + /** + * 修改对象存储配置 + */ + @SaCheckPermission("system:oss:edit") + @Log(title = "对象存储配置", businessType = BusinessType.UPDATE) + @PutMapping() + public void edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) { + ossConfigService.updateByBo(bo); + } + + /** + * 删除对象存储配置 + * + * @param ossConfigIds OSS配置ID串 + */ + @SaCheckPermission("system:oss:remove") + @Log(title = "对象存储配置", businessType = BusinessType.DELETE) + @DeleteMapping("/{ossConfigIds}") + public void remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ossConfigIds) { + ossConfigService.deleteWithValidByIds(List.of(ossConfigIds), true); + } + + /** + * 状态修改 + */ + @SaCheckPermission("system:oss:edit") + @Log(title = "对象存储状态修改", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public void changeStatus(@RequestBody SysOssConfigBo bo) { + ossConfigService.updateOssConfigStatus(bo); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysOssController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysOssController.java new file mode 100644 index 00000000..bed8151e --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysOssController.java @@ -0,0 +1,106 @@ +package cc.iotkit.system.controller.system; + + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.validate.QueryGroup; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysOssBo; +import cc.iotkit.system.domain.vo.SysOssUploadVo; +import cc.iotkit.system.domain.vo.SysOssVo; +import cc.iotkit.system.service.ISysOssService; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.ObjectUtil; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotEmpty; +import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +/** + * 文件上传 控制层 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/resource/oss") +public class SysOssController extends BaseController { + + private final ISysOssService ossService; + + /** + * 查询OSS对象存储列表 + */ + @SaCheckPermission("system:oss:list") + @GetMapping("/list") + public PagedDataVo list(@Validated(QueryGroup.class) SysOssBo bo, PageRequest query) { + return ossService.queryPageList(bo, query); + } + + /** + * 查询OSS对象基于id串 + * + * @param ossIds OSS对象ID串 + */ + @SaCheckPermission("system:oss:list") + @GetMapping("/listByIds/{ossIds}") + public List listByIds(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ossIds) { + return ossService.listByIds(Arrays.asList(ossIds)); + } + + /** + * 上传OSS对象存储 + * + * @param file 文件 + */ + @SaCheckPermission("system:oss:upload") + @Log(title = "OSS对象存储", businessType = BusinessType.INSERT) + @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public SysOssUploadVo upload(@RequestPart("file") MultipartFile file) { + if (ObjectUtil.isNull(file)) { + fail("上传文件不能为空"); + } + SysOssVo oss = ossService.upload(file); + SysOssUploadVo uploadVo = new SysOssUploadVo(); + uploadVo.setUrl(oss.getUrl()); + uploadVo.setFileName(oss.getOriginalName()); + uploadVo.setOssId(oss.getOssId().toString()); + return uploadVo; + } + + /** + * 下载OSS对象 + * + * @param ossId OSS对象ID + */ + @SaCheckPermission("system:oss:download") + @GetMapping("/download/{ossId}") + public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException { + ossService.download(ossId, response); + } + + /** + * 删除OSS对象存储 + * + * @param ossIds OSS对象ID串 + */ + @SaCheckPermission("system:oss:remove") + @Log(title = "OSS对象存储", businessType = BusinessType.DELETE) + @DeleteMapping("/{ossIds}") + public void remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ossIds) { + ossService.deleteWithValidByIds(List.of(ossIds), true); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysPostController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysPostController.java new file mode 100644 index 00000000..15f7b844 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysPostController.java @@ -0,0 +1,113 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.excel.utils.ExcelUtil; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysPostBo; +import cc.iotkit.system.domain.vo.SysPostVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cc.iotkit.system.service.ISysPostService; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 岗位信息操作处理 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/post") +public class SysPostController extends BaseController { + + private final ISysPostService postService; + + /** + * 获取岗位列表 + */ + @SaCheckPermission("system:post:list") + @GetMapping("/list") + public PagedDataVo list(SysPostBo post, PageRequest query) { + return postService.selectPagePostList(post, query); + } + + /** + * 导出岗位列表 + */ + @Log(title = "岗位管理", businessType = BusinessType.EXPORT) + @SaCheckPermission("system:post:export") + @PostMapping("/export") + public void export(SysPostBo post, HttpServletResponse response) { + List list = postService.selectPostList(post); + ExcelUtil.exportExcel(list, "岗位数据", SysPostVo.class, response); + } + + /** + * 根据岗位编号获取详细信息 + * + * @param postId 岗位ID + */ + @SaCheckPermission("system:post:query") + @GetMapping(value = "/{postId}") + public SysPostVo getInfo(@PathVariable Long postId) { + return postService.selectPostById(postId); + } + + /** + * 新增岗位 + */ + @SaCheckPermission("system:post:add") + @Log(title = "岗位管理", businessType = BusinessType.INSERT) + @PostMapping + public void add(@Validated @RequestBody SysPostBo post) { + if (!postService.checkPostNameUnique(post)) { + fail("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } else if (!postService.checkPostCodeUnique(post)) { + fail("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + postService.insertPost(post); + } + + /** + * 修改岗位 + */ + @SaCheckPermission("system:post:edit") + @Log(title = "岗位管理", businessType = BusinessType.UPDATE) + @PutMapping + public void edit(@Validated @RequestBody SysPostBo post) { + if (!postService.checkPostNameUnique(post)) { + fail("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } else if (!postService.checkPostCodeUnique(post)) { + fail("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + postService.updatePost(post); + } + + /** + * 删除岗位 + * + * @param postIds 岗位ID串 + */ + @SaCheckPermission("system:post:remove") + @Log(title = "岗位管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{postIds}") + public void remove(@PathVariable Long[] postIds) { + postService.deletePostByIds(postIds); + } + + /** + * 获取岗位选择框列表 + */ + @GetMapping("/optionselect") + public List optionselect() { + return postService.selectPostAll(); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysProfileController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysProfileController.java new file mode 100644 index 00000000..4cef621b --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysProfileController.java @@ -0,0 +1,123 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.satoken.utils.LoginHelper; +import cc.iotkit.common.utils.StringUtils; +import cc.iotkit.common.utils.file.MimeTypeUtils; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysUserBo; +import cc.iotkit.system.domain.bo.SysUserProfileBo; +import cc.iotkit.system.domain.vo.AvatarVo; +import cc.iotkit.system.domain.vo.ProfileVo; +import cc.iotkit.system.domain.vo.SysOssVo; +import cc.iotkit.system.domain.vo.SysUserVo; +import cn.dev33.satoken.secure.BCrypt; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.io.FileUtil; +import cc.iotkit.system.service.ISysOssService; +import cc.iotkit.system.service.ISysUserService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Arrays; + +/** + * 个人信息 业务处理 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/user/profile") +public class SysProfileController extends BaseController { + + private final ISysUserService userService; + private final ISysOssService ossService; + + /** + * 个人信息 + */ + @GetMapping + public ProfileVo profile() { + SysUserVo user = userService.selectUserById(LoginHelper.getUserId()); + ProfileVo profileVo = new ProfileVo(); + profileVo.setUser(user); + profileVo.setRoleGroup(userService.selectUserRoleGroup(user.getUserName())); + profileVo.setPostGroup(userService.selectUserPostGroup(user.getUserName())); + return profileVo; + } + + /** + * 修改用户 + */ + @Log(title = "个人信息", businessType = BusinessType.UPDATE) + @PutMapping + public void updateProfile(@RequestBody SysUserProfileBo profile) { + SysUserBo user = BeanUtil.toBean(profile, SysUserBo.class); + if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { + fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { + fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setUserId(LoginHelper.getUserId()); + if (userService.updateUserProfile(user) > 0) { + return; + } + fail("修改个人信息异常,请联系管理员"); + } + + /** + * 重置密码 + * + * @param newPassword 旧密码 + * @param oldPassword 新密码 + */ + @Log(title = "个人信息", businessType = BusinessType.UPDATE) + @PutMapping("/updatePwd") + public void updatePwd(String oldPassword, String newPassword) { + SysUserVo user = userService.selectUserById(LoginHelper.getUserId()); + String password = user.getPassword(); + if (!BCrypt.checkpw(oldPassword, password)) { + fail("修改密码失败,旧密码错误"); + } + if (BCrypt.checkpw(newPassword, password)) { + fail("新密码不能与旧密码相同"); + } + + if (userService.resetUserPwd(user.getUserId(), BCrypt.hashpw(newPassword)) > 0) { + return; + } + fail("修改密码异常,请联系管理员"); + } + + /** + * 头像上传 + * + * @param avatarfile 用户头像 + */ + @Log(title = "用户头像", businessType = BusinessType.UPDATE) + @PostMapping(value = "/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public AvatarVo avatar(@RequestPart("avatarfile") MultipartFile avatarfile) { + if (!avatarfile.isEmpty()) { + String extension = FileUtil.extName(avatarfile.getOriginalFilename()); + if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) { + fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式"); + } + SysOssVo oss = ossService.upload(avatarfile); + String avatar = oss.getUrl(); + if (userService.updateUserAvatar(LoginHelper.getUserId(), oss.getOssId())) { + AvatarVo avatarVo = new AvatarVo(); + avatarVo.setImgUrl(avatar); + return avatarVo; + } + } + fail("上传图片异常,请联系管理员"); + return null; + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysRoleController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysRoleController.java new file mode 100644 index 00000000..c1c8fa5a --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysRoleController.java @@ -0,0 +1,224 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.excel.utils.ExcelUtil; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.SysUserRole; +import cc.iotkit.system.domain.bo.SysDeptBo; +import cc.iotkit.system.domain.bo.SysRoleBo; +import cc.iotkit.system.domain.bo.SysUserBo; +import cc.iotkit.system.domain.vo.DeptTreeSelectVo; +import cc.iotkit.system.domain.vo.SysRoleVo; +import cc.iotkit.system.domain.vo.SysUserVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cc.iotkit.system.service.ISysDeptService; +import cc.iotkit.system.service.ISysRoleService; +import cc.iotkit.system.service.ISysUserService; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 角色信息 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/role") +public class SysRoleController extends BaseController { + + private final ISysRoleService roleService; + private final ISysUserService userService; + private final ISysDeptService deptService; + + /** + * 获取角色信息列表 + */ + @SaCheckPermission("system:role:list") + @GetMapping("/list") + public PagedDataVo list(SysRoleBo role, PageRequest query) { + return roleService.selectPageRoleList(role, query); + } + + /** + * 导出角色信息列表 + */ + @Log(title = "角色管理", businessType = BusinessType.EXPORT) + @SaCheckPermission("system:role:export") + @PostMapping("/export") + public void export(SysRoleBo role, HttpServletResponse response) { + List list = roleService.selectRoleList(role); + ExcelUtil.exportExcel(list, "角色数据", SysRoleVo.class, response); + } + + /** + * 根据角色编号获取详细信息 + * + * @param roleId 角色ID + */ + @SaCheckPermission("system:role:query") + @GetMapping(value = "/{roleId}") + public SysRoleVo getInfo(@PathVariable Long roleId) { + roleService.checkRoleDataScope(roleId); + return roleService.selectRoleById(roleId); + } + + /** + * 新增角色 + */ + @SaCheckPermission("system:role:add") + @Log(title = "角色管理", businessType = BusinessType.INSERT) + @PostMapping + public void add(@Validated @RequestBody SysRoleBo role) { + if (!roleService.checkRoleNameUnique(role)) { + fail("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } else if (!roleService.checkRoleKeyUnique(role)) { + fail("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + roleService.insertRole(role); + + } + + /** + * 修改保存角色 + */ + @SaCheckPermission("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping + public void edit(@Validated @RequestBody SysRoleBo role) { + roleService.checkRoleAllowed(role.getRoleId()); + roleService.checkRoleDataScope(role.getRoleId()); + if (!roleService.checkRoleNameUnique(role)) { + fail("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } else if (!roleService.checkRoleKeyUnique(role)) { + fail("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + + if (roleService.updateRole(role) > 0) { + roleService.cleanOnlineUserByRole(role.getRoleId()); + } + fail("修改角色'" + role.getRoleName() + "'失败,请联系管理员"); + } + + /** + * 修改保存数据权限 + */ + @SaCheckPermission("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping("/dataScope") + public void dataScope(@RequestBody SysRoleBo role) { + roleService.checkRoleAllowed(role.getRoleId()); + roleService.checkRoleDataScope(role.getRoleId()); + roleService.authDataScope(role); + } + + /** + * 状态修改 + */ + @SaCheckPermission("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public void changeStatus(@RequestBody SysRoleBo role) { + roleService.checkRoleAllowed(role.getRoleId()); + roleService.checkRoleDataScope(role.getRoleId()); + roleService.updateRoleStatus(role.getRoleId(), role.getStatus()); + } + + /** + * 删除角色 + * + * @param roleIds 角色ID串 + */ + @SaCheckPermission("system:role:remove") + @Log(title = "角色管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{roleIds}") + public void remove(@PathVariable Long[] roleIds) { + roleService.deleteRoleByIds(roleIds); + } + + /** + * 获取角色选择框列表 + */ + @SaCheckPermission("system:role:query") + @GetMapping("/optionselect") + public List optionselect() { + return roleService.selectRoleAll(); + } + + /** + * 查询已分配用户角色列表 + */ + @SaCheckPermission("system:role:list") + @GetMapping("/authUser/allocatedList") + public PagedDataVo allocatedList(SysUserBo user, PageRequest query) { + return userService.selectAllocatedList(user, query); + } + + /** + * 查询未分配用户角色列表 + */ + @SaCheckPermission("system:role:list") + @GetMapping("/authUser/unallocatedList") + public PagedDataVo unallocatedList(SysUserBo user, PageRequest query) { + return userService.selectUnallocatedList(user, query); + } + + /** + * 取消授权用户 + */ + @SaCheckPermission("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancel") + public void cancelAuthUser(@RequestBody SysUserRole userRole) { + roleService.deleteAuthUser(userRole); + } + + /** + * 批量取消授权用户 + * + * @param roleId 角色ID + * @param userIds 用户ID串 + */ + @SaCheckPermission("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancelAll") + public void cancelAuthUserAll(Long roleId, Long[] userIds) { + roleService.deleteAuthUsers(roleId, userIds); + } + + /** + * 批量选择用户授权 + * + * @param roleId 角色ID + * @param userIds 用户ID串 + */ + @SaCheckPermission("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/selectAll") + public void selectAuthUserAll(Long roleId, Long[] userIds) { + roleService.checkRoleDataScope(roleId); + roleService.insertAuthUsers(roleId, userIds); + } + + /** + * 获取对应角色部门树列表 + * + * @param roleId 角色ID + */ + @SaCheckPermission("system:role:list") + @GetMapping(value = "/deptTree/{roleId}") + public DeptTreeSelectVo roleDeptTreeselect(@PathVariable("roleId") Long roleId) { + DeptTreeSelectVo selectVo = new DeptTreeSelectVo(); + selectVo.setCheckedKeys(deptService.selectDeptListByRoleId(roleId)); + selectVo.setDepts(deptService.selectDeptTreeList(new SysDeptBo())); + return selectVo; + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysTenantController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysTenantController.java new file mode 100644 index 00000000..8a3f7997 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysTenantController.java @@ -0,0 +1,175 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.constant.TenantConstants; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.excel.utils.ExcelUtil; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.tenant.helper.TenantHelper; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysTenantBo; +import cc.iotkit.system.domain.vo.SysTenantVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaCheckRole; +import com.baomidou.lock.annotation.Lock4j; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import cc.iotkit.system.service.ISysTenantService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * 租户管理 + * + * @author Michelle.Chung + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/tenant") +public class SysTenantController extends BaseController { + + private final ISysTenantService tenantService; + + /** + * 查询租户列表 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenant:list") + @GetMapping("/list") + public PagedDataVo list(SysTenantBo bo, PageRequest query) { + return tenantService.queryPageList(bo, query); + } + + /** + * 导出租户列表 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenant:export") + @Log(title = "租户", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(SysTenantBo bo, HttpServletResponse response) { + List list = tenantService.queryList(bo); + ExcelUtil.exportExcel(list, "租户", SysTenantVo.class, response); + } + + /** + * 获取租户详细信息 + * + * @param id 主键 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenant:query") + @GetMapping("/{id}") + public SysTenantVo getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return tenantService.queryById(id); + } + + /** + * 新增租户 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenant:add") + @Log(title = "租户", businessType = BusinessType.INSERT) + @Lock4j + @PostMapping() + public void add(@Validated(AddGroup.class) @RequestBody SysTenantBo bo) { + if (!tenantService.checkCompanyNameUnique(bo)) { + fail("新增租户'" + bo.getCompanyName() + "'失败,企业名称已存在"); + } + TenantHelper.ignore(() -> tenantService.insertByBo(bo)); + } + + /** + * 修改租户 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenant:edit") + @Log(title = "租户", businessType = BusinessType.UPDATE) + @PutMapping() + public void edit(@Validated(EditGroup.class) @RequestBody SysTenantBo bo) { + tenantService.checkTenantAllowed(bo.getTenantId()); + if (!tenantService.checkCompanyNameUnique(bo)) { + fail("修改租户'" + bo.getCompanyName() + "'失败,公司名称已存在"); + } + tenantService.updateByBo(bo); + } + + /** + * 状态修改 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenant:edit") + @Log(title = "租户", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public void changeStatus(@RequestBody SysTenantBo bo) { + tenantService.checkTenantAllowed(bo.getTenantId()); + tenantService.updateTenantStatus(bo); + } + + /** + * 删除租户 + * + * @param ids 主键串 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenant:remove") + @Log(title = "租户", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public void remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + tenantService.deleteWithValidByIds(List.of(ids), true); + } + + /** + * 动态切换租户 + * + * @param tenantId 租户ID + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @GetMapping("/dynamic/{tenantId}") + public void dynamicTenant(@NotBlank(message = "租户ID不能为空") @PathVariable String tenantId) { + TenantHelper.setDynamic(tenantId); + } + + /** + * 清除动态租户 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @GetMapping("/dynamic/clear") + public void dynamicClear() { + TenantHelper.clearDynamic(); + } + + + /** + * 同步租户套餐 + * + * @param tenantId 租户id + * @param packageId 套餐id + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenant:edit") + @Log(title = "租户", businessType = BusinessType.UPDATE) + @GetMapping("/syncTenantPackage") + public void syncTenantPackage(@NotBlank(message = "租户ID不能为空") String tenantId, @NotBlank(message = "套餐ID不能为空") String packageId) { + TenantHelper.ignore(() -> tenantService.syncTenantPackage(tenantId, packageId)); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysTenantPackageController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysTenantPackageController.java new file mode 100644 index 00000000..678e4636 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysTenantPackageController.java @@ -0,0 +1,130 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.constant.TenantConstants; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.excel.utils.ExcelUtil; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysTenantPackageBo; +import cc.iotkit.system.domain.vo.SysTenantPackageVo; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaCheckRole; +import cc.iotkit.system.service.ISysTenantPackageService; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 租户套餐管理 + * + * @author Michelle.Chung + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/tenant/package") +public class SysTenantPackageController extends BaseController { + + private final ISysTenantPackageService tenantPackageService; + + /** + * 查询租户套餐列表 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:list") + @GetMapping("/list") + public PagedDataVo list(SysTenantPackageBo bo, PageRequest query) { + return tenantPackageService.queryPageList(bo, query); + } + + /** + * 查询租户套餐下拉选列表 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:list") + @GetMapping("/selectList") + public List selectList() { + return tenantPackageService.selectList(); + } + + /** + * 导出租户套餐列表 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:export") + @Log(title = "租户套餐", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(SysTenantPackageBo bo, HttpServletResponse response) { + List list = tenantPackageService.queryList(bo); + ExcelUtil.exportExcel(list, "租户套餐", SysTenantPackageVo.class, response); + } + + /** + * 获取租户套餐详细信息 + * + * @param packageId 主键 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:query") + @GetMapping("/{packageId}") + public SysTenantPackageVo getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long packageId) { + return tenantPackageService.queryById(packageId); + } + + /** + * 新增租户套餐 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:add") + @Log(title = "租户套餐", businessType = BusinessType.INSERT) + @PostMapping() + public void add(@Validated(AddGroup.class) @RequestBody SysTenantPackageBo bo) { + tenantPackageService.insertByBo(bo); + } + + /** + * 修改租户套餐 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:edit") + @Log(title = "租户套餐", businessType = BusinessType.UPDATE) + @PutMapping() + public void edit(@Validated(EditGroup.class) @RequestBody SysTenantPackageBo bo) { + tenantPackageService.updateByBo(bo); + } + + /** + * 状态修改 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:edit") + @Log(title = "租户套餐", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public void changeStatus(@RequestBody SysTenantPackageBo bo) { + tenantPackageService.updatePackageStatus(bo); + } + + /** + * 删除租户套餐 + * + * @param packageIds 主键串 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:remove") + @Log(title = "租户套餐", businessType = BusinessType.DELETE) + @DeleteMapping("/{packageIds}") + public void remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] packageIds) { + tenantPackageService.deleteWithValidByIds(List.of(packageIds), true); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysUserController.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysUserController.java new file mode 100644 index 00000000..7426d111 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/controller/system/SysUserController.java @@ -0,0 +1,259 @@ +package cc.iotkit.system.controller.system; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.model.LoginUser; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.excel.core.ExcelResult; +import cc.iotkit.common.excel.utils.ExcelUtil; +import cc.iotkit.common.log.annotation.Log; +import cc.iotkit.common.log.enums.BusinessType; +import cc.iotkit.common.satoken.utils.LoginHelper; +import cc.iotkit.common.tenant.helper.TenantHelper; +import cc.iotkit.common.utils.MapstructUtils; +import cc.iotkit.common.utils.StreamUtils; +import cc.iotkit.common.utils.StringUtils; +import cc.iotkit.common.web.core.BaseController; +import cc.iotkit.system.domain.bo.SysDeptBo; +import cc.iotkit.system.domain.bo.SysUserBo; +import cc.iotkit.system.domain.vo.*; +import cc.iotkit.system.service.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.secure.BCrypt; +import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import cc.iotkit.system.listener.SysUserImportListener; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用户信息 + * + * @author Lion Li + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/user") +public class SysUserController extends BaseController { + + private final ISysUserService userService; + private final ISysRoleService roleService; + private final ISysPostService postService; + private final ISysDeptService deptService; + private final ISysTenantService tenantService; + + /** + * 获取用户列表 + */ + @SaCheckPermission("system:user:list") + @GetMapping("/list") + public PagedDataVo list(SysUserBo user, PageRequest query) { + return userService.selectPageUserList(user, query); + } + + /** + * 导出用户列表 + */ + @Log(title = "用户管理", businessType = BusinessType.EXPORT) + @SaCheckPermission("system:user:export") + @PostMapping("/export") + public void export(SysUserBo user, HttpServletResponse response) { + List list = userService.selectUserList(user); + List listVo = MapstructUtils.convert(list, SysUserExportVo.class); + ExcelUtil.exportExcel(listVo, "用户数据", SysUserExportVo.class, response); + } + + /** + * 导入数据 + * + * @param file 导入文件 + * @param updateSupport 是否更新已存在数据 + */ + @Log(title = "用户管理", businessType = BusinessType.IMPORT) + @SaCheckPermission("system:user:import") + @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public void importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception { + ExcelResult result = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class, new SysUserImportListener(updateSupport)); + result.getAnalysis(); + } + + /** + * 获取导入模板 + */ + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) { + ExcelUtil.exportExcel(new ArrayList<>(), "用户数据", SysUserImportVo.class, response); + } + + /** + * 获取用户信息 + * + * @return 用户信息 + */ + @GetMapping("/getInfo") + public UserInfoVo getInfo() { + UserInfoVo userInfoVo = new UserInfoVo(); + LoginUser loginUser = LoginHelper.getLoginUser(); + if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) { + // 超级管理员 如果重新加载用户信息需清除动态租户 + TenantHelper.clearDynamic(); + } + SysUserVo user = userService.selectUserById(loginUser.getUserId()); + userInfoVo.setUser(user); + userInfoVo.setPermissions(loginUser.getMenuPermission()); + userInfoVo.setRoles(loginUser.getRolePermission()); + return userInfoVo; + } + + /** + * 根据用户编号获取详细信息 + * + * @param userId 用户ID + */ + @SaCheckPermission("system:user:query") + @GetMapping(value = {"/", "/{userId}"}) + public SysUserInfoVo getInfo(@PathVariable(value = "userId", required = false) Long userId) { + userService.checkUserDataScope(userId); + SysUserInfoVo userInfoVo = new SysUserInfoVo(); + List roles = roleService.selectRoleAll(); + userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin())); + userInfoVo.setPosts(postService.selectPostAll()); + if (ObjectUtil.isNotNull(userId)) { + SysUserVo sysUser = userService.selectUserById(userId); + userInfoVo.setUser(sysUser); + userInfoVo.setRoleIds(StreamUtils.toList(sysUser.getRoles(), SysRoleVo::getRoleId)); + userInfoVo.setPostIds(postService.selectPostListByUserId(userId)); + } + return userInfoVo; + } + + /** + * 新增用户 + */ + @SaCheckPermission("system:user:add") + @Log(title = "用户管理", businessType = BusinessType.INSERT) + @PostMapping + public void add(@Validated @RequestBody SysUserBo user) { + if (!userService.checkUserNameUnique(user)) { + fail("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { + fail("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); + } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { + fail("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + if (TenantHelper.isEnable()) { + if (!tenantService.checkAccountBalance(TenantHelper.getTenantId())) { + fail("当前租户下用户名额不足,请联系管理员"); + } + } + user.setPassword(BCrypt.hashpw(user.getPassword())); + userService.insertUser(user); + } + + /** + * 修改用户 + */ + @SaCheckPermission("system:user:edit") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping + public void edit(@Validated @RequestBody SysUserBo user) { + userService.checkUserAllowed(user.getUserId()); + userService.checkUserDataScope(user.getUserId()); + if (!userService.checkUserNameUnique(user)) { + fail("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { + fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { + fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + userService.updateUser(user); + } + + /** + * 删除用户 + * + * @param userIds 角色ID串 + */ + @SaCheckPermission("system:user:remove") + @Log(title = "用户管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public void remove(@PathVariable Long[] userIds) { + if (ArrayUtil.contains(userIds, LoginHelper.getUserId())) { + fail("当前用户不能删除"); + } + userService.deleteUserByIds(userIds); + } + + /** + * 重置密码 + */ + @SaCheckPermission("system:user:resetPwd") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/resetPwd") + public void resetPwd(@RequestBody SysUserBo user) { + userService.checkUserAllowed(user.getUserId()); + userService.checkUserDataScope(user.getUserId()); + user.setPassword(BCrypt.hashpw(user.getPassword())); + userService.resetUserPwd(user.getUserId(), user.getPassword()); + } + + /** + * 状态修改 + */ + @SaCheckPermission("system:user:edit") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public void changeStatus(@RequestBody SysUserBo user) { + userService.checkUserAllowed(user.getUserId()); + userService.checkUserDataScope(user.getUserId()); + userService.updateUserStatus(user.getUserId(), user.getStatus()); + } + + /** + * 根据用户编号获取授权角色 + * + * @param userId 用户ID + */ + @SaCheckPermission("system:user:query") + @GetMapping("/authRole/{userId}") + public SysUserInfoVo authRole(@PathVariable Long userId) { + SysUserVo user = userService.selectUserById(userId); + List roles = roleService.selectRolesByUserId(userId); + SysUserInfoVo userInfoVo = new SysUserInfoVo(); + userInfoVo.setUser(user); + userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin())); + return userInfoVo; + } + + /** + * 用户授权角色 + * + * @param userId 用户Id + * @param roleIds 角色ID串 + */ + @SaCheckPermission("system:user:edit") + @Log(title = "用户管理", businessType = BusinessType.GRANT) + @PutMapping("/authRole") + public void insertAuthRole(Long userId, Long[] roleIds) { + userService.checkUserDataScope(userId); + userService.insertUserAuth(userId, roleIds); + } + + /** + * 获取部门树列表 + */ + @SaCheckPermission("system:user:list") + @GetMapping("/deptTree") + public List> deptTree(SysDeptBo dept) { + return deptService.selectDeptTreeList(dept); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/SysCache.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/SysCache.java new file mode 100644 index 00000000..94bce752 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/SysCache.java @@ -0,0 +1,47 @@ +package cc.iotkit.system.domain; + +import cc.iotkit.common.utils.StringUtils; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 缓存信息 + * + * @author Lion Li + */ +@Data +@NoArgsConstructor +public class SysCache { + + /** + * 缓存名称 + */ + private String cacheName = ""; + + /** + * 缓存键名 + */ + private String cacheKey = ""; + + /** + * 缓存内容 + */ + private String cacheValue = ""; + + /** + * 备注 + */ + private String remark = ""; + + public SysCache(String cacheName, String remark) { + this.cacheName = cacheName; + this.remark = remark; + } + + public SysCache(String cacheName, String cacheKey, String cacheValue) { + this.cacheName = StringUtils.replace(cacheName, ":", ""); + this.cacheKey = StringUtils.replace(cacheKey, cacheName, ""); + this.cacheValue = cacheValue; + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/SysUserOnline.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/SysUserOnline.java new file mode 100644 index 00000000..abeb4538 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/SysUserOnline.java @@ -0,0 +1,54 @@ +package cc.iotkit.system.domain; + +import lombok.Data; + +/** + * 当前在线会话 + * + * @author Lion Li + */ + +@Data +public class SysUserOnline { + + /** + * 会话编号 + */ + private String tokenId; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 用户名称 + */ + private String userName; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地址 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 登录时间 + */ + private Long loginTime; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysConfigBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysConfigBo.java new file mode 100644 index 00000000..a7c0c42b --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysConfigBo.java @@ -0,0 +1,61 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysConfig; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; + +/** + * 参数配置业务对象 sys_config + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysConfig.class, reverseConvertGenerate = false) +public class SysConfigBo extends BaseEntity { + + /** + * 参数主键 + */ + @NotNull(message = "参数主键不能为空", groups = {EditGroup.class}) + private Long configId; + + /** + * 参数名称 + */ + @NotBlank(message = "参数名称不能为空", groups = {AddGroup.class, EditGroup.class}) + @Size(min = 0, max = 100, message = "参数名称不能超过{max}个字符") + private String configName; + + /** + * 参数键名 + */ + @NotBlank(message = "参数键名不能为空", groups = {AddGroup.class, EditGroup.class}) + @Size(min = 0, max = 100, message = "参数键名长度不能超过{max}个字符") + private String configKey; + + /** + * 参数键值 + */ + @NotBlank(message = "参数键值不能为空", groups = {AddGroup.class, EditGroup.class}) + @Size(min = 0, max = 500, message = "参数键值长度不能超过{max}个字符") + private String configValue; + + /** + * 系统内置(Y是 N否) + */ + private String configType; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysDeptBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysDeptBo.java new file mode 100644 index 00000000..4a411e2f --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysDeptBo.java @@ -0,0 +1,73 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysDept; +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 部门业务对象 sys_dept + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysDept.class, reverseConvertGenerate = false) +public class SysDeptBo extends BaseEntity { + + /** + * 部门id + */ + @NotNull(message = "部门id不能为空", groups = { EditGroup.class }) + private Long deptId; + + /** + * 父部门ID + */ + private Long parentId; + + /** + * 部门名称 + */ + @NotBlank(message = "部门名称不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 30, message = "部门名称长度不能超过{max}个字符") + private String deptName; + + /** + * 显示顺序 + */ + @NotNull(message = "显示顺序不能为空") + private Integer orderNum; + + /** + * 负责人 + */ + private String leader; + + /** + * 联系电话 + */ + @Size(min = 0, max = 11, message = "联系电话长度不能超过{max}个字符") + private String phone; + + /** + * 邮箱 + */ + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符") + private String email; + + /** + * 部门状态(0正常 1停用) + */ + private String status; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysDictDataBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysDictDataBo.java new file mode 100644 index 00000000..f06fc8e3 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysDictDataBo.java @@ -0,0 +1,88 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysDictData; +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 字典数据业务对象 sys_dict_data + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysDictData.class, reverseConvertGenerate = false) +public class SysDictDataBo extends BaseEntity { + + /** + * 字典编码 + */ + @NotNull(message = "字典编码不能为空", groups = { EditGroup.class }) + private Long dictCode; + + /** + * 字典排序 + */ + private Integer dictSort; + + /** + * 字典标签 + */ + @NotBlank(message = "字典标签不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 100, message = "字典标签长度不能超过{max}个字符") + private String dictLabel; + + /** + * 字典键值 + */ + @NotBlank(message = "字典键值不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 100, message = "字典键值长度不能超过{max}个字符") + private String dictValue; + + /** + * 字典类型 + */ + @NotBlank(message = "字典类型不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 100, message = "字典类型长度不能超过{max}个字符") + private String dictType; + + /** + * 样式属性(其他样式扩展) + */ + @Size(min = 0, max = 100, message = "样式属性长度不能超过{max}个字符") + private String cssClass; + + /** + * 表格回显样式 + */ + private String listClass; + + /** + * 是否默认(Y是 N否) + */ + private String isDefault; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 创建部门 + */ + private Long createDept; + + /** + * 备注 + */ + private String remark; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysDictTypeBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysDictTypeBo.java new file mode 100644 index 00000000..8e2d5f6a --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysDictTypeBo.java @@ -0,0 +1,58 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysDictType; +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 字典类型业务对象 sys_dict_type + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysDictType.class, reverseConvertGenerate = false) +public class SysDictTypeBo extends BaseEntity { + + /** + * 字典主键 + */ + @NotNull(message = "字典主键不能为空", groups = { EditGroup.class }) + private Long dictId; + + /** + * 字典名称 + */ + @NotBlank(message = "字典名称不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 100, message = "字典类型名称长度不能超过{max}个字符") + private String dictName; + + /** + * 字典类型 + */ + @NotBlank(message = "字典类型不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 100, message = "字典类型类型长度不能超过{max}个字符") + @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)") + private String dictType; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysLogininforBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysLogininforBo.java new file mode 100644 index 00000000..d54be394 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysLogininforBo.java @@ -0,0 +1,77 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.model.system.SysLogininfor; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 系统访问记录业务对象 sys_logininfor + * + * @author Michelle.Chung + */ + +@Data +@AutoMapper(target = SysLogininfor.class, reverseConvertGenerate = false) +public class SysLogininforBo { + + /** + * 访问ID + */ + private Long infoId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 用户账号 + */ + private String userName; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 登录状态(0成功 1失败) + */ + private String status; + + /** + * 提示消息 + */ + private String msg; + + /** + * 访问时间 + */ + private Date loginTime; + + /** + * 请求参数 + */ + private Map params = new HashMap<>(); + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysMenuBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysMenuBo.java new file mode 100644 index 00000000..e7844dbe --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysMenuBo.java @@ -0,0 +1,111 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysMenu; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 菜单权限业务对象 sys_menu + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysMenu.class, reverseConvertGenerate = false) +public class SysMenuBo extends BaseEntity { + + /** + * 菜单ID + */ + @NotNull(message = "菜单ID不能为空", groups = { EditGroup.class }) + private Long menuId; + + /** + * 父菜单ID + */ + private Long parentId; + + /** + * 菜单名称 + */ + @NotBlank(message = "菜单名称不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 50, message = "菜单名称长度不能超过{max}个字符") + private String menuName; + + /** + * 显示顺序 + */ + @NotNull(message = "显示顺序不能为空", groups = { AddGroup.class, EditGroup.class }) + private Integer orderNum; + + /** + * 路由地址 + */ + @Size(min = 0, max = 200, message = "路由地址不能超过{max}个字符") + private String path; + + /** + * 组件路径 + */ + @Size(min = 0, max = 200, message = "组件路径不能超过{max}个字符") + private String component; + + /** + * 路由参数 + */ + private String queryParam; + + /** + * 是否为外链(0是 1否) + */ + private String isFrame; + + /** + * 是否缓存(0缓存 1不缓存) + */ + private String isCache; + + /** + * 菜单类型(M目录 C菜单 F按钮) + */ + @NotBlank(message = "菜单类型不能为空", groups = { AddGroup.class, EditGroup.class }) + private String menuType; + + /** + * 显示状态(0显示 1隐藏) + */ + private String visible; + + /** + * 菜单状态(0正常 1停用) + */ + private String status; + + /** + * 权限标识 + */ + @JsonInclude(JsonInclude.Include.NON_NULL) + @Size(min = 0, max = 100, message = "权限标识长度不能超过{max}个字符") + private String perms; + + /** + * 菜单图标 + */ + private String icon; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysNoticeBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysNoticeBo.java new file mode 100644 index 00000000..34843847 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysNoticeBo.java @@ -0,0 +1,63 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysNotice; +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 通知公告业务对象 sys_notice + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysNotice.class, reverseConvertGenerate = false) +public class SysNoticeBo extends BaseEntity { + + /** + * 公告ID + */ + @NotNull(message = "公告ID不能为空", groups = { EditGroup.class }) + private Long noticeId; + + /** + * 公告标题 + */ + @NotBlank(message = "公告标题不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 50, message = "公告标题不能超过{max}个字符") + private String noticeTitle; + + /** + * 公告类型(1通知 2公告) + */ + private String noticeType; + + /** + * 公告内容 + */ + private String noticeContent; + + /** + * 公告状态(0正常 1关闭) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 创建人名称 + */ + private String createByName; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysOperLogBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysOperLogBo.java new file mode 100644 index 00000000..dcada022 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysOperLogBo.java @@ -0,0 +1,127 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.log.event.OperLogEvent; +import cc.iotkit.model.system.SysOperLog; +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import lombok.Data; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 操作日志记录业务对象 sys_oper_log + * + * @author Michelle.Chung + * @date 2023-02-07 + */ + +@Data +@AutoMappers({ + @AutoMapper(target = SysOperLog.class, reverseConvertGenerate = false), + @AutoMapper(target = OperLogEvent.class) +}) +public class SysOperLogBo { + + /** + * 日志主键 + */ + private Long operId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 模块标题 + */ + private String title; + + /** + * 业务类型(0其它 1新增 2修改 3删除) + */ + private Integer businessType; + + /** + * 业务类型数组 + */ + private Integer[] businessTypes; + + /** + * 方法名称 + */ + private String method; + + /** + * 请求方式 + */ + private String requestMethod; + + /** + * 操作类别(0其它 1后台用户 2手机端用户) + */ + private Integer operatorType; + + /** + * 操作人员 + */ + private String operName; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 请求URL + */ + private String operUrl; + + /** + * 主机地址 + */ + private String operIp; + + /** + * 操作地点 + */ + private String operLocation; + + /** + * 请求参数 + */ + private String operParam; + + /** + * 返回参数 + */ + private String jsonResult; + + /** + * 操作状态(0正常 1异常) + */ + private Integer status; + + /** + * 错误消息 + */ + private String errorMsg; + + /** + * 操作时间 + */ + private Date operTime; + + /** + * 消耗时间 + */ + private Long costTime; + + /** + * 请求参数 + */ + private Map params = new HashMap<>(); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysOssBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysOssBo.java new file mode 100644 index 00000000..aded51b5 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysOssBo.java @@ -0,0 +1,49 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.model.system.SysOss; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * OSS对象存储分页查询对象 sys_oss + * + * @author Lion Li + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysOss.class, reverseConvertGenerate = false) +public class SysOssBo extends BaseEntity { + + /** + * ossId + */ + private Long ossId; + + /** + * 文件名 + */ + private String fileName; + + /** + * 原名 + */ + private String originalName; + + /** + * 文件后缀名 + */ + private String fileSuffix; + + /** + * URL地址 + */ + private String url; + + /** + * 服务商 + */ + private String service; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysOssConfigBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysOssConfigBo.java new file mode 100644 index 00000000..4928a9dd --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysOssConfigBo.java @@ -0,0 +1,109 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysOssConfig; +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 对象存储配置业务对象 sys_oss_config + * + * @author Lion Li + * @author 孤舟烟雨 + * @date 2021-08-13 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysOssConfig.class, reverseConvertGenerate = false) +public class SysOssConfigBo extends BaseEntity { + + /** + * 主建 + */ + @NotNull(message = "主建不能为空", groups = {EditGroup.class}) + private Long ossConfigId; + + /** + * 配置key + */ + @NotBlank(message = "配置key不能为空", groups = {AddGroup.class, EditGroup.class}) + @Size(min = 2, max = 100, message = "configKey长度必须介于{min}和{max} 之间") + private String configKey; + + /** + * accessKey + */ + @NotBlank(message = "accessKey不能为空", groups = {AddGroup.class, EditGroup.class}) + @Size(min = 2, max = 100, message = "accessKey长度必须介于{min}和{max} 之间") + private String accessKey; + + /** + * 秘钥 + */ + @NotBlank(message = "secretKey不能为空", groups = {AddGroup.class, EditGroup.class}) + @Size(min = 2, max = 100, message = "secretKey长度必须介于{min}和{max} 之间") + private String secretKey; + + /** + * 桶名称 + */ + @NotBlank(message = "桶名称不能为空", groups = {AddGroup.class, EditGroup.class}) + @Size(min = 2, max = 100, message = "bucketName长度必须介于{min}和{max}之间") + private String bucketName; + + /** + * 前缀 + */ + private String prefix; + + /** + * 访问站点 + */ + @NotBlank(message = "访问站点不能为空", groups = {AddGroup.class, EditGroup.class}) + @Size(min = 2, max = 100, message = "endpoint长度必须介于{min}和{max}之间") + private String endpoint; + + /** + * 自定义域名 + */ + private String domain; + + /** + * 是否https(Y=是,N=否) + */ + private String isHttps; + + /** + * 是否默认(0=是,1=否) + */ + private String status; + + /** + * 域 + */ + private String region; + + /** + * 扩展字段 + */ + private String ext1; + + /** + * 备注 + */ + private String remark; + + /** + * 桶权限类型(0private 1public 2custom) + */ + @NotBlank(message = "桶权限类型不能为空", groups = {AddGroup.class, EditGroup.class}) + private String accessPolicy; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysPostBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysPostBo.java new file mode 100644 index 00000000..713af47a --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysPostBo.java @@ -0,0 +1,62 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysPost; +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 岗位信息业务对象 sys_post + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysPost.class, reverseConvertGenerate = false) +public class SysPostBo extends BaseEntity { + + /** + * 岗位ID + */ + @NotNull(message = "岗位ID不能为空", groups = { EditGroup.class }) + private Long postId; + + /** + * 岗位编码 + */ + @NotBlank(message = "岗位编码不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 64, message = "岗位编码长度不能超过{max}个字符") + private String postCode; + + /** + * 岗位名称 + */ + @NotBlank(message = "岗位名称不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 50, message = "岗位名称长度不能超过{max}个字符") + private String postName; + + /** + * 显示顺序 + */ + @NotNull(message = "显示顺序不能为空", groups = { AddGroup.class, EditGroup.class }) + private Integer postSort; + + /** + * 状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysRoleBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysRoleBo.java new file mode 100644 index 00000000..b77025f6 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysRoleBo.java @@ -0,0 +1,97 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.constant.UserConstants; +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysRole; +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 角色信息业务对象 sys_role + * + * @author Michelle.Chung + */ + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysRole.class, reverseConvertGenerate = false) +public class SysRoleBo extends BaseEntity { + + /** + * 角色ID + */ + @NotNull(message = "角色ID不能为空", groups = { EditGroup.class }) + private Long roleId; + + /** + * 角色名称 + */ + @NotBlank(message = "角色名称不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 30, message = "角色名称长度不能超过{max}个字符") + private String roleName; + + /** + * 角色权限字符串 + */ + @NotBlank(message = "角色权限字符串不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(min = 0, max = 100, message = "权限字符长度不能超过{max}个字符") + private String roleKey; + + /** + * 显示顺序 + */ + @NotNull(message = "显示顺序不能为空", groups = { AddGroup.class, EditGroup.class }) + private Integer roleSort; + + /** + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) + */ + private String dataScope; + + /** + * 菜单树选择项是否关联显示 + */ + private Boolean menuCheckStrictly; + + /** + * 部门树选择项是否关联显示 + */ + private Boolean deptCheckStrictly; + + /** + * 角色状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 菜单组 + */ + private Long[] menuIds; + + /** + * 部门组(数据权限) + */ + private Long[] deptIds; + + public SysRoleBo(Long roleId) { + this.roleId = roleId; + } + + public boolean isSuperAdmin() { + return UserConstants.SUPER_ADMIN_ID.equals(this.roleId); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysTenantBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysTenantBo.java new file mode 100644 index 00000000..e5ff5007 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysTenantBo.java @@ -0,0 +1,113 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysTenant; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; + +import java.util.Date; + +/** + * 租户业务对象 sys_tenant + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysTenant.class, reverseConvertGenerate = false) +public class SysTenantBo extends BaseEntity { + + /** + * id + */ + @NotNull(message = "id不能为空", groups = { EditGroup.class }) + private Long id; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 联系人 + */ + @NotBlank(message = "联系人不能为空", groups = { AddGroup.class, EditGroup.class }) + private String contactUserName; + + /** + * 联系电话 + */ + @NotBlank(message = "联系电话不能为空", groups = { AddGroup.class, EditGroup.class }) + private String contactPhone; + + /** + * 企业名称 + */ + @NotBlank(message = "企业名称不能为空", groups = { AddGroup.class, EditGroup.class }) + private String companyName; + + /** + * 用户名(创建系统用户) + */ + @NotBlank(message = "用户名不能为空", groups = { AddGroup.class }) + private String username; + + /** + * 密码(创建系统用户) + */ + @NotBlank(message = "密码不能为空", groups = { AddGroup.class }) + private String password; + + /** + * 统一社会信用代码 + */ + private String licenseNumber; + + /** + * 地址 + */ + private String address; + + /** + * 域名 + */ + private String domain; + + /** + * 企业简介 + */ + private String intro; + + /** + * 备注 + */ + private String remark; + + /** + * 租户套餐编号 + */ + @NotNull(message = "租户套餐不能为空", groups = { AddGroup.class }) + private Long packageId; + + /** + * 过期时间 + */ + private Date expireTime; + + /** + * 用户数量(-1不限制) + */ + private Long accountCount; + + /** + * 租户状态(0正常 1停用) + */ + private String status; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysTenantPackageBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysTenantPackageBo.java new file mode 100644 index 00000000..06696453 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysTenantPackageBo.java @@ -0,0 +1,58 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.common.validate.AddGroup; +import cc.iotkit.common.validate.EditGroup; +import cc.iotkit.model.system.SysTenantPackage; +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; + +/** + * 租户套餐业务对象 sys_tenant_package + * + * @author Michelle.Chung + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysTenantPackage.class, reverseConvertGenerate = false) +public class SysTenantPackageBo extends BaseEntity { + + /** + * 租户套餐id + */ + @NotNull(message = "租户套餐id不能为空", groups = {EditGroup.class}) + private Long packageId; + + /** + * 套餐名称 + */ + @NotBlank(message = "套餐名称不能为空", groups = {AddGroup.class, EditGroup.class}) + private String packageName; + + /** + * 关联菜单id + */ + @AutoMapping(target = "menuIds", expression = "java(org.dromara.common.core.utils.StringUtils.join(source.getMenuIds(), \",\"))") + private Long[] menuIds; + + /** + * 备注 + */ + private String remark; + + /** + * 菜单树选择项是否关联显示 + */ + private Boolean menuCheckStrictly; + + /** + * 状态(0正常 1停用) + */ + private String status; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysUserBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysUserBo.java new file mode 100644 index 00000000..e797810e --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysUserBo.java @@ -0,0 +1,110 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.constant.UserConstants; +import cc.iotkit.common.domain.model.BaseEntity; +import cc.iotkit.model.system.SysUser; +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 用户信息业务对象 sys_user + * + * @author Michelle.Chung + */ + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SysUser.class, reverseConvertGenerate = false) +public class SysUserBo extends BaseEntity { + + /** + * 用户ID + */ + private Long userId; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户账号 + */ + @NotBlank(message = "用户账号不能为空") + @Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符") + private String userName; + + /** + * 用户昵称 + */ + @Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符") + private String nickName; + + /** + * 用户类型(sys_user系统用户) + */ + private String userType; + + /** + * 用户邮箱 + */ + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符") + private String email; + + /** + * 手机号码 + */ + private String phonenumber; + + /** + * 用户性别(0男 1女 2未知) + */ + private String sex; + + /** + * 密码 + */ + private String password; + + /** + * 帐号状态(0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 角色组 + */ + @Size(min = 1, message = "用户角色不能为空") + private Long[] roleIds; + + /** + * 岗位组 + */ + private Long[] postIds; + + /** + * 数据权限 当前角色ID + */ + private Long roleId; + + public SysUserBo(Long userId) { + this.userId = userId; + } + + public boolean isSuperAdmin() { + return UserConstants.SUPER_ADMIN_ID.equals(this.userId); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysUserProfileBo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysUserProfileBo.java new file mode 100644 index 00000000..ab3186a0 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/bo/SysUserProfileBo.java @@ -0,0 +1,49 @@ +package cc.iotkit.system.domain.bo; + +import cc.iotkit.common.domain.model.BaseEntity; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 个人信息业务处理 + * + * @author Michelle.Chung + */ + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class SysUserProfileBo extends BaseEntity { + + /** + * 用户ID + */ + private Long userId; + + /** + * 用户昵称 + */ + @Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符") + private String nickName; + + /** + * 用户邮箱 + */ + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符") + private String email; + + /** + * 手机号码 + */ + private String phonenumber; + + /** + * 用户性别(0男 1女 2未知) + */ + private String sex; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/AvatarVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/AvatarVo.java new file mode 100644 index 00000000..6538adad --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/AvatarVo.java @@ -0,0 +1,18 @@ +package cc.iotkit.system.domain.vo; + +import lombok.Data; + +/** + * 用户头像信息 + * + * @author Michelle.Chung + */ +@Data +public class AvatarVo { + + /** + * 头像地址 + */ + private String imgUrl; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/CacheListInfoVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/CacheListInfoVo.java new file mode 100644 index 00000000..23d6a82c --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/CacheListInfoVo.java @@ -0,0 +1,23 @@ +package cc.iotkit.system.domain.vo; + +import lombok.Data; + +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * 缓存监控列表信息 + * + * @author Michelle.Chung + */ +@Data +public class CacheListInfoVo { + + private Properties info; + + private Long dbSize; + + private List> commandStats; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/DeptTreeSelectVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/DeptTreeSelectVo.java new file mode 100644 index 00000000..1248e54b --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/DeptTreeSelectVo.java @@ -0,0 +1,26 @@ +package cc.iotkit.system.domain.vo; + +import cn.hutool.core.lang.tree.Tree; +import lombok.Data; + +import java.util.List; + +/** + * 角色部门列表树信息 + * + * @author Michelle.Chung + */ +@Data +public class DeptTreeSelectVo { + + /** + * 选中部门列表 + */ + private List checkedKeys; + + /** + * 下拉树结构列表 + */ + private List> depts; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/MenuTreeSelectVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/MenuTreeSelectVo.java new file mode 100644 index 00000000..293f22b3 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/MenuTreeSelectVo.java @@ -0,0 +1,26 @@ +package cc.iotkit.system.domain.vo; + +import cn.hutool.core.lang.tree.Tree; +import lombok.Data; + +import java.util.List; + +/** + * 角色菜单列表树信息 + * + * @author Michelle.Chung + */ +@Data +public class MenuTreeSelectVo { + + /** + * 选中菜单列表 + */ + private List checkedKeys; + + /** + * 菜单下拉树结构列表 + */ + private List> menus; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/MetaVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/MetaVo.java new file mode 100644 index 00000000..37d4b94f --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/MetaVo.java @@ -0,0 +1,61 @@ +package cc.iotkit.system.domain.vo; + +import org.dromara.common.core.utils.StringUtils; +import lombok.Data; + +/** + * 路由显示信息 + * + * @author ruoyi + */ + +@Data +public class MetaVo { + + /** + * 设置该路由在侧边栏和面包屑中展示的名字 + */ + private String title; + + /** + * 设置该路由的图标,对应路径src/assets/icons/svg + */ + private String icon; + + /** + * 设置为true,则不会被 缓存 + */ + private boolean noCache; + + /** + * 内链地址(http(s)://开头) + */ + private String link; + + public MetaVo(String title, String icon) { + this.title = title; + this.icon = icon; + } + + public MetaVo(String title, String icon, boolean noCache) { + this.title = title; + this.icon = icon; + this.noCache = noCache; + } + + public MetaVo(String title, String icon, String link) { + this.title = title; + this.icon = icon; + this.link = link; + } + + public MetaVo(String title, String icon, boolean noCache, String link) { + this.title = title; + this.icon = icon; + this.noCache = noCache; + if (StringUtils.ishttp(link)) { + this.link = link; + } + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/ProfileVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/ProfileVo.java new file mode 100644 index 00000000..097cb7ab --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/ProfileVo.java @@ -0,0 +1,29 @@ +package cc.iotkit.system.domain.vo; + +import lombok.Data; + +/** + * 用户个人信息 + * + * @author Michelle.Chung + */ +@Data +public class ProfileVo { + + /** + * 用户信息 + */ + private SysUserVo user; + + /** + * 用户所属角色组 + */ + private String roleGroup; + + /** + * 用户所属岗位组 + */ + private String postGroup; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/RouterVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/RouterVo.java new file mode 100644 index 00000000..45023b91 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/RouterVo.java @@ -0,0 +1,62 @@ +package cc.iotkit.system.domain.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; + +import java.util.List; + +/** + * 路由配置信息 + * + * @author Lion Li + */ +@Data +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class RouterVo { + + /** + * 路由名字 + */ + private String name; + + /** + * 路由地址 + */ + private String path; + + /** + * 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现 + */ + private boolean hidden; + + /** + * 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + */ + private String redirect; + + /** + * 组件地址 + */ + private String component; + + /** + * 路由参数:如 {"id": 1, "name": "ry"} + */ + private String query; + + /** + * 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + */ + private Boolean alwaysShow; + + /** + * 其他元素 + */ + private MetaVo meta; + + /** + * 子路由 + */ + private List children; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysConfigVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysConfigVo.java new file mode 100644 index 00000000..28aef620 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysConfigVo.java @@ -0,0 +1,69 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.common.excel.annotation.ExcelDictFormat; +import cc.iotkit.common.excel.convert.ExcelDictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import cc.iotkit.system.domain.SysConfig; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + + +/** + * 参数配置视图对象 sys_config + * + * @author Michelle.Chung + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysConfig.class) +public class SysConfigVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 参数主键 + */ + @ExcelProperty(value = "参数主键") + private Long configId; + + /** + * 参数名称 + */ + @ExcelProperty(value = "参数名称") + private String configName; + + /** + * 参数键名 + */ + @ExcelProperty(value = "参数键名") + private String configKey; + + /** + * 参数键值 + */ + @ExcelProperty(value = "参数键值") + private String configValue; + + /** + * 系统内置(Y是 N否) + */ + @ExcelProperty(value = "系统内置", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_yes_no") + private String configType; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysDeptVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysDeptVo.java new file mode 100644 index 00000000..05b697d1 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysDeptVo.java @@ -0,0 +1,91 @@ +package cc.iotkit.system.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import cc.iotkit.system.domain.SysDept; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 部门视图对象 sys_dept + * + * @author Michelle.Chung + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysDept.class) +public class SysDeptVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 部门id + */ + @ExcelProperty(value = "部门id") + private Long deptId; + + /** + * 父部门id + */ + private Long parentId; + + /** + * 父部门名称 + */ + private String parentName; + + /** + * 祖级列表 + */ + private String ancestors; + + /** + * 部门名称 + */ + @ExcelProperty(value = "部门名称") + private String deptName; + + /** + * 显示顺序 + */ + private Integer orderNum; + + /** + * 负责人 + */ + @ExcelProperty(value = "负责人") + private String leader; + + /** + * 联系电话 + */ + @ExcelProperty(value = "联系电话") + private String phone; + + /** + * 邮箱 + */ + @ExcelProperty(value = "邮箱") + private String email; + + /** + * 部门状态(0正常 1停用) + */ + @ExcelProperty(value = "部门状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_normal_disable") + private String status; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysDictDataVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysDictDataVo.java new file mode 100644 index 00000000..968a3d6b --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysDictDataVo.java @@ -0,0 +1,95 @@ +package cc.iotkit.system.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import cc.iotkit.system.domain.SysDictData; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + +/** + * 字典数据视图对象 sys_dict_data + * + * @author Michelle.Chung + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysDictData.class) +public class SysDictDataVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 字典编码 + */ + @ExcelProperty(value = "字典编码") + private Long dictCode; + + /** + * 字典排序 + */ + @ExcelProperty(value = "字典排序") + private Integer dictSort; + + /** + * 字典标签 + */ + @ExcelProperty(value = "字典标签") + private String dictLabel; + + /** + * 字典键值 + */ + @ExcelProperty(value = "字典键值") + private String dictValue; + + /** + * 字典类型 + */ + @ExcelProperty(value = "字典类型") + private String dictType; + + /** + * 样式属性(其他样式扩展) + */ + private String cssClass; + + /** + * 表格回显样式 + */ + private String listClass; + + /** + * 是否默认(Y是 N否) + */ + @ExcelProperty(value = "是否默认", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_yes_no") + private String isDefault; + + /** + * 状态(0正常 1停用) + */ + @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_normal_disable") + private String status; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysDictTypeVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysDictTypeVo.java new file mode 100644 index 00000000..c7c1d5c3 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysDictTypeVo.java @@ -0,0 +1,66 @@ +package cc.iotkit.system.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import cc.iotkit.system.domain.SysDictType; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + +/** + * 字典类型视图对象 sys_dict_type + * + * @author Michelle.Chung + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysDictType.class) +public class SysDictTypeVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 字典主键 + */ + @ExcelProperty(value = "字典主键") + private Long dictId; + + /** + * 字典名称 + */ + @ExcelProperty(value = "字典名称") + private String dictName; + + /** + * 字典类型 + */ + @ExcelProperty(value = "字典类型") + private String dictType; + + /** + * 状态(0正常 1停用) + */ + @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_normal_disable") + private String status; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysLogininforVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysLogininforVo.java new file mode 100644 index 00000000..51169f4d --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysLogininforVo.java @@ -0,0 +1,93 @@ +package cc.iotkit.system.domain.vo; + +import java.util.Date; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import cc.iotkit.system.domain.SysLogininfor; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + + + +/** + * 系统访问记录视图对象 sys_logininfor + * + * @author Michelle.Chung + * @date 2023-02-07 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysLogininfor.class) +public class SysLogininforVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 访问ID + */ + @ExcelProperty(value = "序号") + private Long infoId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 用户账号 + */ + @ExcelProperty(value = "用户账号") + private String userName; + + /** + * 登录状态(0成功 1失败) + */ + @ExcelProperty(value = "登录状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_common_status") + private String status; + + /** + * 登录IP地址 + */ + @ExcelProperty(value = "登录地址") + private String ipaddr; + + /** + * 登录地点 + */ + @ExcelProperty(value = "登录地点") + private String loginLocation; + + /** + * 浏览器类型 + */ + @ExcelProperty(value = "浏览器") + private String browser; + + /** + * 操作系统 + */ + @ExcelProperty(value = "操作系统") + private String os; + + + /** + * 提示消息 + */ + @ExcelProperty(value = "提示消息") + private String msg; + + /** + * 访问时间 + */ + @ExcelProperty(value = "访问时间") + private Date loginTime; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysMenuVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysMenuVo.java new file mode 100644 index 00000000..78c5f906 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysMenuVo.java @@ -0,0 +1,116 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.system.domain.SysMenu; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + + +/** + * 菜单权限视图对象 sys_menu + * + * @author Michelle.Chung + */ +@Data +@AutoMapper(target = SysMenu.class) +public class SysMenuVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 菜单ID + */ + private Long menuId; + + /** + * 菜单名称 + */ + private String menuName; + + /** + * 父菜单ID + */ + private Long parentId; + + /** + * 显示顺序 + */ + private Integer orderNum; + + /** + * 路由地址 + */ + private String path; + + /** + * 组件路径 + */ + private String component; + + /** + * 路由参数 + */ + private String queryParam; + + /** + * 是否为外链(0是 1否) + */ + private String isFrame; + + /** + * 是否缓存(0缓存 1不缓存) + */ + private String isCache; + + /** + * 菜单类型(M目录 C菜单 F按钮) + */ + private String menuType; + + /** + * 显示状态(0显示 1隐藏) + */ + private String visible; + + /** + * 菜单状态(0正常 1停用) + */ + private String status; + + /** + * 权限标识 + */ + private String perms; + + /** + * 菜单图标 + */ + private String icon; + + /** + * 创建部门 + */ + private Long createDept; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 子菜单 + */ + private List children = new ArrayList<>(); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysNoticeVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysNoticeVo.java new file mode 100644 index 00000000..e969ee46 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysNoticeVo.java @@ -0,0 +1,73 @@ +package cc.iotkit.system.domain.vo; + +import org.dromara.common.translation.annotation.Translation; +import org.dromara.common.translation.constant.TransConstant; +import cc.iotkit.system.domain.SysNotice; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + + +/** + * 通知公告视图对象 sys_notice + * + * @author Michelle.Chung + */ +@Data +@AutoMapper(target = SysNotice.class) +public class SysNoticeVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 公告ID + */ + private Long noticeId; + + /** + * 公告标题 + */ + private String noticeTitle; + + /** + * 公告类型(1通知 2公告) + */ + private String noticeType; + + /** + * 公告内容 + */ + private String noticeContent; + + /** + * 公告状态(0正常 1关闭) + */ + private String status; + + /** + * 备注 + */ + private String remark; + + /** + * 创建者 + */ + private Long createBy; + + /** + * 创建人名称 + */ + @Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy") + private String createByName; + + /** + * 创建时间 + */ + private Date createTime; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOperLogVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOperLogVo.java new file mode 100644 index 00000000..0a1d3845 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOperLogVo.java @@ -0,0 +1,141 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.common.excel.annotation.ExcelDictFormat; +import cc.iotkit.common.excel.convert.ExcelDictConvert; +import cc.iotkit.model.system.SysOperLog; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + + +/** + * 操作日志记录视图对象 sys_oper_log + * + * @author Michelle.Chung + * @date 2023-02-07 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysOperLog.class) +public class SysOperLogVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 日志主键 + */ + @ExcelProperty(value = "日志主键") + private Long operId; + + /** + * 租户编号 + */ + private String tenantId; + + /** + * 模块标题 + */ + @ExcelProperty(value = "操作模块") + private String title; + + /** + * 业务类型(0其它 1新增 2修改 3删除) + */ + @ExcelProperty(value = "业务类型", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_oper_type") + private Integer businessType; + + /** + * 业务类型数组 + */ + private Integer[] businessTypes; + + /** + * 方法名称 + */ + @ExcelProperty(value = "请求方法") + private String method; + + /** + * 请求方式 + */ + @ExcelProperty(value = "请求方式") + private String requestMethod; + + /** + * 操作类别(0其它 1后台用户 2手机端用户) + */ + @ExcelProperty(value = "操作类别", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=其它,1=后台用户,2=手机端用户") + private Integer operatorType; + + /** + * 操作人员 + */ + @ExcelProperty(value = "操作人员") + private String operName; + + /** + * 部门名称 + */ + @ExcelProperty(value = "部门名称") + private String deptName; + + /** + * 请求URL + */ + @ExcelProperty(value = "请求地址") + private String operUrl; + + /** + * 主机地址 + */ + @ExcelProperty(value = "操作地址") + private String operIp; + + /** + * 操作地点 + */ + @ExcelProperty(value = "操作地点") + private String operLocation; + + /** + * 请求参数 + */ + @ExcelProperty(value = "请求参数") + private String operParam; + + /** + * 返回参数 + */ + @ExcelProperty(value = "返回参数") + private String jsonResult; + + /** + * 操作状态(0正常 1异常) + */ + @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_common_status") + private Integer status; + + /** + * 错误消息 + */ + @ExcelProperty(value = "错误消息") + private String errorMsg; + + /** + * 操作时间 + */ + @ExcelProperty(value = "操作时间") + private Date operTime; + + /** + * 消耗时间 + */ + @ExcelProperty(value = "消耗时间") + private Long costTime; +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOssConfigVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOssConfigVo.java new file mode 100644 index 00000000..fafe04aa --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOssConfigVo.java @@ -0,0 +1,94 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.model.system.SysOssConfig; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; + + +/** + * 对象存储配置视图对象 sys_oss_config + * + * @author Lion Li + * @author 孤舟烟雨 + * @date 2021-08-13 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysOssConfig.class) +public class SysOssConfigVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 主建 + */ + private Long ossConfigId; + + /** + * 配置key + */ + private String configKey; + + /** + * accessKey + */ + private String accessKey; + + /** + * 秘钥 + */ + private String secretKey; + + /** + * 桶名称 + */ + private String bucketName; + + /** + * 前缀 + */ + private String prefix; + + /** + * 访问站点 + */ + private String endpoint; + + /** + * 自定义域名 + */ + private String domain; + + /** + * 是否https(Y=是,N=否) + */ + private String isHttps; + + /** + * 域 + */ + private String region; + + /** + * 是否默认(0=是,1=否) + */ + private String status; + + /** + * 扩展字段 + */ + private String ext1; + + /** + * 备注 + */ + private String remark; + + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOssUploadVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOssUploadVo.java new file mode 100644 index 00000000..b1bde186 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOssUploadVo.java @@ -0,0 +1,28 @@ +package cc.iotkit.system.domain.vo; + +import lombok.Data; + +/** + * 上传对象信息 + * + * @author Michelle.Chung + */ +@Data +public class SysOssUploadVo { + + /** + * URL地址 + */ + private String url; + + /** + * 文件名 + */ + private String fileName; + + /** + * 对象存储主键 + */ + private String ossId; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOssVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOssVo.java new file mode 100644 index 00000000..bf36f0ba --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysOssVo.java @@ -0,0 +1,66 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.model.system.SysOss; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * OSS对象存储视图对象 sys_oss + * + * @author Lion Li + */ +@Data +@AutoMapper(target = SysOss.class) +public class SysOssVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 对象存储主键 + */ + private Long ossId; + + /** + * 文件名 + */ + private String fileName; + + /** + * 原名 + */ + private String originalName; + + /** + * 文件后缀名 + */ + private String fileSuffix; + + /** + * URL地址 + */ + private String url; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 上传人 + */ + private Long createBy; + + /** + * 上传人名称 + */ + private String createByName; + + /** + * 服务商 + */ + private String service; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysPostVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysPostVo.java new file mode 100644 index 00000000..96753dc8 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysPostVo.java @@ -0,0 +1,70 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.common.excel.annotation.ExcelDictFormat; +import cc.iotkit.common.excel.convert.ExcelDictConvert; +import cc.iotkit.model.system.SysPost; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + + + +/** + * 岗位信息视图对象 sys_post + * + * @author Michelle.Chung + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysPost.class) +public class SysPostVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 岗位ID + */ + @ExcelProperty(value = "岗位序号") + private Long postId; + + /** + * 岗位编码 + */ + @ExcelProperty(value = "岗位编码") + private String postCode; + + /** + * 岗位名称 + */ + @ExcelProperty(value = "岗位名称") + private String postName; + + /** + * 显示顺序 + */ + @ExcelProperty(value = "岗位排序") + private Integer postSort; + + /** + * 状态(0正常 1停用) + */ + @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_normal_disable") + private String status; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysRoleVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysRoleVo.java new file mode 100644 index 00000000..44a847fb --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysRoleVo.java @@ -0,0 +1,97 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.common.constant.UserConstants; +import cc.iotkit.common.excel.annotation.ExcelDictFormat; +import cc.iotkit.common.excel.convert.ExcelDictConvert; +import cc.iotkit.model.system.SysRole; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 角色信息视图对象 sys_role + * + * @author Michelle.Chung + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysRole.class) +public class SysRoleVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 角色ID + */ + @ExcelProperty(value = "角色序号") + private Long roleId; + + /** + * 角色名称 + */ + @ExcelProperty(value = "角色名称") + private String roleName; + + /** + * 角色权限字符串 + */ + @ExcelProperty(value = "角色权限") + private String roleKey; + + /** + * 显示顺序 + */ + @ExcelProperty(value = "角色排序") + private Integer roleSort; + + /** + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) + */ + @ExcelProperty(value = "数据范围", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限") + private String dataScope; + + /** + * 菜单树选择项是否关联显示 + */ + @ExcelProperty(value = "菜单树选择项是否关联显示") + private Boolean menuCheckStrictly; + + /** + * 部门树选择项是否关联显示 + */ + @ExcelProperty(value = "部门树选择项是否关联显示") + private Boolean deptCheckStrictly; + + /** + * 角色状态(0正常 1停用) + */ + @ExcelProperty(value = "角色状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_normal_disable") + private String status; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + + /** + * 用户是否存在此角色标识 默认不存在 + */ + private boolean flag = false; + + public boolean isSuperAdmin() { + return UserConstants.SUPER_ADMIN_ID.equals(this.roleId); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysTenantPackageVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysTenantPackageVo.java new file mode 100644 index 00000000..414bd074 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysTenantPackageVo.java @@ -0,0 +1,63 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.common.excel.annotation.ExcelDictFormat; +import cc.iotkit.common.excel.convert.ExcelDictConvert; +import cc.iotkit.model.system.SysTenantPackage; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; + + +/** + * 租户套餐视图对象 sys_tenant_package + * + * @author Michelle.Chung + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysTenantPackage.class) +public class SysTenantPackageVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 租户套餐id + */ + @ExcelProperty(value = "租户套餐id") + private Long packageId; + + /** + * 套餐名称 + */ + @ExcelProperty(value = "套餐名称") + private String packageName; + + /** + * 关联菜单id + */ + @ExcelProperty(value = "关联菜单id") + private String menuIds; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 菜单树选择项是否关联显示 + */ + @ExcelProperty(value = "菜单树选择项是否关联显示") + private Boolean menuCheckStrictly; + + /** + * 状态(0正常 1停用) + */ + @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=正常,1=停用") + private String status; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysTenantVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysTenantVo.java new file mode 100644 index 00000000..0c92d227 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysTenantVo.java @@ -0,0 +1,113 @@ +package cc.iotkit.system.domain.vo; + +import java.util.Date; + +import cc.iotkit.common.excel.annotation.ExcelDictFormat; +import cc.iotkit.common.excel.convert.ExcelDictConvert; +import cc.iotkit.model.system.SysTenant; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; + + +/** + * 租户视图对象 sys_tenant + * + * @author Michelle.Chung + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysTenant.class) +public class SysTenantVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * id + */ + @ExcelProperty(value = "id") + private Long id; + + /** + * 租户编号 + */ + @ExcelProperty(value = "租户编号") + private String tenantId; + + /** + * 联系人 + */ + @ExcelProperty(value = "联系人") + private String contactUserName; + + /** + * 联系电话 + */ + @ExcelProperty(value = "联系电话") + private String contactPhone; + + /** + * 企业名称 + */ + @ExcelProperty(value = "企业名称") + private String companyName; + + /** + * 统一社会信用代码 + */ + @ExcelProperty(value = "统一社会信用代码") + private String licenseNumber; + + /** + * 地址 + */ + @ExcelProperty(value = "地址") + private String address; + + /** + * 域名 + */ + @ExcelProperty(value = "域名") + private String domain; + + /** + * 企业简介 + */ + @ExcelProperty(value = "企业简介") + private String intro; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 租户套餐编号 + */ + @ExcelProperty(value = "租户套餐编号") + private Long packageId; + + /** + * 过期时间 + */ + @ExcelProperty(value = "过期时间") + private Date expireTime; + + /** + * 用户数量(-1不限制) + */ + @ExcelProperty(value = "用户数量") + private Long accountCount; + + /** + * 租户状态(0正常 1停用) + */ + @ExcelProperty(value = "租户状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=正常,1=停用") + private String status; + + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserExportVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserExportVo.java new file mode 100644 index 00000000..50ca4235 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserExportVo.java @@ -0,0 +1,96 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.common.excel.annotation.ExcelDictFormat; +import cc.iotkit.common.excel.convert.ExcelDictConvert; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.ReverseAutoMapping; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +/** + * 用户对象导出VO + * + * @author Lion Li + */ + +@Data +@NoArgsConstructor +@AutoMapper(target = SysUserVo.class, convertGenerate = false) +public class SysUserExportVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + @ExcelProperty(value = "用户序号") + private Long userId; + + /** + * 用户账号 + */ + @ExcelProperty(value = "登录名称") + private String userName; + + /** + * 用户昵称 + */ + @ExcelProperty(value = "用户名称") + private String nickName; + + /** + * 用户邮箱 + */ + @ExcelProperty(value = "用户邮箱") + private String email; + + /** + * 手机号码 + */ + @ExcelProperty(value = "手机号码") + private String phonenumber; + + /** + * 用户性别 + */ + @ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_user_sex") + private String sex; + + /** + * 帐号状态(0正常 1停用) + */ + @ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_normal_disable") + private String status; + + /** + * 最后登录IP + */ + @ExcelProperty(value = "最后登录IP") + private String loginIp; + + /** + * 最后登录时间 + */ + @ExcelProperty(value = "最后登录时间") + private Date loginDate; + + /** + * 部门名称 + */ + @ReverseAutoMapping(target = "deptName", source = "dept.deptName") + @ExcelProperty(value = "部门名称") + private String deptName; + + /** + * 负责人 + */ + @ReverseAutoMapping(target = "leader", source = "dept.leader") + @ExcelProperty(value = "部门负责人") + private String leader; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserImportVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserImportVo.java new file mode 100644 index 00000000..a9b5a1cf --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserImportVo.java @@ -0,0 +1,73 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.common.excel.annotation.ExcelDictFormat; +import cc.iotkit.common.excel.convert.ExcelDictConvert; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 用户对象导入VO + * + * @author Lion Li + */ + +@Data +@NoArgsConstructor +// @Accessors(chain = true) // 导入不允许使用 会找不到set方法 +public class SysUserImportVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + @ExcelProperty(value = "用户序号") + private Long userId; + + /** + * 部门ID + */ + @ExcelProperty(value = "部门编号") + private Long deptId; + + /** + * 用户账号 + */ + @ExcelProperty(value = "登录名称") + private String userName; + + /** + * 用户昵称 + */ + @ExcelProperty(value = "用户名称") + private String nickName; + + /** + * 用户邮箱 + */ + @ExcelProperty(value = "用户邮箱") + private String email; + + /** + * 手机号码 + */ + @ExcelProperty(value = "手机号码") + private String phonenumber; + + /** + * 用户性别 + */ + @ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_user_sex") + private String sex; + + /** + * 帐号状态(0正常 1停用) + */ + @ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_normal_disable") + private String status; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserInfoVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserInfoVo.java new file mode 100644 index 00000000..25783adc --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserInfoVo.java @@ -0,0 +1,40 @@ +package cc.iotkit.system.domain.vo; + +import lombok.Data; + +import java.util.List; + +/** + * 用户信息 + * + * @author Michelle.Chung + */ +@Data +public class SysUserInfoVo { + + /** + * 用户信息 + */ + private SysUserVo user; + + /** + * 角色ID列表 + */ + private List roleIds; + + /** + * 角色列表 + */ + private List roles; + + /** + * 岗位ID列表 + */ + private List postIds; + + /** + * 岗位列表 + */ + private List posts; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserVo.java new file mode 100644 index 00000000..8c6f104a --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/SysUserVo.java @@ -0,0 +1,131 @@ +package cc.iotkit.system.domain.vo; + +import cc.iotkit.model.system.SysUser; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + + +/** + * 用户信息视图对象 sys_user + * + * @author Michelle.Chung + */ +@Data +@AutoMapper(target = SysUser.class) +public class SysUserVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + private Long userId; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户账号 + */ + private String userName; + + /** + * 用户昵称 + */ + private String nickName; + + /** + * 用户类型(sys_user系统用户) + */ + private String userType; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String phonenumber; + + /** + * 用户性别(0男 1女 2未知) + */ + private String sex; + + /** + * 头像地址 + */ + private Long avatar; + + /** + * 密码 + */ + @JsonIgnore + @JsonProperty + private String password; + + /** + * 帐号状态(0正常 1停用) + */ + private String status; + + /** + * 最后登录IP + */ + private String loginIp; + + /** + * 最后登录时间 + */ + private Date loginDate; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 部门对象 + */ + private SysDeptVo dept; + + /** + * 角色对象 + */ + private List roles; + + /** + * 角色组 + */ + private Long[] roleIds; + + /** + * 岗位组 + */ + private Long[] postIds; + + /** + * 数据权限 当前角色ID + */ + private Long roleId; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/UserInfoVo.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/UserInfoVo.java new file mode 100644 index 00000000..2b401462 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/domain/vo/UserInfoVo.java @@ -0,0 +1,30 @@ +package cc.iotkit.system.domain.vo; + +import lombok.Data; + +import java.util.Set; + +/** + * 登录用户信息 + * + * @author Michelle.Chung + */ +@Data +public class UserInfoVo { + + /** + * 用户基本信息 + */ + private SysUserVo user; + + /** + * 菜单权限 + */ + private Set permissions; + + /** + * 角色权限 + */ + private Set roles; + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/listener/SysUserImportListener.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/listener/SysUserImportListener.java new file mode 100644 index 00000000..6c2a7735 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/listener/SysUserImportListener.java @@ -0,0 +1,119 @@ +package cc.iotkit.system.listener; + +import cc.iotkit.common.excel.core.ExcelListener; +import cc.iotkit.common.excel.core.ExcelResult; +import cc.iotkit.common.exception.BizException; +import cc.iotkit.common.satoken.utils.LoginHelper; +import cc.iotkit.common.utils.SpringUtils; +import cc.iotkit.common.utils.ValidatorUtils; +import cc.iotkit.system.domain.bo.SysUserBo; +import cc.iotkit.system.domain.vo.SysUserImportVo; +import cc.iotkit.system.domain.vo.SysUserVo; +import cc.iotkit.system.service.ISysUserService; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.crypto.digest.BCrypt; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import cc.iotkit.system.service.ISysConfigService; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * 系统用户自定义导入 + * + * @author Lion Li + */ +@Slf4j +public class SysUserImportListener extends AnalysisEventListener implements ExcelListener { + + private final ISysUserService userService; + + private final String password; + + private final Boolean isUpdateSupport; + + private final Long operUserId; + + private int successNum = 0; + private int failureNum = 0; + private final StringBuilder successMsg = new StringBuilder(); + private final StringBuilder failureMsg = new StringBuilder(); + + public SysUserImportListener(Boolean isUpdateSupport) { + String initPassword = SpringUtils.getBean(ISysConfigService.class).selectConfigByKey("sys.user.initPassword"); + this.userService = SpringUtils.getBean(ISysUserService.class); + this.password = BCrypt.hashpw(initPassword); + this.isUpdateSupport = isUpdateSupport; + this.operUserId = LoginHelper.getUserId(); + } + + @Override + public void invoke(SysUserImportVo userVo, AnalysisContext context) { + SysUserVo sysUser = this.userService.selectUserByUserName(userVo.getUserName()); + try { + // 验证是否存在这个用户 + if (ObjectUtil.isNull(sysUser)) { + SysUserBo user = BeanUtil.toBean(userVo, SysUserBo.class); + ValidatorUtils.validate(user); + user.setPassword(password); + user.setCreateBy(operUserId); + userService.insertUser(user); + successNum++; + successMsg.append("
").append(successNum).append("、账号 ").append(user.getUserName()).append(" 导入成功"); + } else if (isUpdateSupport) { + Long userId = sysUser.getUserId(); + SysUserBo user = BeanUtil.toBean(userVo, SysUserBo.class); + user.setUserId(userId); + ValidatorUtils.validate(user); + userService.checkUserAllowed(user.getUserId()); + userService.checkUserDataScope(user.getUserId()); + user.setUpdateBy(operUserId); + userService.updateUser(user); + successNum++; + successMsg.append("
").append(successNum).append("、账号 ").append(user.getUserName()).append(" 更新成功"); + } else { + failureNum++; + failureMsg.append("
").append(failureNum).append("、账号 ").append(sysUser.getUserName()).append(" 已存在"); + } + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum + "、账号 " + sysUser.getUserName() + " 导入失败:"; + failureMsg.append(msg).append(e.getMessage()); + log.error(msg, e); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + + @Override + public ExcelResult getExcelResult() { + return new ExcelResult<>() { + + @Override + public String getAnalysis() { + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new BizException(failureMsg.toString()); + } else { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + @Override + public List getList() { + return null; + } + + @Override + public List getErrorList() { + return null; + } + }; + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysDeptMapper.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysDeptMapper.java new file mode 100644 index 00000000..1c7d6d7b --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysDeptMapper.java @@ -0,0 +1,46 @@ +package cc.iotkit.system.mapper; + +import cc.iotkit.system.domain.vo.SysDeptVo; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import org.dromara.common.mybatis.annotation.DataColumn; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import cc.iotkit.system.domain.SysDept; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 部门管理 数据层 + * + * @author Lion Li + */ +public interface SysDeptMapper extends BaseMapperPlus { + + /** + * 查询部门管理数据 + * + * @param queryWrapper 查询条件 + * @return 部门信息集合 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "dept_id") + }) + List selectDeptList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + @DataPermission({ + @DataColumn(key = "deptName", value = "dept_id") + }) + SysDeptVo selectDeptById(Long deptId); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @param deptCheckStrictly 部门树选择项是否关联显示 + * @return 选中部门列表 + */ + List selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysDictDataMapper.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysDictDataMapper.java new file mode 100644 index 00000000..eac476a4 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysDictDataMapper.java @@ -0,0 +1,25 @@ +package cc.iotkit.system.mapper; + +import cc.iotkit.system.domain.vo.SysDictDataVo; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.dromara.common.core.constant.UserConstants; +import cc.iotkit.system.domain.SysDictData; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +import java.util.List; + +/** + * 字典表 数据层 + * + * @author Lion Li + */ +public interface SysDictDataMapper extends BaseMapperPlus { + + default List selectDictDataByType(String dictType) { + return selectVoList( + new LambdaQueryWrapper() + .eq(SysDictData::getStatus, UserConstants.DICT_NORMAL) + .eq(SysDictData::getDictType, dictType) + .orderByAsc(SysDictData::getDictSort)); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysMenuMapper.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysMenuMapper.java new file mode 100644 index 00000000..af0cb563 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysMenuMapper.java @@ -0,0 +1,83 @@ +package cc.iotkit.system.mapper; + +import cc.iotkit.system.domain.vo.SysMenuVo; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import org.dromara.common.core.constant.UserConstants; +import cc.iotkit.system.domain.SysMenu; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 菜单表 数据层 + * + * @author Lion Li + */ +public interface SysMenuMapper extends BaseMapperPlus { + + /** + * 根据用户所有权限 + * + * @return 权限列表 + */ + List selectMenuPerms(); + + /** + * 根据用户查询系统菜单列表 + * + * @param queryWrapper 查询条件 + * @return 菜单列表 + */ + List selectMenuListByUserId(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + List selectMenuPermsByUserId(Long userId); + + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + List selectMenuPermsByRoleId(Long roleId); + + /** + * 根据用户ID查询菜单 + * + * @return 菜单列表 + */ + default List selectMenuTreeAll() { + LambdaQueryWrapper lqw = new LambdaQueryWrapper() + .in(SysMenu::getMenuType, UserConstants.TYPE_DIR, UserConstants.TYPE_MENU) + .eq(SysMenu::getStatus, UserConstants.MENU_NORMAL) + .orderByAsc(SysMenu::getParentId) + .orderByAsc(SysMenu::getOrderNum); + return this.selectList(lqw); + } + + /** + * 根据用户ID查询菜单 + * + * @param userId 用户ID + * @return 菜单列表 + */ + List selectMenuTreeByUserId(Long userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @param menuCheckStrictly 菜单树选择项是否关联显示 + * @return 选中菜单列表 + */ + List selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysPostMapper.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysPostMapper.java new file mode 100644 index 00000000..67d43c68 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysPostMapper.java @@ -0,0 +1,32 @@ +package cc.iotkit.system.mapper; + +import cc.iotkit.system.domain.vo.SysPostVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import cc.iotkit.system.domain.SysPost; + +import java.util.List; + +/** + * 岗位信息 数据层 + * + * @author Lion Li + */ +public interface SysPostMapper extends BaseMapperPlus { + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + List selectPostListByUserId(Long userId); + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + List selectPostsByUserName(String userName); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysRoleMapper.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysRoleMapper.java new file mode 100644 index 00000000..d75d9d29 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysRoleMapper.java @@ -0,0 +1,68 @@ +package cc.iotkit.system.mapper; + +import cc.iotkit.system.domain.vo.SysRoleVo; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.mybatis.annotation.DataColumn; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import cc.iotkit.system.domain.SysRole; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 角色表 数据层 + * + * @author Lion Li + */ +public interface SysRoleMapper extends BaseMapperPlus { + + @DataPermission({ + @DataColumn(key = "deptName", value = "d.dept_id") + }) + Page selectPageRoleList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 根据条件分页查询角色数据 + * + * @param queryWrapper 查询条件 + * @return 角色数据集合信息 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "d.dept_id") + }) + List selectRoleList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + @DataPermission({ + @DataColumn(key = "deptName", value = "d.dept_id") + }) + SysRoleVo selectRoleById(Long roleId); + + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + List selectRolePermissionByUserId(Long userId); + + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + List selectRoleListByUserId(Long userId); + + /** + * 根据用户ID查询角色 + * + * @param userName 用户名 + * @return 角色列表 + */ + List selectRolesByUserName(String userName); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysUserMapper.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysUserMapper.java new file mode 100644 index 00000000..579fe43b --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysUserMapper.java @@ -0,0 +1,145 @@ +package cc.iotkit.system.mapper; + +import cc.iotkit.system.domain.vo.SysUserVo; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.mybatis.annotation.DataColumn; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import cc.iotkit.system.domain.SysUser; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 用户表 数据层 + * + * @author Lion Li + */ +public interface SysUserMapper extends BaseMapperPlus { + + @DataPermission({ + @DataColumn(key = "deptName", value = "d.dept_id"), + @DataColumn(key = "userName", value = "u.user_id") + }) + Page selectPageUserList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 根据条件分页查询用户列表 + * + * @param queryWrapper 查询条件 + * @return 用户信息集合信息 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "d.dept_id"), + @DataColumn(key = "userName", value = "u.user_id") + }) + List selectUserList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 根据条件分页查询已配用户角色列表 + * + * @param queryWrapper 查询条件 + * @return 用户信息集合信息 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "d.dept_id"), + @DataColumn(key = "userName", value = "u.user_id") + }) + Page selectAllocatedList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param queryWrapper 查询条件 + * @return 用户信息集合信息 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "d.dept_id"), + @DataColumn(key = "userName", value = "u.user_id") + }) + Page selectUnallocatedList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + SysUserVo selectUserByUserName(String userName); + + /** + * 通过手机号查询用户 + * + * @param phonenumber 手机号 + * @return 用户对象信息 + */ + SysUserVo selectUserByPhonenumber(String phonenumber); + + /** + * 通过邮箱查询用户 + * + * @param email 邮箱 + * @return 用户对象信息 + */ + SysUserVo selectUserByEmail(String email); + + /** + * 通过用户名查询用户(不走租户插件) + * + * @param userName 用户名 + * @param tenantId 租户id + * @return 用户对象信息 + */ + @InterceptorIgnore(tenantLine = "true") + SysUserVo selectTenantUserByUserName(String userName, String tenantId); + + /** + * 通过手机号查询用户(不走租户插件) + * + * @param phonenumber 手机号 + * @param tenantId 租户id + * @return 用户对象信息 + */ + @InterceptorIgnore(tenantLine = "true") + SysUserVo selectTenantUserByPhonenumber(String phonenumber, String tenantId); + + /** + * 通过邮箱查询用户(不走租户插件) + * + * @param email 邮箱 + * @param tenantId 租户id + * @return 用户对象信息 + */ + @InterceptorIgnore(tenantLine = "true") + SysUserVo selectTenantUserByEmail(String email, String tenantId); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "d.dept_id"), + @DataColumn(key = "userName", value = "u.user_id") + }) + SysUserVo selectUserById(Long userId); + + @Override + @DataPermission({ + @DataColumn(key = "deptName", value = "dept_id"), + @DataColumn(key = "userName", value = "user_id") + }) + int update(@Param(Constants.ENTITY) SysUser user, @Param(Constants.WRAPPER) Wrapper updateWrapper); + + @Override + @DataPermission({ + @DataColumn(key = "deptName", value = "dept_id"), + @DataColumn(key = "userName", value = "user_id") + }) + int updateById(@Param(Constants.ENTITY) SysUser user); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysUserRoleMapper.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysUserRoleMapper.java new file mode 100644 index 00000000..fbebca7f --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/mapper/SysUserRoleMapper.java @@ -0,0 +1,15 @@ +package cc.iotkit.system.mapper; + + +import java.util.List; + +/** + * 用户与角色关联表 数据层 + * + * @author Lion Li + */ +public interface SysUserRoleMapper extends BaseMapperPlus { + + List selectUserIdsByRoleId(Long roleId); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/runner/SystemApplicationRunner.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/runner/SystemApplicationRunner.java new file mode 100644 index 00000000..2920a2d2 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/runner/SystemApplicationRunner.java @@ -0,0 +1,28 @@ +package cc.iotkit.system.runner; + +import cc.iotkit.system.service.ISysOssConfigService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +/** + * 初始化 system 模块对应业务数据 + * + * @author Lion Li + */ +@Slf4j +@RequiredArgsConstructor +@Component +public class SystemApplicationRunner implements ApplicationRunner { + + private final ISysOssConfigService ossConfigService; + + @Override + public void run(ApplicationArguments args) throws Exception { + ossConfigService.init(); + log.info("初始化OSS配置成功"); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysConfigService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysConfigService.java new file mode 100644 index 00000000..61ad08c6 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysConfigService.java @@ -0,0 +1,87 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysConfigBo; +import cc.iotkit.system.domain.vo.SysConfigVo; + +import java.util.List; + +/** + * 参数配置 服务层 + * + * @author Lion Li + */ +public interface ISysConfigService { + + + PagedDataVo selectPageConfigList(SysConfigBo config, PageRequest query); + + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return 参数配置信息 + */ + SysConfigVo selectConfigById(Long configId); + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数键名 + * @return 参数键值 + */ + String selectConfigByKey(String configKey); + + /** + * 获取注册开关 + * @param tenantId 租户id + * @return true开启,false关闭 + */ + boolean selectRegisterEnabled(String tenantId); + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + List selectConfigList(SysConfigBo config); + + /** + * 新增参数配置 + * + * @param bo 参数配置信息 + * @return 结果 + */ + String insertConfig(SysConfigBo bo); + + /** + * 修改参数配置 + * + * @param bo 参数配置信息 + * @return 结果 + */ + String updateConfig(SysConfigBo bo); + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + */ + void deleteConfigByIds(Long[] configIds); + + /** + * 重置参数缓存数据 + */ + void resetConfigCache(); + + /** + * 校验参数键名是否唯一 + * + * @param config 参数信息 + * @return 结果 + */ + boolean checkConfigKeyUnique(SysConfigBo config); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDataScopeService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDataScopeService.java new file mode 100644 index 00000000..25163c61 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDataScopeService.java @@ -0,0 +1,26 @@ +package cc.iotkit.system.service; + +/** + * 通用 数据权限 服务 + * + * @author Lion Li + */ +public interface ISysDataScopeService { + + /** + * 获取角色自定义权限 + * + * @param roleId 角色id + * @return 部门id组 + */ + String getRoleCustom(Long roleId); + + /** + * 获取部门及以下权限 + * + * @param deptId 部门id + * @return 部门id组 + */ + String getDeptAndChild(Long deptId); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDeptService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDeptService.java new file mode 100644 index 00000000..57d84948 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDeptService.java @@ -0,0 +1,118 @@ +package cc.iotkit.system.service; + +import cc.iotkit.model.system.SysDept; +import cc.iotkit.system.domain.bo.SysDeptBo; +import cc.iotkit.system.domain.vo.SysDeptVo; +import cn.hutool.core.lang.tree.Tree; + +import java.util.List; + +/** + * 部门管理 服务层 + * + * @author Lion Li + */ +public interface ISysDeptService { + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + List selectDeptList(SysDeptBo dept); + + /** + * 查询部门树结构信息 + * + * @param dept 部门信息 + * @return 部门树信息集合 + */ + List> selectDeptTreeList(SysDeptBo dept); + + /** + * 构建前端所需要下拉树结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + List> buildDeptTreeSelect(List depts); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + List selectDeptListByRoleId(Long roleId); + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + SysDeptVo selectDeptById(Long deptId); + + /** + * 根据ID查询所有子部门数(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + long selectNormalChildrenDeptById(Long deptId); + + /** + * 是否存在部门子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + boolean hasChildByDeptId(Long deptId); + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + boolean checkDeptExistUser(Long deptId); + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + boolean checkDeptNameUnique(SysDeptBo dept); + + /** + * 校验部门是否有数据权限 + * + * @param deptId 部门id + */ + void checkDeptDataScope(Long deptId); + + /** + * 新增保存部门信息 + * + * @param bo 部门信息 + * @return 结果 + */ + int insertDept(SysDeptBo bo); + + /** + * 修改保存部门信息 + * + * @param bo 部门信息 + * @return 结果 + */ + int updateDept(SysDeptBo bo); + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + int deleteDeptById(Long deptId); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDictDataService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDictDataService.java new file mode 100644 index 00000000..e69b0188 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDictDataService.java @@ -0,0 +1,67 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysDictDataBo; +import cc.iotkit.system.domain.vo.SysDictDataVo; + +import java.util.List; + +/** + * 字典 业务层 + * + * @author Lion Li + */ +public interface ISysDictDataService { + + + PagedDataVo selectPageDictDataList(SysDictDataBo dictData, PageRequest query); + + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + List selectDictDataList(SysDictDataBo dictData); + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + String selectDictLabel(String dictType, String dictValue); + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + SysDictDataVo selectDictDataById(Long dictCode); + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + */ + void deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增保存字典数据信息 + * + * @param bo 字典数据信息 + * @return 结果 + */ + List insertDictData(SysDictDataBo bo); + + /** + * 修改保存字典数据信息 + * + * @param bo 字典数据信息 + * @return 结果 + */ + List updateDictData(SysDictDataBo bo); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDictTypeService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDictTypeService.java new file mode 100644 index 00000000..1a245d88 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysDictTypeService.java @@ -0,0 +1,95 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysDictTypeBo; +import cc.iotkit.system.domain.vo.SysDictDataVo; +import cc.iotkit.system.domain.vo.SysDictTypeVo; + +import java.util.List; + +/** + * 字典 业务层 + * + * @author Lion Li + */ +public interface ISysDictTypeService { + + + PagedDataVo selectPageDictTypeList(SysDictTypeBo dictType, PageRequest query); + + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + List selectDictTypeList(SysDictTypeBo dictType); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + List selectDictTypeAll(); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + List selectDictDataByType(String dictType); + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + SysDictTypeVo selectDictTypeById(Long dictId); + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + SysDictTypeVo selectDictTypeByType(String dictType); + + /** + * 批量删除字典信息 + * + * @param dictIds 需要删除的字典ID + */ + void deleteDictTypeByIds(Long[] dictIds); + + /** + * 重置字典缓存数据 + */ + void resetDictCache(); + + /** + * 新增保存字典类型信息 + * + * @param bo 字典类型信息 + * @return 结果 + */ + List insertDictType(SysDictTypeBo bo); + + /** + * 修改保存字典类型信息 + * + * @param bo 字典类型信息 + * @return 结果 + */ + List updateDictType(SysDictTypeBo bo); + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + boolean checkDictTypeUnique(SysDictTypeBo dictType); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysLogininforService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysLogininforService.java new file mode 100644 index 00000000..abc56e95 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysLogininforService.java @@ -0,0 +1,47 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysLogininforBo; +import cc.iotkit.system.domain.vo.SysLogininforVo; + +import java.util.List; + +/** + * 系统访问日志情况信息 服务层 + * + * @author Lion Li + */ +public interface ISysLogininforService { + + + PagedDataVo selectPageLogininforList(SysLogininforBo logininfor, PageRequest query); + + /** + * 新增系统登录日志 + * + * @param bo 访问日志对象 + */ + void insertLogininfor(SysLogininforBo bo); + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + List selectLogininforList(SysLogininforBo logininfor); + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + int deleteLogininforByIds(Long[] infoIds); + + /** + * 清空系统登录日志 + */ + void cleanLogininfor(); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysMenuService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysMenuService.java new file mode 100644 index 00000000..9213568e --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysMenuService.java @@ -0,0 +1,147 @@ +package cc.iotkit.system.service; + +import cc.iotkit.model.system.SysMenu; +import cc.iotkit.system.domain.bo.SysMenuBo; +import cc.iotkit.system.domain.vo.RouterVo; +import cc.iotkit.system.domain.vo.SysMenuVo; +import cn.hutool.core.lang.tree.Tree; + +import java.util.List; +import java.util.Set; + +/** + * 菜单 业务层 + * + * @author Lion Li + */ +public interface ISysMenuService { + + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + List selectMenuList(Long userId); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu 菜单信息 + * @param userId 用户ID + * @return 菜单列表 + */ + List selectMenuList(SysMenuBo menu, Long userId); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + Set selectMenuPermsByUserId(Long userId); + + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + Set selectMenuPermsByRoleId(Long roleId); + + /** + * 根据用户ID查询菜单树信息 + * + * @param userId 用户ID + * @return 菜单列表 + */ + List selectMenuTreeByUserId(Long userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + List selectMenuListByRoleId(Long roleId); + + /** + * 根据租户套餐ID查询菜单树信息 + * + * @param packageId 租户套餐ID + * @return 选中菜单列表 + */ + List selectMenuListByPackageId(Long packageId); + + /** + * 构建前端路由所需要的菜单 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + List buildMenus(List menus); + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + List> buildMenuTreeSelect(List menus); + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + SysMenuVo selectMenuById(Long menuId); + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + boolean hasChildByMenuId(Long menuId); + + /** + * 查询菜单是否存在角色 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + boolean checkMenuExistRole(Long menuId); + + /** + * 新增保存菜单信息 + * + * @param bo 菜单信息 + * @return 结果 + */ + int insertMenu(SysMenuBo bo); + + /** + * 修改保存菜单信息 + * + * @param bo 菜单信息 + * @return 结果 + */ + int updateMenu(SysMenuBo bo); + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + int deleteMenuById(Long menuId); + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + boolean checkMenuNameUnique(SysMenuBo menu); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysNoticeService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysNoticeService.java new file mode 100644 index 00000000..bb004e09 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysNoticeService.java @@ -0,0 +1,67 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysNoticeBo; +import cc.iotkit.system.domain.vo.SysNoticeVo; + +import java.util.List; + +/** + * 公告 服务层 + * + * @author Lion Li + */ +public interface ISysNoticeService { + + + PagedDataVo selectPageNoticeList(SysNoticeBo notice, PageRequest query); + + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + SysNoticeVo selectNoticeById(Long noticeId); + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + List selectNoticeList(SysNoticeBo notice); + + /** + * 新增公告 + * + * @param bo 公告信息 + * @return 结果 + */ + int insertNotice(SysNoticeBo bo); + + /** + * 修改公告 + * + * @param bo 公告信息 + * @return 结果 + */ + int updateNotice(SysNoticeBo bo); + + /** + * 删除公告信息 + * + * @param noticeId 公告ID + * @return 结果 + */ + int deleteNoticeById(Long noticeId); + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + int deleteNoticeByIds(Long[] noticeIds); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysOperLogService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysOperLogService.java new file mode 100644 index 00000000..21edde84 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysOperLogService.java @@ -0,0 +1,54 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysOperLogBo; +import cc.iotkit.system.domain.vo.SysOperLogVo; + +import java.util.List; + +/** + * 操作日志 服务层 + * + * @author Lion Li + */ +public interface ISysOperLogService { + + PagedDataVo selectPageOperLogList(SysOperLogBo operLog, PageRequest query); + + /** + * 新增操作日志 + * + * @param bo 操作日志对象 + */ + void insertOperlog(SysOperLogBo bo); + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + List selectOperLogList(SysOperLogBo operLog); + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + int deleteOperLogByIds(Long[] operIds); + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + SysOperLogVo selectOperLogById(Long operId); + + /** + * 清空操作日志 + */ + void cleanOperLog(); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysOssConfigService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysOssConfigService.java new file mode 100644 index 00000000..eb4ee9dd --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysOssConfigService.java @@ -0,0 +1,65 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysOssConfigBo; +import cc.iotkit.system.domain.vo.SysOssConfigVo; + +import java.util.Collection; + +/** + * 对象存储配置Service接口 + * + * @author Lion Li + * @author 孤舟烟雨 + * @date 2021-08-13 + */ +public interface ISysOssConfigService { + + /** + * 初始化OSS配置 + */ + void init(); + + /** + * 查询单个 + */ + SysOssConfigVo queryById(Long ossConfigId); + + /** + * 查询列表 + */ + PagedDataVo queryPageList(SysOssConfigBo bo, PageRequest query); + + + /** + * 根据新增业务对象插入对象存储配置 + * + * @param bo 对象存储配置新增业务对象 + * @return + */ + Boolean insertByBo(SysOssConfigBo bo); + + /** + * 根据编辑业务对象修改对象存储配置 + * + * @param bo 对象存储配置编辑业务对象 + * @return + */ + Boolean updateByBo(SysOssConfigBo bo); + + /** + * 校验并删除数据 + * + * @param ids 主键集合 + * @param isValid 是否校验,true-删除前校验,false-不校验 + * @return + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 启用停用状态 + */ + int updateOssConfigStatus(SysOssConfigBo bo); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysOssService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysOssService.java new file mode 100644 index 00000000..02ed77e5 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysOssService.java @@ -0,0 +1,33 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysOssBo; +import cc.iotkit.system.domain.vo.SysOssVo; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; + +/** + * 文件上传 服务层 + * + * @author Lion Li + */ +public interface ISysOssService { + + PagedDataVo queryPageList(SysOssBo sysOss, PageRequest query); + + List listByIds(Collection ossIds); + + SysOssVo getById(Long ossId); + + SysOssVo upload(MultipartFile file); + + void download(Long ossId, HttpServletResponse response) throws IOException; + + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysPermissionService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysPermissionService.java new file mode 100644 index 00000000..f3bf4c0a --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysPermissionService.java @@ -0,0 +1,28 @@ +package cc.iotkit.system.service; + +import java.util.Set; + +/** + * 用户权限处理 + * + * @author Lion Li + */ +public interface ISysPermissionService { + + /** + * 获取角色数据权限 + * + * @param userId 用户id + * @return 角色权限信息 + */ + Set getRolePermission(Long userId); + + /** + * 获取菜单数据权限 + * + * @param userId 用户id + * @return 菜单权限信息 + */ + Set getMenuPermission(Long userId); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysPostService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysPostService.java new file mode 100644 index 00000000..c2483836 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysPostService.java @@ -0,0 +1,106 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysPostBo; +import cc.iotkit.system.domain.vo.SysPostVo; + +import java.util.List; + +/** + * 岗位信息 服务层 + * + * @author Lion Li + */ +public interface ISysPostService { + + + PagedDataVo selectPagePostList(SysPostBo post, PageRequest query); + + /** + * 查询岗位信息集合 + * + * @param post 岗位信息 + * @return 岗位列表 + */ + List selectPostList(SysPostBo post); + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + List selectPostAll(); + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + SysPostVo selectPostById(Long postId); + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + List selectPostListByUserId(Long userId); + + /** + * 校验岗位名称 + * + * @param post 岗位信息 + * @return 结果 + */ + boolean checkPostNameUnique(SysPostBo post); + + /** + * 校验岗位编码 + * + * @param post 岗位信息 + * @return 结果 + */ + boolean checkPostCodeUnique(SysPostBo post); + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + long countUserPostById(Long postId); + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + int deletePostById(Long postId); + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + */ + int deletePostByIds(Long[] postIds); + + /** + * 新增保存岗位信息 + * + * @param bo 岗位信息 + * @return 结果 + */ + int insertPost(SysPostBo bo); + + /** + * 修改保存岗位信息 + * + * @param bo 岗位信息 + * @return 结果 + */ + int updatePost(SysPostBo bo); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysRoleService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysRoleService.java new file mode 100644 index 00000000..d26b527c --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysRoleService.java @@ -0,0 +1,182 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysRoleBo; +import cc.iotkit.system.domain.vo.SysRoleVo; + +import java.util.List; +import java.util.Set; + +/** + * 角色业务层 + * + * @author Lion Li + */ +public interface ISysRoleService { + + + PagedDataVo selectPageRoleList(SysRoleBo role, PageRequest query); + + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + List selectRoleList(SysRoleBo role); + + /** + * 根据用户ID查询角色列表 + * + * @param userId 用户ID + * @return 角色列表 + */ + List selectRolesByUserId(Long userId); + + /** + * 根据用户ID查询角色权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + Set selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + List selectRoleAll(); + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + SysRoleVo selectRoleById(Long roleId); + + /** + * 校验角色名称是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + boolean checkRoleNameUnique(SysRoleBo role); + + /** + * 校验角色权限是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + boolean checkRoleKeyUnique(SysRoleBo role); + + /** + * 校验角色是否允许操作 + * + * @param roleId 角色ID + */ + void checkRoleAllowed(Long roleId); + + /** + * 校验角色是否有数据权限 + * + * @param roleId 角色id + */ + void checkRoleDataScope(Long roleId); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + long countUserRoleByRoleId(Long roleId); + + /** + * 新增保存角色信息 + * + * @param bo 角色信息 + * @return 结果 + */ + int insertRole(SysRoleBo bo); + + /** + * 修改保存角色信息 + * + * @param bo 角色信息 + * @return 结果 + */ + int updateRole(SysRoleBo bo); + + /** + * 修改角色状态 + * + * @param roleId 角色ID + * @param status 角色状态 + * @return 结果 + */ + int updateRoleStatus(Long roleId, String status); + + /** + * 修改数据权限信息 + * + * @param bo 角色信息 + * @return 结果 + */ + int authDataScope(SysRoleBo bo); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + int deleteRoleById(Long roleId); + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + int deleteRoleByIds(Long[] roleIds); + + /** + * 取消授权用户角色 + * + * @param userRole 用户和角色关联信息 + * @return 结果 + */ + int deleteAuthUser(SysUserRole userRole); + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要取消授权的用户数据ID + * @return 结果 + */ + int deleteAuthUsers(Long roleId, Long[] userIds); + + /** + * 批量选择授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要删除的用户数据ID + * @return 结果 + */ + int insertAuthUsers(Long roleId, Long[] userIds); + + void cleanOnlineUserByRole(Long roleId); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysTenantPackageService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysTenantPackageService.java new file mode 100644 index 00000000..63c7e1e2 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysTenantPackageService.java @@ -0,0 +1,57 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysTenantPackageBo; +import cc.iotkit.system.domain.vo.SysTenantPackageVo; + +import java.util.Collection; +import java.util.List; + +/** + * 租户套餐Service接口 + * + * @author Michelle.Chung + */ +public interface ISysTenantPackageService { + + /** + * 查询租户套餐 + */ + SysTenantPackageVo queryById(Long packageId); + + /** + * 查询租户套餐列表 + */ + PagedDataVo queryPageList(SysTenantPackageBo bo, PageRequest query); + + /** + * 查询租户套餐已启用列表 + */ + List selectList(); + + /** + * 查询租户套餐列表 + */ + List queryList(SysTenantPackageBo bo); + + /** + * 新增租户套餐 + */ + Boolean insertByBo(SysTenantPackageBo bo); + + /** + * 修改租户套餐 + */ + Boolean updateByBo(SysTenantPackageBo bo); + + /** + * 修改套餐状态 + */ + int updatePackageStatus(SysTenantPackageBo bo); + + /** + * 校验并批量删除租户套餐信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysTenantService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysTenantService.java new file mode 100644 index 00000000..6dfcfaed --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysTenantService.java @@ -0,0 +1,82 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysTenantBo; +import cc.iotkit.system.domain.vo.SysTenantVo; + +import java.util.Collection; +import java.util.List; + +/** + * 租户Service接口 + * + * @author Michelle.Chung + */ +public interface ISysTenantService { + + /** + * 查询租户 + */ + SysTenantVo queryById(Long id); + + /** + * 基于租户ID查询租户 + */ + SysTenantVo queryByTenantId(String tenantId); + + /** + * 查询租户列表 + */ + PagedDataVo queryPageList(SysTenantBo bo, PageRequest query); + + /** + * 查询租户列表 + */ + List queryList(SysTenantBo bo); + + /** + * 新增租户 + */ + Boolean insertByBo(SysTenantBo bo); + + /** + * 修改租户 + */ + Boolean updateByBo(SysTenantBo bo); + + /** + * 修改租户状态 + */ + int updateTenantStatus(SysTenantBo bo); + + /** + * 校验租户是否允许操作 + */ + void checkTenantAllowed(String tenantId); + + /** + * 校验并批量删除租户信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 校验企业名称是否唯一 + */ + boolean checkCompanyNameUnique(SysTenantBo bo); + + /** + * 校验账号余额 + */ + boolean checkAccountBalance(String tenantId); + + /** + * 校验有效期 + */ + boolean checkExpireTime(String tenantId); + + /** + * 同步租户套餐 + */ + Boolean syncTenantPackage(String tenantId, String packageId); +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysUserService.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysUserService.java new file mode 100644 index 00000000..1f28e381 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/ISysUserService.java @@ -0,0 +1,205 @@ +package cc.iotkit.system.service; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.system.domain.bo.SysUserBo; +import cc.iotkit.system.domain.vo.SysUserVo; + +import java.util.List; + +/** + * 用户 业务层 + * + * @author Lion Li + */ +public interface ISysUserService { + + + PagedDataVo selectPageUserList(SysUserBo user, PageRequest query); + + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + List selectUserList(SysUserBo user); + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + PagedDataVo selectAllocatedList(SysUserBo user, PageRequest query); + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + PagedDataVo selectUnallocatedList(SysUserBo user, PageRequest query); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + SysUserVo selectUserByUserName(String userName); + + /** + * 通过手机号查询用户 + * + * @param phonenumber 手机号 + * @return 用户对象信息 + */ + SysUserVo selectUserByPhonenumber(String phonenumber); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + SysUserVo selectUserById(Long userId); + + /** + * 根据用户ID查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + String selectUserRoleGroup(String userName); + + /** + * 根据用户ID查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + String selectUserPostGroup(String userName); + + /** + * 校验用户名称是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + boolean checkUserNameUnique(SysUserBo user); + + /** + * 校验手机号码是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + boolean checkPhoneUnique(SysUserBo user); + + /** + * 校验email是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + boolean checkEmailUnique(SysUserBo user); + + /** + * 校验用户是否允许操作 + * + * @param userId 用户ID + */ + void checkUserAllowed(Long userId); + + /** + * 校验用户是否有数据权限 + * + * @param userId 用户id + */ + void checkUserDataScope(Long userId); + + /** + * 新增用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + int insertUser(SysUserBo user); + + /** + * 注册用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + boolean registerUser(SysUserBo user, String tenantId); + + /** + * 修改用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + int updateUser(SysUserBo user); + + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + void insertUserAuth(Long userId, Long[] roleIds); + + /** + * 修改用户状态 + * + * @param userId 用户ID + * @param status 帐号状态 + * @return 结果 + */ + int updateUserStatus(Long userId, String status); + + /** + * 修改用户基本信息 + * + * @param user 用户信息 + * @return 结果 + */ + int updateUserProfile(SysUserBo user); + + /** + * 修改用户头像 + * + * @param userId 用户ID + * @param avatar 头像地址 + * @return 结果 + */ + boolean updateUserAvatar(Long userId, Long avatar); + + /** + * 重置用户密码 + * + * @param userId 用户ID + * @param password 密码 + * @return 结果 + */ + int resetUserPwd(Long userId, String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + int deleteUserById(Long userId); + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + int deleteUserByIds(Long[] userIds); + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysConfigServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysConfigServiceImpl.java new file mode 100644 index 00000000..e878dc0c --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysConfigServiceImpl.java @@ -0,0 +1,208 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.common.api.PageRequest; +import cc.iotkit.common.constant.CacheNames; +import cc.iotkit.common.domain.vo.PagedDataVo; +import cc.iotkit.common.exception.BizException; +import cc.iotkit.common.service.ConfigService; +import cc.iotkit.common.utils.MapstructUtils; +import cc.iotkit.common.utils.SpringUtils; +import cc.iotkit.common.utils.StringUtils; +import cc.iotkit.system.domain.bo.SysConfigBo; +import cc.iotkit.system.domain.vo.SysConfigVo; +import cc.iotkit.system.mapper.SysConfigMapper; +import cn.hutool.core.util.ObjectUtil; +import cc.iotkit.system.domain.SysConfig; +import cc.iotkit.system.service.ISysConfigService; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CachePut; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 参数配置 服务层实现 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysConfigServiceImpl implements ISysConfigService, ConfigService { + + private final SysConfigMapper baseMapper; + + @Override + public PagedDataVo selectPageConfigList(SysConfigBo config, PageRequest query) { +// LambdaQueryWrapper lqw = buildQueryWrapper(config); +// Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); +// return TableDataInfo.build(page); + return new PagedDataVo(); + } + + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return 参数配置信息 + */ + @Override + public SysConfigVo selectConfigById(Long configId) { +// return baseMapper.selectVoById(configId); + return new SysConfigVo(); + } + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数key + * @return 参数键值 + */ + @Override + public String selectConfigByKey(String configKey) { +// SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper() +// .eq(SysConfig::getConfigKey, configKey)); +// if (ObjectUtil.isNotNull(retConfig)) { +// return retConfig.getConfigValue(); +// } + return StringUtils.EMPTY; + } + + /** + * 获取注册开关 + * @param tenantId 租户id + * @return true开启,false关闭 + */ + @Override + public boolean selectRegisterEnabled(String tenantId) { +// SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper() +// .eq(SysConfig::getConfigKey, "sys.account.registerUser") +// .eq(TenantHelper.isEnable(),SysConfig::getTenantId, tenantId)); +// if (ObjectUtil.isNull(retConfig)) { +// return false; +// } +// return Convert.toBool(retConfig.getConfigValue()); + return false; + } + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + @Override + public List selectConfigList(SysConfigBo config) { +// LambdaQueryWrapper lqw = buildQueryWrapper(config); +// return baseMapper.selectVoList(lqw); + return new ArrayList<>(); + } + +// private LambdaQueryWrapper buildQueryWrapper(SysConfigBo bo) { +// Map params = bo.getParams(); +// LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); +// lqw.like(StringUtils.isNotBlank(bo.getConfigName()), SysConfig::getConfigName, bo.getConfigName()); +// lqw.eq(StringUtils.isNotBlank(bo.getConfigType()), SysConfig::getConfigType, bo.getConfigType()); +// lqw.like(StringUtils.isNotBlank(bo.getConfigKey()), SysConfig::getConfigKey, bo.getConfigKey()); +// lqw.between(params.get("beginTime") != null && params.get("endTime") != null, +// SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime")); +// return lqw; +// } + + /** + * 新增参数配置 + * + * @param bo 参数配置信息 + * @return 结果 + */ + @Override + public String insertConfig(SysConfigBo bo) { +// SysConfig config = MapstructUtils.convert(bo, SysConfig.class); +// int row = baseMapper.insert(config); +// if (row > 0) { +// return config.getConfigValue(); +// } + throw new BizException("操作失败"); + } + + /** + * 修改参数配置 + * + * @param bo 参数配置信息 + * @return 结果 + */ +// @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#bo.configKey") + @Override + public String updateConfig(SysConfigBo bo) { + int row = 0; + SysConfig config = MapstructUtils.convert(bo, SysConfig.class); + if (config.getConfigId() != null) { + SysConfig temp = baseMapper.selectById(config.getConfigId()); + if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) { + CacheUtils.evict(CacheNames.SYS_CONFIG, temp.getConfigKey()); + } + row = baseMapper.updateById(config); + } else { + row = baseMapper.update(config, new LambdaQueryWrapper() + .eq(SysConfig::getConfigKey, config.getConfigKey())); + } + if (row > 0) { + return config.getConfigValue(); + } + throw new BizException("操作失败"); + } + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + */ + @Override + public void deleteConfigByIds(Long[] configIds) { + for (Long configId : configIds) { + SysConfig config = baseMapper.selectById(configId); + if (StringUtils.equals(UserConstants.YES, config.getConfigType())) { + throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); + } + CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey()); + } + baseMapper.deleteBatchIds(Arrays.asList(configIds)); + } + + /** + * 重置参数缓存数据 + */ + @Override + public void resetConfigCache() { + CacheUtils.clear(CacheNames.SYS_CONFIG); + } + + /** + * 校验参数键名是否唯一 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public boolean checkConfigKeyUnique(SysConfigBo config) { + long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId(); + SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper().eq(SysConfig::getConfigKey, config.getConfigKey())); + if (ObjectUtil.isNotNull(info) && info.getConfigId() != configId) { + return false; + } + return true; + } + + /** + * 根据参数 key 获取参数值 + * + * @param configKey 参数 key + * @return 参数值 + */ + @Override + public String getConfigValue(String configKey) { + return SpringUtils.getAopProxy(this).selectConfigByKey(configKey); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDataScopeServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDataScopeServiceImpl.java new file mode 100644 index 00000000..64299ddb --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDataScopeServiceImpl.java @@ -0,0 +1,61 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.SysDept; +import cc.iotkit.system.domain.SysRoleDept; +import cc.iotkit.system.mapper.SysDeptMapper; +import cc.iotkit.system.mapper.SysRoleDeptMapper; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.dromara.common.mybatis.helper.DataBaseHelper; +import org.dromara.common.core.utils.StreamUtils; +import cc.iotkit.system.service.ISysDataScopeService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 数据权限 实现 + *

+ * 注意: 此Service内不允许调用标注`数据权限`注解的方法 + * 例如: deptMapper.selectList 此 selectList 方法标注了`数据权限`注解 会出现循环解析的问题 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service("sdss") +public class SysDataScopeServiceImpl implements ISysDataScopeService { + + private final SysRoleDeptMapper roleDeptMapper; + private final SysDeptMapper deptMapper; + + @Override + public String getRoleCustom(Long roleId) { + List list = roleDeptMapper.selectList( + new LambdaQueryWrapper() + .select(SysRoleDept::getDeptId) + .eq(SysRoleDept::getRoleId, roleId)); + if (CollUtil.isNotEmpty(list)) { + return StreamUtils.join(list, rd -> Convert.toStr(rd.getDeptId())); + } + return null; + } + + @Override + public String getDeptAndChild(Long deptId) { + List deptList = deptMapper.selectList(new LambdaQueryWrapper() + .select(SysDept::getDeptId) + .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); + List ids = StreamUtils.toList(deptList, SysDept::getDeptId); + ids.add(deptId); + List list = deptMapper.selectList(new LambdaQueryWrapper() + .select(SysDept::getDeptId) + .in(SysDept::getDeptId, ids)); + if (CollUtil.isNotEmpty(list)) { + return StreamUtils.join(list, d -> Convert.toStr(d.getDeptId())); + } + return null; + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDeptServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDeptServiceImpl.java new file mode 100644 index 00000000..380b56ec --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,325 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.bo.SysDeptBo; +import cc.iotkit.system.domain.vo.SysDeptVo; +import cc.iotkit.system.mapper.SysDeptMapper; +import cc.iotkit.system.mapper.SysRoleMapper; +import cc.iotkit.system.mapper.SysUserMapper; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import org.dromara.common.core.constant.CacheNames; +import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.DeptService; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.TreeBuildUtils; +import org.dromara.common.mybatis.helper.DataBaseHelper; +import org.dromara.common.redis.utils.CacheUtils; +import org.dromara.common.satoken.utils.LoginHelper; +import cc.iotkit.system.domain.SysDept; +import cc.iotkit.system.domain.SysRole; +import cc.iotkit.system.domain.SysUser; +import cc.iotkit.system.service.ISysDeptService; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 部门管理 服务实现 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysDeptServiceImpl implements ISysDeptService, DeptService { + + private final SysDeptMapper baseMapper; + private final SysRoleMapper roleMapper; + private final SysUserMapper userMapper; + + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + @Override + public List selectDeptList(SysDeptBo dept) { + LambdaQueryWrapper lqw = buildQueryWrapper(dept); + return baseMapper.selectDeptList(lqw); + } + + /** + * 查询部门树结构信息 + * + * @param bo 部门信息 + * @return 部门树信息集合 + */ + @Override + public List> selectDeptTreeList(SysDeptBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + List depts = baseMapper.selectList(lqw); + return buildDeptTreeSelect(depts); + } + + private LambdaQueryWrapper buildQueryWrapper(SysDeptBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(SysDept::getDelFlag, "0"); + lqw.eq(ObjectUtil.isNotNull(bo.getDeptId()), SysDept::getDeptId, bo.getDeptId()); + lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), SysDept::getParentId, bo.getParentId()); + lqw.like(StringUtils.isNotBlank(bo.getDeptName()), SysDept::getDeptName, bo.getDeptName()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysDept::getStatus, bo.getStatus()); + lqw.orderByAsc(SysDept::getParentId); + lqw.orderByAsc(SysDept::getOrderNum); + return lqw; + } + + /** + * 构建前端所需要下拉树结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + @Override + public List> buildDeptTreeSelect(List depts) { + if (CollUtil.isEmpty(depts)) { + return CollUtil.newArrayList(); + } + return TreeBuildUtils.build(depts, (dept, tree) -> + tree.setId(dept.getDeptId()) + .setParentId(dept.getParentId()) + .setName(dept.getDeptName()) + .setWeight(dept.getOrderNum())); + } + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + @Override + public List selectDeptListByRoleId(Long roleId) { + SysRole role = roleMapper.selectById(roleId); + return baseMapper.selectDeptListByRoleId(roleId, role.getDeptCheckStrictly()); + } + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + @Cacheable(cacheNames = CacheNames.SYS_DEPT, key = "#deptId") + @Override + public SysDeptVo selectDeptById(Long deptId) { + SysDeptVo dept = baseMapper.selectVoById(deptId); + if (ObjectUtil.isNull(dept)) { + return null; + } + SysDeptVo parentDept = baseMapper.selectVoOne(new LambdaQueryWrapper() + .select(SysDept::getDeptName).eq(SysDept::getDeptId, dept.getParentId())); + dept.setParentName(ObjectUtil.isNotNull(parentDept) ? parentDept.getDeptName() : null); + return dept; + } + + /** + * 通过部门ID查询部门名称 + * + * @param deptIds 部门ID串逗号分隔 + * @return 部门名称串逗号分隔 + */ + @Override + public String selectDeptNameByIds(String deptIds) { + List list = new ArrayList<>(); + for (Long id : StringUtils.splitTo(deptIds, Convert::toLong)) { + SysDeptVo vo = SpringUtils.getAopProxy(this).selectDeptById(id); + if (ObjectUtil.isNotNull(vo)) { + list.add(vo.getDeptName()); + } + } + return String.join(StringUtils.SEPARATOR, list); + } + + /** + * 根据ID查询所有子部门数(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + @Override + public long selectNormalChildrenDeptById(Long deptId) { + return baseMapper.selectCount(new LambdaQueryWrapper() + .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL) + .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); + } + + /** + * 是否存在子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public boolean hasChildByDeptId(Long deptId) { + return baseMapper.exists(new LambdaQueryWrapper() + .eq(SysDept::getParentId, deptId)); + } + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + @Override + public boolean checkDeptExistUser(Long deptId) { + return userMapper.exists(new LambdaQueryWrapper() + .eq(SysUser::getDeptId, deptId)); + } + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public boolean checkDeptNameUnique(SysDeptBo dept) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysDept::getDeptName, dept.getDeptName()) + .eq(SysDept::getParentId, dept.getParentId()) + .ne(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId())); + return !exist; + } + + /** + * 校验部门是否有数据权限 + * + * @param deptId 部门id + */ + @Override + public void checkDeptDataScope(Long deptId) { + if (ObjectUtil.isNull(deptId)) { + return; + } + if (LoginHelper.isSuperAdmin()) { + return; + } + SysDeptVo dept = baseMapper.selectDeptById(deptId); + if (ObjectUtil.isNull(dept)) { + throw new ServiceException("没有权限访问部门数据!"); + } + } + + /** + * 新增保存部门信息 + * + * @param bo 部门信息 + * @return 结果 + */ + @Override + public int insertDept(SysDeptBo bo) { + SysDept info = baseMapper.selectById(bo.getParentId()); + // 如果父节点不为正常状态,则不允许新增子节点 + if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) { + throw new ServiceException("部门停用,不允许新增"); + } + SysDept dept = MapstructUtils.convert(bo, SysDept.class); + dept.setAncestors(info.getAncestors() + StringUtils.SEPARATOR + dept.getParentId()); + return baseMapper.insert(dept); + } + + /** + * 修改保存部门信息 + * + * @param bo 部门信息 + * @return 结果 + */ + @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#bo.deptId") + @Override + public int updateDept(SysDeptBo bo) { + SysDept dept = MapstructUtils.convert(bo, SysDept.class); + SysDept oldDept = baseMapper.selectById(dept.getDeptId()); + if (!oldDept.getParentId().equals(dept.getParentId())) { + // 如果是新父部门 则校验是否具有新父部门权限 避免越权 + this.checkDeptDataScope(dept.getParentId()); + SysDept newParentDept = baseMapper.selectById(dept.getParentId()); + if (ObjectUtil.isNotNull(newParentDept) && ObjectUtil.isNotNull(oldDept)) { + String newAncestors = newParentDept.getAncestors() + StringUtils.SEPARATOR + newParentDept.getDeptId(); + String oldAncestors = oldDept.getAncestors(); + dept.setAncestors(newAncestors); + updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors); + } + } + int result = baseMapper.updateById(dept); + if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) + && !StringUtils.equals(UserConstants.DEPT_NORMAL, dept.getAncestors())) { + // 如果该部门是启用状态,则启用该部门的所有上级部门 + updateParentDeptStatusNormal(dept); + } + return result; + } + + /** + * 修改该部门的父级部门状态 + * + * @param dept 当前部门 + */ + private void updateParentDeptStatusNormal(SysDept dept) { + String ancestors = dept.getAncestors(); + Long[] deptIds = Convert.toLongArray(ancestors); + baseMapper.update(null, new LambdaUpdateWrapper() + .set(SysDept::getStatus, UserConstants.DEPT_NORMAL) + .in(SysDept::getDeptId, Arrays.asList(deptIds))); + } + + /** + * 修改子元素关系 + * + * @param deptId 被修改的部门ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + private void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) { + List children = baseMapper.selectList(new LambdaQueryWrapper() + .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); + List list = new ArrayList<>(); + for (SysDept child : children) { + SysDept dept = new SysDept(); + dept.setDeptId(child.getDeptId()); + dept.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); + list.add(dept); + } + if (CollUtil.isNotEmpty(list)) { + if (baseMapper.updateBatchById(list)) { + list.forEach(dept -> CacheUtils.evict(CacheNames.SYS_DEPT, dept.getDeptId())); + } + } + } + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#deptId") + @Override + public int deleteDeptById(Long deptId) { + return baseMapper.deleteById(deptId); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDictDataServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 00000000..672443bb --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDictDataServiceImpl.java @@ -0,0 +1,139 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.SysDictData; +import cc.iotkit.system.domain.bo.SysDictDataBo; +import cc.iotkit.system.domain.vo.SysDictDataVo; +import cc.iotkit.system.mapper.SysDictDataMapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.core.constant.CacheNames; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.redis.utils.CacheUtils; +import cc.iotkit.system.service.ISysDictDataService; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CachePut; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 字典 业务层处理 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysDictDataServiceImpl implements ISysDictDataService { + + private final SysDictDataMapper baseMapper; + + @Override + public TableDataInfo selectPageDictDataList(SysDictDataBo dictData, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(dictData); + Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(page); + } + + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + @Override + public List selectDictDataList(SysDictDataBo dictData) { + LambdaQueryWrapper lqw = buildQueryWrapper(dictData); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysDictDataBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(bo.getDictSort() != null, SysDictData::getDictSort, bo.getDictSort()); + lqw.like(StringUtils.isNotBlank(bo.getDictLabel()), SysDictData::getDictLabel, bo.getDictLabel()); + lqw.eq(StringUtils.isNotBlank(bo.getDictType()), SysDictData::getDictType, bo.getDictType()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysDictData::getStatus, bo.getStatus()); + lqw.orderByAsc(SysDictData::getDictSort); + return lqw; + } + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + @Override + public String selectDictLabel(String dictType, String dictValue) { + return baseMapper.selectOne(new LambdaQueryWrapper() + .select(SysDictData::getDictLabel) + .eq(SysDictData::getDictType, dictType) + .eq(SysDictData::getDictValue, dictValue)) + .getDictLabel(); + } + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + @Override + public SysDictDataVo selectDictDataById(Long dictCode) { + return baseMapper.selectVoById(dictCode); + } + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + */ + @Override + public void deleteDictDataByIds(Long[] dictCodes) { + for (Long dictCode : dictCodes) { + SysDictData data = baseMapper.selectById(dictCode); + baseMapper.deleteById(dictCode); + CacheUtils.evict(CacheNames.SYS_DICT, data.getDictType()); + } + } + + /** + * 新增保存字典数据信息 + * + * @param bo 字典数据信息 + * @return 结果 + */ + @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#bo.dictType") + @Override + public List insertDictData(SysDictDataBo bo) { + SysDictData data = MapstructUtils.convert(bo, SysDictData.class); + int row = baseMapper.insert(data); + if (row > 0) { + return baseMapper.selectDictDataByType(data.getDictType()); + } + throw new ServiceException("操作失败"); + } + + /** + * 修改保存字典数据信息 + * + * @param bo 字典数据信息 + * @return 结果 + */ + @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#bo.dictType") + @Override + public List updateDictData(SysDictDataBo bo) { + SysDictData data = MapstructUtils.convert(bo, SysDictData.class); + int row = baseMapper.updateById(data); + if (row > 0) { + return baseMapper.selectDictDataByType(data.getDictType()); + } + throw new ServiceException("操作失败"); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDictTypeServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDictTypeServiceImpl.java new file mode 100644 index 00000000..48e82ee6 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysDictTypeServiceImpl.java @@ -0,0 +1,268 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.SysDictData; +import cc.iotkit.system.domain.SysDictType; +import cc.iotkit.system.domain.bo.SysDictTypeBo; +import cc.iotkit.system.domain.vo.SysDictDataVo; +import cc.iotkit.system.domain.vo.SysDictTypeVo; +import cc.iotkit.system.mapper.SysDictDataMapper; +import cc.iotkit.system.mapper.SysDictTypeMapper; +import cn.dev33.satoken.context.SaHolder; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.core.constant.CacheConstants; +import org.dromara.common.core.constant.CacheNames; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.DictService; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.redis.utils.CacheUtils; +import cc.iotkit.system.service.ISysDictTypeService; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 字典 业务层处理 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService { + + private final SysDictTypeMapper baseMapper; + private final SysDictDataMapper dictDataMapper; + + @Override + public TableDataInfo selectPageDictTypeList(SysDictTypeBo dictType, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(dictType); + Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(page); + } + + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeList(SysDictTypeBo dictType) { + LambdaQueryWrapper lqw = buildQueryWrapper(dictType); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysDictTypeBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getDictName()), SysDictType::getDictName, bo.getDictName()); + lqw.like(StringUtils.isNotBlank(bo.getDictType()), SysDictType::getDictType, bo.getDictType()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysDictType::getStatus, bo.getStatus()); + lqw.between(params.get("beginTime") != null && params.get("endTime") != null, + SysDictType::getCreateTime, params.get("beginTime"), params.get("endTime")); + return lqw; + } + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeAll() { + return baseMapper.selectVoList(); + } + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType") + @Override + public List selectDictDataByType(String dictType) { + List dictDatas = dictDataMapper.selectDictDataByType(dictType); + if (CollUtil.isNotEmpty(dictDatas)) { + return dictDatas; + } + return null; + } + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + @Override + public SysDictTypeVo selectDictTypeById(Long dictId) { + return baseMapper.selectVoById(dictId); + } + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType") + @Override + public SysDictTypeVo selectDictTypeByType(String dictType) { + return baseMapper.selectVoById(new LambdaQueryWrapper().eq(SysDictType::getDictType, dictType)); + } + + /** + * 批量删除字典类型信息 + * + * @param dictIds 需要删除的字典ID + */ + @Override + public void deleteDictTypeByIds(Long[] dictIds) { + for (Long dictId : dictIds) { + SysDictType dictType = baseMapper.selectById(dictId); + if (dictDataMapper.exists(new LambdaQueryWrapper() + .eq(SysDictData::getDictType, dictType.getDictType()))) { + throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName())); + } + CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType()); + } + baseMapper.deleteBatchIds(Arrays.asList(dictIds)); + } + + /** + * 重置字典缓存数据 + */ + @Override + public void resetDictCache() { + CacheUtils.clear(CacheNames.SYS_DICT); + } + + /** + * 新增保存字典类型信息 + * + * @param bo 字典类型信息 + * @return 结果 + */ + @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#bo.dictType") + @Override + public List insertDictType(SysDictTypeBo bo) { + SysDictType dict = MapstructUtils.convert(bo, SysDictType.class); + int row = baseMapper.insert(dict); + if (row > 0) { + return new ArrayList<>(); + } + throw new ServiceException("操作失败"); + } + + /** + * 修改保存字典类型信息 + * + * @param bo 字典类型信息 + * @return 结果 + */ + @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#bo.dictType") + @Override + @Transactional(rollbackFor = Exception.class) + public List updateDictType(SysDictTypeBo bo) { + SysDictType dict = MapstructUtils.convert(bo, SysDictType.class); + SysDictType oldDict = baseMapper.selectById(dict.getDictId()); + dictDataMapper.update(null, new LambdaUpdateWrapper() + .set(SysDictData::getDictType, dict.getDictType()) + .eq(SysDictData::getDictType, oldDict.getDictType())); + int row = baseMapper.updateById(dict); + if (row > 0) { + CacheUtils.evict(CacheNames.SYS_DICT, oldDict.getDictType()); + return dictDataMapper.selectDictDataByType(dict.getDictType()); + } + throw new ServiceException("操作失败"); + } + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + @Override + public boolean checkDictTypeUnique(SysDictTypeBo dictType) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysDictType::getDictType, dictType.getDictType()) + .ne(ObjectUtil.isNotNull(dictType.getDictId()), SysDictType::getDictId, dictType.getDictId())); + return !exist; + } + + /** + * 根据字典类型和字典值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @param separator 分隔符 + * @return 字典标签 + */ + @SuppressWarnings("unchecked cast") + @Override + public String getDictLabel(String dictType, String dictValue, String separator) { + // 优先从本地缓存获取 + List datas = (List) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType); + if (ObjectUtil.isNull(datas)) { + datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); + SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas); + } + + Map map = StreamUtils.toMap(datas, SysDictDataVo::getDictValue, SysDictDataVo::getDictLabel); + if (StringUtils.containsAny(dictValue, separator)) { + return Arrays.stream(dictValue.split(separator)) + .map(v -> map.getOrDefault(v, StringUtils.EMPTY)) + .collect(Collectors.joining(separator)); + } else { + return map.getOrDefault(dictValue, StringUtils.EMPTY); + } + } + + /** + * 根据字典类型和字典标签获取字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @param separator 分隔符 + * @return 字典值 + */ + @SuppressWarnings("unchecked cast") + @Override + public String getDictValue(String dictType, String dictLabel, String separator) { + // 优先从本地缓存获取 + List datas = (List) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType); + if (ObjectUtil.isNull(datas)) { + datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); + SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas); + } + + Map map = StreamUtils.toMap(datas, SysDictDataVo::getDictLabel, SysDictDataVo::getDictValue); + if (StringUtils.containsAny(dictLabel, separator)) { + return Arrays.stream(dictLabel.split(separator)) + .map(l -> map.getOrDefault(l, StringUtils.EMPTY)) + .collect(Collectors.joining(separator)); + } else { + return map.getOrDefault(dictLabel, StringUtils.EMPTY); + } + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysLogininforServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysLogininforServiceImpl.java new file mode 100644 index 00000000..10b5d246 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysLogininforServiceImpl.java @@ -0,0 +1,160 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.SysLogininfor; +import cc.iotkit.system.domain.bo.SysLogininforBo; +import cc.iotkit.system.domain.vo.SysLogininforVo; +import cc.iotkit.system.mapper.SysLogininforMapper; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.core.constant.Constants; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.log.event.LogininforEvent; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.core.utils.ServletUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.ip.AddressUtils; +import cc.iotkit.system.service.ISysLogininforService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * 系统访问日志情况信息 服务层处理 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Slf4j +@Service +public class SysLogininforServiceImpl implements ISysLogininforService { + + private final SysLogininforMapper baseMapper; + + /** + * 记录登录信息 + * + * @param logininforEvent 登录事件 + */ + @Async + @EventListener + public void recordLogininfor(LogininforEvent logininforEvent) { + HttpServletRequest request = logininforEvent.getRequest(); + final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); + final String ip = ServletUtils.getClientIP(request); + + String address = AddressUtils.getRealAddressByIP(ip); + StringBuilder s = new StringBuilder(); + s.append(getBlock(ip)); + s.append(address); + s.append(getBlock(logininforEvent.getUsername())); + s.append(getBlock(logininforEvent.getStatus())); + s.append(getBlock(logininforEvent.getMessage())); + // 打印信息到日志 + log.info(s.toString(), logininforEvent.getArgs()); + // 获取客户端操作系统 + String os = userAgent.getOs().getName(); + // 获取客户端浏览器 + String browser = userAgent.getBrowser().getName(); + // 封装对象 + SysLogininforBo logininfor = new SysLogininforBo(); + logininfor.setTenantId(logininforEvent.getTenantId()); + logininfor.setUserName(logininforEvent.getUsername()); + logininfor.setIpaddr(ip); + logininfor.setLoginLocation(address); + logininfor.setBrowser(browser); + logininfor.setOs(os); + logininfor.setMsg(logininforEvent.getMessage()); + // 日志状态 + if (StringUtils.equalsAny(logininforEvent.getStatus(), Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) { + logininfor.setStatus(Constants.SUCCESS); + } else if (Constants.LOGIN_FAIL.equals(logininforEvent.getStatus())) { + logininfor.setStatus(Constants.FAIL); + } + // 插入数据 + insertLogininfor(logininfor); + } + + private String getBlock(Object msg) { + if (msg == null) { + msg = ""; + } + return "[" + msg.toString() + "]"; + } + + @Override + public TableDataInfo selectPageLogininforList(SysLogininforBo logininfor, PageQuery pageQuery) { + Map params = logininfor.getParams(); + LambdaQueryWrapper lqw = new LambdaQueryWrapper() + .like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr()) + .eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus()) + .like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName()) + .between(params.get("beginTime") != null && params.get("endTime") != null, + SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime")); + if (StringUtils.isBlank(pageQuery.getOrderByColumn())) { + pageQuery.setOrderByColumn("info_id"); + pageQuery.setIsAsc("desc"); + } + Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(page); + } + + /** + * 新增系统登录日志 + * + * @param bo 访问日志对象 + */ + @Override + public void insertLogininfor(SysLogininforBo bo) { + SysLogininfor logininfor = MapstructUtils.convert(bo, SysLogininfor.class); + logininfor.setLoginTime(new Date()); + baseMapper.insert(logininfor); + } + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + @Override + public List selectLogininforList(SysLogininforBo logininfor) { + Map params = logininfor.getParams(); + return baseMapper.selectVoList(new LambdaQueryWrapper() + .like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr()) + .eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus()) + .like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName()) + .between(params.get("beginTime") != null && params.get("endTime") != null, + SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime")) + .orderByDesc(SysLogininfor::getInfoId)); + } + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + @Override + public int deleteLogininforByIds(Long[] infoIds) { + return baseMapper.deleteBatchIds(Arrays.asList(infoIds)); + } + + /** + * 清空系统登录日志 + */ + @Override + public void cleanLogininfor() { + baseMapper.delete(new LambdaQueryWrapper<>()); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysMenuServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysMenuServiceImpl.java new file mode 100644 index 00000000..c7a48944 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,365 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.bo.SysMenuBo; +import cc.iotkit.system.domain.vo.MetaVo; +import cc.iotkit.system.domain.vo.RouterVo; +import cc.iotkit.system.domain.vo.SysMenuVo; +import cc.iotkit.system.mapper.SysMenuMapper; +import cc.iotkit.system.mapper.SysRoleMapper; +import cc.iotkit.system.mapper.SysRoleMenuMapper; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.TreeBuildUtils; +import org.dromara.common.satoken.utils.LoginHelper; +import cc.iotkit.system.domain.SysMenu; +import cc.iotkit.system.domain.SysRole; +import cc.iotkit.system.domain.SysRoleMenu; +import cc.iotkit.system.domain.SysTenantPackage; +import cc.iotkit.system.mapper.SysTenantPackageMapper; +import cc.iotkit.system.service.ISysMenuService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 菜单 业务层处理 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysMenuServiceImpl implements ISysMenuService { + + private final SysMenuMapper baseMapper; + private final SysRoleMapper roleMapper; + private final SysRoleMenuMapper roleMenuMapper; + private final SysTenantPackageMapper tenantPackageMapper; + + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + @Override + public List selectMenuList(Long userId) { + return selectMenuList(new SysMenuBo(), userId); + } + + /** + * 查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + @Override + public List selectMenuList(SysMenuBo menu, Long userId) { + List menuList; + // 管理员显示所有菜单信息 + if (LoginHelper.isSuperAdmin(userId)) { + menuList = baseMapper.selectVoList(new LambdaQueryWrapper() + .like(StringUtils.isNotBlank(menu.getMenuName()), SysMenu::getMenuName, menu.getMenuName()) + .eq(StringUtils.isNotBlank(menu.getVisible()), SysMenu::getVisible, menu.getVisible()) + .eq(StringUtils.isNotBlank(menu.getStatus()), SysMenu::getStatus, menu.getStatus()) + .orderByAsc(SysMenu::getParentId) + .orderByAsc(SysMenu::getOrderNum)); + } else { + QueryWrapper wrapper = Wrappers.query(); + wrapper.eq("sur.user_id", userId) + .like(StringUtils.isNotBlank(menu.getMenuName()), "m.menu_name", menu.getMenuName()) + .eq(StringUtils.isNotBlank(menu.getVisible()), "m.visible", menu.getVisible()) + .eq(StringUtils.isNotBlank(menu.getStatus()), "m.status", menu.getStatus()) + .orderByAsc("m.parent_id") + .orderByAsc("m.order_num"); + List list = baseMapper.selectMenuListByUserId(wrapper); + menuList = MapstructUtils.convert(list, SysMenuVo.class); + } + return menuList; + } + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + @Override + public Set selectMenuPermsByUserId(Long userId) { + List perms = baseMapper.selectMenuPermsByUserId(userId); + Set permsSet = new HashSet<>(); + for (String perm : perms) { + if (StringUtils.isNotEmpty(perm)) { + permsSet.addAll(StringUtils.splitList(perm.trim())); + } + } + return permsSet; + } + + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + @Override + public Set selectMenuPermsByRoleId(Long roleId) { + List perms = baseMapper.selectMenuPermsByRoleId(roleId); + Set permsSet = new HashSet<>(); + for (String perm : perms) { + if (StringUtils.isNotEmpty(perm)) { + permsSet.addAll(StringUtils.splitList(perm.trim())); + } + } + return permsSet; + } + + /** + * 根据用户ID查询菜单 + * + * @param userId 用户名称 + * @return 菜单列表 + */ + @Override + public List selectMenuTreeByUserId(Long userId) { + List menus; + if (LoginHelper.isSuperAdmin(userId)) { + menus = baseMapper.selectMenuTreeAll(); + } else { + menus = baseMapper.selectMenuTreeByUserId(userId); + } + return getChildPerms(menus, 0); + } + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + @Override + public List selectMenuListByRoleId(Long roleId) { + SysRole role = roleMapper.selectById(roleId); + return baseMapper.selectMenuListByRoleId(roleId, role.getMenuCheckStrictly()); + } + + /** + * 根据租户套餐ID查询菜单树信息 + * + * @param packageId 租户套餐ID + * @return 选中菜单列表 + */ + @Override + public List selectMenuListByPackageId(Long packageId) { + SysTenantPackage tenantPackage = tenantPackageMapper.selectById(packageId); + List menuIds = StringUtils.splitTo(tenantPackage.getMenuIds(), Convert::toLong); + if (CollUtil.isEmpty(menuIds)) { + return List.of(); + } + List parentIds = null; + if (tenantPackage.getMenuCheckStrictly()) { + parentIds = baseMapper.selectObjs(new LambdaQueryWrapper() + .select(SysMenu::getParentId) + .in(SysMenu::getMenuId, menuIds), Convert::toLong); + } + return baseMapper.selectObjs(new LambdaQueryWrapper() + .in(SysMenu::getMenuId, menuIds) + .notIn(CollUtil.isNotEmpty(parentIds), SysMenu::getMenuId, parentIds), Convert::toLong); + } + + /** + * 构建前端路由所需要的菜单 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + @Override + public List buildMenus(List menus) { + List routers = new LinkedList<>(); + for (SysMenu menu : menus) { + RouterVo router = new RouterVo(); + router.setHidden("1".equals(menu.getVisible())); + router.setName(menu.getRouteName()); + router.setPath(menu.getRouterPath()); + router.setComponent(menu.getComponentInfo()); + router.setQuery(menu.getQueryParam()); + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + List cMenus = menu.getChildren(); + if (CollUtil.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { + router.setAlwaysShow(true); + router.setRedirect("noRedirect"); + router.setChildren(buildMenus(cMenus)); + } else if (menu.isMenuFrame()) { + router.setMeta(null); + List childrenList = new ArrayList<>(); + RouterVo children = new RouterVo(); + children.setPath(menu.getPath()); + children.setComponent(menu.getComponentInfo()); + children.setName(StringUtils.capitalize(menu.getPath())); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + children.setQuery(menu.getQueryParam()); + childrenList.add(children); + router.setChildren(childrenList); + } else if (menu.getParentId().intValue() == 0 && menu.isInnerLink()) { + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); + router.setPath("/"); + List childrenList = new ArrayList<>(); + RouterVo children = new RouterVo(); + String routerPath = SysMenu.innerLinkReplaceEach(menu.getPath()); + children.setPath(routerPath); + children.setComponent(UserConstants.INNER_LINK); + children.setName(StringUtils.capitalize(routerPath)); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); + childrenList.add(children); + router.setChildren(childrenList); + } + routers.add(router); + } + return routers; + } + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + @Override + public List> buildMenuTreeSelect(List menus) { + if (CollUtil.isEmpty(menus)) { + return CollUtil.newArrayList(); + } + return TreeBuildUtils.build(menus, (menu, tree) -> + tree.setId(menu.getMenuId()) + .setParentId(menu.getParentId()) + .setName(menu.getMenuName()) + .setWeight(menu.getOrderNum())); + } + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + @Override + public SysMenuVo selectMenuById(Long menuId) { + return baseMapper.selectVoById(menuId); + } + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean hasChildByMenuId(Long menuId) { + return baseMapper.exists(new LambdaQueryWrapper().eq(SysMenu::getParentId, menuId)); + } + + /** + * 查询菜单使用数量 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean checkMenuExistRole(Long menuId) { + return roleMenuMapper.exists(new LambdaQueryWrapper().eq(SysRoleMenu::getMenuId, menuId)); + } + + /** + * 新增保存菜单信息 + * + * @param bo 菜单信息 + * @return 结果 + */ + @Override + public int insertMenu(SysMenuBo bo) { + SysMenu menu = MapstructUtils.convert(bo, SysMenu.class); + return baseMapper.insert(menu); + } + + /** + * 修改保存菜单信息 + * + * @param bo 菜单信息 + * @return 结果 + */ + @Override + public int updateMenu(SysMenuBo bo) { + SysMenu menu = MapstructUtils.convert(bo, SysMenu.class); + return baseMapper.updateById(menu); + } + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public int deleteMenuById(Long menuId) { + return baseMapper.deleteById(menuId); + } + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public boolean checkMenuNameUnique(SysMenuBo menu) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysMenu::getMenuName, menu.getMenuName()) + .eq(SysMenu::getParentId, menu.getParentId()) + .ne(ObjectUtil.isNotNull(menu.getMenuId()), SysMenu::getMenuId, menu.getMenuId())); + return !exist; + } + + /** + * 根据父节点的ID获取所有子节点 + * + * @param list 分类表 + * @param parentId 传入的父节点ID + * @return String + */ + private List getChildPerms(List list, int parentId) { + List returnList = new ArrayList<>(); + for (SysMenu t : list) { + // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点 + if (t.getParentId() == parentId) { + recursionFn(list, t); + returnList.add(t); + } + } + return returnList; + } + + /** + * 递归列表 + */ + private void recursionFn(List list, SysMenu t) { + // 得到子节点列表 + List childList = StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId())); + t.setChildren(childList); + for (SysMenu tChild : childList) { + // 判断是否有子节点 + if (list.stream().anyMatch(n -> n.getParentId().equals(tChild.getMenuId()))) { + recursionFn(list, tChild); + } + } + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysNoticeServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 00000000..acc9c436 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysNoticeServiceImpl.java @@ -0,0 +1,122 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.bo.SysNoticeBo; +import cc.iotkit.system.domain.vo.SysNoticeVo; +import cc.iotkit.system.domain.vo.SysUserVo; +import cc.iotkit.system.mapper.SysNoticeMapper; +import cc.iotkit.system.mapper.SysUserMapper; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import cc.iotkit.system.domain.SysNotice; +import cc.iotkit.system.service.ISysNoticeService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.List; + +/** + * 公告 服务层实现 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysNoticeServiceImpl implements ISysNoticeService { + + private final SysNoticeMapper baseMapper; + private final SysUserMapper userMapper; + + @Override + public TableDataInfo selectPageNoticeList(SysNoticeBo notice, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(notice); + Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(page); + } + + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + @Override + public SysNoticeVo selectNoticeById(Long noticeId) { + return baseMapper.selectVoById(noticeId); + } + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + @Override + public List selectNoticeList(SysNoticeBo notice) { + LambdaQueryWrapper lqw = buildQueryWrapper(notice); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysNoticeBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getNoticeTitle()), SysNotice::getNoticeTitle, bo.getNoticeTitle()); + lqw.eq(StringUtils.isNotBlank(bo.getNoticeType()), SysNotice::getNoticeType, bo.getNoticeType()); + if (StringUtils.isNotBlank(bo.getCreateByName())) { + SysUserVo sysUser = userMapper.selectUserByUserName(bo.getCreateByName()); + lqw.eq(SysNotice::getCreateBy, ObjectUtil.isNotNull(sysUser) ? sysUser.getUserId() : null); + } + return lqw; + } + + /** + * 新增公告 + * + * @param bo 公告信息 + * @return 结果 + */ + @Override + public int insertNotice(SysNoticeBo bo) { + SysNotice notice = MapstructUtils.convert(bo, SysNotice.class); + return baseMapper.insert(notice); + } + + /** + * 修改公告 + * + * @param bo 公告信息 + * @return 结果 + */ + @Override + public int updateNotice(SysNoticeBo bo) { + SysNotice notice = MapstructUtils.convert(bo, SysNotice.class); + return baseMapper.updateById(notice); + } + + /** + * 删除公告对象 + * + * @param noticeId 公告ID + * @return 结果 + */ + @Override + public int deleteNoticeById(Long noticeId) { + return baseMapper.deleteById(noticeId); + } + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + @Override + public int deleteNoticeByIds(Long[] noticeIds) { + return baseMapper.deleteBatchIds(Arrays.asList(noticeIds)); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysOperLogServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysOperLogServiceImpl.java new file mode 100644 index 00000000..30249abb --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysOperLogServiceImpl.java @@ -0,0 +1,144 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.SysOperLog; +import cc.iotkit.system.domain.bo.SysOperLogBo; +import cc.iotkit.system.domain.vo.SysOperLogVo; +import cc.iotkit.system.mapper.SysOperLogMapper; +import cn.hutool.core.util.ArrayUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.ip.AddressUtils; +import org.dromara.common.log.event.OperLogEvent; +import cc.iotkit.system.service.ISysOperLogService; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * 操作日志 服务层处理 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysOperLogServiceImpl implements ISysOperLogService { + + private final SysOperLogMapper baseMapper; + + /** + * 操作日志记录 + * + * @param operLogEvent 操作日志事件 + */ + @Async + @EventListener + public void recordOper(OperLogEvent operLogEvent) { + SysOperLogBo operLog = MapstructUtils.convert(operLogEvent, SysOperLogBo.class); + // 远程查询操作地点 + operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); + insertOperlog(operLog); + } + + @Override + public TableDataInfo selectPageOperLogList(SysOperLogBo operLog, PageQuery pageQuery) { + Map params = operLog.getParams(); + LambdaQueryWrapper lqw = new LambdaQueryWrapper() + .like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle()) + .eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0, + SysOperLog::getBusinessType, operLog.getBusinessType()) + .func(f -> { + if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) { + f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes())); + } + }) + .eq(operLog.getStatus() != null, + SysOperLog::getStatus, operLog.getStatus()) + .like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName()) + .between(params.get("beginTime") != null && params.get("endTime") != null, + SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime")); + if (StringUtils.isBlank(pageQuery.getOrderByColumn())) { + pageQuery.setOrderByColumn("oper_id"); + pageQuery.setIsAsc("desc"); + } + Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(page); + } + + /** + * 新增操作日志 + * + * @param bo 操作日志对象 + */ + @Override + public void insertOperlog(SysOperLogBo bo) { + SysOperLog operLog = MapstructUtils.convert(bo, SysOperLog.class); + operLog.setOperTime(new Date()); + baseMapper.insert(operLog); + } + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + @Override + public List selectOperLogList(SysOperLogBo operLog) { + Map params = operLog.getParams(); + return baseMapper.selectVoList(new LambdaQueryWrapper() + .like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle()) + .eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0, + SysOperLog::getBusinessType, operLog.getBusinessType()) + .func(f -> { + if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) { + f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes())); + } + }) + .eq(operLog.getStatus() != null && operLog.getStatus() > 0, + SysOperLog::getStatus, operLog.getStatus()) + .like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName()) + .between(params.get("beginTime") != null && params.get("endTime") != null, + SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime")) + .orderByDesc(SysOperLog::getOperId)); + } + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + @Override + public int deleteOperLogByIds(Long[] operIds) { + return baseMapper.deleteBatchIds(Arrays.asList(operIds)); + } + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + @Override + public SysOperLogVo selectOperLogById(Long operId) { + return baseMapper.selectVoById(operId); + } + + /** + * 清空操作日志 + */ + @Override + public void cleanOperLog() { + baseMapper.delete(new LambdaQueryWrapper<>()); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysOssConfigServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysOssConfigServiceImpl.java new file mode 100644 index 00000000..144c34f3 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysOssConfigServiceImpl.java @@ -0,0 +1,186 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.SysOssConfig; +import cc.iotkit.system.domain.bo.SysOssConfigBo; +import cc.iotkit.system.domain.vo.SysOssConfigVo; +import cc.iotkit.system.mapper.SysOssConfigMapper; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.constant.CacheNames; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.json.utils.JsonUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.oss.constant.OssConstant; +import org.dromara.common.redis.utils.CacheUtils; +import org.dromara.common.redis.utils.RedisUtils; +import org.dromara.common.tenant.core.TenantEntity; +import org.dromara.common.tenant.helper.TenantHelper; +import cc.iotkit.system.service.ISysOssConfigService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 对象存储配置Service业务层处理 + * + * @author Lion Li + * @author 孤舟烟雨 + * @date 2021-08-13 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class SysOssConfigServiceImpl implements ISysOssConfigService { + + private final SysOssConfigMapper baseMapper; + + /** + * 项目启动时,初始化参数到缓存,加载配置类 + */ + @Override + public void init() { + List list = TenantHelper.ignore(() -> + baseMapper.selectList( + new LambdaQueryWrapper().orderByAsc(TenantEntity::getTenantId)) + ); + Map> map = StreamUtils.groupByKey(list, SysOssConfig::getTenantId); + try { + for (String tenantId : map.keySet()) { + TenantHelper.setDynamic(tenantId); + // 加载OSS初始化配置 + for (SysOssConfig config : map.get(tenantId)) { + String configKey = config.getConfigKey(); + if ("0".equals(config.getStatus())) { + RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey); + } + CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); + } + } + } finally { + TenantHelper.clearDynamic(); + } + } + + @Override + public SysOssConfigVo queryById(Long ossConfigId) { + return baseMapper.selectVoById(ossConfigId); + } + + @Override + public TableDataInfo queryPageList(SysOssConfigBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + + private LambdaQueryWrapper buildQueryWrapper(SysOssConfigBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(StringUtils.isNotBlank(bo.getConfigKey()), SysOssConfig::getConfigKey, bo.getConfigKey()); + lqw.like(StringUtils.isNotBlank(bo.getBucketName()), SysOssConfig::getBucketName, bo.getBucketName()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysOssConfig::getStatus, bo.getStatus()); + return lqw; + } + + @Override + public Boolean insertByBo(SysOssConfigBo bo) { + SysOssConfig config = MapstructUtils.convert(bo, SysOssConfig.class); + validEntityBeforeSave(config); + boolean flag = baseMapper.insert(config) > 0; + if (flag) { + CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); + } + return flag; + } + + @Override + public Boolean updateByBo(SysOssConfigBo bo) { + SysOssConfig config = MapstructUtils.convert(bo, SysOssConfig.class); + validEntityBeforeSave(config); + LambdaUpdateWrapper luw = new LambdaUpdateWrapper<>(); + luw.set(ObjectUtil.isNull(config.getPrefix()), SysOssConfig::getPrefix, ""); + luw.set(ObjectUtil.isNull(config.getRegion()), SysOssConfig::getRegion, ""); + luw.set(ObjectUtil.isNull(config.getExt1()), SysOssConfig::getExt1, ""); + luw.set(ObjectUtil.isNull(config.getRemark()), SysOssConfig::getRemark, ""); + luw.eq(SysOssConfig::getOssConfigId, config.getOssConfigId()); + boolean flag = baseMapper.update(config, luw) > 0; + if (flag) { + CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); + } + return flag; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(SysOssConfig entity) { + if (StringUtils.isNotEmpty(entity.getConfigKey()) + && !checkConfigKeyUnique(entity)) { + throw new ServiceException("操作配置'" + entity.getConfigKey() + "'失败, 配置key已存在!"); + } + } + + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if (isValid) { + if (CollUtil.containsAny(ids, OssConstant.SYSTEM_DATA_IDS)) { + throw new ServiceException("系统内置, 不可删除!"); + } + } + List list = CollUtil.newArrayList(); + for (Long configId : ids) { + SysOssConfig config = baseMapper.selectById(configId); + list.add(config); + } + boolean flag = baseMapper.deleteBatchIds(ids) > 0; + if (flag) { + list.forEach(sysOssConfig -> + CacheUtils.evict(CacheNames.SYS_OSS_CONFIG, sysOssConfig.getConfigKey())); + } + return flag; + } + + /** + * 判断configKey是否唯一 + */ + private boolean checkConfigKeyUnique(SysOssConfig sysOssConfig) { + long ossConfigId = ObjectUtil.isNull(sysOssConfig.getOssConfigId()) ? -1L : sysOssConfig.getOssConfigId(); + SysOssConfig info = baseMapper.selectOne(new LambdaQueryWrapper() + .select(SysOssConfig::getOssConfigId, SysOssConfig::getConfigKey) + .eq(SysOssConfig::getConfigKey, sysOssConfig.getConfigKey())); + if (ObjectUtil.isNotNull(info) && info.getOssConfigId() != ossConfigId) { + return false; + } + return true; + } + + /** + * 启用禁用状态 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int updateOssConfigStatus(SysOssConfigBo bo) { + SysOssConfig sysOssConfig = MapstructUtils.convert(bo, SysOssConfig.class); + int row = baseMapper.update(null, new LambdaUpdateWrapper() + .set(SysOssConfig::getStatus, "1")); + row += baseMapper.updateById(sysOssConfig); + if (row > 0) { + RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, sysOssConfig.getConfigKey()); + } + return row; + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysOssServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysOssServiceImpl.java new file mode 100644 index 00000000..afac795f --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysOssServiceImpl.java @@ -0,0 +1,171 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.bo.SysOssBo; +import cc.iotkit.system.domain.vo.SysOssVo; +import cc.iotkit.system.mapper.SysOssMapper; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.core.constant.CacheNames; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.OssService; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.file.FileUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.oss.core.OssClient; +import org.dromara.common.oss.entity.UploadResult; +import org.dromara.common.oss.enumd.AccessPolicyType; +import org.dromara.common.oss.factory.OssFactory; +import cc.iotkit.system.domain.SysOss; +import cc.iotkit.system.service.ISysOssService; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.util.*; + +/** + * 文件上传 服务层实现 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysOssServiceImpl implements ISysOssService, OssService { + + private final SysOssMapper baseMapper; + + @Override + public TableDataInfo queryPageList(SysOssBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + List filterResult = StreamUtils.toList(result.getRecords(), this::matchingUrl); + result.setRecords(filterResult); + return TableDataInfo.build(result); + } + + @Override + public List listByIds(Collection ossIds) { + List list = new ArrayList<>(); + for (Long id : ossIds) { + SysOssVo vo = SpringUtils.getAopProxy(this).getById(id); + if (ObjectUtil.isNotNull(vo)) { + list.add(this.matchingUrl(vo)); + } + } + return list; + } + + @Override + public String selectUrlByIds(String ossIds) { + List list = new ArrayList<>(); + for (Long id : StringUtils.splitTo(ossIds, Convert::toLong)) { + SysOssVo vo = SpringUtils.getAopProxy(this).getById(id); + if (ObjectUtil.isNotNull(vo)) { + list.add(this.matchingUrl(vo).getUrl()); + } + } + return String.join(StringUtils.SEPARATOR, list); + } + + private LambdaQueryWrapper buildQueryWrapper(SysOssBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getFileName()), SysOss::getFileName, bo.getFileName()); + lqw.like(StringUtils.isNotBlank(bo.getOriginalName()), SysOss::getOriginalName, bo.getOriginalName()); + lqw.eq(StringUtils.isNotBlank(bo.getFileSuffix()), SysOss::getFileSuffix, bo.getFileSuffix()); + lqw.eq(StringUtils.isNotBlank(bo.getUrl()), SysOss::getUrl, bo.getUrl()); + lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null, + SysOss::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime")); + lqw.eq(ObjectUtil.isNotNull(bo.getCreateBy()), SysOss::getCreateBy, bo.getCreateBy()); + lqw.eq(StringUtils.isNotBlank(bo.getService()), SysOss::getService, bo.getService()); + return lqw; + } + + @Cacheable(cacheNames = CacheNames.SYS_OSS, key = "#ossId") + @Override + public SysOssVo getById(Long ossId) { + return baseMapper.selectVoById(ossId); + } + + @Override + public void download(Long ossId, HttpServletResponse response) throws IOException { + SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId); + if (ObjectUtil.isNull(sysOss)) { + throw new ServiceException("文件数据不存在!"); + } + FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName()); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); + OssClient storage = OssFactory.instance(); + try(InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) { + int available = inputStream.available(); + IoUtil.copy(inputStream, response.getOutputStream(), available); + response.setContentLength(available); + } catch (Exception e) { + throw new ServiceException(e.getMessage()); + } + } + + @Override + public SysOssVo upload(MultipartFile file) { + String originalfileName = file.getOriginalFilename(); + String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length()); + OssClient storage = OssFactory.instance(); + UploadResult uploadResult; + try { + uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType()); + } catch (IOException e) { + throw new ServiceException(e.getMessage()); + } + // 保存文件信息 + SysOss oss = new SysOss(); + oss.setUrl(uploadResult.getUrl()); + oss.setFileSuffix(suffix); + oss.setFileName(uploadResult.getFilename()); + oss.setOriginalName(originalfileName); + oss.setService(storage.getConfigKey()); + baseMapper.insert(oss); + SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class); + return this.matchingUrl(sysOssVo); + } + + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if (isValid) { + // 做一些业务上的校验,判断是否需要校验 + } + List list = baseMapper.selectBatchIds(ids); + for (SysOss sysOss : list) { + OssClient storage = OssFactory.instance(sysOss.getService()); + storage.delete(sysOss.getUrl()); + } + return baseMapper.deleteBatchIds(ids) > 0; + } + + /** + * 匹配Url + * + * @param oss OSS对象 + * @return oss 匹配Url的OSS对象 + */ + private SysOssVo matchingUrl(SysOssVo oss) { + OssClient storage = OssFactory.instance(oss.getService()); + // 仅修改桶类型为 private 的URL,临时URL时长为120s + if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) { + oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 120)); + } + return oss; + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysPermissionServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysPermissionServiceImpl.java new file mode 100644 index 00000000..d91cd021 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysPermissionServiceImpl.java @@ -0,0 +1,61 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.service.ISysMenuService; +import cc.iotkit.system.service.ISysRoleService; +import org.dromara.common.core.constant.TenantConstants; +import org.dromara.common.satoken.utils.LoginHelper; +import cc.iotkit.system.service.ISysPermissionService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.HashSet; +import java.util.Set; + +/** + * 用户权限处理 + * + * @author ruoyi + */ +@RequiredArgsConstructor +@Service +public class SysPermissionServiceImpl implements ISysPermissionService { + + private final ISysRoleService roleService; + private final ISysMenuService menuService; + + /** + * 获取角色数据权限 + * + * @param userId 用户id + * @return 角色权限信息 + */ + @Override + public Set getRolePermission(Long userId) { + Set roles = new HashSet<>(); + // 管理员拥有所有权限 + if (LoginHelper.isSuperAdmin(userId)) { + roles.add(TenantConstants.SUPER_ADMIN_ROLE_KEY); + } else { + roles.addAll(roleService.selectRolePermissionByUserId(userId)); + } + return roles; + } + + /** + * 获取菜单数据权限 + * + * @param userId 用户id + * @return 菜单权限信息 + */ + @Override + public Set getMenuPermission(Long userId) { + Set perms = new HashSet<>(); + // 管理员拥有所有权限 + if (LoginHelper.isSuperAdmin(userId)) { + perms.add("*:*:*"); + } else { + perms.addAll(menuService.selectMenuPermsByUserId(userId)); + } + return perms; + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysPostServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysPostServiceImpl.java new file mode 100644 index 00000000..aec82ee3 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysPostServiceImpl.java @@ -0,0 +1,188 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.bo.SysPostBo; +import cc.iotkit.system.domain.vo.SysPostVo; +import cc.iotkit.system.mapper.SysPostMapper; +import cc.iotkit.system.mapper.SysUserPostMapper; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import cc.iotkit.system.domain.SysPost; +import cc.iotkit.system.domain.SysUserPost; +import cc.iotkit.system.service.ISysPostService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.List; + +/** + * 岗位信息 服务层处理 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysPostServiceImpl implements ISysPostService { + + private final SysPostMapper baseMapper; + private final SysUserPostMapper userPostMapper; + + @Override + public TableDataInfo selectPagePostList(SysPostBo post, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(post); + Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(page); + } + + /** + * 查询岗位信息集合 + * + * @param post 岗位信息 + * @return 岗位信息集合 + */ + @Override + public List selectPostList(SysPostBo post) { + LambdaQueryWrapper lqw = buildQueryWrapper(post); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysPostBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getPostCode()), SysPost::getPostCode, bo.getPostCode()); + lqw.like(StringUtils.isNotBlank(bo.getPostName()), SysPost::getPostName, bo.getPostName()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysPost::getStatus, bo.getStatus()); + lqw.orderByAsc(SysPost::getPostSort); + return lqw; + } + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + @Override + public List selectPostAll() { + return baseMapper.selectVoList(new QueryWrapper<>()); + } + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + @Override + public SysPostVo selectPostById(Long postId) { + return baseMapper.selectVoById(postId); + } + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + @Override + public List selectPostListByUserId(Long userId) { + return baseMapper.selectPostListByUserId(userId); + } + + /** + * 校验岗位名称是否唯一 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public boolean checkPostNameUnique(SysPostBo post) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysPost::getPostName, post.getPostName()) + .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId())); + return !exist; + } + + /** + * 校验岗位编码是否唯一 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public boolean checkPostCodeUnique(SysPostBo post) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysPost::getPostCode, post.getPostCode()) + .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId())); + return !exist; + } + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + @Override + public long countUserPostById(Long postId) { + return userPostMapper.selectCount(new LambdaQueryWrapper().eq(SysUserPost::getPostId, postId)); + } + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + @Override + public int deletePostById(Long postId) { + return baseMapper.deleteById(postId); + } + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + */ + @Override + public int deletePostByIds(Long[] postIds) { + for (Long postId : postIds) { + SysPost post = baseMapper.selectById(postId); + if (countUserPostById(postId) > 0) { + throw new ServiceException(String.format("%1$s已分配,不能删除", post.getPostName())); + } + } + return baseMapper.deleteBatchIds(Arrays.asList(postIds)); + } + + /** + * 新增保存岗位信息 + * + * @param bo 岗位信息 + * @return 结果 + */ + @Override + public int insertPost(SysPostBo bo) { + SysPost post = MapstructUtils.convert(bo, SysPost.class); + return baseMapper.insert(post); + } + + /** + * 修改保存岗位信息 + * + * @param bo 岗位信息 + * @return 结果 + */ + @Override + public int updatePost(SysPostBo bo) { + SysPost post = MapstructUtils.convert(bo, SysPost.class); + return baseMapper.updateById(post); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysRoleServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysRoleServiceImpl.java new file mode 100644 index 00000000..7f1ad858 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,458 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.bo.SysRoleBo; +import cc.iotkit.system.domain.vo.SysRoleVo; +import cc.iotkit.system.mapper.SysRoleDeptMapper; +import cc.iotkit.system.mapper.SysRoleMapper; +import cc.iotkit.system.mapper.SysRoleMenuMapper; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +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.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.satoken.utils.LoginHelper; +import cc.iotkit.system.domain.SysRole; +import cc.iotkit.system.domain.SysRoleDept; +import cc.iotkit.system.domain.SysRoleMenu; +import cc.iotkit.system.domain.SysUserRole; +import cc.iotkit.system.mapper.SysUserRoleMapper; +import cc.iotkit.system.service.ISysRoleService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; + +/** + * 角色 业务层处理 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysRoleServiceImpl implements ISysRoleService { + + private final SysRoleMapper baseMapper; + private final SysRoleMenuMapper roleMenuMapper; + private final SysUserRoleMapper userRoleMapper; + private final SysRoleDeptMapper roleDeptMapper; + + @Override + public TableDataInfo selectPageRoleList(SysRoleBo role, PageQuery pageQuery) { + Page page = baseMapper.selectPageRoleList(pageQuery.build(), this.buildQueryWrapper(role)); + return TableDataInfo.build(page); + } + + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + @Override + public List selectRoleList(SysRoleBo role) { + return baseMapper.selectRoleList(this.buildQueryWrapper(role)); + } + + private Wrapper buildQueryWrapper(SysRoleBo bo) { + Map params = bo.getParams(); + QueryWrapper wrapper = Wrappers.query(); + wrapper.eq("r.del_flag", UserConstants.ROLE_NORMAL) + .eq(ObjectUtil.isNotNull(bo.getRoleId()), "r.role_id", bo.getRoleId()) + .like(StringUtils.isNotBlank(bo.getRoleName()), "r.role_name", bo.getRoleName()) + .eq(StringUtils.isNotBlank(bo.getStatus()), "r.status", bo.getStatus()) + .like(StringUtils.isNotBlank(bo.getRoleKey()), "r.role_key", bo.getRoleKey()) + .between(params.get("beginTime") != null && params.get("endTime") != null, + "r.create_time", params.get("beginTime"), params.get("endTime")) + .orderByAsc("r.role_sort").orderByAsc("r.create_time");; + return wrapper; + } + + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + @Override + public List selectRolesByUserId(Long userId) { + List userRoles = baseMapper.selectRolePermissionByUserId(userId); + List roles = selectRoleAll(); + for (SysRoleVo role : roles) { + for (SysRoleVo userRole : userRoles) { + if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) { + role.setFlag(true); + break; + } + } + } + return roles; + } + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + @Override + public Set selectRolePermissionByUserId(Long userId) { + List perms = baseMapper.selectRolePermissionByUserId(userId); + Set permsSet = new HashSet<>(); + for (SysRoleVo perm : perms) { + if (ObjectUtil.isNotNull(perm)) { + permsSet.addAll(StringUtils.splitList(perm.getRoleKey().trim())); + } + } + return permsSet; + } + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + @Override + public List selectRoleAll() { + return this.selectRoleList(new SysRoleBo()); + } + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + @Override + public List selectRoleListByUserId(Long userId) { + return baseMapper.selectRoleListByUserId(userId); + } + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + @Override + public SysRoleVo selectRoleById(Long roleId) { + return baseMapper.selectRoleById(roleId); + } + + /** + * 校验角色名称是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public boolean checkRoleNameUnique(SysRoleBo role) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysRole::getRoleName, role.getRoleName()) + .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId())); + return !exist; + } + + /** + * 校验角色权限是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public boolean checkRoleKeyUnique(SysRoleBo role) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysRole::getRoleKey, role.getRoleKey()) + .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId())); + return !exist; + } + + /** + * 校验角色是否允许操作 + * + * @param roleId 角色ID + */ + @Override + public void checkRoleAllowed(Long roleId) { + if (ObjectUtil.isNotNull(roleId) && LoginHelper.isSuperAdmin(roleId)) { + throw new ServiceException("不允许操作超级管理员角色"); + } + } + + /** + * 校验角色是否有数据权限 + * + * @param roleId 角色id + */ + @Override + public void checkRoleDataScope(Long roleId) { + if (ObjectUtil.isNull(roleId)) { + return; + } + if (LoginHelper.isSuperAdmin()) { + return; + } + List roles = this.selectRoleList(new SysRoleBo(roleId)); + if (CollUtil.isEmpty(roles)) { + throw new ServiceException("没有权限访问角色数据!"); + } + + } + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + public long countUserRoleByRoleId(Long roleId) { + return userRoleMapper.selectCount(new LambdaQueryWrapper().eq(SysUserRole::getRoleId, roleId)); + } + + /** + * 新增保存角色信息 + * + * @param bo 角色信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int insertRole(SysRoleBo bo) { + SysRole role = MapstructUtils.convert(bo, SysRole.class); + // 新增角色信息 + baseMapper.insert(role); + bo.setRoleId(role.getRoleId()); + return insertRoleMenu(bo); + } + + /** + * 修改保存角色信息 + * + * @param bo 角色信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int updateRole(SysRoleBo bo) { + SysRole role = MapstructUtils.convert(bo, SysRole.class); + // 修改角色信息 + baseMapper.updateById(role); + // 删除角色与菜单关联 + roleMenuMapper.delete(new LambdaQueryWrapper().eq(SysRoleMenu::getRoleId, role.getRoleId())); + return insertRoleMenu(bo); + } + + /** + * 修改角色状态 + * + * @param roleId 角色ID + * @param status 角色状态 + * @return 结果 + */ + @Override + public int updateRoleStatus(Long roleId, String status) { + return baseMapper.update(null, + new LambdaUpdateWrapper() + .set(SysRole::getStatus, status) + .eq(SysRole::getRoleId, roleId)); + } + + /** + * 修改数据权限信息 + * + * @param bo 角色信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int authDataScope(SysRoleBo bo) { + SysRole role = MapstructUtils.convert(bo, SysRole.class); + // 修改角色信息 + baseMapper.updateById(role); + // 删除角色与部门关联 + roleDeptMapper.delete(new LambdaQueryWrapper().eq(SysRoleDept::getRoleId, role.getRoleId())); + // 新增角色和部门信息(数据权限) + return insertRoleDept(bo); + } + + /** + * 新增角色菜单信息 + * + * @param role 角色对象 + */ + private int insertRoleMenu(SysRoleBo role) { + int rows = 1; + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long menuId : role.getMenuIds()) { + SysRoleMenu rm = new SysRoleMenu(); + rm.setRoleId(role.getRoleId()); + rm.setMenuId(menuId); + list.add(rm); + } + if (list.size() > 0) { + rows = roleMenuMapper.insertBatch(list) ? list.size() : 0; + } + return rows; + } + + /** + * 新增角色部门信息(数据权限) + * + * @param role 角色对象 + */ + private int insertRoleDept(SysRoleBo role) { + int rows = 1; + // 新增角色与部门(数据权限)管理 + List list = new ArrayList(); + for (Long deptId : role.getDeptIds()) { + SysRoleDept rd = new SysRoleDept(); + rd.setRoleId(role.getRoleId()); + rd.setDeptId(deptId); + list.add(rd); + } + if (list.size() > 0) { + rows = roleDeptMapper.insertBatch(list) ? list.size() : 0; + } + return rows; + } + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteRoleById(Long roleId) { + // 删除角色与菜单关联 + roleMenuMapper.delete(new LambdaQueryWrapper().eq(SysRoleMenu::getRoleId, roleId)); + // 删除角色与部门关联 + roleDeptMapper.delete(new LambdaQueryWrapper().eq(SysRoleDept::getRoleId, roleId)); + return baseMapper.deleteById(roleId); + } + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteRoleByIds(Long[] roleIds) { + for (Long roleId : roleIds) { + checkRoleAllowed(roleId); + checkRoleDataScope(roleId); + SysRole role = baseMapper.selectById(roleId); + if (countUserRoleByRoleId(roleId) > 0) { + throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName())); + } + } + List ids = Arrays.asList(roleIds); + // 删除角色与菜单关联 + roleMenuMapper.delete(new LambdaQueryWrapper().in(SysRoleMenu::getRoleId, ids)); + // 删除角色与部门关联 + roleDeptMapper.delete(new LambdaQueryWrapper().in(SysRoleDept::getRoleId, ids)); + return baseMapper.deleteBatchIds(ids); + } + + /** + * 取消授权用户角色 + * + * @param userRole 用户和角色关联信息 + * @return 结果 + */ + @Override + public int deleteAuthUser(SysUserRole userRole) { + int rows = userRoleMapper.delete(new LambdaQueryWrapper() + .eq(SysUserRole::getRoleId, userRole.getRoleId()) + .eq(SysUserRole::getUserId, userRole.getUserId())); + if (rows > 0) { + cleanOnlineUserByRole(userRole.getRoleId()); + } + return rows; + } + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要取消授权的用户数据ID + * @return 结果 + */ + @Override + public int deleteAuthUsers(Long roleId, Long[] userIds) { + int rows = userRoleMapper.delete(new LambdaQueryWrapper() + .eq(SysUserRole::getRoleId, roleId) + .in(SysUserRole::getUserId, Arrays.asList(userIds))); + if (rows > 0) { + cleanOnlineUserByRole(roleId); + } + return rows; + } + + /** + * 批量选择授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要授权的用户数据ID + * @return 结果 + */ + @Override + public int insertAuthUsers(Long roleId, Long[] userIds) { + // 新增用户与角色管理 + int rows = 1; + List list = StreamUtils.toList(List.of(userIds), userId -> { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + return ur; + }); + if (CollUtil.isNotEmpty(list)) { + rows = userRoleMapper.insertBatch(list) ? list.size() : 0; + } + if (rows > 0) { + cleanOnlineUserByRole(roleId); + } + return rows; + } + + @Override + public void cleanOnlineUserByRole(Long roleId) { + List keys = StpUtil.searchTokenValue("", 0, -1, false); + if (CollUtil.isEmpty(keys)) { + return; + } + // 角色关联的在线用户量过大会导致redis阻塞卡顿 谨慎操作 + keys.parallelStream().forEach(key -> { + String token = StringUtils.substringAfterLast(key, ":"); + // 如果已经过期则跳过 + if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < -1) { + return; + } + LoginUser loginUser = LoginHelper.getLoginUser(token); + if (loginUser.getRoles().stream().anyMatch(r -> r.getRoleId().equals(roleId))) { + try { + StpUtil.logoutByTokenValue(token); + } catch (NotLoginException ignored) { + } + } + }); + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysSensitiveServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysSensitiveServiceImpl.java new file mode 100644 index 00000000..02182081 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysSensitiveServiceImpl.java @@ -0,0 +1,26 @@ +package cc.iotkit.system.service.impl; + +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.sensitive.core.SensitiveService; +import org.springframework.stereotype.Service; + +/** + * 脱敏服务 + * 默认管理员不过滤 + * 需自行根据业务重写实现 + * + * @author Lion Li + * @version 3.6.0 + */ +@Service +public class SysSensitiveServiceImpl implements SensitiveService { + + /** + * 是否脱敏 + */ + @Override + public boolean isSensitive() { + return !LoginHelper.isSuperAdmin() || !LoginHelper.isTenantAdmin(); + } + +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysTenantPackageServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysTenantPackageServiceImpl.java new file mode 100644 index 00000000..6d952c9e --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysTenantPackageServiceImpl.java @@ -0,0 +1,146 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.SysTenant; +import cc.iotkit.system.domain.SysTenantPackage; +import cc.iotkit.system.domain.bo.SysTenantPackageBo; +import cc.iotkit.system.domain.vo.SysTenantPackageVo; +import cc.iotkit.system.mapper.SysTenantMapper; +import cc.iotkit.system.mapper.SysTenantPackageMapper; +import cn.hutool.core.collection.CollUtil; +import org.dromara.common.core.constant.TenantConstants; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import cc.iotkit.system.service.ISysTenantPackageService; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 租户套餐Service业务层处理 + * + * @author Michelle.Chung + */ +@RequiredArgsConstructor +@Service +public class SysTenantPackageServiceImpl implements ISysTenantPackageService { + + private final SysTenantPackageMapper baseMapper; + private final SysTenantMapper tenantMapper; + + /** + * 查询租户套餐 + */ + @Override + public SysTenantPackageVo queryById(Long packageId){ + return baseMapper.selectVoById(packageId); + } + + /** + * 查询租户套餐列表 + */ + @Override + public TableDataInfo queryPageList(SysTenantPackageBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + @Override + public List selectList() { + return baseMapper.selectVoList(new LambdaQueryWrapper() + .eq(SysTenantPackage::getStatus, TenantConstants.NORMAL)); + } + + /** + * 查询租户套餐列表 + */ + @Override + public List queryList(SysTenantPackageBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysTenantPackageBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getPackageName()), SysTenantPackage::getPackageName, bo.getPackageName()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysTenantPackage::getStatus, bo.getStatus()); + return lqw; + } + + /** + * 新增租户套餐 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insertByBo(SysTenantPackageBo bo) { + SysTenantPackage add = MapstructUtils.convert(bo, SysTenantPackage.class); + // 保存菜单id + List menuIds = Arrays.asList(bo.getMenuIds()); + if (CollUtil.isNotEmpty(menuIds)) { + add.setMenuIds(StringUtils.join(menuIds, ", ")); + } else { + add.setMenuIds(""); + } + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setPackageId(add.getPackageId()); + } + return flag; + } + + /** + * 修改租户套餐 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateByBo(SysTenantPackageBo bo) { + SysTenantPackage update = MapstructUtils.convert(bo, SysTenantPackage.class); + // 保存菜单id + List menuIds = Arrays.asList(bo.getMenuIds()); + if (CollUtil.isNotEmpty(menuIds)) { + update.setMenuIds(StringUtils.join(menuIds, ", ")); + } else { + update.setMenuIds(""); + } + return baseMapper.updateById(update) > 0; + } + + /** + * 修改套餐状态 + * + * @param bo 套餐信息 + * @return 结果 + */ + @Override + public int updatePackageStatus(SysTenantPackageBo bo) { + SysTenantPackage tenantPackage = MapstructUtils.convert(bo, SysTenantPackage.class); + return baseMapper.updateById(tenantPackage); + } + + /** + * 批量删除租户套餐 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + boolean exists = tenantMapper.exists(new LambdaQueryWrapper().in(SysTenant::getPackageId, ids)); + if (exists) { + throw new ServiceException("租户套餐已被使用"); + } + } + return baseMapper.deleteBatchIds(ids) > 0; + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysTenantServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysTenantServiceImpl.java new file mode 100644 index 00000000..1cd90b47 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysTenantServiceImpl.java @@ -0,0 +1,369 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.*; +import cc.iotkit.system.domain.bo.SysTenantBo; +import cc.iotkit.system.domain.vo.SysTenantVo; +import cc.iotkit.system.mapper.*; +import cn.dev33.satoken.secure.BCrypt; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.CacheNames; +import org.dromara.common.core.constant.Constants; +import org.dromara.common.core.constant.TenantConstants; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.system.domain.*; +import org.dromara.system.mapper.*; +import cc.iotkit.system.service.ISysTenantService; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +/** + * 租户Service业务层处理 + * + * @author Michelle.Chung + */ +@RequiredArgsConstructor +@Service +public class SysTenantServiceImpl implements ISysTenantService { + + private final SysTenantMapper baseMapper; + private final SysTenantPackageMapper tenantPackageMapper; + private final SysUserMapper userMapper; + private final SysDeptMapper deptMapper; + private final SysRoleMapper roleMapper; + private final SysRoleMenuMapper roleMenuMapper; + private final SysRoleDeptMapper roleDeptMapper; + private final SysUserRoleMapper userRoleMapper; + private final SysDictTypeMapper dictTypeMapper; + private final SysDictDataMapper dictDataMapper; + private final SysConfigMapper configMapper; + + /** + * 查询租户 + */ + @Override + public SysTenantVo queryById(Long id) { + return baseMapper.selectVoById(id); + } + + /** + * 基于租户ID查询租户 + */ + @Cacheable(cacheNames = CacheNames.SYS_TENANT, key = "#tenantId") + @Override + public SysTenantVo queryByTenantId(String tenantId) { + return baseMapper.selectVoOne(new LambdaQueryWrapper().eq(SysTenant::getTenantId, tenantId)); + } + + /** + * 查询租户列表 + */ + @Override + public TableDataInfo queryPageList(SysTenantBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询租户列表 + */ + @Override + public List queryList(SysTenantBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysTenantBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(StringUtils.isNotBlank(bo.getTenantId()), SysTenant::getTenantId, bo.getTenantId()); + lqw.like(StringUtils.isNotBlank(bo.getContactUserName()), SysTenant::getContactUserName, bo.getContactUserName()); + lqw.eq(StringUtils.isNotBlank(bo.getContactPhone()), SysTenant::getContactPhone, bo.getContactPhone()); + lqw.like(StringUtils.isNotBlank(bo.getCompanyName()), SysTenant::getCompanyName, bo.getCompanyName()); + lqw.eq(StringUtils.isNotBlank(bo.getLicenseNumber()), SysTenant::getLicenseNumber, bo.getLicenseNumber()); + lqw.eq(StringUtils.isNotBlank(bo.getAddress()), SysTenant::getAddress, bo.getAddress()); + lqw.eq(StringUtils.isNotBlank(bo.getIntro()), SysTenant::getIntro, bo.getIntro()); + lqw.like(StringUtils.isNotBlank(bo.getDomain()), SysTenant::getDomain, bo.getDomain()); + lqw.eq(bo.getPackageId() != null, SysTenant::getPackageId, bo.getPackageId()); + lqw.eq(bo.getExpireTime() != null, SysTenant::getExpireTime, bo.getExpireTime()); + lqw.eq(bo.getAccountCount() != null, SysTenant::getAccountCount, bo.getAccountCount()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysTenant::getStatus, bo.getStatus()); + return lqw; + } + + /** + * 新增租户 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insertByBo(SysTenantBo bo) { + SysTenant add = MapstructUtils.convert(bo, SysTenant.class); + + // 获取所有租户编号 + List tenantIds = baseMapper.selectObjs( + new LambdaQueryWrapper().select(SysTenant::getTenantId), Convert::toStr); + String tenantId = generateTenantId(tenantIds); + add.setTenantId(tenantId); + boolean flag = baseMapper.insert(add) > 0; + if (!flag) { + throw new ServiceException("创建租户失败"); + } + bo.setId(add.getId()); + + // 根据套餐创建角色 + Long roleId = createTenantRole(tenantId, bo.getPackageId()); + + // 创建部门: 公司名是部门名称 + SysDept dept = new SysDept(); + dept.setTenantId(tenantId); + dept.setDeptName(bo.getCompanyName()); + dept.setLeader(bo.getUsername()); + dept.setParentId(Constants.TOP_PARENT_ID); + dept.setAncestors(Constants.TOP_PARENT_ID.toString()); + deptMapper.insert(dept); + Long deptId = dept.getDeptId(); + + // 角色和部门关联表 + SysRoleDept roleDept = new SysRoleDept(); + roleDept.setRoleId(roleId); + roleDept.setDeptId(deptId); + roleDeptMapper.insert(roleDept); + + // 创建系统用户 + SysUser user = new SysUser(); + user.setTenantId(tenantId); + user.setUserName(bo.getUsername()); + user.setNickName(bo.getUsername()); + user.setPassword(BCrypt.hashpw(bo.getPassword())); + user.setDeptId(deptId); + userMapper.insert(user); + + // 用户和角色关联表 + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(user.getUserId()); + userRole.setRoleId(roleId); + userRoleMapper.insert(userRole); + + String defaultTenantId = TenantConstants.DEFAULT_TENANT_ID; + List dictTypeList = dictTypeMapper.selectList( + new LambdaQueryWrapper().eq(SysDictType::getTenantId, defaultTenantId)); + List dictDataList = dictDataMapper.selectList( + new LambdaQueryWrapper().eq(SysDictData::getTenantId, defaultTenantId)); + for (SysDictType dictType : dictTypeList) { + dictType.setDictId(null); + dictType.setTenantId(tenantId); + } + for (SysDictData dictData : dictDataList) { + dictData.setDictCode(null); + dictData.setTenantId(tenantId); + } + dictTypeMapper.insertBatch(dictTypeList); + dictDataMapper.insertBatch(dictDataList); + + List sysConfigList = configMapper.selectList( + new LambdaQueryWrapper().eq(SysConfig::getTenantId, defaultTenantId)); + for (SysConfig config : sysConfigList) { + config.setConfigId(null); + config.setTenantId(tenantId); + } + configMapper.insertBatch(sysConfigList); + return true; + } + + /** + * 生成租户id + * + * @param tenantIds 已有租户id列表 + * @return 租户id + */ + private String generateTenantId(List tenantIds) { + // 随机生成6位 + String numbers = RandomUtil.randomNumbers(6); + // 判断是否存在,如果存在则重新生成 + if (tenantIds.contains(numbers)) { + generateTenantId(tenantIds); + } + return numbers; + } + + /** + * 根据租户菜单创建租户角色 + * + * @param tenantId 租户编号 + * @param packageId 租户套餐id + * @return 角色id + */ + private Long createTenantRole(String tenantId, Long packageId) { + // 获取租户套餐 + SysTenantPackage tenantPackage = tenantPackageMapper.selectById(packageId); + if (ObjectUtil.isNull(tenantPackage)) { + throw new ServiceException("套餐不存在"); + } + // 获取套餐菜单id + List menuIds = StringUtils.splitTo(tenantPackage.getMenuIds(), Convert::toLong); + + // 创建角色 + SysRole role = new SysRole(); + role.setTenantId(tenantId); + role.setRoleName(TenantConstants.TENANT_ADMIN_ROLE_NAME); + role.setRoleKey(TenantConstants.TENANT_ADMIN_ROLE_KEY); + role.setRoleSort(1); + role.setStatus(TenantConstants.NORMAL); + roleMapper.insert(role); + Long roleId = role.getRoleId(); + + // 创建角色菜单 + List roleMenus = new ArrayList<>(menuIds.size()); + menuIds.forEach(menuId -> { + SysRoleMenu roleMenu = new SysRoleMenu(); + roleMenu.setRoleId(roleId); + roleMenu.setMenuId(menuId); + roleMenus.add(roleMenu); + }); + roleMenuMapper.insertBatch(roleMenus); + + return roleId; + } + + /** + * 修改租户 + */ + @CacheEvict(cacheNames = CacheNames.SYS_TENANT, key = "#bo.tenantId") + @Override + public Boolean updateByBo(SysTenantBo bo) { + SysTenant tenant = MapstructUtils.convert(bo, SysTenant.class); + tenant.setTenantId(null); + tenant.setPackageId(null); + return baseMapper.updateById(tenant) > 0; + } + + /** + * 修改租户状态 + * + * @param bo 租户信息 + * @return 结果 + */ + @CacheEvict(cacheNames = CacheNames.SYS_TENANT, key = "#bo.tenantId") + @Override + public int updateTenantStatus(SysTenantBo bo) { + SysTenant tenant = MapstructUtils.convert(bo, SysTenant.class); + return baseMapper.updateById(tenant); + } + + /** + * 校验租户是否允许操作 + * + * @param tenantId 租户ID + */ + @Override + public void checkTenantAllowed(String tenantId) { + if (ObjectUtil.isNotNull(tenantId) && TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { + throw new ServiceException("不允许操作管理租户"); + } + } + + /** + * 批量删除租户 + */ + @CacheEvict(cacheNames = CacheNames.SYS_TENANT, allEntries = true) + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if (isValid) { + // 做一些业务上的校验,判断是否需要校验 + if (ids.contains(TenantConstants.SUPER_ADMIN_ID)) { + throw new ServiceException("超管租户不能删除"); + } + } + return baseMapper.deleteBatchIds(ids) > 0; + } + + /** + * 校验企业名称是否唯一 + */ + @Override + public boolean checkCompanyNameUnique(SysTenantBo bo) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysTenant::getCompanyName, bo.getCompanyName()) + .ne(ObjectUtil.isNotNull(bo.getTenantId()), SysTenant::getTenantId, bo.getTenantId())); + return !exist; + } + + /** + * 校验账号余额 + */ + @Override + public boolean checkAccountBalance(String tenantId) { + SysTenantVo tenant = SpringUtils.getAopProxy(this).queryByTenantId(tenantId); + // 如果余额为-1代表不限制 + if (tenant.getAccountCount() == -1) { + return true; + } + Long userNumber = userMapper.selectCount(new LambdaQueryWrapper<>()); + // 如果余额大于0代表还有可用名额 + return tenant.getAccountCount() - userNumber > 0; + } + + /** + * 校验有效期 + */ + @Override + public boolean checkExpireTime(String tenantId) { + SysTenantVo tenant = SpringUtils.getAopProxy(this).queryByTenantId(tenantId); + // 如果未设置过期时间代表不限制 + if (ObjectUtil.isNull(tenant.getExpireTime())) { + return true; + } + // 如果当前时间在过期时间之前则通过 + return new Date().before(tenant.getExpireTime()); + } + + /** + * 同步租户套餐 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean syncTenantPackage(String tenantId, String packageId) { + SysTenantPackage tenantPackage = tenantPackageMapper.selectById(packageId); + List roles = roleMapper.selectList( + new LambdaQueryWrapper().eq(SysRole::getTenantId, tenantId)); + List roleIds = new ArrayList<>(roles.size() - 1); + List menuIds = StringUtils.splitTo(tenantPackage.getMenuIds(), Convert::toLong); + roles.forEach(item -> { + if (TenantConstants.TENANT_ADMIN_ROLE_KEY.equals(item.getRoleKey())) { + List roleMenus = new ArrayList<>(menuIds.size()); + menuIds.forEach(menuId -> { + SysRoleMenu roleMenu = new SysRoleMenu(); + roleMenu.setRoleId(item.getRoleId()); + roleMenu.setMenuId(menuId); + roleMenus.add(roleMenu); + }); + roleMenuMapper.delete(new LambdaQueryWrapper().eq(SysRoleMenu::getRoleId, item.getRoleId())); + roleMenuMapper.insertBatch(roleMenus); + } else { + roleIds.add(item.getRoleId()); + } + }); + if (!roleIds.isEmpty()) { + roleMenuMapper.delete( + new LambdaQueryWrapper().in(SysRoleMenu::getRoleId, roleIds).notIn(!menuIds.isEmpty(), SysRoleMenu::getMenuId, menuIds)); + } + return true; + } +} diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysUserServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysUserServiceImpl.java new file mode 100644 index 00000000..1e687465 --- /dev/null +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysUserServiceImpl.java @@ -0,0 +1,524 @@ +package cc.iotkit.system.service.impl; + +import cc.iotkit.system.domain.bo.SysUserBo; +import cc.iotkit.system.domain.vo.SysPostVo; +import cc.iotkit.system.domain.vo.SysRoleVo; +import cc.iotkit.system.domain.vo.SysUserVo; +import cc.iotkit.system.mapper.*; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +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.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.constant.CacheNames; +import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.UserService; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.helper.DataBaseHelper; +import org.dromara.common.satoken.utils.LoginHelper; +import cc.iotkit.system.domain.SysDept; +import cc.iotkit.system.domain.SysUser; +import cc.iotkit.system.domain.SysUserPost; +import cc.iotkit.system.domain.SysUserRole; +import org.dromara.system.mapper.*; +import cc.iotkit.system.service.ISysUserService; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +/** + * 用户 业务层处理 + * + * @author Lion Li + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class SysUserServiceImpl implements ISysUserService, UserService { + + private final SysUserMapper baseMapper; + private final SysDeptMapper deptMapper; + private final SysRoleMapper roleMapper; + private final SysPostMapper postMapper; + private final SysUserRoleMapper userRoleMapper; + private final SysUserPostMapper userPostMapper; + + @Override + public TableDataInfo selectPageUserList(SysUserBo user, PageQuery pageQuery) { + Page page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(user)); + return TableDataInfo.build(page); + } + + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + public List selectUserList(SysUserBo user) { + return baseMapper.selectUserList(this.buildQueryWrapper(user)); + } + + private Wrapper buildQueryWrapper(SysUserBo user) { + Map params = user.getParams(); + QueryWrapper wrapper = Wrappers.query(); + wrapper.eq("u.del_flag", UserConstants.USER_NORMAL) + .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId()) + .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) + .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) + .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()) + .between(params.get("beginTime") != null && params.get("endTime") != null, + "u.create_time", params.get("beginTime"), params.get("endTime")) + .and(ObjectUtil.isNotNull(user.getDeptId()), w -> { + List deptList = deptMapper.selectList(new LambdaQueryWrapper() + .select(SysDept::getDeptId) + .apply(DataBaseHelper.findInSet(user.getDeptId(), "ancestors"))); + List ids = StreamUtils.toList(deptList, SysDept::getDeptId); + ids.add(user.getDeptId()); + w.in("u.dept_id", ids); + }); + return wrapper; + } + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + public TableDataInfo selectAllocatedList(SysUserBo user, PageQuery pageQuery) { + QueryWrapper wrapper = Wrappers.query(); + wrapper.eq("u.del_flag", UserConstants.USER_NORMAL) + .eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId()) + .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) + .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) + .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()); + Page page = baseMapper.selectAllocatedList(pageQuery.build(), wrapper); + return TableDataInfo.build(page); + } + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + public TableDataInfo selectUnallocatedList(SysUserBo user, PageQuery pageQuery) { + List userIds = userRoleMapper.selectUserIdsByRoleId(user.getRoleId()); + QueryWrapper wrapper = Wrappers.query(); + wrapper.eq("u.del_flag", UserConstants.USER_NORMAL) + .and(w -> w.ne("r.role_id", user.getRoleId()).or().isNull("r.role_id")) + .notIn(CollUtil.isNotEmpty(userIds), "u.user_id", userIds) + .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) + .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()); + Page page = baseMapper.selectUnallocatedList(pageQuery.build(), wrapper); + return TableDataInfo.build(page); + } + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + @Override + public SysUserVo selectUserByUserName(String userName) { + return baseMapper.selectUserByUserName(userName); + } + + /** + * 通过手机号查询用户 + * + * @param phonenumber 手机号 + * @return 用户对象信息 + */ + @Override + public SysUserVo selectUserByPhonenumber(String phonenumber) { + return baseMapper.selectUserByPhonenumber(phonenumber); + } + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + @Override + public SysUserVo selectUserById(Long userId) { + return baseMapper.selectUserById(userId); + } + + /** + * 查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserRoleGroup(String userName) { + List list = roleMapper.selectRolesByUserName(userName); + if (CollUtil.isEmpty(list)) { + return StringUtils.EMPTY; + } + return StreamUtils.join(list, SysRoleVo::getRoleName); + } + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserPostGroup(String userName) { + List list = postMapper.selectPostsByUserName(userName); + if (CollUtil.isEmpty(list)) { + return StringUtils.EMPTY; + } + return StreamUtils.join(list, SysPostVo::getPostName); + } + + /** + * 校验用户名称是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public boolean checkUserNameUnique(SysUserBo user) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysUser::getUserName, user.getUserName()) + .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); + return !exist; + } + + /** + * 校验手机号码是否唯一 + * + * @param user 用户信息 + */ + @Override + public boolean checkPhoneUnique(SysUserBo user) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysUser::getPhonenumber, user.getPhonenumber()) + .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); + return !exist; + } + + /** + * 校验email是否唯一 + * + * @param user 用户信息 + */ + @Override + public boolean checkEmailUnique(SysUserBo user) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysUser::getEmail, user.getEmail()) + .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); + return !exist; + } + + /** + * 校验用户是否允许操作 + * + * @param userId 用户ID + */ + @Override + public void checkUserAllowed(Long userId) { + if (ObjectUtil.isNotNull(userId) && LoginHelper.isSuperAdmin(userId)) { + throw new ServiceException("不允许操作超级管理员用户"); + } + } + + /** + * 校验用户是否有数据权限 + * + * @param userId 用户id + */ + @Override + public void checkUserDataScope(Long userId) { + if (ObjectUtil.isNull(userId)) { + return; + } + if (LoginHelper.isSuperAdmin()) { + return; + } + if (ObjectUtil.isNull(baseMapper.selectUserById(userId))) { + throw new ServiceException("没有权限访问用户数据!"); + } + } + + /** + * 新增保存用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int insertUser(SysUserBo user) { + SysUser sysUser = MapstructUtils.convert(user, SysUser.class); + // 新增用户信息 + int rows = baseMapper.insert(sysUser); + user.setUserId(sysUser.getUserId()); + // 新增用户岗位关联 + insertUserPost(user, false); + // 新增用户与角色管理 + insertUserRole(user, false); + return rows; + } + + /** + * 注册用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public boolean registerUser(SysUserBo user, String tenantId) { + user.setCreateBy(user.getUserId()); + user.setUpdateBy(user.getUserId()); + SysUser sysUser = MapstructUtils.convert(user, SysUser.class); + sysUser.setTenantId(tenantId); + return baseMapper.insert(sysUser) > 0; + } + + /** + * 修改保存用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int updateUser(SysUserBo user) { + // 新增用户与角色管理 + insertUserRole(user, true); + // 新增用户与岗位管理 + insertUserPost(user, true); + SysUser sysUser = MapstructUtils.convert(user, SysUser.class); + // 防止错误更新后导致的数据误删除 + int flag = baseMapper.updateById(sysUser); + if (flag < 1) { + throw new ServiceException("修改用户" + user.getUserName() + "信息失败"); + } + return flag; + } + + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void insertUserAuth(Long userId, Long[] roleIds) { + insertUserRole(userId, roleIds, true); + } + + /** + * 修改用户状态 + * + * @param userId 用户ID + * @param status 帐号状态 + * @return 结果 + */ + @Override + public int updateUserStatus(Long userId, String status) { + return baseMapper.update(null, + new LambdaUpdateWrapper() + .set(SysUser::getStatus, status) + .eq(SysUser::getUserId, userId)); + } + + /** + * 修改用户基本信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int updateUserProfile(SysUserBo user) { + return baseMapper.update(null, + new LambdaUpdateWrapper() + .set(ObjectUtil.isNotNull(user.getNickName()), SysUser::getNickName, user.getNickName()) + .set(SysUser::getPhonenumber, user.getPhonenumber()) + .set(SysUser::getEmail, user.getEmail()) + .set(SysUser::getSex, user.getSex()) + .eq(SysUser::getUserId, user.getUserId())); + } + + /** + * 修改用户头像 + * + * @param userId 用户ID + * @param avatar 头像地址 + * @return 结果 + */ + @Override + public boolean updateUserAvatar(Long userId, Long avatar) { + return baseMapper.update(null, + new LambdaUpdateWrapper() + .set(SysUser::getAvatar, avatar) + .eq(SysUser::getUserId, userId)) > 0; + } + + /** + * 重置用户密码 + * + * @param userId 用户ID + * @param password 密码 + * @return 结果 + */ + @Override + public int resetUserPwd(Long userId, String password) { + return baseMapper.update(null, + new LambdaUpdateWrapper() + .set(SysUser::getPassword, password) + .eq(SysUser::getUserId, userId)); + } + + /** + * 新增用户角色信息 + * + * @param user 用户对象 + * @param clear 清除已存在的关联数据 + */ + private void insertUserRole(SysUserBo user, boolean clear) { + this.insertUserRole(user.getUserId(), user.getRoleIds(), clear); + } + + /** + * 新增用户岗位信息 + * + * @param user 用户对象 + * @param clear 清除已存在的关联数据 + */ + private void insertUserPost(SysUserBo user, boolean clear) { + Long[] posts = user.getPostIds(); + if (ArrayUtil.isNotEmpty(posts)) { + if (clear) { + // 删除用户与岗位关联 + userPostMapper.delete(new LambdaQueryWrapper().eq(SysUserPost::getUserId, user.getUserId())); + } + // 新增用户与岗位管理 + List list = StreamUtils.toList(List.of(posts), postId -> { + SysUserPost up = new SysUserPost(); + up.setUserId(user.getUserId()); + up.setPostId(postId); + return up; + }); + userPostMapper.insertBatch(list); + } + } + + /** + * 新增用户角色信息 + * + * @param userId 用户ID + * @param roleIds 角色组 + * @param clear 清除已存在的关联数据 + */ + private void insertUserRole(Long userId, Long[] roleIds, boolean clear) { + if (ArrayUtil.isNotEmpty(roleIds)) { + // 判断是否具有此角色的操作权限 + List roles = roleMapper.selectRoleList(new LambdaQueryWrapper<>()); + if (CollUtil.isEmpty(roles)) { + throw new ServiceException("没有权限访问角色的数据"); + } + List roleList = StreamUtils.toList(roles, SysRoleVo::getRoleId); + if (!LoginHelper.isSuperAdmin(userId)) { + roleList.remove(UserConstants.SUPER_ADMIN_ID); + } + List canDoRoleList = StreamUtils.filter(List.of(roleIds), roleList::contains); + if (CollUtil.isEmpty(canDoRoleList)) { + throw new ServiceException("没有权限访问角色的数据"); + } + if (clear) { + // 删除用户与角色关联 + userRoleMapper.delete(new LambdaQueryWrapper().eq(SysUserRole::getUserId, userId)); + } + // 新增用户与角色管理 + List list = StreamUtils.toList(canDoRoleList, roleId -> { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + return ur; + }); + userRoleMapper.insertBatch(list); + } + } + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteUserById(Long userId) { + // 删除用户与角色关联 + userRoleMapper.delete(new LambdaQueryWrapper().eq(SysUserRole::getUserId, userId)); + // 删除用户与岗位表 + userPostMapper.delete(new LambdaQueryWrapper().eq(SysUserPost::getUserId, userId)); + // 防止更新失败导致的数据删除 + int flag = baseMapper.deleteById(userId); + if (flag < 1) { + throw new ServiceException("删除用户失败!"); + } + return flag; + } + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteUserByIds(Long[] userIds) { + for (Long userId : userIds) { + checkUserAllowed(userId); + checkUserDataScope(userId); + } + List ids = List.of(userIds); + // 删除用户与角色关联 + userRoleMapper.delete(new LambdaQueryWrapper().in(SysUserRole::getUserId, ids)); + // 删除用户与岗位表 + userPostMapper.delete(new LambdaQueryWrapper().in(SysUserPost::getUserId, ids)); + // 防止更新失败导致的数据删除 + int flag = baseMapper.deleteBatchIds(ids); + if (flag < 1) { + throw new ServiceException("删除用户失败!"); + } + return flag; + } + + @Cacheable(cacheNames = CacheNames.SYS_USER_NAME, key = "#userId") + @Override + public String selectUserNameById(Long userId) { + SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() + .select(SysUser::getUserName).eq(SysUser::getUserId, userId)); + return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName(); + } +} diff --git a/iot-module/pom.xml b/iot-module/pom.xml new file mode 100644 index 00000000..aba98bfe --- /dev/null +++ b/iot-module/pom.xml @@ -0,0 +1,21 @@ + + + + iotkit-parent + cc.iotkit + ${revision} + + 4.0.0 + + iot-module + pom + + iot-system + iot-manager + iot-rule-engine + + + + \ No newline at end of file diff --git a/iot-starter/pom.xml b/iot-starter/pom.xml index 3164dec2..3f6ab6bb 100644 --- a/iot-starter/pom.xml +++ b/iot-starter/pom.xml @@ -121,11 +121,6 @@ iot-component-converter - - cc.iotkit - iot-auth-server - - cc.iotkit iot-virtual-device @@ -217,8 +212,8 @@ maven-compiler-plugin 3.0 - 11 - 11 + ${java.version} + ${java.version} UTF-8 diff --git a/iot-starter/src/main/java/cc/iotkit/manager/config/ResponseResultHandler.java b/iot-starter/src/main/java/cc/iotkit/manager/config/ResponseResultHandler.java index 3b02f6a7..9500b486 100644 --- a/iot-starter/src/main/java/cc/iotkit/manager/config/ResponseResultHandler.java +++ b/iot-starter/src/main/java/cc/iotkit/manager/config/ResponseResultHandler.java @@ -9,10 +9,8 @@ */ package cc.iotkit.manager.config; +import cc.iotkit.common.api.Response; import cn.dev33.satoken.util.SaResult; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; @@ -42,30 +40,21 @@ public class ResponseResultHandler implements ResponseBodyAdvice { ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof GlobalExceptionHandler.RequestResult) { GlobalExceptionHandler.RequestResult requestResult = (GlobalExceptionHandler.RequestResult) body; - return new ApiResponse(requestResult.getCode(), requestResult.getMessage(), + return new Response(requestResult.getCode(), requestResult.getMessage(), "", System.currentTimeMillis()); } else if (body instanceof SaResult) { SaResult result = (SaResult) body; - return new ApiResponse(result.getCode(), result.getMsg(), result.getData(), System.currentTimeMillis()); + return new Response(result.getCode(), result.getMsg(), result.getData(), System.currentTimeMillis()); } else if (body instanceof Map) { Map map = (Map) body; //spring mvc内部异常 if (map.containsKey("timestamp") && map.containsKey("status") && map.containsKey("error")) { - return new ApiResponse((Integer) map.get("status"), (String) map.get("error"), + return new Response((Integer) map.get("status"), (String) map.get("error"), "", System.currentTimeMillis()); } } - return new ApiResponse(200, "", body, System.currentTimeMillis()); + return new Response(200, "", body, System.currentTimeMillis()); } - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class ApiResponse { - private int code; - private String message; - private Object data; - private long timestamp; - } } diff --git a/iot-starter/src/main/java/cc/iotkit/manager/controller/DeviceController.java b/iot-starter/src/main/java/cc/iotkit/manager/controller/DeviceController.java index 41a4f019..6aa76851 100644 --- a/iot-starter/src/main/java/cc/iotkit/manager/controller/DeviceController.java +++ b/iot-starter/src/main/java/cc/iotkit/manager/controller/DeviceController.java @@ -9,20 +9,13 @@ */ package cc.iotkit.manager.controller; -import cc.iotkit.common.Constants; import cc.iotkit.common.enums.ErrCode; import cc.iotkit.common.exception.BizException; -import cc.iotkit.common.utils.DeviceUtil; -import cc.iotkit.common.utils.ReflectUtil; -import cc.iotkit.common.utils.UniqueIdUtil; import cc.iotkit.comps.service.DeviceBehaviourService; import cc.iotkit.data.IDeviceConfigData; import cc.iotkit.data.IDeviceGroupData; import cc.iotkit.data.IDeviceInfoData; import cc.iotkit.data.IProductData; -import cc.iotkit.manager.model.query.DeviceQuery; -import cc.iotkit.manager.service.DataOwnerService; -import cc.iotkit.manager.service.DeferredDataConsumer; import cc.iotkit.manager.service.DeviceService; import cc.iotkit.model.InvokeResult; import cc.iotkit.model.Paging; @@ -35,7 +28,6 @@ import cc.iotkit.model.product.Product; import cc.iotkit.model.product.ThingModel; import cc.iotkit.temporal.IDevicePropertyData; import cc.iotkit.temporal.IThingModelMessageData; -import cc.iotkit.utils.AuthUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; diff --git a/iot-starter/src/main/java/cc/iotkit/manager/service/DeviceService.java b/iot-starter/src/main/java/cc/iotkit/manager/service/DeviceService.java index 479b0ec0..bd04f5c1 100644 --- a/iot-starter/src/main/java/cc/iotkit/manager/service/DeviceService.java +++ b/iot-starter/src/main/java/cc/iotkit/manager/service/DeviceService.java @@ -14,7 +14,7 @@ import static cc.iotkit.common.enums.ErrCode.DEVICE_OFFLINE; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.thing.ThingService; -import cc.iotkit.common.utils.JsonUtil; +import cc.iotkit.common.utils.JsonUtils; import cc.iotkit.common.utils.UniqueIdUtil; import cc.iotkit.comps.DeviceComponentManager; import cc.iotkit.data.IDeviceConfigData; @@ -106,7 +106,7 @@ public class DeviceService { DeviceInfo device = getAndCheckDevice(deviceId, checkOwner); DeviceConfig config = deviceConfigData.findByDeviceId(deviceId); - Map data = JsonUtil.parse(config.getConfig(), Map.class); + Map data = JsonUtils.parseObject(config.getConfig(), Map.class); return send(deviceId, device.getProductKey(), device.getDeviceName(), data, ThingModelMessage.TYPE_CONFIG, ThingModelMessage.ID_CONFIG_SET); diff --git a/iot-test-tool/iot-test-mqtt/pom.xml b/iot-test-tool/iot-test-mqtt/pom.xml index c5da22f3..9d39066c 100755 --- a/iot-test-tool/iot-test-mqtt/pom.xml +++ b/iot-test-tool/iot-test-mqtt/pom.xml @@ -46,6 +46,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + org.apache.maven.plugins maven-assembly-plugin diff --git a/iot-test-tool/iot-virtual-device/pom.xml b/iot-test-tool/iot-virtual-device/pom.xml index f3d21d9f..06bb8c13 100644 --- a/iot-test-tool/iot-virtual-device/pom.xml +++ b/iot-test-tool/iot-virtual-device/pom.xml @@ -42,4 +42,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8d7e6d80..d1ddfe0e 100755 --- a/pom.xml +++ b/pom.xml @@ -2,12 +2,6 @@ 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.6.2 - - cc.iotkit iotkit-parent @@ -18,37 +12,43 @@ pom - iot-rule-engine iot-components iot-data - - iot-auth-server iot-common iot-starter iot-test-tool + iot-module - 0.4.3-SNAPSHOT + 0.4.5-SNAPSHOT 11 + 2.7.11 4.2.2 - 1.30.0 + 1.34.0 21.1.0 1.9.3 2.13.1 3.7 2.11.0 1.14 - + 5.8.18 + 3.20.1 + 2.2.4 + 1.2.1 + 2.14.2 + 5.2.3 + 3.2.1 + - org.springframework.cloud - spring-cloud-dependencies - 2021.0.0 + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} pom import @@ -83,10 +83,32 @@ ${codec.version} + + com.alibaba + transmittable-thread-local + ${alibaba-ttl.version} + + + + + cn.hutool + hutool-bom + ${hutool.version} + pom + import + + + + + org.redisson + redisson-spring-boot-starter + ${redisson.version} + + org.projectlombok lombok - 1.18.24 + 1.18.26 @@ -101,22 +123,40 @@ 1.57 + cn.dev33 - sa-token-oauth2 - ${sa-token.version} + sa-token-spring-boot3-starter + ${satoken.version} + + + + cn.dev33 + sa-token-jwt + ${satoken.version} + + + cn.hutool + hutool-all + + + + + cn.dev33 + sa-token-core + ${satoken.version} - cn.dev33 - sa-token-spring-boot-starter - ${sa-token.version} + jakarta.servlet + jakarta.servlet-api + 6.0.0 - cn.dev33 - sa-token-dao-redis-jackson - ${sa-token.version} + jakarta.validation + jakarta.validation-api + 3.0.2 @@ -185,13 +225,6 @@ 3.1.1 - - cn.hutool - hutool-bom - 5.8.2 - pom - import - io.vertx @@ -241,6 +274,40 @@ ${graalvm.version} + + io.github.linpeilie + mapstruct-plus-spring-boot-starter + ${mapstruct-plus.version} + + + + com.baomidou + lock4j-redisson-spring-boot-starter + ${lock4j.version} + + + + org.apache.poi + poi + ${poi.version} + + + org.apache.poi + poi-ooxml + ${poi.version} + + + com.alibaba + easyexcel + ${easyexcel.version} + + + org.apache.poi + poi-ooxml-schemas + + + + cc.iotkit iot-model @@ -253,6 +320,36 @@ ${project.version} + + cc.iotkit + iot-common-log + ${project.version} + + + + cc.iotkit + iot-common-excel + ${project.version} + + + + cc.iotkit + iot-common-web + ${project.version} + + + + cc.iotkit + iot-common-security + ${project.version} + + + + cc.iotkit + iot-common-tenant + ${project.version} + + cc.iotkit iot-rule-engine @@ -313,6 +410,12 @@ ${project.version} + + cc.iotkit + iot-common-redis + ${project.version} + + cc.iotkit iot-message-rocketmq