feat: 项目初始化
This commit is contained in:
commit
6f8726000d
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
*.class
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
target/
|
||||
|
||||
# eclipse
|
||||
.settings/
|
||||
.classpath
|
||||
.project
|
||||
logs/
|
||||
|
||||
# idea
|
||||
.idea/
|
||||
*.iml
|
||||
.murphy.yml
|
||||
|
||||
*velocity.log*
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.factorypath
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.ipr
|
||||
*.log
|
||||
tmp/
|
||||
!DmJdbcDriver18.jar
|
||||
!kingbase8-8.6.0.jar
|
||||
/upload/
|
||||
105
cloud-admin/pom.xml
Normal file
105
cloud-admin/pom.xml
Normal file
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.byhah</groupId>
|
||||
<artifactId>cloud</artifactId>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>cloud-admin</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>com.byhah.deploy</groupId>-->
|
||||
<!-- <artifactId>byhah-deploy-basic-email</artifactId>-->
|
||||
<!--</dependency>-->
|
||||
<dependency>
|
||||
<groupId>com.byhah.deploy</groupId>
|
||||
<artifactId>byhah-deploy-basic-sms</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
<artifactId>okio</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.byhah.deploy</groupId>
|
||||
<artifactId>byhah-deploy-basic-sse</artifactId>
|
||||
</dependency>
|
||||
<!--基础依赖-->
|
||||
<dependency>
|
||||
<groupId>com.byhah.deploy</groupId>
|
||||
<artifactId>byhah-deploy-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.byhah.deploy</groupId>
|
||||
<artifactId>byhah-deploy-starter-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.byhah.deploy</groupId>
|
||||
<artifactId>byhah-deploy-starter-json</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.byhah.deploy</groupId>
|
||||
<artifactId>byhah-deploy-starter-redisson</artifactId>
|
||||
</dependency>
|
||||
<!--本地starter-->
|
||||
<dependency>
|
||||
<groupId>com.byhah</groupId>
|
||||
<artifactId>cloud-starter-orm</artifactId>
|
||||
</dependency>
|
||||
<!-- beetl模板引擎 -->
|
||||
<dependency>
|
||||
<groupId>com.ibeetl</groupId>
|
||||
<artifactId>beetl</artifactId>
|
||||
</dependency>
|
||||
<!--系统硬件信息-->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token 整合 redis (使用jackson序列化方式) -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-redisson-jackson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- poi-tl -->
|
||||
<dependency>
|
||||
<groupId>com.deepoove</groupId>
|
||||
<artifactId>poi-tl</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.google.cloud.tools</groupId>
|
||||
<artifactId>jib-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,19 @@
|
||||
package com.byhah.cloud.admin;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.Banner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@MapperScan("com.byhah.cloud.admin.mapper")
|
||||
@SpringBootApplication
|
||||
public class AdminApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication springApplication = new SpringApplication(AdminApplication.class);
|
||||
springApplication.setBannerMode(Banner.Mode.OFF);
|
||||
springApplication.run(args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
|
||||
package com.byhah.cloud.admin.config;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.byhah.cloud.admin.module.dev.util.DevLogUtil;
|
||||
import com.byhah.cloud.admin.utils.LoginUser;
|
||||
import com.byhah.cloud.admin.utils.UserUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 业务日志aop切面
|
||||
*/
|
||||
@Aspect
|
||||
@Order
|
||||
@Component
|
||||
public class DevLogAop {
|
||||
|
||||
/**
|
||||
* 日志切入点
|
||||
*/
|
||||
@Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
|
||||
private void getLogPointCut() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作成功返回结果记录日志
|
||||
*/
|
||||
@AfterReturning(pointcut = "getLogPointCut()", returning = "result")
|
||||
public void doAfterReturning(JoinPoint joinPoint, Object result) {
|
||||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
Operation operation = method.getAnnotation(Operation.class);
|
||||
if (operation != null) {
|
||||
String description = operation.description();
|
||||
if (!description.startsWith("ignore")) {
|
||||
String userName = "未知";
|
||||
try {
|
||||
LoginUser loginUser = UserUtil.getLoginUser();
|
||||
if (ObjectUtil.isNotNull(loginUser)) {
|
||||
userName = loginUser.getName();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
// 异步记录日志
|
||||
DevLogUtil.executeOperationLog(operation.summary(), userName, joinPoint, JSONUtil.toJsonStr(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作发生异常记录日志
|
||||
*/
|
||||
@AfterThrowing(pointcut = "getLogPointCut()", throwing = "exception")
|
||||
public void doAfterThrowing(JoinPoint joinPoint, Exception exception) {
|
||||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
Operation operation = method.getAnnotation(Operation.class);
|
||||
if (operation != null) {
|
||||
String description = operation.description();
|
||||
if (!description.startsWith("ignore")) {
|
||||
String userName = "未知";
|
||||
try {
|
||||
LoginUser loginUser = UserUtil.getLoginUser();
|
||||
if (ObjectUtil.isNotNull(loginUser)) {
|
||||
userName = loginUser.getName();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
// 异步记录日志
|
||||
DevLogUtil.executeExceptionLog(operation.summary(), userName, joinPoint, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
|
||||
package com.byhah.cloud.admin.config;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.filter.SaServletFilter;
|
||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||
import cn.dev33.satoken.router.SaHttpMethod;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.byhah.cloud.admin.utils.UserUtil;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 配置
|
||||
**/
|
||||
@Configuration
|
||||
public class GlobalConfigure implements WebMvcConfigurer {
|
||||
|
||||
/**
|
||||
* 无需登录的接口地址集合
|
||||
*/
|
||||
private static final String[] NO_LOGIN_PATH_ARR = {
|
||||
/* 主入口 */
|
||||
"/",
|
||||
/* 静态资源 */
|
||||
"/favicon.ico",
|
||||
"/doc.html",
|
||||
"/webjars/**",
|
||||
"/swagger-resources/**",
|
||||
"/v3/api-docs",
|
||||
"/v3/api-docs/**",
|
||||
"/v3/api-docs-ext",
|
||||
|
||||
/* 认证相关 */
|
||||
"/auth/getPhoneValidCode",
|
||||
"/auth/doLogin",
|
||||
|
||||
/* 系统基础配置 */
|
||||
"/dev/config/sysBaseList",
|
||||
|
||||
/* 系统字典树 */
|
||||
"/dev/dict/tree",
|
||||
|
||||
/* 文件下载 */
|
||||
"/dev/file/download",
|
||||
"/anon/**",
|
||||
// 健康检测
|
||||
"/actuator/health"
|
||||
};
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
|
||||
.addPathPatterns("/**")
|
||||
.excludePathPatterns(NO_LOGIN_PATH_ARR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限认证接口实现类,集成权限认证功能
|
||||
**/
|
||||
@Component
|
||||
public static class StpInterfaceImpl implements StpInterface {
|
||||
|
||||
/**
|
||||
* 返回一个账号所拥有的权限码集合
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPermissionList(Object loginId, String loginType) {
|
||||
return CollUtil.newArrayList(UserUtil.getLoginUser().getPermissionCodeList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回一个账号所拥有的角色标识集合
|
||||
*/
|
||||
@Override
|
||||
public List<String> getRoleList(Object loginId, String loginType) {
|
||||
return CollUtil.newArrayList(UserUtil.getLoginUser().getRoleCodeList());
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SaServletFilter getSaServletFilter() {
|
||||
return new SaServletFilter()
|
||||
.setBeforeAuth(obj -> {
|
||||
// ---------- 设置跨域响应头 ----------
|
||||
SaHolder.getResponse()
|
||||
// 是否启用浏览器默认XSS防护: 0=禁用 | 1=启用 | 1; mode=block 启用, 并在检查到XSS攻击时,停止渲染页面
|
||||
.setHeader("X-XSS-Protection", "1; mode=block")
|
||||
// 禁用浏览器内容嗅探
|
||||
.setHeader("X-Content-Type-Options", "nosniff")
|
||||
// 允许指定域访问跨域资源
|
||||
.setHeader("Access-Control-Allow-Origin", "*")
|
||||
// 允许所有请求方式
|
||||
.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
|
||||
// 有效时间
|
||||
.setHeader("Access-Control-Max-Age", "3600")
|
||||
// 允许的header参数
|
||||
.setHeader("Access-Control-Allow-Headers", "*");
|
||||
|
||||
// 如果是预检请求,则立即返回到前端
|
||||
SaRouter.match(SaHttpMethod.OPTIONS)
|
||||
// OPTIONS预检请求,不做处理
|
||||
.free(r -> {
|
||||
})
|
||||
.back();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,166 @@
|
||||
package com.byhah.cloud.admin.config;
|
||||
|
||||
import cn.dev33.satoken.exception.DisableServiceException;
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.exception.NotPermissionException;
|
||||
import cn.dev33.satoken.exception.NotRoleException;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
**/
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
/**
|
||||
* 数据验证异常 400
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler({BindException.class, MethodArgumentNotValidException.class})
|
||||
public R<String> requestException(Exception e) {
|
||||
log.warn("[参数异常] {}", e.getMessage());
|
||||
BindingResult bindingResult = null;
|
||||
if (e instanceof BindException) {
|
||||
bindingResult = ((BindException) e).getBindingResult();
|
||||
} else if (e instanceof MethodArgumentNotValidException) {
|
||||
bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
|
||||
}
|
||||
String errText = e.getMessage();
|
||||
if (Objects.nonNull(bindingResult)) {
|
||||
Iterator<FieldError> iterator = bindingResult.getFieldErrors().iterator();
|
||||
if (!iterator.hasNext()) {
|
||||
errText = "";
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('[');
|
||||
while (true) {
|
||||
FieldError fieldError = iterator.next();
|
||||
sb.append(fieldError.getDefaultMessage());
|
||||
if (!iterator.hasNext()) {
|
||||
sb.append(']');
|
||||
errText = sb.toString();
|
||||
break;
|
||||
}
|
||||
sb.append(',').append(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
return R.error(String.format("请求参数错误:%s", errText));
|
||||
}
|
||||
|
||||
/**
|
||||
* 未传参 400
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||||
public R<Void> httpMessageNotReadableException() {
|
||||
return R.error("传入数据有误");
|
||||
}
|
||||
|
||||
/**
|
||||
* 400
|
||||
* controller 入参转换异常
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler({MethodArgumentTypeMismatchException.class, ConversionFailedException.class})
|
||||
public R<Void> methodArgumentTypeMismatchException(Exception e) {
|
||||
log.warn("[全局异常] - 入参类型转换异常: [{}]", e.getMessage());
|
||||
return R.error("参数类型错误");
|
||||
}
|
||||
|
||||
/**
|
||||
* 未登录 401
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.UNAUTHORIZED)
|
||||
@ExceptionHandler(NotLoginException.class)
|
||||
public R<String> notLoginException() {
|
||||
return R.error("未登录");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 没有权限 403
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
@ExceptionHandler({NotRoleException.class, NotPermissionException.class, DisableServiceException.class})
|
||||
public R<String> forbidden() {
|
||||
return R.error("权限不足");
|
||||
}
|
||||
|
||||
/**
|
||||
* 无接口 404
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
@ExceptionHandler({NoResourceFoundException.class})
|
||||
public R<String> notFound() {
|
||||
return R.error("无路径");
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求方法错误 405
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
|
||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||
public R<String> httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
|
||||
return R.error("不支持的请求方法");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 不支持的MediaType 415
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
|
||||
@ExceptionHandler({HttpMediaTypeNotSupportedException.class})
|
||||
public R<String> httpMessageNotReadableException(Exception e) {
|
||||
return R.error("不支持的MediaType");
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ExceptionHandler(CommonException.class)
|
||||
public R<String> handlerCommonException(CommonException e) {
|
||||
log.warn("[业务异常] {}", e.getMessage());
|
||||
return R.error(e.getMsg());
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行时异常
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public R<String> runtimeException(RuntimeException e) {
|
||||
log.error("[运行时异常] ", e);
|
||||
return R.error(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 未知异常
|
||||
**/
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ExceptionHandler(Exception.class)
|
||||
public R<String> handleException(Exception e) {
|
||||
log.error("[未知异常] ", e);
|
||||
return R.error("未知错误");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,120 @@
|
||||
|
||||
package com.byhah.cloud.admin.listener;
|
||||
|
||||
import cn.dev33.satoken.listener.SaTokenListener;
|
||||
import cn.dev33.satoken.stp.SaLoginModel;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.byhah.cloud.admin.module.dev.util.DevLogUtil;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysUser;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysUserService;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 自定义登录监听器
|
||||
**/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AuthListener implements SaTokenListener {
|
||||
|
||||
private final SysUserService userService;
|
||||
|
||||
/**
|
||||
* 每次登录时触发
|
||||
*/
|
||||
@Override
|
||||
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
|
||||
// 更新用户的登录时间和登录ip等信息
|
||||
userService.updateUserLoginInfo(Convert.toLong(loginId), loginModel.getDevice());
|
||||
// 记录登录日志
|
||||
Object name = loginModel.getExtra("name");
|
||||
if (ObjectUtil.isNotEmpty(name)) {
|
||||
DevLogUtil.executeLoginLog(Convert.toStr(name));
|
||||
} else {
|
||||
DevLogUtil.executeLoginLog(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 每次注销时触发
|
||||
*/
|
||||
@Override
|
||||
public void doLogout(String loginType, Object loginId, String tokenValue) {
|
||||
// 记录登出日志
|
||||
SysUser user = userService.getById(Convert.toLong(loginId));
|
||||
if (Objects.nonNull(user)) {
|
||||
DevLogUtil.executeLogoutLog(user.getName());
|
||||
} else {
|
||||
DevLogUtil.executeLogoutLog(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 每次被踢下线时触发
|
||||
*/
|
||||
@Override
|
||||
public void doKickout(String loginType, Object loginId, String tokenValue) {
|
||||
// ...
|
||||
}
|
||||
|
||||
/**
|
||||
* 每次被顶下线时触发
|
||||
*/
|
||||
@Override
|
||||
public void doReplaced(String loginType, Object loginId, String 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 s, String s1, String s2, long l) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCloseSafe(String s, String s1, String s2) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 每次创建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) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.byhah.cloud.admin.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevMessageSearchDto;
|
||||
import com.byhah.cloud.admin.module.dev.vo.DevMessageVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import com.byhah.cloud.orm.mapper.dev.IDevMessageMapper;
|
||||
|
||||
/**
|
||||
* 站内信Mapper接口
|
||||
**/
|
||||
@Primary
|
||||
public interface DevMessageMapper extends IDevMessageMapper {
|
||||
|
||||
IPage<DevMessageVo> messages(Page<?> page, @Param("dto") DevMessageSearchDto dto);
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.byhah.cloud.admin.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysOrgSearchDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysUserSearchDto;
|
||||
import com.byhah.cloud.admin.module.sys.vo.SysOrgVo;
|
||||
import com.byhah.cloud.admin.module.sys.vo.SysUserVo;
|
||||
import com.byhah.cloud.orm.mapper.sys.ISysUserMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Primary
|
||||
public interface SysUserMapper extends ISysUserMapper {
|
||||
IPage<SysUserVo> sysUsers(Page<?> page, @Param("dto") SysUserSearchDto dto);
|
||||
|
||||
IPage<SysOrgVo> sysOrgs(Page<?> page, @Param("dto") SysOrgSearchDto dto);
|
||||
|
||||
Set<String> selectPermissionCodeByRoles(@Param("roles") Set<String> roles);
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import com.byhah.cloud.admin.module.auth.dto.PwdLoginDto;
|
||||
import com.byhah.cloud.admin.module.auth.service.AuthService;
|
||||
import com.byhah.cloud.admin.module.auth.vo.LoginResult;
|
||||
import com.byhah.cloud.admin.utils.LoginUser;
|
||||
import com.byhah.cloud.admin.utils.UserUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
@Tag(name = "登录")
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
public class AuthController {
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
@Operation(summary = "账号密码登录")
|
||||
@PostMapping("/doLogin")
|
||||
public R<LoginResult> doLogin(@RequestBody @Valid PwdLoginDto dto) {
|
||||
return R.ok(authService.doLogin(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "退出")
|
||||
@SaCheckLogin
|
||||
@GetMapping("/doLogout")
|
||||
public R<String> doLogout() {
|
||||
StpUtil.logout();
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取用户信息")
|
||||
@SaCheckLogin
|
||||
@GetMapping("/getLoginUser")
|
||||
public R<LoginUser> getLoginUser() {
|
||||
return R.ok(UserUtil.getLoginUser());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.byhah.cloud.admin.module.auth.vo.AuthSessionAnalysisVo;
|
||||
import com.byhah.cloud.admin.module.auth.vo.AuthSessionVo;
|
||||
import com.byhah.cloud.admin.module.auth.service.AuthSessionService;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
@Tag(name = "会话治理")
|
||||
@RestController
|
||||
@RequestMapping("/auth/session")
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
public class AuthSessionController {
|
||||
|
||||
private final AuthSessionService authSessionService;
|
||||
|
||||
|
||||
@Operation(summary = "会话统计")
|
||||
@GetMapping("/analysis")
|
||||
public R<AuthSessionAnalysisVo> analysis() {
|
||||
return R.ok(authSessionService.analysis());
|
||||
}
|
||||
|
||||
@Operation(summary = "查询会话")
|
||||
@GetMapping("/page")
|
||||
public R<Page<AuthSessionVo>> pageForB() {
|
||||
return R.ok(authSessionService.pageForB(PageUtils.toPage()));
|
||||
}
|
||||
|
||||
@Operation(summary = "强退会话")
|
||||
@PostMapping("/exit")
|
||||
public R<String> exitSessionForB(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> dto) {
|
||||
authSessionService.exitSession(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "强退token")
|
||||
@PostMapping("/exitToken")
|
||||
public R<String> exitTokenForB(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<String> dto) {
|
||||
authSessionService.exitToken(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* Session退出参数
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public class AuthExitSessionDto {
|
||||
|
||||
/** 用户id */
|
||||
@Schema(description = "用户id", required = true)
|
||||
@NotBlank(message = "userId不能为空")
|
||||
private String userId;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* Token退出参数
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public class AuthExitTokenDto {
|
||||
|
||||
/** token值 */
|
||||
@Schema(description = "token值", required = true)
|
||||
@NotBlank(message = "tokenValue不能为空")
|
||||
private String tokenValue;
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 获取手机验证码参数
|
||||
**/
|
||||
@Data
|
||||
public class AuthPhoneDto {
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
@Schema(description = "手机号", required = true)
|
||||
@NotBlank(message = "手机号不能为空")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
@Schema(description = "验证码", required = true)
|
||||
@NotBlank(message = "验证码不能为空")
|
||||
private String validCode;
|
||||
|
||||
/**
|
||||
* 验证码请求号
|
||||
*/
|
||||
@Schema(description = "验证码请求号", required = true)
|
||||
@NotBlank(message = "验证码请求号不能为空")
|
||||
private String validCodeReqNo;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 会话查询参数
|
||||
*
|
||||
**/
|
||||
@Data
|
||||
public class AuthSessionPageParam {
|
||||
private String searchKey;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
public class PhoneLoginDto {
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
@Schema(description = "手机号", required = true)
|
||||
@NotBlank(message = "手机号不能为空")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
@Schema(description = "验证码", required = true)
|
||||
@NotBlank(message = "验证码不能为空")
|
||||
private String validCode;
|
||||
|
||||
/**
|
||||
* 验证码请求号
|
||||
*/
|
||||
@Schema(description = "验证码请求号", required = true)
|
||||
@NotBlank(message = "验证码请求号不能为空")
|
||||
private String validCodeReqNo;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 账号密码登录参数
|
||||
**/
|
||||
@Data
|
||||
public class PwdLoginDto {
|
||||
@Schema(description = "账号", required = true)
|
||||
@NotBlank(message = "账号不能为空")
|
||||
private String account;
|
||||
@Schema(description = "密码", required = true)
|
||||
@NotBlank(message = "密码不能为空")
|
||||
private String password;
|
||||
|
||||
@Schema(description = "登录选取的目标id")
|
||||
private Long targetId;
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
package com.byhah.cloud.admin.module.auth.service;
|
||||
|
||||
import cn.dev33.satoken.stp.SaLoginModel;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.byhah.cloud.admin.mapper.SysUserMapper;
|
||||
import com.byhah.cloud.admin.module.auth.dto.PwdLoginDto;
|
||||
import com.byhah.cloud.admin.module.auth.vo.LoginResult;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysUserService;
|
||||
import com.byhah.cloud.admin.utils.LoginDataScope;
|
||||
import com.byhah.cloud.admin.utils.LoginUser;
|
||||
import com.byhah.cloud.basic.constant.ConfigKey;
|
||||
import com.byhah.cloud.basic.constant.RoleCode;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysRole;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysTenant;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysUser;
|
||||
import com.byhah.cloud.basic.core.enums.Gender;
|
||||
import com.byhah.cloud.basic.core.enums.PlatformType;
|
||||
import com.byhah.cloud.basic.core.enums.auth.AuthExceptionEnum;
|
||||
import com.byhah.cloud.basic.core.util.CryptogramUtil;
|
||||
import com.byhah.cloud.orm.mapper.sys.ISysTenantMapper;
|
||||
import com.byhah.cloud.orm.support.service.DevSupportService;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.deploy.basic.core.utils.Asserts;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AuthService {
|
||||
private final ISysTenantMapper tenantMapper;
|
||||
|
||||
private final SysUserMapper sysUserMapper;
|
||||
private final SysUserService userService;
|
||||
private final DevSupportService devSupportService;
|
||||
|
||||
public LoginResult doLogin(PwdLoginDto dto) {
|
||||
String account = dto.getAccount();
|
||||
String password = dto.getPassword();
|
||||
String passwordHash;
|
||||
try {
|
||||
// 做哈希值
|
||||
passwordHash = CryptogramUtil.doHashValue(password);
|
||||
} catch (Exception e) {
|
||||
throw new CommonException(AuthExceptionEnum.PWD_DECRYPT_ERROR.getValue());
|
||||
}
|
||||
SysUser user = userService.getUserByAccount(account);
|
||||
Asserts.notNull(user, AuthExceptionEnum.ACCOUNT_ERROR.getValue());
|
||||
Asserts.isEquals(user.getPassword(), passwordHash, AuthExceptionEnum.PWD_ERROR.getValue());
|
||||
// 执行登录
|
||||
return execLogin(user, dto.getTargetId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行登录
|
||||
**/
|
||||
private LoginResult execLogin(SysUser user, Long targetId) {
|
||||
String account = user.getAccount();
|
||||
// 校验状态
|
||||
Asserts.isTrue(user.getStatus(), AuthExceptionEnum.ACCOUNT_DISABLED.getValue());
|
||||
|
||||
List<LoginResult.LoginOrgItem> orgItems = new ArrayList<>();
|
||||
// 填充系统级
|
||||
List<SysRole> roleList = userService.getRoleList(user.getId());
|
||||
if (CollUtil.isNotEmpty(roleList)) {
|
||||
orgItems.add(new LoginResult.LoginOrgItem(-1L, "不选择", 1));
|
||||
}
|
||||
// 租户级
|
||||
SysTenant tenant = tenantMapper.lambdaQueryChain().eq(SysTenant::getAccount, account).one();
|
||||
if (Objects.nonNull(tenant)) {
|
||||
orgItems.add(new LoginResult.LoginOrgItem(tenant.getId(), tenant.getName(), 2));
|
||||
}
|
||||
|
||||
Set<String> roles = new HashSet<>();
|
||||
// 登录的类型 1-系统 2-租户
|
||||
Integer userType;
|
||||
// 选择了具体登录对象
|
||||
if (Objects.nonNull(targetId)) {
|
||||
if (targetId.equals(-1L)) {
|
||||
userType = 1;
|
||||
} else {
|
||||
// 选择了对象
|
||||
Long finalTargetId = targetId;
|
||||
Optional<LoginResult.LoginOrgItem> any = orgItems.stream().filter(x -> finalTargetId.equals(x.getId())).findAny();
|
||||
Asserts.isTrue(any.isPresent(), "选择部门不存在,请刷新后重试");
|
||||
LoginResult.LoginOrgItem orgItem = any.get();
|
||||
userType = orgItem.getType();
|
||||
}
|
||||
} else if (orgItems.size() == 1) {
|
||||
// 只有一个部门 直接登录
|
||||
userType = orgItems.getFirst().getType();
|
||||
targetId = orgItems.getFirst().getId();
|
||||
} else {
|
||||
Asserts.isTrue(CollUtil.isNotEmpty(orgItems), "无角色信息");
|
||||
return new LoginResult(orgItems);
|
||||
}
|
||||
|
||||
LoginDataScope dataScope = new LoginDataScope();
|
||||
if (userType == 1) {
|
||||
roles.addAll(roleList.stream().map(SysRole::getCode).toList());
|
||||
} else if (userType == 2) {
|
||||
roles.add(RoleCode.TENANT);
|
||||
dataScope.setTenantId(targetId);
|
||||
}
|
||||
Asserts.isTrue(CollUtil.isNotEmpty(roles), "用户无角色信息");
|
||||
// 执行登录
|
||||
StpUtil.login(user.getId(), new SaLoginModel().setDevice(String.valueOf(PlatformType.ADMIN.getType())).setExtra("name", user.getName()));
|
||||
// 角色码集合
|
||||
LoginUser loginUser = new LoginUser();
|
||||
BeanUtils.copyProperties(user, loginUser);
|
||||
loginUser.setGender(Optional.ofNullable(user.getGender()).map(Gender::getType).orElse(null));
|
||||
// 工作台快捷方式
|
||||
if (Objects.isNull(user.getWorkBenchData())) {
|
||||
String dataStr = devSupportService.getConfig(ConfigKey.Sys.SYS_DEFAULT_WORKBENCH_DATA_KEY);
|
||||
user.setWorkBenchData(JSONUtil.toBean(dataStr, SysUser.WorkBenchData.class));
|
||||
}
|
||||
// 获取权限码
|
||||
loginUser.setPermissionCodeList(sysUserMapper.selectPermissionCodeByRoles(roles));
|
||||
// 获取角色码
|
||||
loginUser.setRoleCodeList(roles);
|
||||
loginUser.setDataScope(dataScope);
|
||||
// 缓存用户信息,此处使用TokenSession为了指定时间内无操作则自动下线
|
||||
StpUtil.getTokenSession().set("user", loginUser);
|
||||
// 返回token
|
||||
return new LoginResult(StpUtil.getTokenInfo().tokenValue);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.service;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.date.*;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.byhah.cloud.admin.module.auth.vo.AuthSessionAnalysisVo;
|
||||
import com.byhah.cloud.admin.module.auth.vo.AuthSessionVo;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysUserService;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 会话治理Service接口实现类
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AuthSessionService {
|
||||
|
||||
private final SysUserService userService;
|
||||
|
||||
public AuthSessionAnalysisVo analysis() {
|
||||
AuthSessionAnalysisVo vo = new AuthSessionAnalysisVo();
|
||||
List<JSONObject> sessionList = StpUtil.searchSessionId("", -1, -1, true).stream().map(sessionId -> {
|
||||
JSONObject jsonObject = JSONUtil.createObj();
|
||||
String userId = StrUtil.split(sessionId, StrUtil.COLON).get(3);
|
||||
SaSession saSession = StpUtil.getSessionByLoginId(userId, false);
|
||||
int tokenCount = saSession.getTokenSignList().size();
|
||||
long createTime = saSession.getCreateTime();
|
||||
jsonObject.set("userId", userId);
|
||||
jsonObject.set("tokenCount", tokenCount);
|
||||
jsonObject.set("createTime", DateTime.of(createTime));
|
||||
return jsonObject;
|
||||
}).toList();
|
||||
|
||||
List<Integer> tokenCountList = CollectionUtil.newArrayList();
|
||||
tokenCountList.addAll(sessionList.stream().map(jsonObject -> jsonObject.getInt("tokenCount")).collect(Collectors.toList()));
|
||||
CollectionUtil.sort(tokenCountList, Comparator.comparingInt(Integer::intValue));
|
||||
int currentSessionTotalCount = sessionList.size();
|
||||
vo.setCurrentSessionTotalCount(Convert.toStr(currentSessionTotalCount));
|
||||
vo.setMaxTokenCount(Convert.toStr(tokenCountList.get(tokenCountList.size() - 1)));
|
||||
List<Date> sessionCreateTimeList = CollectionUtil.newArrayList();
|
||||
sessionCreateTimeList.addAll(sessionList.stream().map(jsonObject -> jsonObject.getDate("createTime")).collect(Collectors.toList()));
|
||||
DateTime oneHourAgo = DateUtil.offset(DateTime.now(), DateField.HOUR, -1);
|
||||
vo.setOneHourNewlyAdded(Convert.toStr(sessionCreateTimeList.stream().filter(date -> DateUtil.compare(oneHourAgo, date) <= 0).count()));
|
||||
return vo;
|
||||
}
|
||||
|
||||
|
||||
public Page<AuthSessionVo> pageForB(Page<AuthSessionVo> defaultPage) {
|
||||
long current = defaultPage.getCurrent();
|
||||
int total = StpUtil.searchSessionId("", -1, Convert.toInt(defaultPage.getSize()), true).size();
|
||||
if (ObjectUtil.isNotEmpty(total)) {
|
||||
defaultPage = new Page<>(current, defaultPage.getSize(), total);
|
||||
List<Long> userIdList = StpUtil.searchSessionId("",
|
||||
Convert.toInt((current - 1) * defaultPage.getSize()),
|
||||
Convert.toInt(defaultPage.getSize()), true).stream().map(sessionId ->
|
||||
Long.valueOf(StrUtil.split(sessionId, StrUtil.COLON).get(3))).collect(Collectors.toList());
|
||||
if (ObjectUtil.isNotEmpty(userIdList)) {
|
||||
List<AuthSessionVo> vo = userService.listByIds(userIdList).stream().map(userJsonObject -> {
|
||||
SaSession saSession = StpUtil.getSessionByLoginId(userJsonObject.getId(), false);
|
||||
AuthSessionVo res = new AuthSessionVo();
|
||||
BeanUtils.copyProperties(userJsonObject, res);
|
||||
res.setSessionId(saSession.getId());
|
||||
res.setSessionCreateTime(LocalDateTimeUtil.of(saSession.getCreateTime()));
|
||||
long sessionTimeOut = saSession.getTimeout();
|
||||
if (sessionTimeOut == -1) {
|
||||
res.setSessionTimeout("永久");
|
||||
} else {
|
||||
res.setSessionTimeout(DateUtil.formatBetween(saSession.getTimeout(), BetweenFormatter.Level.SECOND));
|
||||
}
|
||||
List<AuthSessionVo.TokenSignInfo> tokenInfoList = saSession.getTokenSignList().stream().map(tokenSign -> {
|
||||
AuthSessionVo.TokenSignInfo tokenSignInfo = new AuthSessionVo.TokenSignInfo();
|
||||
tokenSignInfo.setTokenValue(tokenSign.getValue());
|
||||
tokenSignInfo.setTokenDevice(tokenSign.getDevice());
|
||||
long tokenTimeout = SaManager.getSaTokenDao().getTimeout(StpUtil.stpLogic.splicingKeyTokenValue(tokenSign.getValue()));
|
||||
long tokenTimeoutConfig = StpUtil.stpLogic.getConfigOrGlobal().getTimeout();
|
||||
if (tokenTimeout == -1) {
|
||||
tokenSignInfo.setTokenTimeout("永久");
|
||||
tokenSignInfo.setTokenTimeoutPercent(100d);
|
||||
} else {
|
||||
tokenSignInfo.setTokenTimeout(DateUtil.formatBetween(SaManager.getSaTokenDao()
|
||||
.getTimeout(StpUtil.stpLogic.splicingKeyTokenValue(tokenSign.getValue())), BetweenFormatter.Level.SECOND));
|
||||
if (tokenTimeoutConfig == -1) {
|
||||
tokenSignInfo.setTokenTimeoutPercent(0d);
|
||||
} else {
|
||||
tokenSignInfo.setTokenTimeoutPercent(NumberUtil.div(tokenTimeout, tokenTimeoutConfig));
|
||||
}
|
||||
}
|
||||
return tokenSignInfo;
|
||||
}).collect(Collectors.toList());
|
||||
res.setTokenSignList(tokenInfoList);
|
||||
return res;
|
||||
}).collect(Collectors.toList());
|
||||
defaultPage.setRecords(vo);
|
||||
}
|
||||
}
|
||||
return defaultPage;
|
||||
}
|
||||
|
||||
|
||||
public void exitSession(List<Long> dto) {
|
||||
dto.forEach(StpUtil::logout);
|
||||
}
|
||||
|
||||
|
||||
public void exitToken(List<String> dto) {
|
||||
dto.forEach(StpUtil::logoutByTokenValue);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 图片验证码结果
|
||||
**/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class AuthPicValidCodeVo {
|
||||
|
||||
/**
|
||||
* 验证码图片,Base64
|
||||
*/
|
||||
@Schema(description = "验证码图片,Base64")
|
||||
private String validCodeBase64;
|
||||
|
||||
/**
|
||||
* 验证码请求号
|
||||
*/
|
||||
@Schema(description = "验证码请求号")
|
||||
private String validCodeReqNo;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 会话统计结果
|
||||
*
|
||||
**/
|
||||
@Data
|
||||
public class AuthSessionAnalysisVo {
|
||||
|
||||
/** 当前会话总数量 */
|
||||
@Schema(description = "当前会话总数量")
|
||||
private String currentSessionTotalCount;
|
||||
|
||||
/** 最大签发令牌数 */
|
||||
@Schema(description = "最大签发令牌数")
|
||||
private String maxTokenCount;
|
||||
|
||||
/** 最近1小时会话数 */
|
||||
@Schema(description = "最近1小时会话数")
|
||||
private String oneHourNewlyAdded;
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.auth.vo;
|
||||
|
||||
import com.byhah.cloud.basic.core.entity.system.SysUser;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会话结果集
|
||||
**/
|
||||
@Data
|
||||
public class AuthSessionVo {
|
||||
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "头像")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "账号")
|
||||
private String account;
|
||||
|
||||
@Schema(description = "姓名")
|
||||
private String name;
|
||||
private SysUser.UserLoginInfo lastLoginInfo;
|
||||
private SysUser.UserLoginInfo latestLoginInfo;
|
||||
|
||||
@Schema(description = "会话id")
|
||||
private String sessionId;
|
||||
|
||||
@Schema(description = "会话创建时间")
|
||||
private LocalDateTime sessionCreateTime;
|
||||
|
||||
@Schema(description = "会话剩余有效期")
|
||||
private String sessionTimeout;
|
||||
|
||||
@Schema(description = "令牌信息集合")
|
||||
private List<TokenSignInfo> tokenSignList;
|
||||
|
||||
@Data
|
||||
public static class TokenSignInfo {
|
||||
|
||||
/**
|
||||
* token值
|
||||
*/
|
||||
@Schema(description = "token值")
|
||||
private String tokenValue;
|
||||
|
||||
/**
|
||||
* 登录设备
|
||||
*/
|
||||
@Schema(description = "登录设备")
|
||||
private String tokenDevice;
|
||||
|
||||
/**
|
||||
* token剩余有效期
|
||||
*/
|
||||
@Schema(description = "token剩余有效期")
|
||||
private String tokenTimeout;
|
||||
|
||||
/**
|
||||
* token剩余有效期百分比
|
||||
*/
|
||||
@Schema(description = "token剩余有效期百分比")
|
||||
private Double tokenTimeoutPercent;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package com.byhah.cloud.admin.module.auth.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class LoginResult {
|
||||
@Schema(description = "登录token")
|
||||
private String token;
|
||||
|
||||
@Schema(description = "是否需要重新登录")
|
||||
private boolean reLogin;
|
||||
|
||||
@Schema(description = "可供选择的登录对象")
|
||||
private List<LoginOrgItem> orgItems;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public static class LoginOrgItem {
|
||||
private Long id;
|
||||
private String name;
|
||||
/**
|
||||
* 1-系统级(直接根据绑定角色查权限、不区分数据权限) 2-租户/tenant
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
public LoginOrgItem(Long id, String name, Integer type) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public LoginResult(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public LoginResult(List<LoginOrgItem> items) {
|
||||
this.orgItems = items;
|
||||
this.reLogin = true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.byhah.cloud.admin.module.common.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* excel通用处理service
|
||||
*
|
||||
* @author ZYJ
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ExcelCommonService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package com.byhah.cloud.admin.module.dev.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.byhah.cloud.admin.module.dev.dto.*;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevConfigService;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevConfigBatchParam;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevConfigDto;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevConfigSearchDto;
|
||||
import com.byhah.cloud.basic.constant.ConfigKey;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevConfig;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "配置")
|
||||
@RestController
|
||||
@RequestMapping("/dev/config")
|
||||
@RequiredArgsConstructor
|
||||
public class DevConfigController {
|
||||
|
||||
private final DevConfigService service;
|
||||
|
||||
@Operation(summary = "获取配置分页")
|
||||
@GetMapping("/page")
|
||||
public R<Page<DevConfig>> page(DevConfigSearchDto dto) {
|
||||
dto.setCategory(ConfigKey.SysCategory.BIZ_DEFINE);
|
||||
return R.ok(service.page(PageUtils.toPage(), dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取系统基础配置")
|
||||
@GetMapping("/sysBaseList")
|
||||
public R<List<DevConfig>> sysBaseList() {
|
||||
DevConfigSearchDto dto = new DevConfigSearchDto();
|
||||
dto.setCategory(ConfigKey.SysCategory.SYS_BASE);
|
||||
return R.ok(service.page(PageUtils.toNoSizePage(), dto).getRecords());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取配置列表")
|
||||
@GetMapping("/list")
|
||||
public R<List<DevConfig>> list(DevConfigSearchDto dto) {
|
||||
return R.ok(service.page(PageUtils.toNoSizePage(), dto).getRecords());
|
||||
}
|
||||
|
||||
@Operation(summary = "添加配置")
|
||||
@PostMapping("/add")
|
||||
public R<String> add(@RequestBody @Valid DevConfigDto dto) {
|
||||
service.add(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑配置")
|
||||
@PostMapping("/edit")
|
||||
public R<String> edit(@RequestBody @Validated(Update.class) DevConfigDto dto) {
|
||||
service.edit(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除配置")
|
||||
@PostMapping("/delete")
|
||||
public R<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
service.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取配置详情")
|
||||
@GetMapping("/detail")
|
||||
public R<DevConfig> detail(Long id) {
|
||||
return R.ok(service.detail(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "配置批量更新")
|
||||
@PostMapping("/editBatch")
|
||||
public R<String> editBatch(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<DevConfigBatchParam> devConfigBatchParamList) {
|
||||
service.editBatch(devConfigBatchParamList);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.byhah.cloud.admin.module.dev.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevService;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "开发")
|
||||
@RestController
|
||||
@RequestMapping("/dev")
|
||||
@RequiredArgsConstructor
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
public class DevController {
|
||||
private final static String PWD = "&h..C)Mk0TtZZPxv";
|
||||
private final DevService devService;
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.controller;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevDictDto;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevDictSearchDto;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevDictService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevDict;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.cloud.admin.module.dev.dto.*;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "字典")
|
||||
@RestController
|
||||
@RequestMapping("/dev/dict")
|
||||
@RequiredArgsConstructor
|
||||
public class DevDictController {
|
||||
|
||||
private final DevDictService devDictService;
|
||||
|
||||
@Operation(summary = "获取字典分页")
|
||||
@GetMapping("/page")
|
||||
public R<IPage<DevDict>> page(DevDictSearchDto dto) {
|
||||
return R.ok(devDictService.page(PageUtils.toPage(), dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取字典列表")
|
||||
@GetMapping("/list")
|
||||
public R<List<DevDict>> list(DevDictSearchDto dto) {
|
||||
return R.ok(devDictService.page(PageUtils.toNoSizePage(), dto).getRecords());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取字典树")
|
||||
@GetMapping("/tree")
|
||||
public R<List<Tree<Long>>> tree() {
|
||||
return R.ok(devDictService.tree());
|
||||
}
|
||||
|
||||
@Operation(summary = "添加字典")
|
||||
@PostMapping("/add")
|
||||
public R<String> add(@RequestBody @Validated(Insert.class) DevDictDto dto) {
|
||||
devDictService.add(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑字典")
|
||||
@PostMapping("/edit")
|
||||
public R<String> edit(@RequestBody @Validated(Update.class) DevDictDto dto) {
|
||||
devDictService.edit(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除字典")
|
||||
@PostMapping("/delete")
|
||||
public R<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
devDictService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取字典详情")
|
||||
@GetMapping("/detail")
|
||||
public R<DevDict> detail(Long id) {
|
||||
return R.ok(devDictService.detail(id));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevFileSearchDto;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevFileService;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevFile;
|
||||
import com.byhah.cloud.orm.support.service.DevSupportService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "文件")
|
||||
@RequestMapping("/dev/file")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class DevFileController {
|
||||
|
||||
private final DevFileService devFileService;
|
||||
|
||||
private final DevSupportService devSupportService;
|
||||
|
||||
@Operation(summary = "上传文件返回url或id",description = "ignore")
|
||||
@PostMapping("/upload")
|
||||
R<String> upload(@RequestParam(required = false) Integer engine,@RequestParam(required = false) Long maxSize, @RequestParam(defaultValue = "false") Boolean returnId, @RequestPart("file") MultipartFile file) throws IOException {
|
||||
return R.ok(devSupportService.upload(engine, returnId, maxSize, file));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取文件分页列表")
|
||||
@GetMapping("/page")
|
||||
R<Page<DevFile>> page(DevFileSearchDto dto) {
|
||||
return R.ok(devFileService.page(PageUtils.toPage(), dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取文件列表")
|
||||
@GetMapping("/list")
|
||||
R<List<DevFile>> list(DevFileSearchDto dto) {
|
||||
return R.ok(devFileService.page(PageUtils.toNoSizePage(), dto).getRecords());
|
||||
}
|
||||
|
||||
@Operation(summary = "下载文件")
|
||||
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
void download(Long id, HttpServletResponse response) {
|
||||
devFileService.download(id, response);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除文件")
|
||||
@PostMapping(value = "/delete")
|
||||
R<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
devFileService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取文件详情")
|
||||
@GetMapping("/detail")
|
||||
R<DevFile> detail(Long id) {
|
||||
return R.ok(devFileService.detail(id));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevLogSearchDto;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevLog;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevLogService;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
|
||||
@Tag(name = "日志")
|
||||
@RestController
|
||||
@RequestMapping("/dev/log")
|
||||
@RequiredArgsConstructor
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
public class DevLogController {
|
||||
|
||||
private final DevLogService devLogService;
|
||||
|
||||
@Operation(summary = "获取日志分页")
|
||||
@GetMapping("/page")
|
||||
public R<Page<DevLog>> page(@Validated DevLogSearchDto dto) {
|
||||
return R.ok(devLogService.page(PageUtils.toPage(), dto));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevMessageSearchDto;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevMessageSendDto;
|
||||
import com.byhah.cloud.admin.module.dev.vo.DevMessageVo;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevMessageService;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
@Tag(name = "站内信")
|
||||
@RequestMapping("/dev/message")
|
||||
@RestController
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
@RequiredArgsConstructor
|
||||
public class DevMessageController {
|
||||
|
||||
private final DevMessageService devMessageService;
|
||||
|
||||
@Operation(summary = "发送站内信")
|
||||
@PostMapping("/send")
|
||||
public R<Void> send(@RequestBody @Valid DevMessageSendDto dto) {
|
||||
devMessageService.send(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取站内信分页")
|
||||
@GetMapping("/page")
|
||||
public R<IPage<DevMessageVo>> page(DevMessageSearchDto dto) {
|
||||
return R.ok(devMessageService.page(PageUtils.toPage(), dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除站内信")
|
||||
@PostMapping("/delete")
|
||||
public R<Void> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
devMessageService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取站内信详情")
|
||||
@GetMapping("/detail")
|
||||
public R<DevMessageVo> detail(Long id) {
|
||||
return R.ok(devMessageService.detail(id));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import com.byhah.cloud.admin.module.dev.vo.DevMonitorServerVo;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevMonitorService;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
|
||||
@Tag(name = "监控")
|
||||
@RestController
|
||||
@RequestMapping("/dev/monitor")
|
||||
@RequiredArgsConstructor
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
public class DevMonitorController {
|
||||
|
||||
private final DevMonitorService devMonitorService;
|
||||
|
||||
@Operation(summary = "获取服务器监控信息")
|
||||
@GetMapping("/serverInfo")
|
||||
public R<DevMonitorServerVo> serverInfo() {
|
||||
return R.ok(devMonitorService.serverInfo());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevSmsSearchDto;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevSmsSendDto;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevSmsService;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevSms;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* 短信
|
||||
**/
|
||||
@Tag(name = "短信")
|
||||
@RestController
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
@RequestMapping("/dev/sms")
|
||||
@RequiredArgsConstructor
|
||||
public class DevSmsController {
|
||||
|
||||
private final DevSmsService devSmsService;
|
||||
|
||||
@Operation(summary = "发送短信")
|
||||
@PostMapping("/send")
|
||||
R<Void> send(@RequestBody @Validated DevSmsSendDto dto) {
|
||||
devSmsService.send(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取短信分页")
|
||||
@GetMapping("/page")
|
||||
public R<Page<DevSms>> page(DevSmsSearchDto dto) {
|
||||
return R.ok(devSmsService.page(PageUtils.toPage(), dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除短信")
|
||||
@PostMapping("/delete")
|
||||
public R<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
devSmsService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取短信详情")
|
||||
@GetMapping("/detail")
|
||||
public R<DevSms> detail(Long id) {
|
||||
return R.ok(devSmsService.detail(id));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 配置批量更新参数
|
||||
**/
|
||||
@Data
|
||||
public class DevConfigBatchParam {
|
||||
|
||||
/** 配置键 */
|
||||
@Schema(description = "配置键", required = true)
|
||||
@NotBlank(message = "configKey不能为空")
|
||||
private String configKey;
|
||||
|
||||
/** 配置值 */
|
||||
@Schema(description = "配置值", required = true)
|
||||
@NotBlank(message = "configValue不能为空")
|
||||
private String configValue;
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
|
||||
/**
|
||||
* 配置添加参数
|
||||
*/
|
||||
@Data
|
||||
public class DevConfigDto {
|
||||
|
||||
@Null(groups = Insert.class, message = "id必须为空")
|
||||
@NotNull(groups = Update.class, message = "id不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "配置键", required = true)
|
||||
@NotBlank(message = "configKey不能为空")
|
||||
private String configKey;
|
||||
|
||||
@Schema(description = "配置值", required = true)
|
||||
@NotBlank(message = "configValue不能为空")
|
||||
private String configValue;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序码", required = true)
|
||||
@NotNull(message = "sortCode不能为空")
|
||||
private Integer sortCode;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.model.CommonSearch;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 配置列表参数
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DevConfigSearchDto extends CommonSearch {
|
||||
|
||||
/** 配置分类 */
|
||||
@Schema(description = "配置分类")
|
||||
private String category;
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
|
||||
/**
|
||||
* 字典添加参数
|
||||
*/
|
||||
@Data
|
||||
public class DevDictDto {
|
||||
@Schema(description = "id")
|
||||
@NotNull(message = "id不能为空", groups = Update.class)
|
||||
@Null(message = "id不能为空", groups = Insert.class)
|
||||
private Long id;
|
||||
@Schema(description = "父id")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "字典文字")
|
||||
@NotBlank(message = "dictLabel不能为空")
|
||||
private String label;
|
||||
|
||||
@Schema(description = "字典值")
|
||||
@NotBlank(message = "dictValue不能为空")
|
||||
private String value;
|
||||
|
||||
@Schema(description = "排序码")
|
||||
@NotNull(message = "sortCode不能为空")
|
||||
private Integer sortCode;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.model.CommonSearch;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 字典查询参数
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DevDictSearchDto extends CommonSearch {
|
||||
|
||||
@Schema(description = "父id")
|
||||
private Long parentId;
|
||||
|
||||
/** 字典分类 */
|
||||
@Schema(description = "字典分类")
|
||||
private String category;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.model.CommonSearch;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 邮件查询参数
|
||||
**/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DevEmailSearchDto extends CommonSearch {
|
||||
@Schema(description = "邮件引擎")
|
||||
private Integer engine;
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class DevEmailSendDto {
|
||||
@Schema(description = "发送引擎 1-本地 2-阿里 3-腾讯")
|
||||
@Range(min = 1,max = 3)
|
||||
private Integer engine;
|
||||
|
||||
@Schema(description = "发送类型 1-纯文本 2-html 3-模板")
|
||||
@Range(min = 1,max = 3)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "发件人昵称 阿里和腾讯才有")
|
||||
private String sendUser;
|
||||
|
||||
@Schema(description = "接收人邮箱地址,多个逗号拼接")
|
||||
@NotBlank(message = "receiveAccounts不能为空")
|
||||
private String receiveAccounts;
|
||||
|
||||
@Schema(description = "邮件主题")
|
||||
@NotBlank(message = "subject不能为空")
|
||||
private String subject;
|
||||
|
||||
@Schema(description = "邮件正文")
|
||||
@NotBlank(message = "content不能为空")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "预先创建且通过审核的模板名称", required = true)
|
||||
private String templateName;
|
||||
|
||||
@Schema(description = "预先创建且通过审核的模板的参数json")
|
||||
private String templateParam;
|
||||
|
||||
@Schema(description = "标签名")
|
||||
private String tagName;
|
||||
|
||||
@Schema(description = "图片展位符 本地html有")
|
||||
private Map<String, InputStream> imageMap = MapUtil.newHashMap();
|
||||
|
||||
@Schema(description = "附件列表 本地邮件有")
|
||||
private List<File> files = CollectionUtil.newArrayList();
|
||||
|
||||
@Schema(description = "附件列表 腾讯邮件有")
|
||||
List<JSONObject> attachmentList = CollectionUtil.newArrayList();
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DevFileDto {
|
||||
@Schema(description = "上传引擎,默认取系统设置 1-本地 2-阿里 3-腾讯 4-MINIO")
|
||||
private Integer engine;
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.model.CommonSearch;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 文件分页列表参数
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DevFileSearchDto extends CommonSearch {
|
||||
|
||||
@Schema(description = "文件引擎")
|
||||
private Integer engine;
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.model.CommonSearch;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 日志查询参数
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DevLogSearchDto extends CommonSearch {
|
||||
|
||||
@Schema(description = "日志分类")
|
||||
@NotNull
|
||||
private Integer category;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 站内信查询参数
|
||||
**/
|
||||
@Data
|
||||
public class DevMessageSearchDto {
|
||||
@Schema(description = "站内信分类")
|
||||
private Integer category;
|
||||
|
||||
@Schema(description = "主题关键词")
|
||||
private String searchKey;
|
||||
|
||||
@Schema(description = "接收用户id")
|
||||
private Long receiveUserId;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 站内信发送参数
|
||||
**/
|
||||
@Data
|
||||
public class DevMessageSendDto {
|
||||
|
||||
@Schema(description = "主题", required = true)
|
||||
@NotBlank(message = "subject不能为空")
|
||||
private String subject;
|
||||
|
||||
@Schema(description = "接收人id集合", required = true)
|
||||
@NotEmpty(message = "receiverIdList不能为空")
|
||||
private List<Long> receiverIdList;
|
||||
|
||||
@Schema(description = "正文")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "分类")
|
||||
@NotNull(message = "category不能为空")
|
||||
private Integer category;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.model.CommonSearch;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 短信查询参数
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DevSmsSearchDto extends CommonSearch {
|
||||
@Schema(description = "短信引擎")
|
||||
private Integer engine;
|
||||
|
||||
@Schema(description = "手机号关键词")
|
||||
private String searchKey;
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 短信发送——阿里云参数
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public class DevSmsSendAliyunParam {
|
||||
|
||||
/** 手机号 */
|
||||
@Schema(description = "手机号,多个逗号拼接", required = true)
|
||||
@NotBlank(message = "phoneNumbers不能为空")
|
||||
private String phoneNumbers;
|
||||
|
||||
/** 模板编码 */
|
||||
@Schema(description = "短信服务控制台配置且审核通过的模板编码", required = true)
|
||||
@NotBlank(message = "templateCode不能为空")
|
||||
private String templateCode;
|
||||
|
||||
/** 发送参数 */
|
||||
@Schema(description = "短信模板变量对应的实际值,JSON格式")
|
||||
private String templateParam;
|
||||
|
||||
/** 短信签名 */
|
||||
@Schema(description = "短信服务控制台配置且审核通过的短信签名")
|
||||
private String signName;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DevSmsSendDto {
|
||||
private Integer engine;
|
||||
|
||||
@Schema(description = "手机号,多个逗号拼接")
|
||||
@NotBlank(message = "phoneNumbers不能为空")
|
||||
private String phoneNumbers;
|
||||
|
||||
@Schema(description = "短信服务控制台配置且审核通过的模板编码")
|
||||
@NotBlank(message = "templateCode不能为空")
|
||||
private String templateCode;
|
||||
|
||||
@Schema(description = "短信模板变量对应的实际值,JSON格式")
|
||||
private String templateParam;
|
||||
|
||||
@Schema(description = "短信服务控制台配置且审核通过的短信签名")
|
||||
private String signName;
|
||||
|
||||
@Schema(description = "在短信控制台添加应用后生成的实际SdkAppId 腾讯才有")
|
||||
private String sdkAppId;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 短信发送——阿里云参数
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public class DevSmsSendTencentParam {
|
||||
|
||||
/** 手机号 */
|
||||
@Schema(description = "手机号,多个逗号拼接", required = true)
|
||||
@NotBlank(message = "phoneNumbers不能为空")
|
||||
private String phoneNumbers;
|
||||
|
||||
/** 模板编码 */
|
||||
@Schema(description = "短信服务控制台配置且审核通过的模板编码", required = true)
|
||||
@NotBlank(message = "templateCode不能为空")
|
||||
private String templateCode;
|
||||
|
||||
/** 发送参数 */
|
||||
@Schema(description = "短信模板变量对应的顺序。支持传入多个参数,逗号拼接")
|
||||
private String templateParam;
|
||||
|
||||
/** sdkAppId */
|
||||
@Schema(description = "在短信控制台添加应用后生成的实际SdkAppId")
|
||||
private String sdkAppId;
|
||||
|
||||
/** 短信签名 */
|
||||
@Schema(description = "短信服务控制台配置且审核通过的短信签名")
|
||||
private String signName;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.byhah.cloud.admin.module.dev.dto.dev;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Data
|
||||
public class PushMsgDto {
|
||||
private Long targetId;
|
||||
private Integer type;
|
||||
private LocalDate date;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.byhah.cloud.admin.module.dev.dto.dev;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class WxMpMsgDto {
|
||||
private String wxMpAppId;
|
||||
private String templateId;
|
||||
private String toUsers;
|
||||
private String page;
|
||||
private Map<String, String> data;
|
||||
private String appId;
|
||||
}
|
||||
@ -0,0 +1,110 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevConfigBatchParam;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevConfigDto;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevConfigSearchDto;
|
||||
import com.byhah.cloud.basic.constant.ConfigKey;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevConfig;
|
||||
import com.byhah.cloud.orm.mapper.dev.IDevConfigMapper;
|
||||
import com.byhah.cloud.orm.support.service.DevSupportService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DevConfigService extends ServiceImpl<IDevConfigMapper, DevConfig> {
|
||||
|
||||
private final DevSupportService devSupportService;
|
||||
|
||||
public Page<DevConfig> page(Page<DevConfig> page, DevConfigSearchDto dto) {
|
||||
String searchKey = dto.getSearchKey();
|
||||
String category = dto.getCategory();
|
||||
return lambdaQuery().eq(StrUtil.isNotBlank(searchKey), DevConfig::getConfigKey, searchKey)
|
||||
.eq(StrUtil.isNotBlank(category), DevConfig::getCategory, category)
|
||||
.orderByAsc(DevConfig::getSortCode)
|
||||
.page(page);
|
||||
}
|
||||
|
||||
|
||||
public void add(DevConfigDto dto) {
|
||||
checkParam(dto);
|
||||
DevConfig devConfig = BeanUtil.toBean(dto, DevConfig.class);
|
||||
devConfig.setCategory(ConfigKey.SysCategory.BIZ_DEFINE);
|
||||
save(devConfig);
|
||||
}
|
||||
|
||||
public void edit(DevConfigDto dto) {
|
||||
DevConfig devConfig = queryEntity(dto.getId());
|
||||
checkParam(dto);
|
||||
BeanUtil.copyProperties(dto, devConfig);
|
||||
devConfig.setCategory(ConfigKey.SysCategory.BIZ_DEFINE);
|
||||
updateById(devConfig);
|
||||
// 移除对应的缓存
|
||||
devSupportService.removeConfigCache(devConfig.getConfigKey());
|
||||
}
|
||||
|
||||
private void checkParam(DevConfigDto dto) {
|
||||
boolean hasSameConfig = count(new LambdaQueryWrapper<DevConfig>()
|
||||
.eq(DevConfig::getConfigKey, dto.getConfigKey())
|
||||
.ne(Objects.nonNull(dto.getId()), DevConfig::getId, dto.getId())) > 0;
|
||||
if (hasSameConfig) {
|
||||
throw new CommonException("存在重复的配置,配置键为:{}", dto.getConfigKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(List<Long> ids) {
|
||||
if (CollUtil.isNotEmpty(ids)) {
|
||||
List<DevConfig> devConfigList = listByIds(ids);
|
||||
if (ObjectUtil.isNotEmpty(devConfigList)) {
|
||||
List<String> devConfigResultList = CollUtil.newArrayList(devConfigList.stream()
|
||||
.map(DevConfig::getCategory).collect(Collectors.toSet()));
|
||||
if (devConfigResultList.size() != 1 || !devConfigResultList.get(0).equals(ConfigKey.SysCategory.BIZ_DEFINE)) {
|
||||
throw new CommonException("不可删除系统内置配置");
|
||||
}
|
||||
List<DevConfig> deleteDevConfigList = listByIds(ids);
|
||||
// 执行删除
|
||||
removeByIds(ids);
|
||||
deleteDevConfigList.forEach(x -> devSupportService.removeConfigCache(x.getConfigKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public DevConfig detail(Long id) {
|
||||
return queryEntity(id);
|
||||
}
|
||||
|
||||
|
||||
public DevConfig queryEntity(Long id) {
|
||||
DevConfig devConfig = getById(id);
|
||||
if (ObjectUtil.isEmpty(devConfig)) {
|
||||
throw new CommonException("配置不存在,id值为:{}", id);
|
||||
}
|
||||
return devConfig;
|
||||
}
|
||||
|
||||
|
||||
public void editBatch(List<DevConfigBatchParam> configs) {
|
||||
configs.forEach(config -> {
|
||||
lambdaUpdate().eq(DevConfig::getConfigKey, config.getConfigKey())
|
||||
.set(DevConfig::getConfigValue, config.getConfigValue()).update();
|
||||
// 移除对应的缓存
|
||||
devSupportService.removeConfigCache(config.getConfigKey());
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNode;
|
||||
import cn.hutool.core.lang.tree.TreeUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.deploy.basic.core.utils.Asserts;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevDictDto;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevDictSearchDto;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevDict;
|
||||
import com.byhah.cloud.orm.mapper.dev.IDevDictMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 字典Service接口实现类
|
||||
**/
|
||||
@Service
|
||||
public class DevDictService extends ServiceImpl<IDevDictMapper, DevDict> {
|
||||
|
||||
public IPage<DevDict> page(Page<DevDict> page, DevDictSearchDto dto) {
|
||||
return lambdaQuery().eq(Objects.nonNull(dto.getParentId()), DevDict::getParentId, dto.getParentId())
|
||||
.like(StrUtil.isNotBlank(dto.getSearchKey()), DevDict::getLabel, dto.getSearchKey()).page(page);
|
||||
}
|
||||
|
||||
public List<DevDict> list(DevDictSearchDto dto) {
|
||||
LambdaQueryWrapper<DevDict> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
if (ObjectUtil.isNotEmpty(dto.getParentId())) {
|
||||
lambdaQueryWrapper.eq(DevDict::getParentId, dto.getParentId());
|
||||
}
|
||||
return this.list(lambdaQueryWrapper);
|
||||
}
|
||||
|
||||
|
||||
public List<Tree<Long>> tree() {
|
||||
LambdaQueryWrapper<DevDict> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.orderByAsc(DevDict::getSortCode);
|
||||
List<DevDict> devDictList = this.list(lambdaQueryWrapper);
|
||||
List<TreeNode<Long>> treeNodeList = devDictList.stream().map(devDict ->
|
||||
new TreeNode<>(devDict.getId(), devDict.getParentId(),
|
||||
devDict.getLabel(), devDict.getSortCode()).setExtra(JSONUtil.parseObj(devDict)))
|
||||
.collect(Collectors.toList());
|
||||
return TreeUtil.build(treeNodeList, 0L);
|
||||
}
|
||||
|
||||
|
||||
public void add(DevDictDto dto) {
|
||||
checkParam(dto);
|
||||
if (Objects.isNull(dto.getParentId())) {
|
||||
dto.setParentId(0L);
|
||||
}
|
||||
DevDict devDict = BeanUtil.toBean(dto, DevDict.class);
|
||||
this.save(devDict);
|
||||
}
|
||||
|
||||
private void checkParam(DevDictDto dto) {
|
||||
final Long id = dto.getId();
|
||||
final Long parentId = dto.getParentId();
|
||||
final String label = dto.getLabel();
|
||||
final String value = dto.getValue();
|
||||
Long count = lambdaQuery().eq(DevDict::getParentId, parentId)
|
||||
.eq(DevDict::getLabel, label)
|
||||
.ne(Objects.nonNull(id), DevDict::getId, id)
|
||||
.count();
|
||||
Asserts.isTrue(count == 0, String.format("存在重复的字典文字,名称为:%s", label));
|
||||
|
||||
count = lambdaQuery().eq(DevDict::getParentId, parentId)
|
||||
.eq(DevDict::getValue, value)
|
||||
.ne(Objects.nonNull(id), DevDict::getId, id)
|
||||
.count();
|
||||
Asserts.isTrue(count == 0, String.format("存在重复的字典值,名称为:%s", value));
|
||||
}
|
||||
|
||||
|
||||
public void edit(DevDictDto dto) {
|
||||
DevDict devDict = this.queryEntity(dto.getId());
|
||||
if (Objects.isNull(dto.getParentId())) {
|
||||
dto.setParentId(0L);
|
||||
}
|
||||
checkParam(dto);
|
||||
BeanUtil.copyProperties(dto, devDict);
|
||||
this.updateById(devDict);
|
||||
}
|
||||
|
||||
public void delete(List<Long> ids) {
|
||||
if (ObjectUtil.isNotEmpty(ids)) {
|
||||
this.removeByIds(ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public DevDict detail(Long id) {
|
||||
return this.queryEntity(id);
|
||||
}
|
||||
|
||||
|
||||
public DevDict queryEntity(Long id) {
|
||||
DevDict devDict = this.getById(id);
|
||||
if (ObjectUtil.isEmpty(devDict)) {
|
||||
throw new CommonException("字典不存在,id值为:{}", id);
|
||||
}
|
||||
return devDict;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package com.byhah.cloud.admin.module.dev.service;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevFileSearchDto;
|
||||
import com.byhah.cloud.orm.mapper.dev.IDevFileMapper;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevFile;
|
||||
import com.byhah.cloud.basic.core.enums.dev.DevFileEngine;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.deploy.basic.util.web.DownloadUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 文件Service接口实现类
|
||||
**/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DevFileService extends ServiceImpl<IDevFileMapper, DevFile> {
|
||||
|
||||
public Page<DevFile> page(Page<DevFile> page, DevFileSearchDto dto) {
|
||||
return lambdaQuery().eq(Objects.nonNull(dto.getEngine()), DevFile::getEngine, dto.getEngine())
|
||||
.like(StrUtil.isNotBlank(dto.getSearchKey()), DevFile::getName, dto.getSearchKey())
|
||||
.page(page);
|
||||
}
|
||||
|
||||
public void download(Long id, HttpServletResponse response) {
|
||||
DevFile devFile;
|
||||
try {
|
||||
devFile = queryEntity(id);
|
||||
} catch (Exception e) {
|
||||
throw new CommonException(e.getMessage());
|
||||
}
|
||||
if (devFile.getEngine() != DevFileEngine.LOCAL) {
|
||||
throw new CommonException("非本地文件不支持此方式下载,id值为:" + devFile.getId());
|
||||
}
|
||||
File file = FileUtil.file(devFile.getStoragePath());
|
||||
if (!FileUtil.exist(file)) {
|
||||
throw new CommonException("找不到存储的文件,id值为:" + devFile.getId());
|
||||
}
|
||||
DownloadUtil.download(devFile.getName(), IoUtil.readBytes(FileUtil.getInputStream(file)), response);
|
||||
}
|
||||
|
||||
|
||||
public void delete(List<Long> ids) {
|
||||
removeByIds(ids);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public DevFile detail(Long id) {
|
||||
return queryEntity(id);
|
||||
}
|
||||
|
||||
|
||||
public DevFile queryEntity(Long id) {
|
||||
DevFile devFile = getById(id);
|
||||
if (ObjectUtil.isEmpty(devFile)) {
|
||||
throw new CommonException("文件不存在,id值为:{}", id);
|
||||
}
|
||||
return devFile;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevLogSearchDto;
|
||||
import com.byhah.cloud.orm.mapper.dev.IDevLogMapper;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevLog;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 日志Service接口实现类
|
||||
*/
|
||||
@Service
|
||||
public class DevLogService extends ServiceImpl<IDevLogMapper, DevLog> {
|
||||
|
||||
public Page<DevLog> page(Page<DevLog> page, DevLogSearchDto dto) {
|
||||
return lambdaQuery().eq(DevLog::getCategory, dto.getCategory())
|
||||
.like(StrUtil.isNotBlank(dto.getSearchKey()), DevLog::getName, dto.getSearchKey())
|
||||
.orderByDesc(DevLog::getCreatedAt)
|
||||
.page(page);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,118 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.service;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.admin.mapper.DevMessageMapper;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevMessageSearchDto;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevMessageSendDto;
|
||||
import com.byhah.cloud.admin.module.dev.vo.DevMessageVo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.byhah.cloud.orm.mapper.dev.IDevMessageUserMapper;
|
||||
import com.byhah.cloud.orm.mapper.sys.ISysUserMapper;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevMessage;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevMessageUser;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysUser;
|
||||
import com.byhah.cloud.basic.core.enums.dev.DevMessageType;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 站内信Service接口实现类
|
||||
**/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DevMessageService extends ServiceImpl<DevMessageMapper, DevMessage> {
|
||||
|
||||
private final ISysUserMapper sysUserMapper;
|
||||
private final IDevMessageUserMapper messageUserMapper;
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void send(DevMessageSendDto dto) {
|
||||
dto.setContent(ObjectUtil.isEmpty(dto.getContent()) ?
|
||||
dto.getSubject() : dto.getContent());
|
||||
dto.setCategory(ObjectUtil.isEmpty(dto.getCategory()) ?
|
||||
DevMessageType.SYS.getType() : dto.getCategory());
|
||||
DevMessage message = BeanUtil.toBean(dto, DevMessage.class);
|
||||
save(message);
|
||||
List<Long> receiverIds = dto.getReceiverIdList();
|
||||
if (CollUtil.isNotEmpty(receiverIds)) {
|
||||
for (Long receiverId : receiverIds) {
|
||||
DevMessageUser messageUser = new DevMessageUser();
|
||||
messageUser.setUserId(receiverId);
|
||||
messageUser.setMessageId(message.getId());
|
||||
messageUserMapper.insert(messageUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public IPage<DevMessageVo> page(Page<?> page, DevMessageSearchDto dto) {
|
||||
return baseMapper.messages(page, dto);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(List<Long> ids) {
|
||||
if (ObjectUtil.isNotEmpty(ids)) {
|
||||
// 清除站内信与用户关联关系
|
||||
messageUserMapper.lambdaUpdateChain().in(DevMessageUser::getMessageId, ids).remove();
|
||||
// 执行删除
|
||||
removeByIds(ids);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DevMessageVo detail(Long id) {
|
||||
DevMessageVo devMessageResult = new DevMessageVo();
|
||||
DevMessage devMessage = queryEntity(id);
|
||||
BeanUtil.copyProperties(devMessage, devMessageResult);
|
||||
DevMessageUser myMessage = messageUserMapper.lambdaQueryChain().eq(DevMessageUser::getMessageId, id)
|
||||
.eq(DevMessageUser::getUserId, StpUtil.getLoginIdAsLong())
|
||||
.one();
|
||||
if (ObjectUtil.isNotEmpty(myMessage)) {
|
||||
// 设置为已读
|
||||
myMessage.setRead(true);
|
||||
myMessage.setReadAt(LocalDateTime.now());
|
||||
messageUserMapper.updateById(myMessage);
|
||||
}
|
||||
List<DevMessageVo.DevReceiveInfo> receiveInfoList = messageUserMapper.lambdaQueryChain().eq(DevMessageUser::getMessageId, id).list()
|
||||
.stream().map(messageUser -> {
|
||||
Long userId = messageUser.getUserId();
|
||||
DevMessageVo.DevReceiveInfo receiveInfo = new DevMessageVo.DevReceiveInfo();
|
||||
Optional<SysUser> user = sysUserMapper.lambdaQueryChain().eq(SysUser::getId, userId).oneOpt();
|
||||
String userName = user.map(SysUser::getName).orElse("未知用户");
|
||||
receiveInfo.setReceiveUserId(userId);
|
||||
receiveInfo.setReceiveUserName(userName);
|
||||
receiveInfo.setRead(messageUser.getRead());
|
||||
return receiveInfo;
|
||||
}).collect(Collectors.toList());
|
||||
devMessageResult.setReceiveInfoList(receiveInfoList);
|
||||
return devMessageResult;
|
||||
}
|
||||
|
||||
|
||||
public DevMessage queryEntity(Long id) {
|
||||
DevMessage devMessage = getById(id);
|
||||
if (ObjectUtil.isEmpty(devMessage)) {
|
||||
throw new CommonException("站内信不存在,id值为:{}", id);
|
||||
}
|
||||
return devMessage;
|
||||
}
|
||||
|
||||
public void readAll(Long userId) {
|
||||
messageUserMapper.lambdaUpdateChain().eq(DevMessageUser::getUserId, userId).set(DevMessageUser::getRead, userId).update();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,151 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.service;
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.system.JvmInfo;
|
||||
import cn.hutool.system.OsInfo;
|
||||
import cn.hutool.system.RuntimeInfo;
|
||||
import cn.hutool.system.SystemUtil;
|
||||
import com.byhah.cloud.admin.module.dev.vo.DevMonitorServerVo;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.byhah.deploy.basic.util.NetWorkUtil;
|
||||
import oshi.SystemInfo;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
import oshi.hardware.GlobalMemory;
|
||||
import oshi.hardware.HardwareAbstractionLayer;
|
||||
import oshi.software.os.FileSystem;
|
||||
import oshi.software.os.OperatingSystem;
|
||||
import oshi.util.Util;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* 监控Service接口实现类
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class DevMonitorService {
|
||||
|
||||
|
||||
public DevMonitorServerVo serverInfo() {
|
||||
DevMonitorServerVo vo = new DevMonitorServerVo();
|
||||
SystemInfo si = new SystemInfo();
|
||||
HardwareAbstractionLayer hal = si.getHardware();
|
||||
CentralProcessor cpu = hal.getProcessor();
|
||||
|
||||
// CPU信息
|
||||
DevMonitorServerVo.DevMonitorCpuInfo devMonitorCpuInfo = new DevMonitorServerVo.DevMonitorCpuInfo();
|
||||
devMonitorCpuInfo.setCupName(StrUtil.trim(cpu.getProcessorIdentifier().getName()));
|
||||
devMonitorCpuInfo.setCupNum(cpu.getPhysicalPackageCount() + "颗物理CPU");
|
||||
devMonitorCpuInfo.setCpuPhysicalCoreNum(cpu.getPhysicalProcessorCount() + "个物理核心");
|
||||
devMonitorCpuInfo.setCpuLogicalCoreNum(cpu.getLogicalProcessorCount() + "个逻辑核心");
|
||||
long[] prevTicks = cpu.getSystemCpuLoadTicks();
|
||||
Util.sleep(1000);
|
||||
long[] ticks = cpu.getSystemCpuLoadTicks();
|
||||
long nice = ticks[CentralProcessor.TickType.NICE.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.NICE.getIndex()];
|
||||
long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
|
||||
long softIrq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
|
||||
long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
|
||||
long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
|
||||
long user = ticks[CentralProcessor.TickType.USER.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.USER.getIndex()];
|
||||
long ioWait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
|
||||
long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
|
||||
long totalCpu = user + nice + sys + idle + ioWait + irq + softIrq + steal;
|
||||
devMonitorCpuInfo.setCpuSysUseRate(NumberUtil.div(NumberUtil.mul(sys, 100), totalCpu, 2) + "%");
|
||||
devMonitorCpuInfo.setCpuUserUseRate(NumberUtil.div(NumberUtil.mul(user, 100), totalCpu, 2) + "%");
|
||||
devMonitorCpuInfo.setCpuTotalUseRate(NumberUtil.div(NumberUtil.mul(NumberUtil.add(sys, user), 100), totalCpu, 2));
|
||||
devMonitorCpuInfo.setCpuWaitRate(NumberUtil.div(NumberUtil.mul(ioWait, 100), totalCpu, 2) + "%");
|
||||
devMonitorCpuInfo.setCpuFreeRate(NumberUtil.div(NumberUtil.mul(idle, 100), totalCpu, 2) + "%");
|
||||
vo.setDevMonitorCpuInfo(devMonitorCpuInfo);
|
||||
|
||||
// 内存信息
|
||||
GlobalMemory memory = hal.getMemory();
|
||||
DevMonitorServerVo.DevMonitorMemoryInfo devMonitorMemoryInfo = new DevMonitorServerVo.DevMonitorMemoryInfo();
|
||||
long used = memory.getTotal() - memory.getAvailable();
|
||||
devMonitorMemoryInfo.setMemoryTotal(FileUtil.readableFileSize(memory.getTotal()));
|
||||
devMonitorMemoryInfo.setMemoryUsed(FileUtil.readableFileSize(used));
|
||||
devMonitorMemoryInfo.setMemoryFree(FileUtil.readableFileSize(memory.getAvailable()));
|
||||
devMonitorMemoryInfo.setMemoryUseRate(NumberUtil.mul(NumberUtil.div(used, memory.getTotal(), 4), 100));
|
||||
vo.setDevMonitorMemoryInfo(devMonitorMemoryInfo);
|
||||
|
||||
// 存储信息
|
||||
DevMonitorServerVo.DevMonitorStorageInfo devMonitorStorageInfo = new DevMonitorServerVo.DevMonitorStorageInfo();
|
||||
OperatingSystem operatingSystem = si.getOperatingSystem();
|
||||
FileSystem fileSystem = operatingSystem.getFileSystem();
|
||||
AtomicLong storageTotal = new AtomicLong();
|
||||
AtomicLong storageUsed = new AtomicLong();
|
||||
AtomicLong storageFree = new AtomicLong();
|
||||
fileSystem.getFileStores().forEach(osFileStore -> {
|
||||
long totalSpace = osFileStore.getTotalSpace();
|
||||
long usableSpace = osFileStore.getUsableSpace();
|
||||
long freeSpace = osFileStore.getFreeSpace();
|
||||
long usedSpace = totalSpace - usableSpace;
|
||||
storageTotal.addAndGet(totalSpace);
|
||||
storageUsed.addAndGet(usedSpace);
|
||||
storageFree.addAndGet(freeSpace);
|
||||
});
|
||||
devMonitorStorageInfo.setStorageTotal(FileUtil.readableFileSize(storageTotal.get()));
|
||||
devMonitorStorageInfo.setStorageUsed(FileUtil.readableFileSize(storageUsed.get()));
|
||||
devMonitorStorageInfo.setStorageFree(FileUtil.readableFileSize(storageFree.get()));
|
||||
devMonitorStorageInfo.setStorageUseRate(NumberUtil.mul(NumberUtil.div(storageUsed.doubleValue(), storageTotal.doubleValue(), 4), 100));
|
||||
vo.setDevMonitorStorageInfo(devMonitorStorageInfo);
|
||||
|
||||
// 网络信息
|
||||
DevMonitorServerVo.DevMonitorNetworkInfo devMonitorNetworkInfo = new DevMonitorServerVo.DevMonitorNetworkInfo();
|
||||
Map<String, String> networkUpRate = NetWorkUtil.getNetworkUpRate();
|
||||
devMonitorNetworkInfo.setUpLinkRate(networkUpRate.get("UP"));
|
||||
devMonitorNetworkInfo.setDownLinkRate(networkUpRate.get("DOWN"));
|
||||
vo.setDevMonitorNetworkInfo(devMonitorNetworkInfo);
|
||||
|
||||
// 服务器信息
|
||||
OsInfo osInfo = SystemUtil.getOsInfo();
|
||||
DevMonitorServerVo.DevMonitorServerInfo devMonitorServerInfo = new DevMonitorServerVo.DevMonitorServerInfo();
|
||||
devMonitorServerInfo.setServerName(NetUtil.getLocalHostName());
|
||||
devMonitorServerInfo.setServerOs(osInfo.getName());
|
||||
devMonitorServerInfo.setServerIp(NetUtil.getLocalhostStr());
|
||||
devMonitorServerInfo.setServerArchitecture(osInfo.getArch());
|
||||
vo.setDevMonitorServerInfo(devMonitorServerInfo);
|
||||
|
||||
// JVM信息
|
||||
DevMonitorServerVo.DevMonitorJvmInfo devMonitorJvmInfo = new DevMonitorServerVo.DevMonitorJvmInfo();
|
||||
RuntimeInfo runtimeInfo = SystemUtil.getRuntimeInfo();
|
||||
JvmInfo jvmInfo = SystemUtil.getJvmInfo();
|
||||
devMonitorJvmInfo.setJvmName(jvmInfo.getName());
|
||||
devMonitorJvmInfo.setJvmVersion(jvmInfo.getVersion());
|
||||
long totalMemory = runtimeInfo.getTotalMemory();
|
||||
devMonitorJvmInfo.setJvmMemoryTotal(FileUtil.readableFileSize(totalMemory));
|
||||
devMonitorJvmInfo.setJvmMemoryFree(FileUtil.readableFileSize(runtimeInfo.getFreeMemory()));
|
||||
long jvmMemoryUsed = NumberUtil.sub(new BigDecimal(runtimeInfo
|
||||
.getTotalMemory()), new BigDecimal(runtimeInfo.getFreeMemory())).longValue();
|
||||
devMonitorJvmInfo.setJvmMemoryUsed(FileUtil.readableFileSize(jvmMemoryUsed));
|
||||
double jvmUseRate = NumberUtil.mul(NumberUtil.div(jvmMemoryUsed, totalMemory, 4), 100);
|
||||
devMonitorJvmInfo.setJvmUseRate(jvmUseRate);
|
||||
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
|
||||
DateTime startTime = DateUtil.date(runtimeMXBean.getStartTime());
|
||||
devMonitorJvmInfo.setJvmStartTime(DateUtil.formatDateTime(startTime));
|
||||
devMonitorJvmInfo.setJvmRunTime(DateUtil.formatBetween(startTime, DateTime.now()));
|
||||
devMonitorJvmInfo.setJavaVersion(SystemUtil.get("java.version", false));
|
||||
devMonitorJvmInfo.setJavaPath(SystemUtil.get("java.home", false));
|
||||
vo.setDevMonitorJvmInfo(devMonitorJvmInfo);
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.byhah.cloud.admin.module.dev.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DevService {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.PhoneUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevSmsSearchDto;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevSmsSendDto;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevSms;
|
||||
import com.byhah.cloud.basic.core.enums.dev.DevSmsEngine;
|
||||
import com.byhah.cloud.orm.mapper.dev.IDevSmsMapper;
|
||||
import com.byhah.cloud.orm.support.service.DevSupportService;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.deploy.basic.sms.client.SmsAliyunClient;
|
||||
import com.byhah.deploy.basic.sms.client.SmsTencentClient;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.byhah.cloud.basic.constant.ConfigKey.Sms.*;
|
||||
|
||||
/**
|
||||
* 短信Service接口实现类
|
||||
**/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DevSmsService extends ServiceImpl<IDevSmsMapper, DevSms> {
|
||||
private final DevSupportService devSupportService;
|
||||
|
||||
public void send(DevSmsSendDto dto) {
|
||||
validPhone(dto.getPhoneNumbers());
|
||||
DevSmsEngine engine = DevSmsEngine.forValue(dto.getEngine());
|
||||
String receipt = send(engine, dto);
|
||||
DevSms devSms = new DevSms();
|
||||
BeanUtil.copyProperties(dto, devSms);
|
||||
devSms.setEngine(DevSmsEngine.ALIYUN);
|
||||
devSms.setReceiptInfo(receipt);
|
||||
save(devSms);
|
||||
}
|
||||
|
||||
private String send(DevSmsEngine engine, DevSmsSendDto dto) {
|
||||
if (engine == DevSmsEngine.ALIYUN) {
|
||||
String accessKeyId = devSupportService.getConfig(SMS_ALIYUN_ACCESS_KEY_ID_KEY);
|
||||
String accessKeySecret = devSupportService.getConfig(SMS_ALIYUN_ACCESS_KEY_SECRET_KEY);
|
||||
String endPoint = devSupportService.getConfig(SMS_ALIYUN_END_POINT_KEY);
|
||||
String signName = dto.getSignName();
|
||||
if (StrUtil.isBlank(signName)) {
|
||||
signName = devSupportService.getConfig(SMS_ALIYUN_DEFAULT_SIGN_NAME_KEY);
|
||||
}
|
||||
SmsAliyunClient client = new SmsAliyunClient(accessKeyId, accessKeySecret, endPoint);
|
||||
return client.sendSms(dto.getPhoneNumbers(), signName, dto.getTemplateCode(), dto.getTemplateParam());
|
||||
} else if (engine == DevSmsEngine.TENCENT) {
|
||||
String secretId = devSupportService.getConfig(SMS_TENCENT_SECRET_ID_KEY);
|
||||
String secretKey = devSupportService.getConfig(SMS_TENCENT_SECRET_KEY_KEY);
|
||||
String regionId = devSupportService.getConfig(SMS_TENCENT_REGION_ID_KEY);
|
||||
String sdkAppId = devSupportService.getConfig(SMS_TENCENT_DEFAULT_SDK_APP_ID_KEY);
|
||||
String signName = dto.getSignName();
|
||||
if (StrUtil.isBlank(signName)) {
|
||||
signName = devSupportService.getConfig(SMS_TENCENT_DEFAULT_SIGN_NAME_KEY);
|
||||
}
|
||||
SmsTencentClient client = new SmsTencentClient(secretId, secretKey, regionId, sdkAppId);
|
||||
return client.sendSms(dto.getPhoneNumbers(), signName, dto.getTemplateCode(), dto.getTemplateParam());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Page<DevSms> page(Page<DevSms> page, DevSmsSearchDto dto) {
|
||||
return lambdaQuery().eq(Objects.nonNull(dto.getEngine()), DevSms::getEngine, dto.getEngine())
|
||||
.like(CharSequenceUtil.isNotBlank(dto.getSearchKey()), DevSms::getPhoneNumbers, dto.getSearchKey())
|
||||
.page(page);
|
||||
}
|
||||
|
||||
|
||||
public void delete(List<Long> ids) {
|
||||
removeByIds(ids);
|
||||
}
|
||||
|
||||
|
||||
public DevSms detail(Long id) {
|
||||
return queryEntity(id);
|
||||
}
|
||||
|
||||
|
||||
public DevSms queryEntity(Long id) {
|
||||
DevSms devSms = getById(id);
|
||||
if (ObjectUtil.isEmpty(devSms)) {
|
||||
throw new CommonException("短信不存在,id值为:%s", id);
|
||||
}
|
||||
return devSms;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验手机格式
|
||||
**/
|
||||
private void validPhone(String phones) {
|
||||
StrUtil.split(phones, StrUtil.COMMA).forEach(phone -> {
|
||||
if (!PhoneUtil.isMobile(phone)) {
|
||||
throw new CommonException("手机号码:%s格式错误", phone);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.util;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.byhah.deploy.basic.util.IpAddressUtil;
|
||||
import com.byhah.deploy.basic.util.web.ServletUtils;
|
||||
import com.byhah.deploy.basic.util.web.UaUtil;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevLogService;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevLog;
|
||||
import com.byhah.cloud.basic.core.enums.dev.DevLogType;
|
||||
import com.byhah.cloud.basic.core.util.CommonJoinPointUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 日志工具类
|
||||
*/
|
||||
public class DevLogUtil {
|
||||
|
||||
private static final DevLogService devLogService = SpringUtil.getBean(DevLogService.class);
|
||||
|
||||
/**
|
||||
* 记录操作日志
|
||||
*/
|
||||
public static void executeOperationLog(String methodName, String userName, JoinPoint joinPoint, String resultJson) {
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
DevLog devLog = genBasOpLog();
|
||||
ThreadUtil.execute(() -> {
|
||||
devLog.setCategory(DevLogType.OPERATE);
|
||||
devLog.setName(methodName);
|
||||
devLog.setExeStatus(true);
|
||||
devLog.setClassName(joinPoint.getTarget().getClass().getName());
|
||||
devLog.setMethodName(joinPoint.getSignature().getName());
|
||||
devLog.setReqMethod(request.getMethod());
|
||||
devLog.setReqUrl(request.getRequestURI());
|
||||
devLog.setParamJson(CommonJoinPointUtil.getArgsJsonString(joinPoint));
|
||||
devLog.setResultJson(resultJson);
|
||||
devLog.setOpTime(LocalDateTime.now());
|
||||
devLog.setOpUser(userName);
|
||||
devLogService.save(devLog);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录异常日志
|
||||
*/
|
||||
public static void executeExceptionLog(String methodName, String userName, JoinPoint joinPoint, Exception exception) {
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
DevLog devLog = genBasOpLog();
|
||||
ThreadUtil.execute(() -> {
|
||||
devLog.setCategory(DevLogType.EXCEPTION);
|
||||
devLog.setName(methodName);
|
||||
devLog.setExeStatus(false);
|
||||
devLog.setExeMessage(ExceptionUtil.stacktraceToString(exception, Integer.MAX_VALUE));
|
||||
devLog.setClassName(joinPoint.getTarget().getClass().getName());
|
||||
devLog.setMethodName(joinPoint.getSignature().getName());
|
||||
devLog.setReqMethod(request.getMethod());
|
||||
devLog.setReqUrl(request.getRequestURI());
|
||||
devLog.setParamJson(CommonJoinPointUtil.getArgsJsonString(joinPoint));
|
||||
devLog.setOpTime(LocalDateTime.now());
|
||||
devLog.setOpUser(userName);
|
||||
devLogService.save(devLog);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登录日志
|
||||
*/
|
||||
public static void executeLoginLog(String userName) {
|
||||
DevLog devLog = genBasOpLog();
|
||||
ThreadUtil.execute(() -> {
|
||||
devLog.setCategory(DevLogType.LOGIN);
|
||||
devLog.setName("用户登录");
|
||||
devLog.setExeStatus(true);
|
||||
devLog.setOpTime(LocalDateTime.now());
|
||||
devLog.setOpUser(userName);
|
||||
devLogService.save(devLog);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登出日志
|
||||
*/
|
||||
public static void executeLogoutLog(String userName) {
|
||||
DevLog devLog = genBasOpLog();
|
||||
ThreadUtil.execute(() -> {
|
||||
devLog.setCategory(DevLogType.LOGOUT);
|
||||
devLog.setName("用户登出");
|
||||
devLog.setExeStatus(true);
|
||||
devLog.setOpTime(LocalDateTime.now());
|
||||
devLog.setOpUser(userName);
|
||||
devLogService.save(devLog);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建基础操作日志
|
||||
*/
|
||||
private static DevLog genBasOpLog() {
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
String ip = ServletUtils.getClientIP(request);
|
||||
long loginId;
|
||||
try {
|
||||
loginId = StpUtil.getLoginIdAsLong();
|
||||
if (ObjectUtil.isEmpty(loginId)) {
|
||||
loginId = -1L;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
loginId = -1L;
|
||||
}
|
||||
DevLog devLog = new DevLog();
|
||||
devLog.setOpIp(ip);
|
||||
devLog.setOpAddress(IpAddressUtil.getCityInfo(ip));
|
||||
devLog.setOpBrowser(UaUtil.getBrowser(request));
|
||||
devLog.setOpOs(UaUtil.getOs(request));
|
||||
devLog.setCreatedBy(loginId);
|
||||
return devLog;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.byhah.cloud.admin.module.dev.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DevMessageVo {
|
||||
private Long id;
|
||||
private String category;
|
||||
private String subject;
|
||||
private String content;
|
||||
private LocalDateTime createdAt;
|
||||
@Schema(description = "当前用户是否已读")
|
||||
private Boolean read;
|
||||
|
||||
@Schema(description = "接收信息集合")
|
||||
private List<DevReceiveInfo> receiveInfoList;
|
||||
|
||||
/**
|
||||
* 接收信息类
|
||||
*/
|
||||
@Data
|
||||
public static class DevReceiveInfo {
|
||||
|
||||
/**
|
||||
* 接收人ID
|
||||
*/
|
||||
@Schema(description = "接收人ID")
|
||||
private Long receiveUserId;
|
||||
|
||||
/**
|
||||
* 接收人姓名
|
||||
*/
|
||||
@Schema(description = "接收人姓名")
|
||||
private String receiveUserName;
|
||||
|
||||
/**
|
||||
* 是否已读
|
||||
*/
|
||||
@Schema(description = "是否已读")
|
||||
private Boolean read;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,232 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.dev.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 服务器监控结果
|
||||
*/
|
||||
@Data
|
||||
public class DevMonitorServerVo {
|
||||
|
||||
/* ==============概览数据============ */
|
||||
/** CPU信息 */
|
||||
@Schema(description = "CPU信息")
|
||||
private DevMonitorCpuInfo devMonitorCpuInfo;
|
||||
|
||||
/** 内存信息 */
|
||||
@Schema(description = "内存信息")
|
||||
private DevMonitorMemoryInfo devMonitorMemoryInfo;
|
||||
|
||||
/** 存储信息 */
|
||||
@Schema(description = "存储信息")
|
||||
private DevMonitorStorageInfo devMonitorStorageInfo;
|
||||
|
||||
/** 网络信息 */
|
||||
@Schema(description = "网络信息")
|
||||
private DevMonitorNetworkInfo devMonitorNetworkInfo;
|
||||
|
||||
/* ==============服务器数据============ */
|
||||
/** 服务器信息 */
|
||||
@Schema(description = "服务器信息")
|
||||
private DevMonitorServerInfo devMonitorServerInfo;
|
||||
|
||||
/* ==============JVM数据============ */
|
||||
/** JVM信息 */
|
||||
@Schema(description = "JVM信息")
|
||||
private DevMonitorJvmInfo devMonitorJvmInfo;
|
||||
|
||||
/**
|
||||
* CPU信息类
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public static class DevMonitorCpuInfo {
|
||||
|
||||
/** CPU名称 */
|
||||
@Schema(description = "CPU名称")
|
||||
private String cupName;
|
||||
|
||||
/** CPU数量 */
|
||||
@Schema(description = "CPU数量")
|
||||
private String cupNum;
|
||||
|
||||
/** CPU物理核心数 */
|
||||
@Schema(description = "CPU物理核心数")
|
||||
private String cpuPhysicalCoreNum;
|
||||
|
||||
/** CPU逻辑核心数 */
|
||||
@Schema(description = "CPU逻辑核心数")
|
||||
private String cpuLogicalCoreNum;
|
||||
|
||||
/** CPU系统使用率 */
|
||||
@Schema(description = "CPU系统使用率")
|
||||
private String cpuSysUseRate;
|
||||
|
||||
/** CPU用户使用率 */
|
||||
@Schema(description = "CPU用户使用率")
|
||||
private String cpuUserUseRate;
|
||||
|
||||
/** CPU当前总使用率 */
|
||||
@Schema(description = "CPU当前总使用率")
|
||||
private Double cpuTotalUseRate;
|
||||
|
||||
/** CPU当前等待率 */
|
||||
@Schema(description = "CPU当前等待率")
|
||||
private String cpuWaitRate;
|
||||
|
||||
/** CPU当前空闲率 */
|
||||
@Schema(description = "CPU当前空闲率")
|
||||
private String cpuFreeRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内存信息类
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public static class DevMonitorMemoryInfo {
|
||||
|
||||
/** 内存总量 */
|
||||
@Schema(description = "内存总量")
|
||||
private String memoryTotal;
|
||||
|
||||
/** 内存已用 */
|
||||
@Schema(description = "内存已用")
|
||||
private String memoryUsed;
|
||||
|
||||
/** 内存剩余 */
|
||||
@Schema(description = "内存剩余")
|
||||
private String memoryFree;
|
||||
|
||||
/** 内存使用率 */
|
||||
@Schema(description = "内存使用率")
|
||||
private Double memoryUseRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储信息
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public static class DevMonitorStorageInfo {
|
||||
|
||||
/** 存储总量 */
|
||||
@Schema(description = "存储总量")
|
||||
private String storageTotal;
|
||||
|
||||
/** 存储已用 */
|
||||
@Schema(description = "存储已用")
|
||||
private String storageUsed;
|
||||
|
||||
/** 存储剩余 */
|
||||
@Schema(description = "存储剩余")
|
||||
private String storageFree;
|
||||
|
||||
/** 存储使用率 */
|
||||
@Schema(description = "存储使用率")
|
||||
private Double storageUseRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 网络信息类
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public static class DevMonitorNetworkInfo {
|
||||
|
||||
/** 上行速率 */
|
||||
@Schema(description = "上行速率")
|
||||
private String upLinkRate;
|
||||
|
||||
/** 下行速率 */
|
||||
@Schema(description = "下行速率")
|
||||
private String downLinkRate;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务器信息类
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public static class DevMonitorServerInfo {
|
||||
|
||||
/** 服务器名称 */
|
||||
@Schema(description = "服务器名称")
|
||||
private String serverName;
|
||||
|
||||
/** 服务器操作系统 */
|
||||
@Schema(description = "服务器操作系统")
|
||||
private String serverOs;
|
||||
|
||||
/** 服务器IP */
|
||||
@Schema(description = "服务器IP")
|
||||
private String serverIp;
|
||||
|
||||
/** 服务器架构 */
|
||||
@Schema(description = "服务器架构")
|
||||
private String serverArchitecture;
|
||||
}
|
||||
|
||||
/**
|
||||
* JVM信息类
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public static class DevMonitorJvmInfo {
|
||||
|
||||
/** JVM名称 */
|
||||
@Schema(description = "JVM名称")
|
||||
private String jvmName;
|
||||
|
||||
/** JVM版本 */
|
||||
@Schema(description = "JVM版本")
|
||||
private String jvmVersion;
|
||||
|
||||
/** JVM总分配内存 */
|
||||
@Schema(description = "JVM总分配内存")
|
||||
private String jvmMemoryTotal;
|
||||
|
||||
/** JVM已用内存 */
|
||||
@Schema(description = "JVM已用内存")
|
||||
private String jvmMemoryUsed;
|
||||
|
||||
/** JVM剩余内存 */
|
||||
@Schema(description = "JVM剩余内存")
|
||||
private String jvmMemoryFree;
|
||||
|
||||
/** JVM内存使用率 */
|
||||
@Schema(description = "JVM内存使用率")
|
||||
private Double jvmUseRate;
|
||||
|
||||
/** JVM启动时间 */
|
||||
@Schema(description = "JVM启动时间")
|
||||
private String jvmStartTime;
|
||||
|
||||
/** JVM运行时长 */
|
||||
@Schema(description = "JVM运行时长")
|
||||
private String jvmRunTime;
|
||||
|
||||
/** Java版本 */
|
||||
@Schema(description = "Java版本")
|
||||
private String javaVersion;
|
||||
|
||||
/** Java安装路径 */
|
||||
@Schema(description = "Java安装路径")
|
||||
private String javaPath;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.gen.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.cloud.admin.module.gen.dto.GenBasicDto;
|
||||
import com.byhah.cloud.admin.module.gen.service.GenBasicService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.byhah.cloud.basic.core.entity.gen.GenBasic;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.cloud.admin.module.gen.dto.*;
|
||||
import com.byhah.cloud.admin.module.gen.vo.GenBasicPreviewVo;
|
||||
import com.byhah.cloud.admin.module.gen.vo.GenBasicTableColumnVo;
|
||||
import com.byhah.cloud.admin.module.gen.vo.GenBasicTableVo;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 代码生成基础
|
||||
**/
|
||||
@Tag(name = "代码生成基础")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/gen/basic")
|
||||
public class GenBasicController {
|
||||
|
||||
private final GenBasicService genBasicService;
|
||||
|
||||
@Operation(summary = "获取代码生成基础分页")
|
||||
@GetMapping("/page")
|
||||
public R<IPage<GenBasic>> page() {
|
||||
return R.ok(genBasicService.page(PageUtils.toPage()));
|
||||
}
|
||||
|
||||
@Operation(summary = "添加代码生成基础")
|
||||
@PostMapping("/add")
|
||||
public R<GenBasic> add(@RequestBody @Valid GenBasicDto dto) {
|
||||
return R.ok(genBasicService.add(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑代码生成基础")
|
||||
@PostMapping("/edit")
|
||||
public R<GenBasic> edit(@RequestBody @Valid GenBasicDto dto) {
|
||||
return R.ok(genBasicService.edit(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除代码生成基础")
|
||||
@PostMapping("/delete")
|
||||
public R<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
genBasicService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取代码生成基础详情")
|
||||
@GetMapping("/detail")
|
||||
public R<GenBasic> detail(Long id) {
|
||||
return R.ok(genBasicService.detail(id));
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "获取所有表信息")
|
||||
@GetMapping("/tables")
|
||||
public R<List<GenBasicTableVo>> dbsTable() {
|
||||
return R.ok(genBasicService.tables());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取表内所有字段信息")
|
||||
@GetMapping("/tableColumns")
|
||||
public R<List<GenBasicTableColumnVo>> tableColumns(String tableName) {
|
||||
return R.ok(genBasicService.tableColumns(tableName));
|
||||
}
|
||||
|
||||
@Operation(summary = "执行代码生成(压缩包)")
|
||||
@GetMapping(value = "/execGenZip", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public void execGenZip(Long id, HttpServletResponse response) {
|
||||
genBasicService.execGenZip(id, response);
|
||||
}
|
||||
|
||||
@Operation(summary = "预览代码生成")
|
||||
@GetMapping(value = "/previewGen")
|
||||
public R<GenBasicPreviewVo> previewGen(@Valid Long id) {
|
||||
return R.ok(genBasicService.previewGen(id));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.gen.controller;
|
||||
|
||||
import com.byhah.cloud.admin.module.gen.dto.GenConfigDto;
|
||||
import com.byhah.cloud.admin.module.gen.service.GenConfigService;
|
||||
import com.byhah.cloud.basic.core.entity.gen.GenConfig;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "代码生成详细配置")
|
||||
@RestController
|
||||
@RequestMapping("/gen/config")
|
||||
@RequiredArgsConstructor
|
||||
public class GenConfigController {
|
||||
|
||||
private final GenConfigService genConfigService;
|
||||
|
||||
@Operation(summary = "获取代码生成详细配置分页")
|
||||
@GetMapping("/list")
|
||||
public R<List<GenConfig>> list(Long basicId) {
|
||||
return R.ok(genConfigService.lambdaQuery().eq(GenConfig::getBasicId, basicId).list());
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑代码生成详细配置")
|
||||
@PostMapping("/edit")
|
||||
public R<String> edit(@RequestBody @Valid GenConfigDto dto) {
|
||||
genConfigService.edit(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除代码生成详细配置")
|
||||
@PostMapping("/delete")
|
||||
public R<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
genConfigService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取代码生成详细配置详情")
|
||||
@GetMapping("/detail")
|
||||
public R<GenConfig> detail(@Valid Long id) {
|
||||
return R.ok(genConfigService.detail(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "批量编辑代码生成详细配置")
|
||||
@PostMapping("/editBatch")
|
||||
public R<String> editBatch(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<GenConfigDto> dto) {
|
||||
genConfigService.editBatch(dto);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.gen.dto;
|
||||
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
|
||||
/**
|
||||
* 代码生成基础添加参数
|
||||
**/
|
||||
@Data
|
||||
public class GenBasicDto {
|
||||
@Schema(description = "id", required = true)
|
||||
@NotNull(message = "id不能为空", groups = Update.class)
|
||||
@Null(message = "id必须为空", groups = Insert.class)
|
||||
private Long id;
|
||||
/**
|
||||
* 主表名称
|
||||
*/
|
||||
@Schema(description = "主表名称", required = true)
|
||||
@NotNull(message = "dbTable不能为空")
|
||||
private String dbTable;
|
||||
|
||||
/**
|
||||
* 主表主键
|
||||
*/
|
||||
@Schema(description = "主表主键", required = true)
|
||||
@NotNull(message = "dbTableKey不能为空")
|
||||
private String dbTableKey;
|
||||
|
||||
/**
|
||||
* 模块名
|
||||
*/
|
||||
@Schema(description = "模块名", required = true)
|
||||
@NotNull(message = "moduleName不能为空")
|
||||
private String moduleName;
|
||||
|
||||
/**
|
||||
* 表前缀移除
|
||||
*/
|
||||
@Schema(description = "表前缀移除", required = true)
|
||||
@NotNull(message = "tablePrefix不能为空")
|
||||
private Boolean tablePrefix;
|
||||
|
||||
/**
|
||||
* 生成方式
|
||||
*/
|
||||
@Schema(description = "生成方式", required = true)
|
||||
@NotNull(message = "generateType不能为空")
|
||||
private String generateType;
|
||||
|
||||
/**
|
||||
* 所属模块
|
||||
*/
|
||||
@Schema(description = "所属模块", required = true)
|
||||
@NotNull(message = "module不能为空")
|
||||
private Long module;
|
||||
|
||||
/**
|
||||
* 上级目录
|
||||
*/
|
||||
@Schema(description = "上级目录", required = true)
|
||||
@NotNull(message = "menuPid不能为空")
|
||||
private String menuPid;
|
||||
|
||||
/**
|
||||
* 功能名
|
||||
*/
|
||||
@Schema(description = "功能名", required = true)
|
||||
@NotNull(message = "functionName不能为空")
|
||||
private String functionName;
|
||||
|
||||
/**
|
||||
* 业务名
|
||||
*/
|
||||
@Schema(description = "业务名", required = true)
|
||||
@NotNull(message = "busName不能为空")
|
||||
private String busName;
|
||||
|
||||
/**
|
||||
* 类名
|
||||
*/
|
||||
@Schema(description = "类名", required = true)
|
||||
@NotNull(message = "className不能为空")
|
||||
private String className;
|
||||
|
||||
/**
|
||||
* 表单布局
|
||||
*/
|
||||
@Schema(description = "表单布局", required = true)
|
||||
@NotNull(message = "formLayout不能为空")
|
||||
private String formLayout;
|
||||
|
||||
/**
|
||||
* 使用栅格
|
||||
*/
|
||||
@Schema(description = "使用栅格", required = true)
|
||||
@NotNull(message = "gridWhether不能为空")
|
||||
private Boolean gridWhether;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
@Schema(description = "排序", required = true)
|
||||
@NotNull(message = "sortCode不能为空")
|
||||
private Integer sortCode;
|
||||
|
||||
/**
|
||||
* 作者名
|
||||
*/
|
||||
@Schema(description = "作者名", required = true)
|
||||
private String authorName;
|
||||
|
||||
/**
|
||||
* 包名
|
||||
*/
|
||||
@Schema(description = "包名", required = true)
|
||||
private String packageName;
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.gen.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 代码生成详细配置编辑参数
|
||||
**/
|
||||
@Data
|
||||
public class GenConfigDto {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@Schema(description = "id", required = true)
|
||||
@NotNull(message = "id不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 基础ID
|
||||
*/
|
||||
@Schema(description = "基础ID", required = true)
|
||||
@NotNull(message = "basicId不能为空")
|
||||
private Long basicId;
|
||||
|
||||
/**
|
||||
* 是否主键
|
||||
*/
|
||||
@Schema(description = "是否主键", required = true)
|
||||
@NotNull(message = "isTableKey不能为空")
|
||||
private Boolean isTableKey;
|
||||
|
||||
/**
|
||||
* 字段
|
||||
*/
|
||||
@Schema(description = "字段", required = true)
|
||||
@NotBlank(message = "fieldName不能为空")
|
||||
private String fieldName;
|
||||
|
||||
/**
|
||||
* 注释
|
||||
*/
|
||||
@Schema(description = "注释", required = true)
|
||||
// @NotBlank(message = "fieldRemark不能为空")
|
||||
private String fieldRemark;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
@Schema(description = "类型", required = true)
|
||||
@NotBlank(message = "fieldType不能为空")
|
||||
private String fieldType;
|
||||
|
||||
/**
|
||||
* 实体类型
|
||||
*/
|
||||
@Schema(description = "实体类型", required = true)
|
||||
@NotBlank(message = "fieldJavaType不能为空")
|
||||
private String fieldJavaType;
|
||||
|
||||
/**
|
||||
* 作用类型
|
||||
*/
|
||||
@Schema(description = "作用类型", required = true)
|
||||
@NotBlank(message = "effectType不能为空")
|
||||
private String effectType;
|
||||
|
||||
@Schema(description = "选择器数据源一级分类", required = true)
|
||||
private String firstDataType;
|
||||
|
||||
@Schema(description = "选择器数据源二级分类", required = true)
|
||||
private String secondDataType;
|
||||
|
||||
/**
|
||||
* 列表显示
|
||||
*/
|
||||
@Schema(description = "列表显示", required = true)
|
||||
@NotNull(message = "whetherTable不能为空")
|
||||
private Boolean whetherTable;
|
||||
|
||||
/**
|
||||
* 列省略
|
||||
*/
|
||||
@Schema(description = "列省略", required = true)
|
||||
@NotNull(message = "whetherRetract不能为空")
|
||||
private Boolean whetherRetract;
|
||||
|
||||
/**
|
||||
* 增改
|
||||
*/
|
||||
@Schema(description = "增改", required = true)
|
||||
@NotNull(message = "whetherAddUpdate不能为空")
|
||||
private Boolean whetherAddUpdate;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
*/
|
||||
@Schema(description = "必填", required = true)
|
||||
@NotNull(message = "whetherRequired不能为空")
|
||||
private Boolean whetherRequired;
|
||||
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
@Schema(description = "查询", required = true)
|
||||
@NotNull(message = "queryWhether不能为空")
|
||||
private Boolean queryWhether;
|
||||
|
||||
/**
|
||||
* 查询方式
|
||||
*/
|
||||
@Schema(description = "查询方式", required = true)
|
||||
private String queryType;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
@Schema(description = "排序", required = true)
|
||||
private Integer sortCode;
|
||||
}
|
||||
@ -0,0 +1,522 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.gen.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.admin.module.gen.dto.GenBasicDto;
|
||||
import com.byhah.cloud.admin.module.gen.dto.GenConfigDto;
|
||||
import com.byhah.cloud.admin.utils.GenDbTypeUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.beetl.core.Configuration;
|
||||
import org.beetl.core.GroupTemplate;
|
||||
import org.beetl.core.Template;
|
||||
import org.beetl.core.resource.ClasspathResourceLoader;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.byhah.cloud.orm.mapper.gen.GenBasicMapper;
|
||||
import com.byhah.cloud.basic.core.entity.gen.GenBasic;
|
||||
import com.byhah.cloud.basic.core.entity.gen.GenConfig;
|
||||
import com.byhah.cloud.basic.core.enums.gen.GenEffectType;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.deploy.basic.util.web.DownloadUtil;
|
||||
import com.byhah.cloud.admin.module.gen.vo.GenBasicPreviewVo;
|
||||
import com.byhah.cloud.admin.module.gen.vo.GenBasicTableColumnVo;
|
||||
import com.byhah.cloud.admin.module.gen.vo.GenBasicTableVo;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* 代码生成基础Service接口实现类
|
||||
**/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class GenBasicService extends ServiceImpl<GenBasicMapper, GenBasic> {
|
||||
|
||||
private static final String DB_URL_KEY = "spring.datasource.url";
|
||||
|
||||
private static final String DB_USERNAME_KEY = "spring.datasource.username";
|
||||
|
||||
private static final String DB_PASSWORD_KEY = "spring.datasource.password";
|
||||
|
||||
private static final List<JSONObject> GEN_SQL_FILE_LIST = CollectionUtil.newArrayList(
|
||||
Collections.singleton(JSONUtil.createObj().set("name", "Menu.sql.btl")));
|
||||
|
||||
private static final List<JSONObject> GEN_FRONT_FILE_LIST = CollectionUtil.newArrayList(
|
||||
JSONUtil.createObj().set("name", "Api.js.btl").set("path", "api"),
|
||||
JSONUtil.createObj().set("name", "form.vue.btl").set("path", "views/biz"),
|
||||
JSONUtil.createObj().set("name", "index.vue.btl").set("path", "views/biz"));
|
||||
|
||||
private static final List<JSONObject> GEN_BACKEND_FILE_LIST = CollectionUtil.newArrayList(
|
||||
JSONUtil.createObj().set("name", "Controller.java.btl").set("path", "controller"),
|
||||
JSONUtil.createObj().set("name", "Entity.java.btl").set("path", "entity"),
|
||||
JSONUtil.createObj().set("name", "Mapper.java.btl").set("path", "mapper"),
|
||||
JSONUtil.createObj().set("name", "Mapper.xml.btl").set("path", "mapper" + File.separator + "mapping"),
|
||||
JSONUtil.createObj().set("name", "Dto.java.btl").set("path", "dto"),
|
||||
JSONUtil.createObj().set("name", "Vo.java.btl").set("path", "vo"),
|
||||
JSONUtil.createObj().set("name", "SearchDto.java.btl").set("path", "dto"),
|
||||
JSONUtil.createObj().set("name", "Service.java.btl").set("path", "service"));
|
||||
|
||||
private static final String SORT_CODE_KEY = "sort_code";
|
||||
private static final String CREATE_USER_KEY = "created_by";
|
||||
private static final String CREATE_TIME_KEY = "created_at";
|
||||
private static final String UPDATE_USER_KEY = "updated_by";
|
||||
private static final String UPDATE_TIME_KEY = "updated_at";
|
||||
private static final String DELETE_FLAG_KEY = "deleted";
|
||||
|
||||
private final Environment environment;
|
||||
private final GenConfigService genConfigService;
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public GenBasic add(GenBasicDto dto) {
|
||||
GenBasic genBasic = BeanUtil.toBean(dto, GenBasic.class);
|
||||
save(genBasic);
|
||||
addGenConfig(genBasic);
|
||||
return genBasic;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public GenBasic edit(GenBasicDto dto) {
|
||||
GenBasic genBasic = queryEntity(dto.getId());
|
||||
if (!genBasic.getDbTable().equals(dto.getDbTable())) {
|
||||
// 删除配置表内该表的字段
|
||||
QueryWrapper<GenConfig> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.lambda().eq(GenConfig::getBasicId, genBasic.getId());
|
||||
genConfigService.remove(queryWrapper);
|
||||
// 新增新表的数据字段
|
||||
addGenConfig(genBasic);
|
||||
}
|
||||
BeanUtil.copyProperties(dto, genBasic);
|
||||
updateById(genBasic);
|
||||
return genBasic;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增表字段至配置内
|
||||
*/
|
||||
private void addGenConfig(GenBasic genBasic) {
|
||||
List<GenBasicTableColumnVo> resultList = tableColumns(genBasic.getDbTable());
|
||||
for (int i = 0; i < resultList.size(); i++) {
|
||||
GenBasicTableColumnVo item = resultList.get(i);
|
||||
GenConfigDto dto = new GenConfigDto();
|
||||
dto.setBasicId(genBasic.getId());
|
||||
dto.setIsTableKey(item.getColumnName().equals(genBasic.getDbTableKey()));
|
||||
dto.setFieldName(item.getColumnName());
|
||||
dto.setFieldType(item.getTypeName());
|
||||
dto.setFieldRemark(item.getColumnRemark());
|
||||
dto.setFieldJavaType(GenDbTypeUtil.getJavaTypeBySqlType(item.getTypeName()));
|
||||
dto.setEffectType(GenEffectType.INPUT.getValue().toLowerCase());
|
||||
// 除主键、删除标志、创建人、创建时间、修改人和修改时间外,所有默认在列表显示、在增改显示、非列省略、非必填,非查询
|
||||
boolean flag = genBasic.getDbTableKey().equalsIgnoreCase(item.getColumnName()) ||
|
||||
DELETE_FLAG_KEY.equalsIgnoreCase(item.getColumnName()) ||
|
||||
CREATE_USER_KEY.equalsIgnoreCase(item.getColumnName()) ||
|
||||
CREATE_TIME_KEY.equalsIgnoreCase(item.getColumnName()) ||
|
||||
UPDATE_USER_KEY.equalsIgnoreCase(item.getColumnName()) ||
|
||||
UPDATE_TIME_KEY.equalsIgnoreCase(item.getColumnName());
|
||||
dto.setWhetherTable(!flag);
|
||||
dto.setWhetherAddUpdate(!flag);
|
||||
dto.setWhetherRetract(false);
|
||||
dto.setWhetherRequired(false);
|
||||
dto.setQueryWhether(false);
|
||||
dto.setSortCode(i);
|
||||
GenConfig genConfig = BeanUtil.toBean(dto, GenConfig.class);
|
||||
genConfigService.save(genConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(List<Long> ids) {
|
||||
if (ObjectUtil.isNotEmpty(ids)) {
|
||||
// 级联删除配置
|
||||
genConfigService.remove(new LambdaQueryWrapper<GenConfig>().in(GenConfig::getBasicId, ids));
|
||||
// 执行删除
|
||||
removeByIds(ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public GenBasic detail(Long id) {
|
||||
return queryEntity(id);
|
||||
}
|
||||
|
||||
|
||||
public GenBasic queryEntity(Long id) {
|
||||
GenBasic genBasic = getById(id);
|
||||
if (ObjectUtil.isEmpty(genBasic)) {
|
||||
throw new CommonException("代码生成基础不存在,id值为:{}", id);
|
||||
}
|
||||
return genBasic;
|
||||
}
|
||||
|
||||
|
||||
public List<GenBasicTableVo> tables() {
|
||||
Connection conn = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
conn = DriverManager.getConnection(Objects.requireNonNull(environment.getProperty(DB_URL_KEY)),
|
||||
Objects.requireNonNull(environment.getProperty(DB_USERNAME_KEY)),
|
||||
Objects.requireNonNull(environment.getProperty(DB_PASSWORD_KEY)));
|
||||
DatabaseMetaData metaData = conn.getMetaData();
|
||||
String url = metaData.getURL();
|
||||
String schema = null;
|
||||
if (url.toLowerCase().contains("jdbc:oracle")) {
|
||||
schema = metaData.getUserName();
|
||||
}
|
||||
List<GenBasicTableVo> tables = new ArrayList<>();
|
||||
rs = metaData.getTables(null, schema, "%", new String[]{"TABLE"});
|
||||
while (rs.next()) {
|
||||
String tableName = rs.getString("TABLE_NAME");
|
||||
if (!StrUtil.startWithIgnoreCase(tableName, "ACT_")) {
|
||||
GenBasicTableVo vo = new GenBasicTableVo();
|
||||
vo.setTableName(tableName);
|
||||
String remarks = rs.getString("REMARKS");
|
||||
if (ObjectUtil.isEmpty(remarks)) {
|
||||
vo.setTableRemark(tableName);
|
||||
} else {
|
||||
vo.setTableRemark(remarks);
|
||||
}
|
||||
tables.add(vo);
|
||||
}
|
||||
}
|
||||
return tables;
|
||||
} catch (SQLException sqlException) {
|
||||
sqlException.printStackTrace();
|
||||
throw new CommonException("获取数据库表失败");
|
||||
} finally {
|
||||
JdbcUtils.closeResultSet(rs);
|
||||
JdbcUtils.closeConnection(conn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<GenBasicTableColumnVo> tableColumns(String tableName) {
|
||||
Connection conn = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
conn = DriverManager.getConnection(Objects.requireNonNull(environment.getProperty(DB_URL_KEY)),
|
||||
Objects.requireNonNull(environment.getProperty(DB_USERNAME_KEY)),
|
||||
Objects.requireNonNull(environment.getProperty(DB_PASSWORD_KEY)));
|
||||
DatabaseMetaData metaData = conn.getMetaData();
|
||||
String url = metaData.getURL();
|
||||
String schema = null;
|
||||
if (url.toLowerCase().contains("jdbc:oracle")) {
|
||||
schema = metaData.getUserName();
|
||||
}
|
||||
List<GenBasicTableColumnVo> columns = new ArrayList<>();
|
||||
rs = metaData.getColumns(null, schema, tableName, "%");
|
||||
while (rs.next()) {
|
||||
String columnName = rs.getString("COLUMN_NAME").toLowerCase();
|
||||
GenBasicTableColumnVo res = new GenBasicTableColumnVo();
|
||||
res.setColumnName(columnName);
|
||||
String remarks = rs.getString("REMARKS");
|
||||
if (ObjectUtil.isEmpty(remarks)) {
|
||||
res.setColumnRemark(columnName);
|
||||
} else {
|
||||
res.setColumnRemark(remarks);
|
||||
}
|
||||
String typeName = rs.getString("TYPE_NAME").toLowerCase();
|
||||
if (ObjectUtil.isEmpty(typeName)) {
|
||||
res.setTypeName("none");
|
||||
} else {
|
||||
res.setTypeName(typeName);
|
||||
}
|
||||
columns.add(res);
|
||||
}
|
||||
return columns;
|
||||
} catch (SQLException sqlException) {
|
||||
sqlException.printStackTrace();
|
||||
throw new CommonException("获取数据库表字段失败,表名称:{}", tableName);
|
||||
} finally {
|
||||
JdbcUtils.closeResultSet(rs);
|
||||
JdbcUtils.closeConnection(conn);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void execGenZip(Long id, HttpServletResponse response) {
|
||||
try {
|
||||
File tempFolder = genTempFolder(id);
|
||||
if (tempFolder == null) {
|
||||
throw new CommonException("代码生成基础不存在,id值为:" + id);
|
||||
}
|
||||
// 压缩
|
||||
File zip = ZipUtil.zip(tempFolder);
|
||||
// 压缩完毕删除临时目录
|
||||
FileUtil.del(tempFolder);
|
||||
// 下载
|
||||
DownloadUtil.download(zip, response);
|
||||
} catch (Exception e) {
|
||||
throw new CommonException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取临时目录
|
||||
*/
|
||||
private File genTempFolder(Long id) {
|
||||
GenBasic genBasic = getById(id);
|
||||
if (ObjectUtil.isEmpty(genBasic)) {
|
||||
// 如果是压缩包下载应该使用CommonResponseUtil渲染异常
|
||||
return null;
|
||||
}
|
||||
GenBasicPreviewVo vo = previewGen(id);
|
||||
// 先删除压缩包
|
||||
FileUtil.del(FileUtil.getTmpDirPath() + File.separator + genBasic.getFunctionName() + ".zip");
|
||||
// 生成临时目录
|
||||
File tempFolder = FileUtil.file(FileUtil.getTmpDirPath() + File.separator + genBasic.getFunctionName());
|
||||
// 生成SQL代码到临时目录
|
||||
vo.getGenBasicCodeSqlResultList().forEach(genBasicCodeResult ->
|
||||
FileUtil.writeUtf8String(genBasicCodeResult.getCodeFileContent(), FileUtil.file(tempFolder + File.separator +
|
||||
genBasicCodeResult.getCodeFileWithPathName())));
|
||||
// 生成前端代码到临时目录
|
||||
vo.getGenBasicCodeFrontendResultList().forEach(genBasicCodeResult ->
|
||||
FileUtil.writeUtf8String(genBasicCodeResult.getCodeFileContent(), FileUtil.file(tempFolder + File.separator
|
||||
+ "frontend" + File.separator + genBasicCodeResult.getCodeFileWithPathName())));
|
||||
// 生成后端代码到临时目录
|
||||
vo.getGenBasicCodeBackendResultList().forEach(genBasicCodeResult ->
|
||||
FileUtil.writeUtf8String(genBasicCodeResult.getCodeFileContent(), FileUtil.file(tempFolder + File.separator
|
||||
+ "backend" + File.separator + genBasicCodeResult.getCodeFileWithPathName())));
|
||||
return tempFolder;
|
||||
}
|
||||
|
||||
|
||||
public GenBasicPreviewVo previewGen(Long id) {
|
||||
GenBasic genBasic = queryEntity(id);
|
||||
JSONObject bindingJsonObject = getBindingJsonObject(genBasic);
|
||||
GenBasicPreviewVo vo = new GenBasicPreviewVo();
|
||||
try {
|
||||
// SQL基础路径
|
||||
String genSqlBasicPath = "sql";
|
||||
// SQL
|
||||
GroupTemplate groupTemplateSql = new GroupTemplate(new ClasspathResourceLoader("sqlend"),
|
||||
Configuration.defaultConfiguration());
|
||||
List<GenBasicPreviewVo.GenBasicCodeResult> genBasicCodeSqlResultList = CollectionUtil.newArrayList();
|
||||
GEN_SQL_FILE_LIST.forEach(fileJsonObject -> {
|
||||
String fileTemplateName = fileJsonObject.getStr("name");
|
||||
GenBasicPreviewVo.GenBasicCodeResult genBasicCodeSqlResult = new GenBasicPreviewVo.GenBasicCodeResult();
|
||||
Template templateSql = groupTemplateSql.getTemplate(fileTemplateName);
|
||||
templateSql.binding(bindingJsonObject);
|
||||
String resultName = StrUtil.removeSuffix(fileTemplateName, ".btl");
|
||||
genBasicCodeSqlResult.setCodeFileName(resultName);
|
||||
genBasicCodeSqlResult.setCodeFileWithPathName(genSqlBasicPath + File.separator + resultName);
|
||||
genBasicCodeSqlResult.setCodeFileContent(templateSql.render());
|
||||
genBasicCodeSqlResultList.add(genBasicCodeSqlResult);
|
||||
});
|
||||
vo.setGenBasicCodeSqlResultList(genBasicCodeSqlResultList);
|
||||
|
||||
// 前端基础路径
|
||||
String genFrontBasicPath = "";
|
||||
// 前端
|
||||
GroupTemplate groupTemplateFront = new GroupTemplate(new ClasspathResourceLoader("frontend"),
|
||||
Configuration.defaultConfiguration());
|
||||
List<GenBasicPreviewVo.GenBasicCodeResult> genBasicCodeFrontendResultList = CollectionUtil.newArrayList();
|
||||
GEN_FRONT_FILE_LIST.forEach(fileJsonObject -> {
|
||||
String fileTemplateName = fileJsonObject.getStr("name");
|
||||
String fileTemplatePath = fileJsonObject.getStr("path") + File.separator + genBasic.getModuleName();
|
||||
GenBasicPreviewVo.GenBasicCodeResult genBasicCodeFrontResult = new GenBasicPreviewVo.GenBasicCodeResult();
|
||||
Template templateFront = groupTemplateFront.getTemplate(fileTemplateName);
|
||||
templateFront.binding(bindingJsonObject);
|
||||
String resultName = StrUtil.removeSuffix(fileTemplateName, ".btl");
|
||||
if (fileTemplateName.equalsIgnoreCase("Api.js.btl")) {
|
||||
resultName = StrUtil.lowerFirst(genBasic.getClassName()) + resultName;
|
||||
genBasicCodeFrontResult.setCodeFileName(resultName);
|
||||
genBasicCodeFrontResult.setCodeFileWithPathName(genFrontBasicPath + fileTemplatePath + File.separator + resultName);
|
||||
} else {
|
||||
genBasicCodeFrontResult.setCodeFileName(resultName);
|
||||
genBasicCodeFrontResult.setCodeFileWithPathName(genFrontBasicPath + fileTemplatePath + File.separator + genBasic.getBusName() + File.separator + resultName);
|
||||
}
|
||||
genBasicCodeFrontResult.setCodeFileContent(templateFront.render());
|
||||
genBasicCodeFrontendResultList.add(genBasicCodeFrontResult);
|
||||
});
|
||||
vo.setGenBasicCodeFrontendResultList(genBasicCodeFrontendResultList);
|
||||
|
||||
// 后端基础路径
|
||||
String genBackendBasicPath = StrUtil.replace(genBasic.getPackageName(), StrUtil.DOT, File.separator) + File.separator + "module"
|
||||
+ File.separator + genBasic.getModuleName() + File.separator;
|
||||
// 后端
|
||||
GroupTemplate groupTemplateBackEnd = new GroupTemplate(new ClasspathResourceLoader("backend"),
|
||||
Configuration.defaultConfiguration());
|
||||
List<GenBasicPreviewVo.GenBasicCodeResult> genBasicCodeBackendResultList = CollectionUtil.newArrayList();
|
||||
GEN_BACKEND_FILE_LIST.forEach(fileJsonObject -> {
|
||||
String fileTemplateName = fileJsonObject.getStr("name");
|
||||
String fileTemplatePath = fileJsonObject.getStr("path");
|
||||
GenBasicPreviewVo.GenBasicCodeResult res = new GenBasicPreviewVo.GenBasicCodeResult();
|
||||
Template templateBackend = groupTemplateBackEnd.getTemplate(fileTemplateName);
|
||||
templateBackend.binding(bindingJsonObject);
|
||||
String resultName = StrUtil.removeSuffix(fileTemplateName, ".btl");
|
||||
if (fileTemplateName.equalsIgnoreCase("Entity.java.btl")) {
|
||||
resultName = ".java";
|
||||
}
|
||||
String fileName = genBasic.getClassName() + resultName;
|
||||
if (fileTemplateName.equalsIgnoreCase("Mapper.java.btl")) {
|
||||
fileName = "I" + fileName;
|
||||
}
|
||||
res.setCodeFileName(fileName);
|
||||
res.setCodeFileWithPathName(genBackendBasicPath + fileTemplatePath + File.separator + fileName);
|
||||
res.setCodeFileContent(templateBackend.render());
|
||||
genBasicCodeBackendResultList.add(res);
|
||||
});
|
||||
vo.setGenBasicCodeBackendResultList(genBasicCodeBackendResultList);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error(">>> 代码生成异常:", e);
|
||||
throw new CommonException("代码生成异常");
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据代码生成基础获取构造的参数
|
||||
*/
|
||||
public JSONObject getBindingJsonObject(GenBasic genBasic) {
|
||||
JSONObject bindingJsonObject = JSONUtil.createObj();
|
||||
// 代码模块名
|
||||
bindingJsonObject.set("moduleName", genBasic.getModuleName());
|
||||
// 功能名
|
||||
bindingJsonObject.set("functionName", genBasic.getFunctionName());
|
||||
// 业务名
|
||||
bindingJsonObject.set("busName", genBasic.getBusName());
|
||||
// 包名
|
||||
bindingJsonObject.set("packageName", genBasic.getPackageName());
|
||||
// 库名
|
||||
bindingJsonObject.set("dbTable", genBasic.getDbTable());
|
||||
// 类名
|
||||
bindingJsonObject.set("className", genBasic.getClassName());
|
||||
// 类首字母小写名
|
||||
bindingJsonObject.set("classNameFirstLower", StrUtil.lowerFirst(genBasic.getClassName()));
|
||||
// 主键名
|
||||
bindingJsonObject.set("dbTableKey", genBasic.getDbTableKey());
|
||||
// 主键Java类型
|
||||
bindingJsonObject.set("dbTableKeyJavaType", "String");
|
||||
// 主键名驼峰
|
||||
bindingJsonObject.set("dbTableKeyCamelCase", StrUtil.toCamelCase(genBasic.getDbTableKey().toLowerCase()));
|
||||
// 主键首字母大写名
|
||||
bindingJsonObject.set("dbTableKeyFirstUpper", StrUtil.upperFirst(StrUtil.toCamelCase(genBasic.getDbTableKey().toLowerCase())));
|
||||
// 主键注释
|
||||
bindingJsonObject.set("dbTableKeyRemark", genBasic.getDbTableKey());
|
||||
// 表单布局
|
||||
bindingJsonObject.set("formLayout", genBasic.getFormLayout());
|
||||
// 使用栅格
|
||||
bindingJsonObject.set("gridWhether", genBasic.getGridWhether());
|
||||
// 父菜单ID
|
||||
Long menuPid = genBasic.getMenuPid();
|
||||
bindingJsonObject.set("parentId", menuPid == 0 ? genBasic.getModule() : menuPid);
|
||||
// 菜单ID
|
||||
bindingJsonObject.set("menuId", IdWorker.getIdStr());
|
||||
// 菜单编码
|
||||
bindingJsonObject.set("menuCode", RandomUtil.randomString(10));
|
||||
// 菜单路径
|
||||
bindingJsonObject.set("menuPath", StrUtil.SLASH + genBasic.getModuleName() + StrUtil.SLASH + genBasic.getBusName());
|
||||
// 菜单组件
|
||||
bindingJsonObject.set("menuComponent", "biz" + StrUtil.SLASH + genBasic.getModuleName() + StrUtil.SLASH + genBasic.getBusName() + StrUtil.SLASH + "index");
|
||||
// 模块ID
|
||||
bindingJsonObject.set("moduleId", genBasic.getModule());
|
||||
// 添加按钮ID
|
||||
bindingJsonObject.set("addButtonId", IdWorker.getIdStr());
|
||||
// 编辑按钮ID
|
||||
bindingJsonObject.set("editButtonId", IdWorker.getIdStr());
|
||||
// 删除按钮ID
|
||||
bindingJsonObject.set("deleteButtonId", IdWorker.getIdStr());
|
||||
// 作者
|
||||
bindingJsonObject.set("authorName", genBasic.getAuthorName());
|
||||
// 生成时间
|
||||
bindingJsonObject.set("genTime", DateUtil.format(DateTime.now(), " yyyy/MM/dd HH:mm"));
|
||||
// 定义配置详情列表
|
||||
List<JSONObject> configList = CollectionUtil.newArrayList();
|
||||
// 定义是否有排序字段
|
||||
AtomicBoolean hasSortCodeField = new AtomicBoolean(false);
|
||||
genConfigService.list(new LambdaQueryWrapper<GenConfig>().eq(GenConfig::getBasicId, genBasic.getId()))
|
||||
.forEach(genConfig -> {
|
||||
// 定义字段信息
|
||||
JSONObject configItem = JSONUtil.createObj();
|
||||
if (genConfig.getFieldName().equalsIgnoreCase(SORT_CODE_KEY)) {
|
||||
hasSortCodeField.set(true);
|
||||
}
|
||||
// 如果是主键,则无需作为添加参数,需要作为编辑参数,需要主键注解
|
||||
if (genConfig.getFieldName().equalsIgnoreCase(genBasic.getDbTableKey())) {
|
||||
configItem.set("needAdd", false);
|
||||
configItem.set("needEdit", true);
|
||||
configItem.set("needPage", false);
|
||||
configItem.set("needPageType", "none");
|
||||
configItem.set("required", true);
|
||||
configItem.set("needTableId", true);
|
||||
bindingJsonObject.set("dbTableKeyJavaType", genConfig.getFieldJavaType());
|
||||
bindingJsonObject.set("dbTableKeyRemark", genConfig.getFieldRemark());
|
||||
} else {
|
||||
// 排除删除标志
|
||||
String logicDeleteField = "deleted";
|
||||
if (genConfig.getFieldName().equalsIgnoreCase(logicDeleteField)) {
|
||||
configItem.set("needAdd", false);
|
||||
configItem.set("needEdit", false);
|
||||
configItem.set("needPage", false);
|
||||
configItem.set("needPageType", "none");
|
||||
configItem.set("required", false);
|
||||
configItem.set("needTableId", false);
|
||||
} else {
|
||||
configItem.set("needAdd", genConfig.getWhetherAddUpdate());
|
||||
configItem.set("needEdit", genConfig.getWhetherAddUpdate());
|
||||
configItem.set("needPage", genConfig.getQueryWhether());
|
||||
configItem.set("needPageType", genConfig.getQueryType());
|
||||
configItem.set("required", genConfig.getWhetherRequired());
|
||||
configItem.set("needTableId", false);
|
||||
}
|
||||
}
|
||||
// 列显示
|
||||
configItem.set("whetherTable", genConfig.getWhetherTable());
|
||||
// 列省略
|
||||
configItem.set("whetherRetract", genConfig.getWhetherRetract());
|
||||
// 增改
|
||||
configItem.set("whetherAddUpdate", genConfig.getWhetherAddUpdate());
|
||||
// 作用类型
|
||||
configItem.set("effectType", genConfig.getEffectType());
|
||||
// 一二级数据分类
|
||||
configItem.set("firstDataType", genConfig.getFirstDataType());
|
||||
configItem.set("secondDataType", genConfig.getSecondDataType());
|
||||
// 实体类型
|
||||
configItem.set("fieldJavaType", genConfig.getFieldJavaType());
|
||||
// 字段驼峰名
|
||||
configItem.set("fieldNameCamelCase", StrUtil.toCamelCase(genConfig.getFieldName().toLowerCase()));
|
||||
// 字段驼峰首字母大写名
|
||||
configItem.set("fieldNameCamelCaseFirstUpper", StrUtil.upperFirst(StrUtil.toCamelCase(genConfig.getFieldName().toLowerCase())));
|
||||
// 字段注释
|
||||
configItem.set("fieldRemark", genConfig.getFieldRemark());
|
||||
// 是否需要自动插入
|
||||
configItem.set("needAutoInsert", CREATE_USER_KEY.equalsIgnoreCase(genConfig.getFieldName()) ||
|
||||
CREATE_TIME_KEY.equalsIgnoreCase(genConfig.getFieldName()));
|
||||
// 是否需要自动更新
|
||||
configItem.set("needAutoUpdate", UPDATE_USER_KEY.equalsIgnoreCase(genConfig.getFieldName()) ||
|
||||
UPDATE_TIME_KEY.equalsIgnoreCase(genConfig.getFieldName()));
|
||||
// 是否需要逻辑删除
|
||||
configItem.set("needLogicDelete", DELETE_FLAG_KEY.equalsIgnoreCase(genConfig.getFieldName()));
|
||||
configList.add(configItem);
|
||||
|
||||
});
|
||||
// 配置信息
|
||||
bindingJsonObject.set("configList", configList);
|
||||
// 有排序字段
|
||||
bindingJsonObject.set("hasSortCodeField", hasSortCodeField.get());
|
||||
return bindingJsonObject;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.gen.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.admin.module.gen.dto.GenConfigDto;
|
||||
import com.byhah.cloud.orm.mapper.gen.GenConfigMapper;
|
||||
import com.byhah.cloud.basic.core.entity.gen.GenConfig;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 代码生成详情配置Service接口实现类
|
||||
*
|
||||
**/
|
||||
@Service
|
||||
public class GenConfigService extends ServiceImpl<GenConfigMapper, GenConfig> {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void edit(GenConfigDto dto) {
|
||||
GenConfig genConfig = this.queryEntity(dto.getId());
|
||||
BeanUtil.copyProperties(dto, genConfig);
|
||||
this.updateById(genConfig);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(List<Long> ids) {
|
||||
if (ObjectUtil.isNotEmpty(ids)) {
|
||||
// 执行删除
|
||||
this.removeByIds(ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public GenConfig detail(Long id) {
|
||||
return this.queryEntity(id);
|
||||
}
|
||||
|
||||
|
||||
public GenConfig queryEntity(Long id) {
|
||||
GenConfig genConfig = this.getById(id);
|
||||
if (ObjectUtil.isEmpty(genConfig)) {
|
||||
throw new CommonException("代码生成详情配置不存在,id值为:{}", id);
|
||||
}
|
||||
return genConfig;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void editBatch(List<GenConfigDto> dto) {
|
||||
dto.forEach(this::edit);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.gen.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 预览代码生成结果
|
||||
**/
|
||||
@Data
|
||||
public class GenBasicPreviewVo {
|
||||
|
||||
/**
|
||||
* SQL代码结果集
|
||||
*/
|
||||
@Schema(description = "SQL代码结果集")
|
||||
private List<GenBasicCodeResult> genBasicCodeSqlResultList;
|
||||
|
||||
/**
|
||||
* 前端代码结果集
|
||||
*/
|
||||
@Schema(description = "前端代码结果集")
|
||||
private List<GenBasicCodeResult> genBasicCodeFrontendResultList;
|
||||
|
||||
/**
|
||||
* 后端代码结果集
|
||||
*/
|
||||
@Schema(description = "后端代码结果集")
|
||||
private List<GenBasicCodeResult> genBasicCodeBackendResultList;
|
||||
|
||||
|
||||
@Data
|
||||
public static class GenBasicCodeResult {
|
||||
|
||||
/**
|
||||
* 代码文件名称
|
||||
*/
|
||||
@Schema(description = "代码文件名称")
|
||||
private String codeFileName;
|
||||
|
||||
/**
|
||||
* 代码文件带路径名称
|
||||
*/
|
||||
@Schema(description = "代码文件带路径名称")
|
||||
private String codeFileWithPathName;
|
||||
|
||||
/**
|
||||
* 代码文件内容
|
||||
*/
|
||||
@Schema(description = "代码文件内容")
|
||||
private String codeFileContent;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.gen.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 数据库表字段结果
|
||||
*
|
||||
**/
|
||||
@Data
|
||||
public class GenBasicTableColumnVo {
|
||||
|
||||
/** 字段名称 */
|
||||
@Schema(description = "字段名称")
|
||||
private String columnName;
|
||||
|
||||
/** 字段类型 */
|
||||
@Schema(description = "字段类型")
|
||||
private String typeName;
|
||||
|
||||
/** 字段注释 */
|
||||
@Schema(description = "字段注释")
|
||||
private String columnRemark;
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.gen.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 数据库表结果
|
||||
*
|
||||
**/
|
||||
@Data
|
||||
public class GenBasicTableVo {
|
||||
|
||||
/** 表名称 */
|
||||
@Schema(description = "表名称")
|
||||
private String tableName;
|
||||
|
||||
/** 表注释 */
|
||||
@Schema(description = "表注释")
|
||||
private String tableRemark;
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.controller;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevMessageSearchDto;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevMessageService;
|
||||
import com.byhah.cloud.admin.module.dev.vo.DevMessageVo;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysIndexService;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevLog;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* 系统首页
|
||||
*/
|
||||
@Tag(name = "系统首页")
|
||||
@RequestMapping("/sys/index")
|
||||
@RestController
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
public class SysIndexController {
|
||||
|
||||
private final SysIndexService sysIndexService;
|
||||
private final DevMessageService messageService;
|
||||
|
||||
@Operation(summary = "获取当前用户站内信列表")
|
||||
@GetMapping("/message/list")
|
||||
R<List<DevMessageVo>> messageList() {
|
||||
DevMessageSearchDto dto = new DevMessageSearchDto();
|
||||
dto.setReceiveUserId(StpUtil.getLoginIdAsLong());
|
||||
return R.ok(messageService.page(PageUtils.toNoSizePage(), dto).getRecords());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取站内信详情")
|
||||
@GetMapping("/message/detail")
|
||||
R<DevMessageVo> messageDetail(Long id) {
|
||||
return R.ok(messageService.detail(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "站内信全部标记已读")
|
||||
@PostMapping("/message/allMessageMarkRead")
|
||||
R<String> allMessageMarkRead() {
|
||||
messageService.readAll(StpUtil.getLoginIdAsLong());
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取当前用户访问日志列表")
|
||||
@GetMapping("/visLog/list")
|
||||
R<List<DevLog>> visLogList() {
|
||||
return R.ok(sysIndexService.visLogList());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取当前用户操作日志列表")
|
||||
@GetMapping("/opLog/list")
|
||||
R<List<DevLog>> opLogList() {
|
||||
return R.ok(sysIndexService.opLogList());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.byhah.cloud.admin.module.sys.vo.SysOrgVo;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysOrgDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysOrgSearchDto;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysOrgService;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 组织
|
||||
*/
|
||||
@Tag(name = "组织")
|
||||
@RequestMapping("/sys/org")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class SysOrgController {
|
||||
|
||||
private final SysOrgService sysOrgService;
|
||||
|
||||
@Operation(summary = "获取组织分页")
|
||||
@GetMapping("/page")
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
R<IPage<SysOrgVo>> page(SysOrgSearchDto dto) {
|
||||
return R.ok(sysOrgService.page(PageUtils.toPage(), dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取组织树")
|
||||
@GetMapping("/tree")
|
||||
R<List<Tree<Long>>> tree() {
|
||||
return R.ok(sysOrgService.tree());
|
||||
}
|
||||
|
||||
@Operation(summary = "添加组织")
|
||||
@PostMapping("/add")
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
R<Void> add(@RequestBody @Validated(Insert.class) SysOrgDto dto) {
|
||||
sysOrgService.add(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑组织")
|
||||
@PostMapping("/edit")
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
R<Void> edit(@RequestBody @Validated(Update.class) SysOrgDto dto) {
|
||||
sysOrgService.edit(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除组织")
|
||||
@PostMapping("/delete")
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
R<String> delete(@RequestBody @Validated @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
sysOrgService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.byhah.cloud.admin.module.sys.dto.ChangeModuleDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.ResourceTreeDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysResourceDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysResourceSearchDto;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysResourceService;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysResource;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "菜单")
|
||||
@RestController
|
||||
@RequestMapping("/sys/resource")
|
||||
@RequiredArgsConstructor
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
public class SysResourceController {
|
||||
|
||||
private final SysResourceService sysMenuService;
|
||||
|
||||
@Operation(summary = "获取菜单分页")
|
||||
@GetMapping("/page")
|
||||
public R<Page<SysResource>> page(SysResourceSearchDto dto) {
|
||||
return R.ok(sysMenuService.page(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取菜单列表")
|
||||
@GetMapping("/list")
|
||||
public R<List<SysResource>> list(SysResourceSearchDto dto) {
|
||||
return R.ok(sysMenuService.page(dto).getRecords());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取菜单树")
|
||||
@GetMapping("/tree")
|
||||
public R<List<Tree<Long>>> tree(ResourceTreeDto dto) {
|
||||
return R.ok(sysMenuService.menuTreeSelector(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "添加菜单")
|
||||
@PostMapping("/add")
|
||||
public R<String> add(@RequestBody @Validated(Insert.class) SysResourceDto dto) {
|
||||
sysMenuService.add(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑菜单")
|
||||
@PostMapping("/edit")
|
||||
public R<String> edit(@RequestBody @Validated(Update.class) SysResourceDto dto) {
|
||||
sysMenuService.edit(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "更改菜单所属模块")
|
||||
@PostMapping("/changeModule")
|
||||
public R<String> changeModule(@RequestBody @Valid ChangeModuleDto dto) {
|
||||
sysMenuService.changeModule(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除菜单")
|
||||
@PostMapping("/delete")
|
||||
public R<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
sysMenuService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取菜单详情")
|
||||
@GetMapping("/detail")
|
||||
public R<SysResource> detail(Long id) {
|
||||
return R.ok(sysMenuService.getById(id));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysRoleDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysRoleGrantResourceDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysRoleGrantUserDto;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysRoleService;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysResource;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysRole;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
@Tag(name = "角色")
|
||||
@RestController
|
||||
@RequestMapping("/sys/role")
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
public class SysRoleController {
|
||||
|
||||
private final SysRoleService sysRoleService;
|
||||
|
||||
@Operation(summary = "获取角色分页")
|
||||
@GetMapping("/page")
|
||||
public R<Page<SysRole>> page(@RequestParam(required = false) String searchKey) {
|
||||
return R.ok(sysRoleService.lambdaQuery().like(CharSequenceUtil.isNotBlank(searchKey), SysRole::getName, searchKey).orderByAsc(SysRole::getSortCode).page(PageUtils.toPage()));
|
||||
}
|
||||
|
||||
@Operation(summary = "添加角色")
|
||||
@PostMapping("/add")
|
||||
public R<String> add(@RequestBody @Validated(Insert.class) SysRoleDto dto) {
|
||||
sysRoleService.add(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑角色")
|
||||
@PostMapping("/edit")
|
||||
public R<String> edit(@RequestBody @Validated(Update.class) SysRoleDto dto) {
|
||||
sysRoleService.edit(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除角色")
|
||||
@PostMapping("/delete")
|
||||
public R<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
sysRoleService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取角色详情")
|
||||
@GetMapping("/detail")
|
||||
public R<SysRole> detail(Long id) {
|
||||
return R.ok(sysRoleService.detail(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取角色拥有资源")
|
||||
@GetMapping("/ownResource")
|
||||
public R<List<SysResource>> ownResource(Long id) {
|
||||
return R.ok(sysRoleService.ownResource(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "给角色授权资源")
|
||||
@PostMapping("/grantResource")
|
||||
public R<String> grantResource(@RequestBody @Valid SysRoleGrantResourceDto dto) {
|
||||
sysRoleService.grantResource(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取角色下的用户")
|
||||
@GetMapping("/ownUser")
|
||||
public R<List<Long>> ownUser(Long id) {
|
||||
return R.ok(sysRoleService.ownUser(id));
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "给角色授权用户")
|
||||
@PostMapping("/grantUser")
|
||||
public R<String> grantUser(@RequestBody @Valid SysRoleGrantUserDto dto) {
|
||||
sysRoleService.grantUser(dto);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package com.byhah.cloud.admin.module.sys.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysTenantDto;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysTenantService;
|
||||
import com.byhah.cloud.admin.module.sys.vo.SysTenantVo;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysTenant;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "租户")
|
||||
@RestController
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/sys/tenant")
|
||||
public class SysTenantController {
|
||||
|
||||
private final SysTenantService sysTenantService;
|
||||
|
||||
@Operation(summary = "获取租户分页")
|
||||
@GetMapping("/page")
|
||||
R<IPage<SysTenantVo>> page() {
|
||||
return R.ok(sysTenantService.page(PageUtils.toPage()).convert(SysTenantVo::new));
|
||||
}
|
||||
|
||||
@Operation(summary = "添加租户")
|
||||
@SaCheckPermission("sys:tenant:add")
|
||||
@PostMapping("/add")
|
||||
R<Void> add(@RequestBody @Validated(Insert.class) SysTenantDto dto) {
|
||||
sysTenantService.add(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑租户")
|
||||
@SaCheckPermission("sys:tenant:edit")
|
||||
@PostMapping("/edit")
|
||||
R<Void> edit(@RequestBody @Validated(Update.class) SysTenantDto dto) {
|
||||
sysTenantService.edit(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除租户")
|
||||
@SaCheckPermission("sys:tenant:delete")
|
||||
@PostMapping("/delete")
|
||||
R<String> delete(@RequestBody @Validated @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
sysTenantService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取租户详情")
|
||||
@GetMapping("/detail")
|
||||
R<SysTenant> detail(Long id) {
|
||||
return R.ok(sysTenantService.detail(id));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.controller;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import com.byhah.cloud.admin.module.dev.dto.DevMessageSearchDto;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevMessageService;
|
||||
import com.byhah.cloud.admin.module.dev.vo.DevMessageVo;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysUserSignatureDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysUserUpdateInfoDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysUserUpdatePwdDto;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysUserService;
|
||||
import com.byhah.cloud.admin.utils.UserUtil;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysUser;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户个人
|
||||
**/
|
||||
@Tag(name = "用户个人")
|
||||
@RequestMapping("/sys/userCenter")
|
||||
@RestController
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
public class SysUserCenterController {
|
||||
|
||||
private final SysUserService sysUserService;
|
||||
private final DevMessageService messageService;
|
||||
|
||||
@Operation(summary = "修改用户密码")
|
||||
@PostMapping("/updatePassword")
|
||||
public R<String> updatePassword(@RequestBody @Valid SysUserUpdatePwdDto dto) {
|
||||
sysUserService.updatePassword(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "修改用户头像")
|
||||
@PostMapping("/updateAvatar")
|
||||
public R<String> updateAvatar(@RequestPart("file") MultipartFile file) {
|
||||
return R.ok(sysUserService.updateAvatar(file));
|
||||
}
|
||||
|
||||
@Operation(summary = "修改用户签名图片")
|
||||
@PostMapping("/updateSignature")
|
||||
public R<String> updateSignature(@RequestBody @Valid SysUserSignatureDto dto) {
|
||||
sysUserService.updateSignature(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取登录用户菜单")
|
||||
@GetMapping("/loginMenu")
|
||||
public R<List<Tree<Long>>> loginMenu() {
|
||||
return R.ok(sysUserService.ownMenu(UserUtil.getLoginUser()));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取登录用户组织树")
|
||||
@GetMapping("/loginOrgTree")
|
||||
public R<List<Tree<Long>>> loginOrgTree() {
|
||||
return R.ok(sysUserService.loginOrgTree(StpUtil.getLoginIdAsLong()));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑个人信息")
|
||||
@PostMapping("/updateUserInfo")
|
||||
public R<String> updateUserInfo(@RequestBody @Valid SysUserUpdateInfoDto dto) {
|
||||
dto.setId(StpUtil.getLoginIdAsLong());
|
||||
sysUserService.updateUserInfo(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取登录用户的站内信分页")
|
||||
@GetMapping("/loginUnreadMessagePage")
|
||||
public R<IPage<DevMessageVo>> loginMessagePage(DevMessageSearchDto dto) {
|
||||
dto.setReceiveUserId(StpUtil.getLoginIdAsLong());
|
||||
return R.ok(messageService.page(PageUtils.toPage(), dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "读取登录用户站内信详情")
|
||||
@GetMapping("/loginUnreadMessageDetail")
|
||||
public R<DevMessageVo> loginMessageDetail(Long id) {
|
||||
return R.ok(messageService.detail(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id集合获取用户集合")
|
||||
@PostMapping("/getUserListByIdList")
|
||||
public R<List<SysUser>> getUserListByIdList(@RequestBody CommonValidList<Long> ids) {
|
||||
return R.ok(sysUserService.getUserListByIdList(ids));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import com.byhah.deploy.basic.validation.entity.CommonValidList;
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import com.byhah.deploy.starter.web.R;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysUserDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysUserGrantRoleDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysUserSearchDto;
|
||||
import com.byhah.cloud.admin.module.sys.service.SysUserService;
|
||||
import com.byhah.cloud.admin.module.sys.vo.SysUserVo;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysRole;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysUser;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户
|
||||
**/
|
||||
@Tag(name = "用户")
|
||||
@RestController
|
||||
@RequestMapping("/sys/user")
|
||||
@RequiredArgsConstructor
|
||||
@SaCheckRole(value = SystemKey.SYS_ROLE)
|
||||
public class SysUserController {
|
||||
|
||||
private final SysUserService sysUserService;
|
||||
|
||||
@Operation(summary = "获取用户分页")
|
||||
@GetMapping("/page")
|
||||
R<IPage<SysUserVo>> page(SysUserSearchDto dto) {
|
||||
return R.ok(sysUserService.page(PageUtils.toPage(), dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "添加用户")
|
||||
@PostMapping("/add")
|
||||
R<String> add(@RequestBody @Validated(Insert.class) SysUserDto dto) {
|
||||
sysUserService.add(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑用户")
|
||||
@PostMapping("/edit")
|
||||
R<String> edit(@RequestBody @Validated(Update.class) SysUserDto dto) {
|
||||
sysUserService.edit(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除用户")
|
||||
@PostMapping("/delete")
|
||||
R<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||
CommonValidList<Long> ids) {
|
||||
sysUserService.delete(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取用户详情")
|
||||
@GetMapping("/detail")
|
||||
R<SysUser> detail(Long id) {
|
||||
return R.ok(sysUserService.detail(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "禁用用户")
|
||||
@PostMapping("/disableUser/{id}")
|
||||
R<String> disableUser(@PathVariable Long id) {
|
||||
sysUserService.disableUser(id);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "启用用户")
|
||||
@PostMapping("/enableUser/{id}")
|
||||
R<String> enableUser(@PathVariable Long id) {
|
||||
sysUserService.enableUser(id);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "重置用户密码")
|
||||
@PostMapping("/resetPassword/{id}")
|
||||
R<String> resetPassword(@PathVariable Long id) {
|
||||
sysUserService.resetPassword(id);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取用户拥有角色")
|
||||
@GetMapping("/ownRole")
|
||||
R<List<SysRole>> ownRole(Long id) {
|
||||
return R.ok(sysUserService.ownRole(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "给用户授权角色")
|
||||
@PostMapping("/grantRole")
|
||||
R<String> grantRole(@RequestBody @Valid SysUserGrantRoleDto dto) {
|
||||
sysUserService.grantRole(dto);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class ChangeModuleDto {
|
||||
@NotNull
|
||||
private Long id;
|
||||
@NotNull
|
||||
private Long module;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ResourceTreeDto {
|
||||
@Schema(description = "筛选模块 传入是不会查出模块层资源")
|
||||
private Long module;
|
||||
|
||||
@Schema(description = "排除掉的资源类型")
|
||||
private List<Integer> excludeCategory;
|
||||
|
||||
private String searchKey;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
|
||||
/**
|
||||
* 组织添加参数
|
||||
**/
|
||||
@Data
|
||||
public class SysOrgDto {
|
||||
@Schema(description = "id")
|
||||
@NotNull(message = "id不能为空", groups = Update.class)
|
||||
@Null(message = "id必须为空", groups = Insert.class)
|
||||
private Long id;
|
||||
@Schema(description = "父id")
|
||||
private Long parentId;
|
||||
@Schema(description = "名称")
|
||||
@NotBlank(message = "name不能为空")
|
||||
private String name;
|
||||
@Schema(description = "排序码")
|
||||
@NotNull(message = "sortCode不能为空")
|
||||
private Integer sortCode;
|
||||
@Schema(description = "主管id")
|
||||
private Long directorId;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.model.CommonSearch;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 组织查询参数
|
||||
**/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysOrgSearchDto extends CommonSearch {
|
||||
/**
|
||||
* 父id
|
||||
*/
|
||||
@Schema(description = "父id")
|
||||
private Long parentId;
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
|
||||
/**
|
||||
* 菜单添加参数
|
||||
**/
|
||||
@Data
|
||||
public class SysResourceDto {
|
||||
|
||||
@NotNull(groups = Update.class)
|
||||
@Null(groups = Insert.class)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 父id
|
||||
*/
|
||||
@Schema(description = "父id", required = true)
|
||||
// @NotNull(message = "parentId不能为空")
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题", required = true)
|
||||
@NotBlank(message = "title不能为空")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 菜单类型
|
||||
*/
|
||||
@Schema(description = "菜单类型", required = true)
|
||||
// @NotBlank(message = "menuType不能为空")
|
||||
private Integer menuType;
|
||||
|
||||
/**
|
||||
* 路径
|
||||
*/
|
||||
@Schema(description = "路径", required = true)
|
||||
// @NotBlank(message = "path不能为空")
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 排序码
|
||||
*/
|
||||
@Schema(description = "排序码", required = true)
|
||||
@NotNull(message = "sortCode不能为空")
|
||||
private Integer sortCode;
|
||||
|
||||
/**
|
||||
* 别名
|
||||
*/
|
||||
@Schema(description = "别名")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 组件
|
||||
*/
|
||||
@Schema(description = "组件")
|
||||
private String component;
|
||||
|
||||
private Long module;
|
||||
|
||||
/**
|
||||
* 图标
|
||||
*/
|
||||
@Schema(description = "图标")
|
||||
private String icon;
|
||||
|
||||
private String code;
|
||||
|
||||
@Range(min = 1, max = 4)
|
||||
private Integer category;
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.model.CommonSearch;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 菜单查询参数
|
||||
**/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysResourceSearchDto extends CommonSearch {
|
||||
/**
|
||||
* 模块
|
||||
*/
|
||||
@Schema(description = "模块")
|
||||
private Long module;
|
||||
|
||||
@Schema(description = "菜单类型 1:模块 2:菜单 3:按钮 4:单页面")
|
||||
private Integer category;
|
||||
|
||||
private Long parentId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
|
||||
/**
|
||||
* 角色添加参数
|
||||
**/
|
||||
@Data
|
||||
public class SysRoleDto {
|
||||
|
||||
@NotNull(message = "id不能为空",groups = Update.class)
|
||||
@Null(message = "id必须为空",groups = Insert.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名称", required = true)
|
||||
@NotBlank(message = "name不能为空")
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "权限代码不能为空")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "排序码", required = true)
|
||||
@NotNull(message = "sortCode不能为空")
|
||||
private Integer sortCode;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色授权资源参数
|
||||
**/
|
||||
@Data
|
||||
public class SysRoleGrantResourceDto {
|
||||
|
||||
/**
|
||||
* 角色id
|
||||
*/
|
||||
@Schema(description = "角色id", required = true)
|
||||
@NotNull(message = "id不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 授权资源信息
|
||||
*/
|
||||
@Valid
|
||||
@Schema(description = "授权资源信息", required = true)
|
||||
@NotNull(message = "grantInfoList不能为空")
|
||||
private List<Long> resourceIds;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色授权用户参数
|
||||
*
|
||||
**/
|
||||
@Data
|
||||
public class SysRoleGrantUserDto {
|
||||
|
||||
/**
|
||||
* 角色id
|
||||
*/
|
||||
@Schema(description = "角色id", required = true)
|
||||
@NotNull(message = "id不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 授权用户信息
|
||||
*/
|
||||
@Schema(description = "授权用户信息", required = true)
|
||||
@NotNull(message = "grantInfoList不能为空")
|
||||
private List<Long> grantInfoList;
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
|
||||
/**
|
||||
* sys_tenant编辑参数
|
||||
**/
|
||||
@Data
|
||||
public class SysTenantDto {
|
||||
@NotNull(message = "id不能为空", groups = Update.class)
|
||||
@Null(message = "id必须为空", groups = Insert.class)
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
private String name;
|
||||
@NotBlank
|
||||
private String phone;
|
||||
|
||||
@NotBlank
|
||||
private String account;
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import com.byhah.deploy.basic.validation.group.Insert;
|
||||
import com.byhah.deploy.basic.validation.group.Update;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 用户添加参数
|
||||
**/
|
||||
@Data
|
||||
public class SysUserDto {
|
||||
@Schema(description = "id", required = true)
|
||||
@NotNull(message = "id不能为空",groups = Update.class)
|
||||
@Null(message = "id必须为空",groups = Insert.class)
|
||||
private Long id;
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@Schema(description = "账号")
|
||||
@NotBlank(message = "account不能为空")
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
@Schema(description = "姓名", required = true)
|
||||
@NotBlank(message = "name不能为空")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 组织id
|
||||
*/
|
||||
@Schema(description = "组织id")
|
||||
private Long orgId;
|
||||
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
@Schema(description = "头像,图片base64")
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 签名
|
||||
*/
|
||||
@Schema(description = "签名,图片base64")
|
||||
private String signature;
|
||||
|
||||
/**
|
||||
* 性别
|
||||
*/
|
||||
@Schema(description = "性别")
|
||||
private Integer gender;
|
||||
|
||||
/**
|
||||
* 手机
|
||||
*/
|
||||
@Schema(description = "手机")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 排序码
|
||||
*/
|
||||
@Schema(description = "排序码")
|
||||
private Integer sortCode;
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户授权角色参数
|
||||
*
|
||||
**/
|
||||
@Data
|
||||
public class SysUserGrantRoleDto {
|
||||
|
||||
/** id */
|
||||
@Schema(description = "id", required = true)
|
||||
@NotNull(message = "id不能为空")
|
||||
private Long id;
|
||||
|
||||
/** 角色id集合 */
|
||||
@Schema(description = "角色id集合", required = true)
|
||||
@NotNull(message = "roleIdList不能为空")
|
||||
private List<Long> roleIdList;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.model.CommonSearch;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户查询参数
|
||||
**/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysUserSearchDto extends CommonSearch {
|
||||
|
||||
/**
|
||||
* 用户状态
|
||||
*/
|
||||
@Schema(description = "用户状态")
|
||||
private String userStatus;
|
||||
|
||||
/**
|
||||
* 所属组织
|
||||
*/
|
||||
@Schema(description = "所属组织")
|
||||
private Long orgId;
|
||||
|
||||
private List<Long> ids;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 用户修改签名图片接口
|
||||
*
|
||||
**/
|
||||
@Data
|
||||
public class SysUserSignatureDto {
|
||||
|
||||
/** 签名图片base64编码 */
|
||||
@Schema(description = "signature", required = true)
|
||||
@NotBlank(message = "signature签名图片不能为空")
|
||||
private String signature;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import com.byhah.cloud.basic.core.entity.system.SysUser;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 编辑个人信息参数
|
||||
**/
|
||||
@Data
|
||||
public class SysUserUpdateInfoDto {
|
||||
|
||||
private Long id;
|
||||
@Schema(description = "姓名", required = true)
|
||||
@NotBlank(message = "name不能为空")
|
||||
private String name;
|
||||
@Schema(description = "手机")
|
||||
private String phone;
|
||||
@Schema(description = "性别")
|
||||
private Integer gender;
|
||||
@Schema(description = "签名,图片base64")
|
||||
private String signature;
|
||||
private SysUser.WorkBenchData workBenchData;
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 用户修改密码参数
|
||||
**/
|
||||
@Data
|
||||
public class SysUserUpdatePwdDto {
|
||||
|
||||
/** 旧密码 */
|
||||
@Schema(description = "旧密码", required = true)
|
||||
@NotBlank(message = "password不能为空")
|
||||
private String password;
|
||||
|
||||
/** 新密码 */
|
||||
@Schema(description = "新密码", required = true)
|
||||
@NotBlank(message = "newPassword不能为空")
|
||||
private String newPassword;
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.byhah.cloud.admin.module.dev.service.DevLogService;
|
||||
import com.byhah.cloud.admin.utils.UserUtil;
|
||||
import com.byhah.cloud.basic.core.entity.dev.DevLog;
|
||||
import com.byhah.cloud.basic.core.enums.dev.DevLogType;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统首页Service接口实现类
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysIndexService {
|
||||
private final DevLogService devLogApi;
|
||||
|
||||
public List<DevLog> visLogList() {
|
||||
return devLogApi.page(PageUtils.toPage(), new LambdaQueryWrapper<DevLog>()
|
||||
.eq(DevLog::getOpUser, UserUtil.getLoginUser().getName())
|
||||
.in(DevLog::getCategory, DevLogType.LOGIN, DevLogType.LOGOUT)
|
||||
.orderByDesc(DevLog::getCreatedAt))
|
||||
.getRecords();
|
||||
}
|
||||
|
||||
|
||||
public List<DevLog> opLogList() {
|
||||
return devLogApi.page(PageUtils.toPage(), new LambdaQueryWrapper<DevLog>()
|
||||
.select(DevLog::getId, DevLog::getCategory, DevLog::getName, DevLog::getOpTime, DevLog::getExeStatus)
|
||||
.eq(DevLog::getOpUser, UserUtil.getLoginUser().getName())
|
||||
.in(DevLog::getCategory, DevLogType.OPERATE, DevLogType.EXCEPTION)
|
||||
.orderByDesc(DevLog::getCreatedAt))
|
||||
.getRecords();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,146 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNode;
|
||||
import cn.hutool.core.lang.tree.TreeUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.admin.mapper.SysUserMapper;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysOrgDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysOrgSearchDto;
|
||||
import com.byhah.cloud.admin.module.sys.vo.SysOrgVo;
|
||||
import com.byhah.cloud.orm.mapper.sys.ISysOrgMapper;
|
||||
import com.byhah.cloud.orm.mapper.sys.ISysUserMapper;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysOrg;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysUser;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.deploy.basic.core.utils.Asserts;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 组织Service接口实现类
|
||||
**/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysOrgService extends ServiceImpl<ISysOrgMapper, SysOrg> {
|
||||
private final SysUserMapper sysUserMapper;
|
||||
private final ISysUserMapper userMapper;
|
||||
|
||||
|
||||
public IPage<SysOrgVo> page(Page<?> page, SysOrgSearchDto dto) {
|
||||
return sysUserMapper.sysOrgs(page, dto);
|
||||
}
|
||||
|
||||
|
||||
public List<Tree<Long>> tree() {
|
||||
List<SysOrg> sysOrgList = list();
|
||||
List<TreeNode<Long>> treeNodeList = sysOrgList.stream().map(sysOrg ->
|
||||
new TreeNode<>(sysOrg.getId(), sysOrg.getParentId(),
|
||||
sysOrg.getName(), sysOrg.getSortCode()).setExtra(JSONUtil.parseObj(sysOrg)))
|
||||
.collect(Collectors.toList());
|
||||
return TreeUtil.build(treeNodeList, 0L);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void add(SysOrgDto dto) {
|
||||
if (Objects.isNull(dto.getParentId())) {
|
||||
dto.setParentId(0L);
|
||||
}
|
||||
SysOrg sysOrg = BeanUtil.toBean(dto, SysOrg.class);
|
||||
Long count = lambdaQuery().eq(SysOrg::getParentId, dto.getParentId()).eq(SysOrg::getName, dto.getName()).count();
|
||||
Asserts.isTrue(count == 0, "存在重复的同级组织");
|
||||
sysOrg.setCode(RandomUtil.randomString(10));
|
||||
save(sysOrg);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void edit(SysOrgDto dto) {
|
||||
if (Objects.isNull(dto.getParentId())) {
|
||||
dto.setParentId(0L);
|
||||
}
|
||||
SysOrg dbOrg = queryEntity(dto.getId());
|
||||
BeanUtil.copyProperties(dto, dbOrg);
|
||||
Long count = lambdaQuery().eq(SysOrg::getParentId, dto.getParentId()).ne(SysOrg::getId, dto.getId()).eq(SysOrg::getName, dto.getName()).count();
|
||||
Asserts.isTrue(count == 0, "存在重复的同级组织");
|
||||
List<SysOrg> originDataList = getAllOrgList();
|
||||
boolean errorLevel = getChildListById(originDataList, dbOrg.getId(), true).stream()
|
||||
.map(SysOrg::getId).toList().contains(dbOrg.getParentId());
|
||||
if (errorLevel) {
|
||||
throw new CommonException("不可选择上级组织:{}", getById(originDataList, dbOrg.getParentId()).getName());
|
||||
}
|
||||
updateById(dbOrg);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(List<Long> orgIdList) {
|
||||
if (ObjectUtil.isNotEmpty(orgIdList)) {
|
||||
List<SysOrg> allOrgList = getAllOrgList();
|
||||
// 获取所有子组织
|
||||
List<Long> toDeleteOrgIdList = CollectionUtil.newArrayList();
|
||||
orgIdList.forEach(orgId -> toDeleteOrgIdList.addAll(getChildListById(allOrgList, orgId, true).stream()
|
||||
.map(SysOrg::getId).toList()));
|
||||
// 组织下有人不能删除(直属组织)
|
||||
boolean hasOrgUser = userMapper.lambdaQueryChain().in(SysUser::getOrgId, toDeleteOrgIdList).count() > 0;
|
||||
if (hasOrgUser) {
|
||||
throw new CommonException("请先删除组织下的用户");
|
||||
}
|
||||
// 执行删除
|
||||
removeByIds(toDeleteOrgIdList);
|
||||
}
|
||||
}
|
||||
|
||||
public SysOrg queryEntity(Long id) {
|
||||
SysOrg sysOrg = getById(id);
|
||||
if (ObjectUtil.isEmpty(sysOrg)) {
|
||||
throw new CommonException("组织不存在,id值为:{}", id);
|
||||
}
|
||||
return sysOrg;
|
||||
}
|
||||
|
||||
public List<SysOrg> getAllOrgList() {
|
||||
return list(new LambdaQueryWrapper<SysOrg>().orderByAsc(SysOrg::getSortCode));
|
||||
}
|
||||
|
||||
/* ====以下为各种递归方法==== */
|
||||
public List<SysOrg> getChildListById(List<SysOrg> originDataList, Long id, boolean includeSelf) {
|
||||
List<SysOrg> resultList = CollectionUtil.newArrayList();
|
||||
execRecursionFindChild(originDataList, id, resultList);
|
||||
if (includeSelf) {
|
||||
SysOrg self = getById(originDataList, id);
|
||||
if (ObjectUtil.isNotEmpty(self)) {
|
||||
resultList.add(self);
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public void execRecursionFindChild(List<SysOrg> originDataList, Long id, List<SysOrg> resultList) {
|
||||
originDataList.forEach(item -> {
|
||||
if (item.getParentId().equals(id)) {
|
||||
resultList.add(item);
|
||||
execRecursionFindChild(originDataList, item.getId(), resultList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public SysOrg getById(List<SysOrg> originDataList, Long id) {
|
||||
int index = CollStreamUtil.toList(originDataList, SysOrg::getId).indexOf(id);
|
||||
return index == -1 ? null : originDataList.get(index);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
|
||||
package com.byhah.cloud.admin.module.sys.service;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.basic.core.enums.sys.SysRelationType;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.byhah.cloud.orm.mapper.sys.ISysRelationMapper;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysRelation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 关系Service接口实现类
|
||||
**/
|
||||
@Service
|
||||
public class SysRelationService extends ServiceImpl<ISysRelationMapper, SysRelation> {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveRelationBatch(Long objectId, List<Long> targetIdList, SysRelationType category, boolean clear) {
|
||||
// 是否需要先删除关系
|
||||
if (clear) {
|
||||
this.remove(new LambdaQueryWrapper<SysRelation>().eq(SysRelation::getObjectId, objectId)
|
||||
.eq(SysRelation::getCategory, category));
|
||||
}
|
||||
List<SysRelation> sysRelationList = CollectionUtil.newArrayList();
|
||||
for (Long id : targetIdList) {
|
||||
SysRelation sysRelation = new SysRelation();
|
||||
sysRelation.setObjectId(objectId);
|
||||
sysRelation.setTargetId(id);
|
||||
sysRelation.setCategory(category);
|
||||
sysRelationList.add(sysRelation);
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(sysRelationList)) {
|
||||
this.saveBatch(sysRelationList);
|
||||
}
|
||||
}
|
||||
|
||||
public List<SysRelation> getRelationListByObjectIdAndCategory(Long objectId, SysRelationType category) {
|
||||
LambdaQueryWrapper<SysRelation> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.eq(SysRelation::getObjectId, objectId);
|
||||
if (Objects.nonNull(category)) {
|
||||
lambdaQueryWrapper.eq(SysRelation::getCategory, category);
|
||||
}
|
||||
return this.list(lambdaQueryWrapper);
|
||||
}
|
||||
|
||||
|
||||
public List<SysRelation> getRelationListByObjectIdListAndCategory(List<Long> objectIdList, SysRelationType category) {
|
||||
LambdaQueryWrapper<SysRelation> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.in(SysRelation::getObjectId, objectIdList);
|
||||
if (Objects.nonNull(category)) {
|
||||
lambdaQueryWrapper.eq(SysRelation::getCategory, category);
|
||||
}
|
||||
return this.list(lambdaQueryWrapper);
|
||||
}
|
||||
|
||||
public List<SysRelation> getRelationListByTargetIdAndCategory(Long targetId, SysRelationType category) {
|
||||
LambdaQueryWrapper<SysRelation> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.eq(SysRelation::getTargetId, targetId);
|
||||
if (ObjectUtil.isNotEmpty(category)) {
|
||||
lambdaQueryWrapper.eq(SysRelation::getCategory, category);
|
||||
}
|
||||
return this.list(lambdaQueryWrapper);
|
||||
}
|
||||
|
||||
public List<Long> getRelationTargetIdListByObjectIdAndCategory(Long objectId, SysRelationType category) {
|
||||
return this.getRelationListByObjectIdAndCategory(objectId, category).stream()
|
||||
.map(SysRelation::getTargetId).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Long> getRelationTargetIdListByObjectIdListAndCategory(List<Long> objectIdList, SysRelationType category) {
|
||||
return this.getRelationListByObjectIdListAndCategory(objectIdList, category).stream()
|
||||
.map(SysRelation::getTargetId).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Long> getRelationObjectIdListByTargetIdAndCategory(Long targetId, SysRelationType category) {
|
||||
return this.getRelationListByTargetIdAndCategory(targetId, category).stream()
|
||||
.map(SysRelation::getObjectId).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,213 @@
|
||||
package com.byhah.cloud.admin.module.sys.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNode;
|
||||
import cn.hutool.core.lang.tree.TreeUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.admin.module.sys.dto.ChangeModuleDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.ResourceTreeDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysResourceDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysResourceSearchDto;
|
||||
import com.byhah.cloud.orm.mapper.sys.ISysResourceMapper;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysRelation;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysResource;
|
||||
import com.byhah.cloud.basic.core.enums.sys.SysMenuType;
|
||||
import com.byhah.cloud.basic.core.enums.sys.SysResourceType;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.deploy.basic.core.utils.Asserts;
|
||||
import com.byhah.deploy.basic.util.web.PageUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.byhah.cloud.basic.core.enums.sys.SysResourceType.*;
|
||||
|
||||
/**
|
||||
* 菜单Service接口实现类
|
||||
**/
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@RequiredArgsConstructor
|
||||
public class SysResourceService extends ServiceImpl<ISysResourceMapper, SysResource> {
|
||||
|
||||
private final SysRelationService sysRelationService;
|
||||
|
||||
|
||||
public Page<SysResource> page(SysResourceSearchDto dto) {
|
||||
return lambdaQuery().eq(SysResource::getCategory, dto.getCategory()).like(StrUtil.isNotBlank(dto.getSearchKey()), SysResource::getTitle, dto.getSearchKey())
|
||||
.eq(Objects.nonNull(dto.getModule()), SysResource::getModule, dto.getModule())
|
||||
.eq(Objects.nonNull(dto.getParentId()), SysResource::getParentId, dto.getParentId())
|
||||
.orderByAsc(SysResource::getSortCode)
|
||||
.page(PageUtils.toPage());
|
||||
}
|
||||
|
||||
private void fillParentSysResourceInfo(List<SysResource> resourceList) {
|
||||
if (CollUtil.isNotEmpty(resourceList)) {
|
||||
List<Long> parentIds = resourceList.stream().map(SysResource::getParentId).filter(x -> !Objects.equals(x, 0L)).distinct().collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(parentIds)) {
|
||||
List<SysResource> parents = lambdaQuery().ne(SysResource::getCategory, MODULE).in(SysResource::getId, parentIds).list();
|
||||
if (CollUtil.isNotEmpty(parents)) {
|
||||
fillParentSysResourceInfo(parents);
|
||||
resourceList.addAll(parents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void add(SysResourceDto dto) {
|
||||
checkParam(dto);
|
||||
SysResource resource = BeanUtil.toBean(dto, SysResource.class);
|
||||
Long count = lambdaQuery().eq(SysResource::getParentId, resource.getParentId()).eq(SysResource::getTitle, resource.getTitle()).count();
|
||||
Asserts.isTrue(count == 0, "存在重复的菜单");
|
||||
if (Objects.nonNull(dto.getParentId()) && dto.getParentId() != 0L) {
|
||||
SysResource parent = getById(dto.getParentId());
|
||||
Asserts.notNull(parent, "上级菜单不存在");
|
||||
if (parent.getCategory() == MODULE) {
|
||||
resource.setModule(parent.getId());
|
||||
} else {
|
||||
resource.setModule(parent.getModule());
|
||||
}
|
||||
}
|
||||
resource.setCategory(SysResourceType.forValue(dto.getCategory()));
|
||||
save(resource);
|
||||
}
|
||||
|
||||
private void checkParam(SysResourceDto dto) {
|
||||
if (dto.getCategory() != SPA.getType()) {
|
||||
Asserts.notNull(dto.getParentId(), "parentId不能为空");
|
||||
}
|
||||
if (dto.getCategory() == MENU.getType()) {
|
||||
Asserts.notNull(dto.getMenuType(), "菜单类型不能为空");
|
||||
if (dto.getMenuType() == SysMenuType.MENU.getType()) {
|
||||
Asserts.notNull(dto.getComponent(), "component不能为空");
|
||||
} else if (dto.getMenuType() == SysMenuType.IFRAME.getType() || dto.getMenuType() == SysMenuType.LINK.getType()) {
|
||||
dto.setName(RandomUtil.randomNumbers(10));
|
||||
dto.setComponent(null);
|
||||
} else {
|
||||
dto.setName(null);
|
||||
dto.setComponent(null);
|
||||
}
|
||||
} else if (dto.getCategory() == MODULE.getType()) {
|
||||
Asserts.isTrue(StrUtil.isNotBlank(dto.getTitle()), "模块名不能为空");
|
||||
Asserts.isTrue(StrUtil.isNotBlank(dto.getIcon()), "模块图标不能为空");
|
||||
} else if (dto.getCategory() == BUTTON.getType()) {
|
||||
Asserts.isTrue(StrUtil.isNotBlank(dto.getTitle()), "按钮名不能为空");
|
||||
Asserts.isTrue(StrUtil.isNotBlank(dto.getCode()), "按钮编码不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void edit(SysResourceDto dto) {
|
||||
SysResource resource = queryEntity(dto.getId());
|
||||
checkParam(dto);
|
||||
BeanUtil.copyProperties(dto, resource);
|
||||
boolean repeatTitle = count(new LambdaQueryWrapper<SysResource>().eq(SysResource::getParentId, resource.getParentId()).eq(SysResource::getCategory, MENU).eq(SysResource::getTitle, resource.getTitle()).ne(SysResource::getId, resource.getId())) > 0;
|
||||
if (repeatTitle) {
|
||||
throw new CommonException("存在重复的菜单,名称为:{}", resource.getTitle());
|
||||
}
|
||||
List<SysResource> originDataList = list(new LambdaQueryWrapper<SysResource>().eq(SysResource::getCategory, MENU));
|
||||
boolean errorLevel = getChildListById(originDataList, resource.getId(), true).stream().map(SysResource::getId).toList().contains(resource.getParentId());
|
||||
if (errorLevel) {
|
||||
throw new CommonException("不可选择上级菜单:{}", getById(originDataList, resource.getParentId()).getName());
|
||||
}
|
||||
if (Objects.nonNull(dto.getParentId()) && dto.getParentId() != 0L) {
|
||||
SysResource parentMenu = getById(dto.getParentId());
|
||||
Asserts.notNull(parentMenu, "上级菜单不存在");
|
||||
}
|
||||
updateById(resource);
|
||||
}
|
||||
|
||||
|
||||
public void changeModule(ChangeModuleDto dto) {
|
||||
SysResource resource = queryEntity(dto.getId());
|
||||
if (!resource.getParentId().equals(0L)) {
|
||||
throw new CommonException("非顶级菜单不可修改所属模块");
|
||||
}
|
||||
List<SysResource> resources = list(new LambdaQueryWrapper<SysResource>().eq(SysResource::getCategory, MENU));
|
||||
List<SysResource> sysResourceChildList = getChildListById(resources, resource.getId(), true).stream().peek(x -> x.setModule(dto.getModule())).collect(Collectors.toList());
|
||||
updateBatchById(sysResourceChildList);
|
||||
}
|
||||
|
||||
|
||||
public void delete(List<Long> ids) {
|
||||
if (ObjectUtil.isNotEmpty(ids)) {
|
||||
List<Long> all = childs(ids, new ArrayList<>());
|
||||
removeByIds(all);
|
||||
sysRelationService.lambdaUpdate().in(SysRelation::getTargetId, all).remove();
|
||||
}
|
||||
}
|
||||
|
||||
private List<Long> childs(List<Long> parents, List<Long> all) {
|
||||
all.addAll(parents);
|
||||
List<Long> childs = lambdaQuery().in(SysResource::getParentId, parents).select(SysResource::getId).list().stream().map(SysResource::getId).collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(childs)) {
|
||||
childs(childs, all);
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
|
||||
public SysResource detail(Long id) {
|
||||
return queryEntity(id);
|
||||
}
|
||||
|
||||
|
||||
public SysResource queryEntity(Long id) {
|
||||
SysResource SysResource = getById(id);
|
||||
if (ObjectUtil.isEmpty(SysResource)) {
|
||||
throw new CommonException("菜单不存在,id值为:{}", id);
|
||||
}
|
||||
return SysResource;
|
||||
}
|
||||
|
||||
public List<Tree<Long>> menuTreeSelector(ResourceTreeDto dto) {
|
||||
List<SysResource> resourceList = lambdaQuery().notIn(CollUtil.isNotEmpty(dto.getExcludeCategory()), SysResource::getCategory, dto.getExcludeCategory()).eq(StrUtil.isNotBlank(dto.getSearchKey()), SysResource::getTitle, dto.getSearchKey()).eq(Objects.nonNull(dto.getModule()), SysResource::getModule, dto.getModule()).list();
|
||||
fillParentSysResourceInfo(resourceList);
|
||||
List<TreeNode<Long>> treeNodeList = resourceList.stream().map(x -> new TreeNode<>(x.getId(), x.getParentId(), x.getTitle(), x.getSortCode()).setExtra(JSONUtil.parseObj(x))).collect(Collectors.toList());
|
||||
Long root = Optional.ofNullable(dto.getModule()).orElse(0L);
|
||||
return TreeUtil.build(treeNodeList, root);
|
||||
}
|
||||
|
||||
/* ====以下为各种递归方法==== */
|
||||
public List<SysResource> getChildListById(List<SysResource> originDataList, Long id, boolean includeSelf) {
|
||||
List<SysResource> resultList = CollUtil.newArrayList();
|
||||
execRecursionFindChild(originDataList, id, resultList);
|
||||
if (includeSelf) {
|
||||
SysResource self = getById(originDataList, id);
|
||||
if (ObjectUtil.isNotEmpty(self)) {
|
||||
resultList.add(self);
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public void execRecursionFindChild(List<SysResource> originDataList, Long id, List<SysResource> resultList) {
|
||||
originDataList.forEach(item -> {
|
||||
if (item.getParentId().equals(id)) {
|
||||
resultList.add(item);
|
||||
execRecursionFindChild(originDataList, item.getId(), resultList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public SysResource getById(List<SysResource> originDataList, Long id) {
|
||||
for (SysResource resource : originDataList) {
|
||||
if (resource.getId().equals(id)) {
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
package com.byhah.cloud.admin.module.sys.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
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.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysRoleDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysRoleGrantResourceDto;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysRoleGrantUserDto;
|
||||
import com.byhah.cloud.orm.mapper.sys.ISysRoleMapper;
|
||||
import com.byhah.cloud.basic.constant.SystemKey;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysRelation;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysResource;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysRole;
|
||||
import com.byhah.cloud.basic.core.enums.sys.SysRelationType;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.deploy.basic.core.utils.Asserts;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 角色Service接口实现类
|
||||
**/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysRoleService extends ServiceImpl<ISysRoleMapper, SysRole> {
|
||||
|
||||
private final SysRelationService sysRelationService;
|
||||
private final SysResourceService sysMenuService;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void add(SysRoleDto dto) {
|
||||
Long count = lambdaQuery().eq(SysRole::getName, dto.getName()).count();
|
||||
Asserts.isTrue(count == 0, "角色名称已存在");
|
||||
count = lambdaQuery().eq(SysRole::getCode, dto.getCode()).count();
|
||||
Asserts.isTrue(count == 0, "角色权限代码已存在");
|
||||
SysRole sysRole = BeanUtil.toBean(dto, SysRole.class);
|
||||
save(sysRole);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void edit(SysRoleDto dto) {
|
||||
SysRole dbRole = queryEntity(dto.getId());
|
||||
boolean superRole = dbRole.getCode().equals(SystemKey.SYS_ROLE);
|
||||
if (superRole) {
|
||||
throw new CommonException("不可编辑超管角色");
|
||||
}
|
||||
Long count = lambdaQuery().eq(SysRole::getName, dto.getName()).ne(SysRole::getId, dbRole.getId()).count();
|
||||
Asserts.isTrue(count == 0, "角色名称已存在");
|
||||
count = lambdaQuery().eq(SysRole::getCode, dto.getCode()).ne(SysRole::getId, dbRole.getId()).count();
|
||||
Asserts.isTrue(count == 0, "角色权限代码已存在");
|
||||
BeanUtil.copyProperties(dto, dbRole);
|
||||
updateById(dbRole);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(List<Long> ids) {
|
||||
if (ObjectUtil.isNotEmpty(ids)) {
|
||||
boolean containsSuperAdminRole = listByIds(ids).stream().map(SysRole::getCode).collect(Collectors.toSet()).contains(SystemKey.SYS_ROLE);
|
||||
if (containsSuperAdminRole) {
|
||||
throw new CommonException("不可删除系统内置超管角色");
|
||||
}
|
||||
// 级联删除角色与用户关系
|
||||
sysRelationService.remove(new LambdaUpdateWrapper<SysRelation>().in(SysRelation::getTargetId, ids).eq(SysRelation::getCategory, SysRelationType.USER_HAS_ROLE));
|
||||
// 级联删除角色与资源关系
|
||||
sysRelationService.remove(new LambdaUpdateWrapper<SysRelation>().in(SysRelation::getObjectId, ids).eq(SysRelation::getCategory, SysRelationType.ROLE_HAS_RESOURCE));
|
||||
// 执行删除
|
||||
removeByIds(ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public SysRole detail(Long id) {
|
||||
return queryEntity(id);
|
||||
}
|
||||
|
||||
|
||||
public List<SysResource> ownResource(Long id) {
|
||||
List<Long> ids = sysRelationService.getRelationListByObjectIdAndCategory(id, SysRelationType.ROLE_HAS_RESOURCE).stream().map(SysRelation::getTargetId).collect(Collectors.toList());
|
||||
return CollUtil.isNotEmpty(ids) ? sysMenuService.listByIds(ids) : Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
public void grantResource(SysRoleGrantResourceDto dto) {
|
||||
Long id = dto.getId();
|
||||
SysRole sysRole = queryEntity(id);
|
||||
List<Long> menuIdList = dto.getResourceIds();
|
||||
if (!SystemKey.SYS_ROLE.equals(sysRole.getCode())) {
|
||||
if (ObjectUtil.isNotEmpty(menuIdList)) {
|
||||
Set<Long> sysModuleIdList = sysMenuService.listByIds(menuIdList).stream().map(SysResource::getModule).collect(Collectors.toSet());
|
||||
boolean containsSystemModule = sysMenuService.listByIds(sysModuleIdList).stream().map(SysResource::getCode).collect(Collectors.toSet()).contains(SystemKey.SYS_MODULE);
|
||||
if (containsSystemModule) {
|
||||
throw new CommonException("非超管角色不可被授权系统模块菜单资源");
|
||||
}
|
||||
}
|
||||
}
|
||||
sysRelationService.saveRelationBatch(id, menuIdList, SysRelationType.ROLE_HAS_RESOURCE,true);
|
||||
}
|
||||
|
||||
public List<Long> ownUser(Long id) {
|
||||
return sysRelationService.getRelationObjectIdListByTargetIdAndCategory(id, SysRelationType.USER_HAS_ROLE);
|
||||
}
|
||||
|
||||
public void grantUser(SysRoleGrantUserDto dto) {
|
||||
Long id = dto.getId();
|
||||
List<Long> grantInfoList = dto.getGrantInfoList();
|
||||
sysRelationService.remove(new LambdaQueryWrapper<SysRelation>().eq(SysRelation::getTargetId, id).eq(SysRelation::getCategory, SysRelationType.USER_HAS_ROLE));
|
||||
sysRelationService.saveBatch(grantInfoList.stream().map(userId -> {
|
||||
SysRelation sysRelation = new SysRelation();
|
||||
sysRelation.setObjectId(userId);
|
||||
sysRelation.setTargetId(id);
|
||||
sysRelation.setCategory(SysRelationType.USER_HAS_ROLE);
|
||||
return sysRelation;
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
|
||||
public SysRole queryEntity(Long id) {
|
||||
SysRole sysRole = getById(id);
|
||||
if (ObjectUtil.isEmpty(sysRole)) {
|
||||
throw new CommonException("角色不存在,id值为:{}", id);
|
||||
}
|
||||
return sysRole;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package com.byhah.cloud.admin.module.sys.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.byhah.deploy.basic.core.exception.CommonException;
|
||||
import com.byhah.cloud.admin.module.sys.dto.SysTenantDto;
|
||||
import com.byhah.cloud.basic.core.entity.system.SysTenant;
|
||||
import com.byhah.cloud.orm.mapper.sys.ISysTenantMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* sys_tenantService实现类
|
||||
**/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class SysTenantService extends ServiceImpl<ISysTenantMapper, SysTenant> {
|
||||
private final SysUserService userService;
|
||||
|
||||
public void add(SysTenantDto dto) {
|
||||
SysTenant tenant = BeanUtil.toBean(dto, SysTenant.class);
|
||||
this.save(tenant);
|
||||
// 保存用户
|
||||
userService.add(dto.getName(), dto.getAccount(), dto.getPhone());
|
||||
}
|
||||
|
||||
public void edit(SysTenantDto dto) {
|
||||
SysTenant dbTenant = this.queryEntity(dto.getId());
|
||||
BeanUtil.copyProperties(dto, dbTenant);
|
||||
this.updateById(dbTenant);
|
||||
if (!dbTenant.getAccount().equals(dto.getAccount())) {
|
||||
userService.add(dto.getName(), dto.getAccount(), dto.getPhone());
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(List<Long> ids) {
|
||||
this.removeByIds(ids);
|
||||
}
|
||||
|
||||
public SysTenant detail(Long id) {
|
||||
return this.queryEntity(id);
|
||||
}
|
||||
|
||||
public SysTenant queryEntity(Long id) {
|
||||
SysTenant sysTenant = this.getById(id);
|
||||
if (ObjectUtil.isEmpty(sysTenant)) {
|
||||
throw new CommonException("sys_tenant不存在,id值为:{}", id);
|
||||
}
|
||||
return sysTenant;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user