commit 0523155715249017da76a827d08b8a335d49b605 Author: Administrator Date: Mon Nov 29 10:00:15 2021 +0800 first commit by ailanyin diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd446f4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +###################################################################### +# Build Tools + +.gradle +/build/ +!gradle/wrapper/gradle-wrapper.jar + +target/ +!.mvn/wrapper/maven-wrapper.jar + +###################################################################### +# IDE + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +nbproject/private/ +build/* +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +###################################################################### +# Others +*.log +*.xml.versionsBackup + +!*/build/*.java +!*/build/*.html +!*/build/*.xml \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..69fd631 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +### 环境: + +​ jdk17 + mysql8 + redis (推荐) + +​ jdk8 + mysql5.7 + redis (理论也能跑) + + + +### 启动: + +0. 以上的环境已经准备ok + + 1. 创建 ailanyin-boot 数据库,并导入项目 doc 目录下的 ailanyin-boot.sql + + 2. 修改 application-dev.yml 下的 mysql 账号密码 + + 3. 默认 redis 没有密码,如果你的 redis 有密码,也一并更改 + + 4. 启动 ailanyin-admin 模块下的 AdminApplication + + + +### 约定(强制): + + 1. 增加--POST,修改--PUT,删除--DELETE,查询--GET + + 2. 用户错误操作,请不要 new RuntimeException,使用Asserts.fail(msg(String)); + + + +### 说明(必看): + + 1. 操作日志的开关,以及级别在参数设置里面,默认是开,记录修改删除(PUT-DELETE) + 2. 是否开启注册,在参数设置里面 + 3. 是否开启验证码,在参数设置里面 (目前是有效期 2 分钟,代码可改) + 4. 是否开启拉黑机制,在参数设置里面(目前是 30 分钟内输出 5 次密码拉黑,代码可改) \ No newline at end of file diff --git a/ailanyin-admin/pom.xml b/ailanyin-admin/pom.xml new file mode 100644 index 0000000..02e58ca --- /dev/null +++ b/ailanyin-admin/pom.xml @@ -0,0 +1,40 @@ + + + + vis389_backend + com.ailanyin + 1.0-SNAPSHOT + + 4.0.0 + + ailanyin-admin + + + + + com.github.oshi + oshi-core + + + com.ailanyin + ailanyin-model-mapper + + + com.ailanyin + ailanyin-security + + + + + + ${artifactId}-dm8 + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/AdminApplication.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/AdminApplication.java new file mode 100644 index 0000000..32ef059 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/AdminApplication.java @@ -0,0 +1,22 @@ +package com.ailanyin.admin; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 13:01 + */ +@SpringBootApplication +@ComponentScan(basePackages = {"com.ailanyin.admin","com.ailanyin.common"}) +@MapperScan({"com.ailanyin.mapper"}) +@EnableScheduling +public class AdminApplication { + public static void main(String[] args) { + SpringApplication.run(AdminApplication.class, args); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/aspect/AdminLogAspect.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/aspect/AdminLogAspect.java new file mode 100644 index 0000000..374c512 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/aspect/AdminLogAspect.java @@ -0,0 +1,169 @@ +package com.ailanyin.admin.aspect; + +import com.ailanyin.admin.service.SysLogService; +import com.ailanyin.common.service.RedisService; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.common.utils.IpUtil; +import com.ailanyin.model.SysLog; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.ApiOperation; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.*; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.*; + +/** + * 日志切面 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:43 + */ +@Aspect +@Component +@Order(1) +public class AdminLogAspect { + + @Autowired + private SysLogService sysLogService; + @Autowired + private RedisService redisService; + + @Value("${redis.database}") + private String database; + + private static final String SWITCH_KEY = ":sys:config:sys.log.switch"; + private static final String LEVEL_KEY = ":sys:config:sys.log.level"; + private static final String SWITCH_ON = "on"; + + @Pointcut("execution(public * com.ailanyin.admin.controller.*.*(..))") + public void webLog() { + } + + @Before("webLog()") + public void doBefore(JoinPoint joinPoint) throws Throwable { + } + + @AfterReturning(value = "webLog()", returning = "ret") + public void doAfterReturning(Object ret) throws Throwable { + } + + @Around("webLog()") + public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { + + if (getSwitchFlag()) { + return addLog(joinPoint); + } + return joinPoint.proceed(); + } + + /** + * 查询是否符合级别 + * + * @param httpMethod get/put/post/delete + * @return boolean + */ + private boolean getLevelFlag(String httpMethod) { + try { + return redisService.get(database + LEVEL_KEY).toString().contains(httpMethod); + } catch (Exception e) { + return false; + } + } + + /** + * 查询日志是否开启 + * + * @return boolean + */ + private boolean getSwitchFlag() { + try { + return SWITCH_ON.equals(redisService.get(database + SWITCH_KEY)); + } catch (Exception e) { + return false; + } + } + + /** + * 添加进数据库 + * + * @param joinPoint joinPoint + * @return obj + * @throws Throwable Throwable + */ + private Object addLog(ProceedingJoinPoint joinPoint) throws Throwable { + long startTime = System.currentTimeMillis(); + //获取当前请求对象 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = attributes.getRequest(); + String httpMethod = request.getMethod(); + Object result = joinPoint.proceed(); + if (getLevelFlag(httpMethod)) { + SysLog sysLog = new SysLog(); + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + if (method.isAnnotationPresent(ApiOperation.class)) { + ApiOperation log = method.getAnnotation(ApiOperation.class); + sysLog.setDescription(log.value()); + } + long endTime = System.currentTimeMillis(); + sysLog.setUsername(request.getRemoteUser()); + sysLog.setIp(IpUtil.getIpAddr(request)); + sysLog.setMethod(httpMethod); + sysLog.setParameter(JSON.toJSONString(getParameter(method, joinPoint.getArgs()))); + sysLog.setSpendTime((int) (endTime - startTime)); + sysLog.setStartTime(new Date()); + sysLog.setUri(request.getRequestURI()); + sysLogService.insertLog(sysLog); + } + return result; + } + + /** + * 根据方法和传入的参数获取请求参数 + */ + private Object getParameter(Method method, Object[] args) { + List argList = new ArrayList<>(); + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + //将RequestBody注解修饰的参数作为请求参数 + RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class); + if (requestBody != null) { + argList.add(args[i]); + } + //将RequestParam注解修饰的参数作为请求参数 + RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); + if (requestParam != null) { + Map map = new HashMap<>(16); + String key = parameters[i].getName(); + if (EmptyUtil.isNotEmpty(requestParam.value())) { + key = requestParam.value(); + } + map.put(key, args[i]); + argList.add(map); + } + } + if (argList.size() == 0) { + return null; + } else if (argList.size() == 1) { + return argList.get(0); + } else { + return argList; + } + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/aspect/DataScopeAspect.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/aspect/DataScopeAspect.java new file mode 100644 index 0000000..f69666b --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/aspect/DataScopeAspect.java @@ -0,0 +1,131 @@ +package com.ailanyin.admin.aspect; + +import com.ailanyin.admin.vo.LoginUser; +import com.ailanyin.common.annotation.DataScope; +import com.ailanyin.common.model.BaseEntity; +import com.ailanyin.common.utils.StringUtil; +import com.ailanyin.model.SysRole; +import com.ailanyin.model.SysUser; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +/** + * 数据过滤处理 + * + * @author ruoyi + */ +@Aspect +@Component +public class DataScopeAspect { + + /** + * 全部数据权限 + */ + private static final String DATA_SCOPE_ALL = "1"; + + /** + * 自定数据权限 + */ + private static final String DATA_SCOPE_CUSTOM = "2"; + + /** + * 部门数据权限 + */ + private static final String DATA_SCOPE_DEPT = "3"; + + /** + * 部门及以下数据权限 + */ + private static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; + + /** + * 仅本人数据权限 + */ + private static final String DATA_SCOPE_SELF = "5"; + + /** + * 数据权限过滤关键字 + */ + private static final String DATA_SCOPE = "dataScope"; + + @Before("@annotation(controllerDataScope)") + public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable { + clearDataScope(point); + handleDataScope(point, controllerDataScope); + } + + private void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) { + // 获取当前的用户 + SecurityContext ctx = SecurityContextHolder.getContext(); + Authentication auth = ctx.getAuthentication(); + LoginUser loginUser = (LoginUser) auth.getPrincipal(); + if (StringUtil.isNotNull(loginUser)) { + SysUser currentUser = loginUser.getUser(); + // 如果是超级管理员,则不过滤数据 + if (StringUtil.isNotNull(currentUser) && !currentUser.isAdmin()) { + dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), + controllerDataScope.userAlias()); + } + } + } + + /** + * 数据范围过滤 + * + * @param joinPoint 切点 + * @param user 用户 + * @param userAlias 别名 + */ + private static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) { + StringBuilder sqlString = new StringBuilder(); + + for (SysRole role : user.getRoles()) { + String dataScope = role.getDataScope(); + if (DATA_SCOPE_ALL.equals(dataScope)) { + sqlString = new StringBuilder(); + break; + } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { + sqlString.append(StringUtil.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, + role.getRoleId())); + } else if (DATA_SCOPE_DEPT.equals(dataScope)) { + sqlString.append(StringUtil.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); + } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { + sqlString.append(StringUtil.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", + deptAlias, user.getDeptId(), user.getDeptId())); + } else if (DATA_SCOPE_SELF.equals(dataScope)) { + if (StringUtil.isNotBlank(userAlias)) { + sqlString.append(StringUtil.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); + } else { + // 数据权限为仅本人且没有userAlias别名不查询任何数据 + sqlString.append(" OR 1=0 "); + } + } + } + + if (StringUtil.isNotBlank(sqlString.toString())) { + Object params = joinPoint.getArgs()[0]; + if (StringUtil.isNotNull(params) && params instanceof BaseEntity) { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); + } + } + } + + /** + * 拼接权限sql前先清空params.dataScope参数防止注入 + */ + private void clearDataScope(final JoinPoint joinPoint) { + Object params = joinPoint.getArgs()[0]; + if (StringUtil.isNotNull(params) && params instanceof BaseEntity) { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, ""); + } + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/config/AdminSecurityConfig.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/config/AdminSecurityConfig.java new file mode 100644 index 0000000..b954c8c --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/config/AdminSecurityConfig.java @@ -0,0 +1,33 @@ +package com.ailanyin.admin.config; + +import com.ailanyin.admin.service.impl.UserDetailsServiceImpl; +import com.ailanyin.security.config.BaseSecurityConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.userdetails.UserDetailsService; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/19 0019 上午 11:54 + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled=true) +public class AdminSecurityConfig extends BaseSecurityConfig { + + @Autowired + private UserDetailsServiceImpl userDetailsService; + + + @Bean + @Override + public UserDetailsService userDetailsService() { + //获取登录用户信息 + return username -> userDetailsService.loadUserByUsername(username); + } + +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/config/GlobalCorsConfig.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/config/GlobalCorsConfig.java new file mode 100644 index 0000000..5f20fdc --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/config/GlobalCorsConfig.java @@ -0,0 +1,43 @@ +package com.ailanyin.admin.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +/** + * 全局跨域配置 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:43 + */ +@Configuration +public class GlobalCorsConfig { + + /** + * 允许跨域调用的过滤器 + * 支持最新 springboot 2.5.5 + * + * @return CorsFilter + */ + @Bean + public CorsFilter corsFilter() { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + // 设置访问源地址 + config.addAllowedOriginPattern("*"); + // 设置访问源请求头 + config.addAllowedHeader("*"); + // 设置访问源请求方法 + config.addAllowedMethod("*"); + // 有效期 1800秒 + config.setMaxAge(1800L); + // 添加映射路径,拦截一切请求 + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + // 返回新的CorsFilter + return new CorsFilter(source); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/config/Knife4jConfig.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/config/Knife4jConfig.java new file mode 100644 index 0000000..aeb38f5 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/config/Knife4jConfig.java @@ -0,0 +1,49 @@ +package com.ailanyin.admin.config; + + +import com.ailanyin.common.config.BaseSwaggerConfig; +import com.ailanyin.common.model.SwaggerProperties; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * Knife4j 接口文档配置 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:43 + */ +@Configuration +@EnableSwagger2 +public class Knife4jConfig extends BaseSwaggerConfig { + + + @Value("${spring.profiles.active}") + private String active; + + private static final String DEV = "dev"; + + @Override + public SwaggerProperties swaggerProperties() { + + if (DEV.equals(active)) { + return SwaggerProperties.builder() + .apiBasePackage("com.ailanyin.admin.controller") + .title("vis389_backend") + .description("相关接口文档") + .contactName("ailanyin") + .version("dev") + .enableSecurity(true) + .build(); + } + return SwaggerProperties.builder() + .apiBasePackage("com.controller") + .title("生产环境开发文档已经关闭") + .description("生产环境开发文档已经关闭") + .contactName("ailanyin") + .version("prod") + .enableSecurity(false) + .build(); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/config/SysConfig.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/config/SysConfig.java new file mode 100644 index 0000000..1986bff --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/config/SysConfig.java @@ -0,0 +1,21 @@ +package com.ailanyin.admin.config; + +import com.ailanyin.common.model.IdWorker; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 系统配置 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/18 0018 下午 13:21 + */ +@Configuration +public class SysConfig { + + @Bean + public IdWorker idWorker() { + return new IdWorker(1,1); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/BaseExceptionController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/BaseExceptionController.java new file mode 100644 index 0000000..3d36694 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/BaseExceptionController.java @@ -0,0 +1,55 @@ +package com.ailanyin.admin.controller; + + +import com.ailanyin.admin.service.ExceptionLogService; +import com.ailanyin.common.exception.ApiException; +import com.ailanyin.common.result.AjaxResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * 全局异常处理 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:43 + */ +@ControllerAdvice +public class BaseExceptionController { + + @Autowired + private ExceptionLogService exceptionLogService; + + /** + * 非自定义异常 + * 存进数据库 + * + * @param e Exception + * @return AjaxResult + */ + @ExceptionHandler(value = Exception.class) + @ResponseBody + public AjaxResult error(Exception e){ + e.printStackTrace(); + try { + exceptionLogService.insertExceptionLog(e); + } catch (Exception ex) { + ex.printStackTrace(); + } + return AjaxResult.error(e.getMessage()); + } + + /** + * 自定义异常, 控制台不打印 + * + * @param e ApiException + * @return AjaxResult + */ + @ExceptionHandler(ApiException.class) + @ResponseBody + public AjaxResult handlerBingException(ApiException e) { + return AjaxResult.error(e.getMessage()); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/CommonFileController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/CommonFileController.java new file mode 100644 index 0000000..b85beeb --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/CommonFileController.java @@ -0,0 +1,43 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.CommonFileService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.utils.FileUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/25 0025 上午 11:13 + */ +@RestController +@Api(tags = "通用文件上传下载") +public class CommonFileController { + + @Autowired + private CommonFileService commonFileService; + + @ApiOperation(value = "文件下载") + @GetMapping("common/download") + public void fileDownload(String fileName, HttpServletResponse response) throws Exception { + String realFileName = fileName.substring(fileName.indexOf("_") + 1); + String filePath = FileUtil.getDownloadPath() + fileName; + FileUtil.setAttachmentResponseHeader(response, realFileName); + FileUtil.writeBytes(filePath, response.getOutputStream()); + FileUtil.deleteFile(filePath); + } + + @PostMapping("common/upload") + @ApiOperation(value = "文件上传") + public AjaxResult fileUpload(MultipartFile file) { + return AjaxResult.success(commonFileService.fileUpload(file)); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/ExceptionLogController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/ExceptionLogController.java new file mode 100644 index 0000000..21604a8 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/ExceptionLogController.java @@ -0,0 +1,44 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.ExceptionLogService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.result.CommonPage; +import com.ailanyin.model.ExceptionLog; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/2 0002 下午 17:22 + */ +@RestController +@RequestMapping("/system/exception") +@Api(tags = "后台异常信息管理") +public class ExceptionLogController { + + @Autowired + private ExceptionLogService exceptionLogService; + + @GetMapping("/list") + @ApiOperation(value = "获取异常日志列表") + public CommonPage list(ExceptionLog exceptionLog, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = exceptionLogService.selectExceptionLog(exceptionLog); + return CommonPage.restPage(list); + } + + @DeleteMapping("/remove") + @ApiOperation(value = "批量删除异常日志") + public AjaxResult removeExceptionLog(@RequestBody List logIds) { + exceptionLogService.removeExceptionLog(logIds); + return AjaxResult.success(); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysBlacklistUserController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysBlacklistUserController.java new file mode 100644 index 0000000..bca5665 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysBlacklistUserController.java @@ -0,0 +1,63 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysBlacklistUserService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.result.CommonPage; +import com.ailanyin.common.utils.ExcelUtil; +import com.ailanyin.model.SysBlacklistUser; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/1 0001 下午 15:12 + */ +@RestController +@RequestMapping("/system/blacklist") +@Api(tags = "后台黑名单管理") +public class SysBlacklistUserController { + + @Autowired + private SysBlacklistUserService sysBlacklistUserService; + + @GetMapping("/list") + @PreAuthorize("hasAuthority('system:blacklist:query')") + @ApiOperation(value = "获取黑名单列表") + public CommonPage list(SysBlacklistUser blacklistUser, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysBlacklistUserService.selectBlackList(blacklistUser); + return CommonPage.restPage(list); + } + + + @GetMapping("/export") + @PreAuthorize("hasAuthority('system:blacklist:export')") + @ApiOperation(value = "导出黑名单") + public AjaxResult export(SysBlacklistUser blacklistUser) { + List list = sysBlacklistUserService.selectBlackList(blacklistUser); + try { + return AjaxResult.success(ExcelUtil.exportExcel(list, "黑名单表", "黑名单", SysBlacklistUser.class, "黑名单")); + } catch (IOException e) { + e.printStackTrace(); + return AjaxResult.error(e.getMessage()); + } + } + + @DeleteMapping("/remove") + @PreAuthorize("hasAuthority('system:blacklist:remove')") + @ApiOperation(value = "批量删除黑名单") + public AjaxResult removeBlacklistUser(@RequestBody List ids) { + sysBlacklistUserService.removeBlacklistUser(ids); + return AjaxResult.success(); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysConfigController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysConfigController.java new file mode 100644 index 0000000..6adf7bb --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysConfigController.java @@ -0,0 +1,81 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysConfigService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.result.CommonPage; +import com.ailanyin.model.SysConfig; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:43 + */ +@RestController +@RequestMapping("/system/config") +@Api(tags = "后台参数管理") +public class SysConfigController { + + @Autowired + private SysConfigService sysConfigService; + + @GetMapping("/list") + @PreAuthorize("hasAuthority('system:config:list')") + @ApiOperation(value = "获取参数配置列表") + public CommonPage list(SysConfig config, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysConfigService.selectConfigList(config); + return CommonPage.restPage(list); + } + + + @PreAuthorize("hasAuthority('system:config:query')") + @GetMapping(value = "/{configId}") + @ApiOperation(value = "根据参数编号获取详细信息") + public AjaxResult getInfo(@PathVariable Long configId) { + return AjaxResult.success(sysConfigService.selectConfigById(configId)); + } + + + @PreAuthorize("hasAuthority('system:config:add')") + @PostMapping + @ApiOperation(value = "新增参数配置") + public AjaxResult addSysConfig(@Validated @RequestBody SysConfig config) { + sysConfigService.addSysConfig(config); + return AjaxResult.success(); + } + + @PreAuthorize("hasAuthority('system:config:edit')") + @PutMapping + @ApiOperation(value = "修改参数配置") + public AjaxResult updateSysConfig(@Validated @RequestBody SysConfig config) { + sysConfigService.updateSysConfig(config); + return AjaxResult.success(); + } + + + @PreAuthorize("hasAuthority('system:config:remove')") + @DeleteMapping("/{configIds}") + @ApiOperation(value = "删除参数配置") + public AjaxResult removeSysConfig(@PathVariable Long[] configIds) { + sysConfigService.deleteConfigByIds(configIds); + return AjaxResult.success(); + } + + @GetMapping(value = "/configKey/{configKey}") + @ApiOperation(value = "根据参数键名查询参数值") + public AjaxResult getConfigKey(@PathVariable String configKey) { + return AjaxResult.success(sysConfigService.selectConfigByKey(configKey)); + } + +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysDeptController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysDeptController.java new file mode 100644 index 0000000..803291f --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysDeptController.java @@ -0,0 +1,102 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysDeptService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.model.SysDept; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Iterator; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:18 + */ +@RestController +@RequestMapping("/system/dept") +@Api(tags = "后台部门管理") +public class SysDeptController { + + @Autowired + private SysDeptService sysDeptService; + + @PostMapping + @ApiOperation(value = "添加部门") + @PreAuthorize("hasAuthority('system:dept:add')") + public AjaxResult addDept(@Validated @RequestBody SysDept dept) { + sysDeptService.addDept(dept); + return AjaxResult.success(); + } + + @PutMapping + @ApiOperation(value = "修改部门") + @PreAuthorize("hasAuthority('system:dept:edit')") + public AjaxResult updateDept(@Validated @RequestBody SysDept dept) { + sysDeptService.updateDept(dept); + return AjaxResult.success(); + } + + @DeleteMapping("/{deptId}") + @ApiOperation(value = "删除部门") + @PreAuthorize("hasAuthority('system:dept:remove')") + public AjaxResult removeDept(@PathVariable Long deptId) { + sysDeptService.removeDept(deptId); + return AjaxResult.success(); + } + + @GetMapping(value = "/roleDeptTreeSelect/{roleId}") + @ApiOperation(value = "角色部门列表树") + public AjaxResult roleDeptTreeSelect(@PathVariable("roleId") Long roleId) { + List deptList = sysDeptService.selectDeptList(new SysDept()); + AjaxResult result = AjaxResult.success(); + result.put("checkedKeys", sysDeptService.selectDeptListByRoleId(roleId)); + result.put("deptList", sysDeptService.buildDeptTreeSelect(deptList)); + return result; + } + + @GetMapping("/treeSelect") + @ApiOperation(value = "部门下拉列表树") + public AjaxResult treeSelect(SysDept dept) { + List deptList = sysDeptService.selectDeptList(dept); + return AjaxResult.success(sysDeptService.buildDeptTreeSelect(deptList)); + } + + @GetMapping(value = "/{deptId}") + @ApiOperation(value = "部门详细信息") + @PreAuthorize("hasAuthority('system:dept:query')") + public AjaxResult getInfo(@PathVariable Long deptId) { + sysDeptService.checkDeptDataScope(deptId); + return AjaxResult.success(sysDeptService.selectDeptById(deptId)); + } + + @GetMapping("/list/exclude/{deptId}") + @ApiOperation(value = "查询部门列表(排除节点)") + @PreAuthorize("hasAuthority('system:dept:list')") + public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) { + List deptList = sysDeptService.selectDeptList(new SysDept()); + Iterator it = deptList.iterator(); + while (it.hasNext()) { + SysDept d = (SysDept) it.next(); + if (d.getDeptId().intValue() == deptId + || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")) { + it.remove(); + } + } + return AjaxResult.success(deptList); + } + + @GetMapping("/list") + @ApiOperation(value = "部门列表") + @PreAuthorize("hasAuthority('system:dept:list')") + public AjaxResult list(SysDept dept) { + return AjaxResult.success(sysDeptService.selectDeptList(dept)); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysDictDataController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysDictDataController.java new file mode 100644 index 0000000..9190699 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysDictDataController.java @@ -0,0 +1,89 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysDictDataService; +import com.ailanyin.admin.service.SysDictTypeService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.result.CommonPage; +import com.ailanyin.common.utils.StringUtil; +import com.ailanyin.model.SysDictData; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 17:02 + */ +@RestController +@RequestMapping("/system/dict/data") +@Api(tags = "后台字典管理") +public class SysDictDataController { + + @Autowired + private SysDictDataService sysDictDataService; + @Autowired + private SysDictTypeService sysDictTypeService; + + @PreAuthorize("hasAuthority('system:dict:list')") + @GetMapping("/list") + @ApiOperation(value = "获取字典列表") + public CommonPage list(SysDictData dictData, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysDictDataService.selectDictDataList(dictData); + return CommonPage.restPage(list); + } + + @PreAuthorize("hasAuthority('system:dict:query')") + @GetMapping(value = "/{dictCode}") + @ApiOperation(value = "获取字典详情") + public AjaxResult getInfo(@PathVariable Long dictCode) { + return AjaxResult.success(sysDictDataService.selectDictDataById(dictCode)); + } + + @PreAuthorize("hasAuthority('system:dict:add')") + @PostMapping + @ApiOperation(value = "新增字典") + public AjaxResult addDictData(@Validated @RequestBody SysDictData dict) { + sysDictDataService.addDictData(dict); + return AjaxResult.success(); + } + + @GetMapping(value = "/type/{dictType}") + @ApiOperation(value = "根据字典类型查询字典数据信息") + public AjaxResult dictType(@PathVariable String dictType) { + List data = sysDictTypeService.selectDictDataByType(dictType); + if (StringUtil.isNull(data)) { + data = new ArrayList<>(); + } + return AjaxResult.success(data); + } + + + @PreAuthorize("hasAuthority('system:dict:edit')") + @PutMapping + @ApiOperation(value = "修改字典类型") + public AjaxResult updateDictData(@Validated @RequestBody SysDictData dict) + { + sysDictDataService.updateDictData(dict); + return AjaxResult.success(); + } + + @PreAuthorize("hasAuthority('system:dict:remove')") + @DeleteMapping("/{dictCodes}") + @ApiOperation(value = "批量删除字典类型") + public AjaxResult remove(@PathVariable Long[] dictCodes) + { + sysDictDataService.deleteDictDataByIds(dictCodes); + return AjaxResult.success(); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysDictTypeController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysDictTypeController.java new file mode 100644 index 0000000..908f258 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysDictTypeController.java @@ -0,0 +1,89 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysDictTypeService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.result.CommonPage; +import com.ailanyin.model.SysDictType; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/22 0022 上午 11:42 + */ +@RestController +@RequestMapping("/system/dict/type") +@Api(tags = "后台字典类型管理") +public class SysDictTypeController { + + @Autowired + private SysDictTypeService sysDictTypeService; + + @PreAuthorize("hasAuthority('system:dict:list')") + @GetMapping("/list") + @ApiOperation(value = "获取字典类型列表") + public CommonPage list(SysDictType dictType, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysDictTypeService.selectDictTypeList(dictType); + return CommonPage.restPage(list); + + } + + @PreAuthorize("hasAuthority('system:dict:query')") + @GetMapping(value = "/{dictId}") + @ApiOperation(value = "查询字典类型详细") + public AjaxResult getInfo(@PathVariable Long dictId) { + return AjaxResult.success(sysDictTypeService.selectDictTypeById(dictId)); + } + + @PreAuthorize("hasAuthority('system:dict:add')") + @PostMapping + @ApiOperation(value = "新增字典类型") + public AjaxResult addDictType(@Validated @RequestBody SysDictType dict) { + sysDictTypeService.addDictType(dict); + return AjaxResult.success(); + } + + + @PreAuthorize("hasAuthority('system:dict:edit')") + @PutMapping + @ApiOperation(value = "修改字典类型") + public AjaxResult updateDictType(@Validated @RequestBody SysDictType dict) { + sysDictTypeService.updateDictType(dict); + return AjaxResult.success(); + } + + @PreAuthorize("hasAuthority('system:dict:remove')") + @DeleteMapping("/{dictIds}") + @ApiOperation(value = "删除字典类型") + public AjaxResult remove(@PathVariable Long[] dictIds) { + sysDictTypeService.deleteDictTypeByIds(dictIds); + return AjaxResult.success(); + } + + @PreAuthorize("hasAuthority('system:dict:remove')") + @DeleteMapping("/refreshCache") + @ApiOperation(value = "刷新字典缓存") + public AjaxResult refreshCache() { + + sysDictTypeService.resetDictCache(); + return AjaxResult.success(); + } + + @GetMapping("/optionselect") + @ApiOperation(value = "获取字典选择框列表") + public AjaxResult optionSelect() { + List dictTypes = sysDictTypeService.selectDictTypeAll(); + return AjaxResult.success(dictTypes); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysLogController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysLogController.java new file mode 100644 index 0000000..e2ab80f --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysLogController.java @@ -0,0 +1,70 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysLogService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.result.CommonPage; +import com.ailanyin.common.utils.ExcelUtil; +import com.ailanyin.model.SysLog; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/28 0028 下午 14:45 + */ +@RestController +@RequestMapping("/system/log") +@Api(tags = "后台日志管理") +public class SysLogController { + + @Autowired + private SysLogService sysLogService; + + @GetMapping("/list") + @ApiOperation(value = "分页获取日志列表") + @PreAuthorize("hasAuthority('system:log:list')") + public CommonPage list(SysLog sysLog, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysLogService.list(sysLog); + return CommonPage.restPage(list); + } + + @DeleteMapping("/clean") + @ApiOperation(value = "清空日志") + @PreAuthorize("hasAuthority('system:log:remove')") + public AjaxResult cleanLog() { + sysLogService.cleanLog(); + return AjaxResult.success(); + } + + @DeleteMapping("/remove") + @ApiOperation(value = "批量删除日志") + @PreAuthorize("hasAuthority('system:log:remove')") + public AjaxResult removeLog(@RequestBody List logIds) { + sysLogService.removeLog(logIds); + return AjaxResult.success(); + } + + @GetMapping("/export") + @PreAuthorize("hasAuthority('system:log:export')") + @ApiOperation(value = "导出日志") + public AjaxResult export(SysLog sysLog) { + List list = sysLogService.list(sysLog); + try { + return AjaxResult.success(ExcelUtil.exportExcel(list, "系统日志表", "系统日志", SysLog.class, "系统日志")); + } catch (IOException e) { + e.printStackTrace(); + return AjaxResult.error(e.getMessage()); + } + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysLoginController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysLoginController.java new file mode 100644 index 0000000..c13d5ac --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysLoginController.java @@ -0,0 +1,106 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysLoginService; +import com.ailanyin.admin.service.SysMenuService; +import com.ailanyin.admin.service.SysPermissionService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.admin.vo.LoginBodyVo; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.model.SysMenu; +import com.ailanyin.model.SysUser; +import com.ailanyin.security.service.SecurityUserService; +import com.ailanyin.security.utils.JwtTokenUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.Set; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 15:54 + */ +@RestController +@Api(tags = "登录管理") +public class SysLoginController { + + @Autowired + private SysUserService sysUserService; + @Autowired + private SysLoginService sysLoginService; + @Autowired + private SysMenuService sysMenuService; + @Autowired + private SysPermissionService sysPermissionService; + @Autowired + private SecurityUserService securityUserService; + @Autowired + private JwtTokenUtil jwtTokenUtil; + + @Value("${jwt.tokenHeader}") + private String tokenHeader; + @Value("${jwt.tokenHead}") + private String tokenHead; + + @GetMapping("/getRouters") + @ApiOperation(value = "获取路由信息") + public AjaxResult getRouters() { + Long userId = sysUserService.getCurrentUser().getUserId(); + List menus = sysMenuService.selectMenuTreeByUserId(userId); + return AjaxResult.success(sysMenuService.buildMenus(menus)); + } + + @GetMapping("/getInfo") + @ApiOperation(value = "获取用户信息") + public AjaxResult getInfo() { + SysUser user = sysUserService.getCurrentUser(); + // 角色集合 + Set roles = sysPermissionService.getRolePermission(user); + // 权限集合 + Set permissions = sysPermissionService.getMenuPermission(user); + AjaxResult ajax = AjaxResult.success(); + ajax.put("user", user); + ajax.put("roles", roles); + ajax.put("permissions", permissions); + return ajax; + } + + @PostMapping("/login") + @ApiOperation(value = "用户登录") + public AjaxResult login(@RequestBody LoginBodyVo loginBody) { + return sysLoginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid()); + + } + + @GetMapping("/captchaImage") + @ApiOperation(value = "获取登录验证码") + public AjaxResult getCaptchaImage() { + return sysLoginService.getCaptchaImage(); + } + + @PostMapping("/register") + @ApiOperation(value = "用户注册") + public AjaxResult register(@RequestBody LoginBodyVo register) { + sysLoginService.register(register); + return AjaxResult.success(); + } + + @PostMapping("/myLogout") + @ApiOperation(value = "退出登录") + public void logout(HttpServletRequest request) { + String authHeader = request.getHeader(this.tokenHeader); + if (authHeader != null && authHeader.startsWith(this.tokenHead)) { + String authToken = authHeader.substring(this.tokenHead.length()); + String username = jwtTokenUtil.getUserNameFromToken(authToken); + securityUserService.delUserDetailsFromMap(username); + } + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysMenuController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysMenuController.java new file mode 100644 index 0000000..94208c7 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysMenuController.java @@ -0,0 +1,87 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysMenuService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.model.SysMenu; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 11:24 + */ +@RestController +@RequestMapping("/system/menu") +@Api(tags = "后台菜单管理") +public class SysMenuController { + + @Autowired + private SysMenuService sysMenuService; + @Autowired + private SysUserService sysUserService; + + @PostMapping + @ApiOperation(value = "添加菜单") + @PreAuthorize("hasAuthority('system:menu:add')") + public AjaxResult insertMenu(@Validated @RequestBody SysMenu menu) { + sysMenuService.insertMenu(menu); + return AjaxResult.success(); + } + + + @PutMapping + @ApiOperation(value = "修改菜单") + @PreAuthorize("hasAuthority('system:menu:edit')") + public AjaxResult updateMenu(@Validated @RequestBody SysMenu menu) { + sysMenuService.updateMenu(menu); + return AjaxResult.success(); + } + + @DeleteMapping("/{menuId}") + @ApiOperation(value = "删除菜单") + @PreAuthorize("hasAuthority('system:menu:remove')") + public AjaxResult removeMenu(@PathVariable("menuId") Long menuId) { + sysMenuService.removeMenuById(menuId); + return AjaxResult.success(); + } + + @ApiOperation(value = "加载对应角色菜单列表树") + @GetMapping(value = "/roleMenuTreeSelect/{roleId}") + public AjaxResult roleMenuTreeSelect(@PathVariable("roleId") Long roleId) { + List menus = sysMenuService.selectMenuList(sysUserService.getCurrentUser().getUserId()); + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", sysMenuService.selectMenuListByRoleId(roleId)); + ajax.put("menus", sysMenuService.buildMenuTreeSelect(menus)); + return ajax; + } + + @GetMapping("/treeSelect") + @ApiOperation(value = "查询菜单下拉树") + public AjaxResult treeSelect(SysMenu menu) { + List menus = sysMenuService.selectMenuList(menu, sysUserService.getCurrentUser().getUserId()); + return AjaxResult.success(sysMenuService.buildMenuTreeSelect(menus)); + } + + @GetMapping("/list") + @ApiOperation(value = "获取菜单列表") + @PreAuthorize("hasAuthority('system:menu:list')") + public AjaxResult list(SysMenu menu) { + List menus = sysMenuService.selectMenuList(menu, sysUserService.getCurrentUser().getUserId()); + return AjaxResult.success(menus); + } + + @GetMapping(value = "/{menuId}") + @PreAuthorize("hasAuthority('system:menu:query')") + @ApiOperation(value = "根据菜单编号获取详细信息") + public AjaxResult getInfo(@PathVariable Long menuId) { + return AjaxResult.success(sysMenuService.selectMenuById(menuId)); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysMonitorController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysMonitorController.java new file mode 100644 index 0000000..ce32f79 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysMonitorController.java @@ -0,0 +1,57 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.entity.server.Server; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.utils.StringUtil; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.*; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/29 0029 下午 13:52 + */ +@RestController +@RequestMapping("/monitor") +@Api(tags = "后台监控管理") +public class SysMonitorController { + + @Autowired + private RedisTemplate redisTemplate; + + @GetMapping("server") + public AjaxResult getServerInfo() throws Exception { + Server server = new Server(); + server.copyTo(); + return AjaxResult.success(server); + } + + @GetMapping("/cache") + public AjaxResult getRedisInfo() throws Exception { + Properties info = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.info()); + Properties commandStats = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.info("commandstats")); + Object dbSize = redisTemplate.execute((RedisCallback) connection -> connection.dbSize()); + + Map result = new HashMap<>(3); + result.put("info", info); + result.put("dbSize", dbSize); + + List> pieList = new ArrayList<>(); + commandStats.stringPropertyNames().forEach(key -> { + Map data = new HashMap<>(2); + String property = commandStats.getProperty(key); + data.put("name", StringUtil.removeStart(key, "cmdstat_")); + data.put("value", StringUtil.substringBetween(property, "calls=", ",usec")); + pieList.add(data); + }); + result.put("commandStats", pieList); + return AjaxResult.success(result); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysPostController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysPostController.java new file mode 100644 index 0000000..38bf270 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysPostController.java @@ -0,0 +1,79 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysPostService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.result.CommonPage; +import com.ailanyin.model.SysPost; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 后台岗位管理 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 14:41 + */ +@RestController +@RequestMapping("/system/post") +@Api(tags = "后台岗位管理") +public class SysPostController { + + @Autowired + private SysPostService sysPostService; + + @PostMapping + @ApiOperation(value = "添加岗位") + @PreAuthorize("hasAuthority('system:post:add')") + public AjaxResult insertPost(@Validated @RequestBody SysPost post) { + sysPostService.insertPost(post); + return AjaxResult.success(); + } + + @PutMapping + @ApiOperation(value = "修改岗位") + @PreAuthorize("hasAuthority('system:post:edit')") + public AjaxResult updatePost(@Validated @RequestBody SysPost post) { + sysPostService.updatePost(post); + return AjaxResult.success(); + } + + @DeleteMapping("/{postIds}") + @ApiOperation(value = "删除岗位") + @PreAuthorize("hasAuthority('system:post:remove')") + public AjaxResult remove(@PathVariable Long[] postIds) { + sysPostService.deletePostByIds(postIds); + return AjaxResult.success(); + } + + @GetMapping("/optionselect") + @ApiOperation(value = "获取岗位选择框列表") + public AjaxResult optionSelect() { + return AjaxResult.success(sysPostService.selectPostAll()); + } + + @GetMapping(value = "/{postId}") + @ApiOperation(value = "获取岗位具体信息") + @PreAuthorize("hasAuthority('system:post:query')") + public AjaxResult getInfo(@PathVariable Long postId) { + return AjaxResult.success(sysPostService.selectPostById(postId)); + } + + @GetMapping("/list") + @ApiOperation(value = "获取岗位分页列表") + @PreAuthorize("hasAuthority('system:post:list')") + public CommonPage list(SysPost post, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysPostService.selectPostList(post); + return CommonPage.restPage(list); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysRoleController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysRoleController.java new file mode 100644 index 0000000..13bdd75 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysRoleController.java @@ -0,0 +1,153 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysRoleService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.result.CommonPage; +import com.ailanyin.model.SysRole; +import com.ailanyin.model.SysUser; +import com.ailanyin.model.SysUserRole; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 13:01 + */ +@RestController +@RequestMapping("/system/role") +@Api(tags = "后台角色管理") +public class SysRoleController { + + @Autowired + private SysRoleService sysRoleService; + @Autowired + private SysUserService sysUserService; + + @GetMapping("/list") + @ApiOperation(value = "获取角色列表") + @PreAuthorize("hasAuthority('system:role:list')") + public CommonPage list(SysRole role, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysRoleService.selectRoleList(role); + return CommonPage.restPage(list); + } + + @PostMapping + @ApiOperation(value = "新增角色") + @PreAuthorize("hasAuthority('system:role:add')") + public AjaxResult insertRole(@Validated @RequestBody SysRole role) { + sysRoleService.insertRole(role); + return AjaxResult.success(); + } + + @PutMapping + @ApiOperation(value = "修改角色") + @PreAuthorize("hasAuthority('system:role:edit')") + public AjaxResult updateRole(@Validated @RequestBody SysRole role) { + sysRoleService.updateRole(role); + return AjaxResult.success(); + } + + @GetMapping(value = "/{roleId}") + @ApiOperation(value = "获取角色信息") + @PreAuthorize("hasAuthority('system:role:query')") + public AjaxResult getInfo(@PathVariable Long roleId) { + return AjaxResult.success(sysRoleService.selectRoleById(roleId)); + } + + @GetMapping(value = "/refreshRole") + @ApiOperation(value = "重置超级管理员权限") + @PreAuthorize("hasAuthority('system:role:refresh')") + public AjaxResult refreshRole() { + sysRoleService.refreshRole(); + return AjaxResult.success(); + } + + @DeleteMapping("/{roleIds}") + @ApiOperation(value = "批量删除角色") + @PreAuthorize("hasAuthority('system:role:remove')") + public AjaxResult removeRole(@PathVariable Long[] roleIds) { + sysRoleService.deleteRoleByIds(roleIds); + return AjaxResult.success(); + } + + @PutMapping("/dataScope") + @ApiOperation(value = "修改保存数据权限") + @PreAuthorize("hasAuthority('system:role:edit')") + public AjaxResult dataScope(@RequestBody SysRole role) { + sysRoleService.authDataScope(role); + return AjaxResult.success(); + } + + @PutMapping("/changeStatus") + @ApiOperation(value = "状态修改") + @PreAuthorize("hasAuthority('system:role:edit')") + public AjaxResult changeStatus(@RequestBody SysRole role) { + sysRoleService.updateRoleStatus(role); + return AjaxResult.success(); + } + + @GetMapping("/optionselect") + @PreAuthorize("hasAuthority('system:role:query')") + @ApiOperation(value = "获取角色选择框列表") + public AjaxResult optionSelect() { + return AjaxResult.success(sysRoleService.selectRoleAll()); + } + + @PutMapping("/authUser/selectAll") + @ApiOperation(value = "批量选择用户授权") + @PreAuthorize("hasAuthority('system:role:edit')") + public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds) { + sysRoleService.insertAuthUsers(roleId, userIds); + return AjaxResult.success(); + } + + @PutMapping("/authUser/cancelAll") + @ApiOperation(value = "批量取消授权用户") + @PreAuthorize("hasAuthority('system:role:edit')") + public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds) { + sysRoleService.deleteAuthUsers(roleId, userIds); + return AjaxResult.success(); + } + + @PutMapping("/authUser/cancel") + @ApiOperation(value = "取消授权用户") + @PreAuthorize("hasAuthority('system:role:edit')") + public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole) { + sysRoleService.deleteAuthUser(userRole); + return AjaxResult.success(); + } + + @GetMapping("/authUser/allocatedList") + @ApiOperation(value = "查询已分配用户角色列表") + @PreAuthorize("hasAuthority('system:role:list')") + public CommonPage allocatedList(SysUser user, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysUserService.selectAllocatedList(user); + return CommonPage.restPage(list); + } + + @GetMapping("/authUser/unallocatedList") + @ApiOperation(value = "查询未分配用户角色列表") + @PreAuthorize("hasAuthority('system:role:list')") + public CommonPage unallocatedList(SysUser user, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysUserService.selectUnallocatedList(user); + return CommonPage.restPage(list); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysUserController.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysUserController.java new file mode 100644 index 0000000..1577c13 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/controller/SysUserController.java @@ -0,0 +1,219 @@ +package com.ailanyin.admin.controller; + +import com.ailanyin.admin.service.SysPostService; +import com.ailanyin.admin.service.SysRoleService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.result.CommonPage; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.common.utils.ExcelUtil; +import com.ailanyin.model.SysRole; +import com.ailanyin.model.SysUser; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 15:11 + */ +@RestController +@RequestMapping("/system/user") +@Api(tags = "后台用户管理") +public class SysUserController { + + @Autowired + private SysUserService sysUserService; + @Autowired + private SysRoleService sysRoleService; + @Autowired + private SysPostService sysPostService; + + + @PostMapping + @ApiOperation(value = "新增用户") + @PreAuthorize("hasAuthority('system:user:add')") + public AjaxResult insertUser(@Validated @RequestBody SysUser user) { + sysUserService.insertUser(user); + return AjaxResult.success(); + } + + @PutMapping + @ApiOperation(value = "修改用户") + @PreAuthorize("hasAuthority('system:user:edit')") + public AjaxResult updateUser(@Validated @RequestBody SysUser user) { + sysUserService.updateUser(user); + return AjaxResult.success(); + } + + @DeleteMapping("/{userIds}") + @ApiOperation(value = "批量删除用户") + @PreAuthorize("hasAuthority('system:user:remove')") + public AjaxResult removeUser(@PathVariable Long[] userIds) { + sysUserService.deleteUserByIds(userIds); + return AjaxResult.success(); + } + + @PutMapping("/resetPwd") + @ApiOperation(value = "重置密码") + @PreAuthorize("hasAuthority('system:user:resetPwd')") + public AjaxResult resetPwd(@RequestBody SysUser user) { + sysUserService.resetPwd(user); + return AjaxResult.success(); + } + + @PutMapping("/changeStatus") + @ApiOperation(value = "修改状态") + @PreAuthorize("hasAuthority('system:user:edit')") + public AjaxResult changeStatus(@RequestBody SysUser user) { + sysUserService.updateUserStatus(user); + return AjaxResult.success(); + } + + @GetMapping("/authRole/{userId}") + @ApiOperation(value = "根据用户编号获取授权角色") + @PreAuthorize("hasAuthority('system:user:query')") + public AjaxResult authRole(@PathVariable("userId") Long userId) { + AjaxResult ajax = AjaxResult.success(); + SysUser user = sysUserService.selectUserById(userId); + List roles = sysRoleService.selectRolesByUserId(userId); + ajax.put("user", user); + ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + return ajax; + } + + @PutMapping("/authRole") + @ApiOperation(value = "用户授权角色") + @PreAuthorize("hasAuthority('system:user:edit')") + public AjaxResult insertAuthRole(Long userId, Long[] roleIds) { + sysUserService.insertUserAuth(userId, roleIds); + return AjaxResult.success(); + } + + @GetMapping(value = {"/", "/{userId}"}) + @ApiOperation(value = "获取用户详情") + @PreAuthorize("hasAuthority('system:user:query')") + public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) { + sysUserService.checkUserDataScope(userId); + AjaxResult result = AjaxResult.success(); + List roles = sysRoleService.selectRoleAll(); + result.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + result.put("posts", sysPostService.selectPostAll()); + if (EmptyUtil.isNotEmpty(userId)) { + result.put(AjaxResult.DATA_TAG, sysUserService.selectUserById(userId)); + result.put("postIds", sysPostService.selectPostListByUserId(userId)); + result.put("roleIds", sysRoleService.selectRoleListByUserId(userId)); + } + return result; + } + + @GetMapping("/list") + @ApiOperation(value = "获取用户列表") + @PreAuthorize("hasAuthority('system:user:list')") + public CommonPage list(SysUser user, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysUserService.selectUserList(user); + return CommonPage.restPage(list); + } + + @GetMapping("/listDeleteUser") + @ApiOperation(value = "获取已删除用户列表") + @PreAuthorize("hasAuthority('system:user:recovery')") + public CommonPage listDeleteUser(SysUser user, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + PageHelper.startPage(pageNum, pageSize); + List list = sysUserService.selectDeleteUserList(user); + return CommonPage.restPage(list); + } + + @PutMapping("/recovery") + @ApiOperation(value = "恢复已删除用户") + @PreAuthorize("hasAuthority('system:user:recovery')") + public AjaxResult recoveryDeleteUser(@RequestBody List ids) { + sysUserService.recoveryDeleteUser(ids); + return AjaxResult.success(); + } + + @DeleteMapping("/realDeleteUser") + @ApiOperation(value = "彻底删除用户") + @PreAuthorize("hasAuthority('system:user:recovery')") + public AjaxResult realDeleteUser(@RequestBody List ids) { + sysUserService.realDeleteUser(ids); + return AjaxResult.success(); + } + + @GetMapping("/importTemplate") + @ApiOperation(value = "导出模板") + @PreAuthorize("hasAuthority('system:user:import')") + public AjaxResult importTemplate() throws Exception { + return AjaxResult.success(ExcelUtil.exportExcel(new ArrayList<>(), "员工信息表", "员工信息", SysUser.class, "员工信息")); + } + + + @GetMapping("/export") + @ApiOperation(value = "导出用户列表") + @PreAuthorize("hasAuthority('system:user:export')") + public AjaxResult export(SysUser user) { + List list = sysUserService.selectUserList(user); + try { + return AjaxResult.success(ExcelUtil.exportExcel(list, "员工信息表", "员工信息", SysUser.class, "员工信息")); + } catch (IOException e) { + e.printStackTrace(); + return AjaxResult.error(e.getMessage()); + } + } + + + @PostMapping("/importData") + @ApiOperation(value = "导入用户列表") + @PreAuthorize("hasAuthority('system:user:import')") + public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception { + List list = ExcelUtil.importExcel(file, SysUser.class); + sysUserService.importData(list, updateSupport); + return AjaxResult.success(); + } + + @GetMapping("/profile") + @ApiOperation(value = "获取个人信息") + public AjaxResult profile() { + SysUser user = sysUserService.getCurrentUser(); + AjaxResult ajax = AjaxResult.success(user); + ajax.put("roleGroup", sysUserService.selectUserRoleGroup(user.getUserName())); + ajax.put("postGroup", sysUserService.selectUserPostGroup(user.getUserName())); + return ajax; + } + + @PutMapping("/profile") + @ApiOperation(value = "修改个人信息") + public AjaxResult updateProfile(@RequestBody SysUser user) { + sysUserService.updateProfile(user); + return AjaxResult.success(); + } + + @PutMapping("/profile/updatePwd") + @ApiOperation(value = "个人信息->重置密码") + public AjaxResult updatePwd(String oldPassword, String newPassword) { + sysUserService.updatePwd(oldPassword, newPassword); + return AjaxResult.success(); + } + + @PostMapping("/profile/avatar") + public AjaxResult updateAvatar(@RequestParam("avatar") MultipartFile file) { + sysUserService.updateAvatar(file); + return AjaxResult.success(); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/Test.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/Test.java new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/Test.java @@ -0,0 +1 @@ + diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Cpu.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Cpu.java new file mode 100644 index 0000000..d1f16dd --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Cpu.java @@ -0,0 +1,102 @@ +package com.ailanyin.admin.entity.server; + + +import com.ailanyin.common.utils.BigDecimalUtil; + +/** + * CPU相关信息 + * + * @author ruoyi + */ +public class Cpu +{ + /** + * 核心数 + */ + private int cpuNum; + + /** + * CPU总的使用率 + */ + private double total; + + /** + * CPU系统使用率 + */ + private double sys; + + /** + * CPU用户使用率 + */ + private double used; + + /** + * CPU当前等待率 + */ + private double wait; + + /** + * CPU当前空闲率 + */ + private double free; + + public int getCpuNum() + { + return cpuNum; + } + + public void setCpuNum(int cpuNum) + { + this.cpuNum = cpuNum; + } + + public double getTotal() + { + return BigDecimalUtil.round(BigDecimalUtil.mul(total, 100), 2); + } + + public void setTotal(double total) + { + this.total = total; + } + + public double getSys() + { + return BigDecimalUtil.round(BigDecimalUtil.mul(sys / total, 100), 2); + } + + public void setSys(double sys) + { + this.sys = sys; + } + + public double getUsed() + { + return BigDecimalUtil.round(BigDecimalUtil.mul(used / total, 100), 2); + } + + public void setUsed(double used) + { + this.used = used; + } + + public double getWait() + { + return BigDecimalUtil.round(BigDecimalUtil.mul(wait / total, 100), 2); + } + + public void setWait(double wait) + { + this.wait = wait; + } + + public double getFree() + { + return BigDecimalUtil.round(BigDecimalUtil.mul(free / total, 100), 2); + } + + public void setFree(double free) + { + this.free = free; + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Jvm.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Jvm.java new file mode 100644 index 0000000..7e8fe45 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Jvm.java @@ -0,0 +1,110 @@ +package com.ailanyin.admin.entity.server; + + +import com.ailanyin.common.utils.BigDecimalUtil; +import com.ailanyin.common.utils.DateUtil; + +import java.lang.management.ManagementFactory; + +/** + * JVM相关信息 + * + * @author ruoyi + */ +public class Jvm { + /** + * 当前JVM占用的内存总数(M) + */ + private double total; + + /** + * JVM最大可用内存总数(M) + */ + private double max; + + /** + * JVM空闲内存(M) + */ + private double free; + + /** + * JDK版本 + */ + private String version; + + /** + * JDK路径 + */ + private String home; + + public double getTotal() { + return BigDecimalUtil.div(total, (1024 * 1024), 2); + } + + public void setTotal(double total) { + this.total = total; + } + + public double getMax() { + return BigDecimalUtil.div(max, (1024 * 1024), 2); + } + + public void setMax(double max) { + this.max = max; + } + + public double getFree() { + return BigDecimalUtil.div(free, (1024 * 1024), 2); + } + + public void setFree(double free) { + this.free = free; + } + + public double getUsed() { + return BigDecimalUtil.div(total - free, (1024 * 1024), 2); + } + + public double getUsage() { + return BigDecimalUtil.mul(BigDecimalUtil.div(total - free, total, 4), 100); + } + + /** + * 获取JDK名称 + */ + public String getName() { + return ManagementFactory.getRuntimeMXBean().getVmName(); + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getHome() { + return home; + } + + public void setHome(String home) { + this.home = home; + } + + /** + * JDK启动时间 + */ + public String getStartTime() { + return DateUtil.parseDateToStr(DateUtil.YYYY_MM_DD_HH_MM_SS, DateUtil.getServerStartDate()); + } + + /** + * JDK运行时间 + */ + public String getRunTime() { + return DateUtil.getDatePoor(DateUtil.getNowDate(), DateUtil.getServerStartDate()); + } + + +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Mem.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Mem.java new file mode 100644 index 0000000..708bef8 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Mem.java @@ -0,0 +1,62 @@ +package com.ailanyin.admin.entity.server; + + +import com.ailanyin.common.utils.BigDecimalUtil; + +/** + * 內存相关信息 + * + * @author ruoyi + */ +public class Mem +{ + /** + * 内存总量 + */ + private double total; + + /** + * 已用内存 + */ + private double used; + + /** + * 剩余内存 + */ + private double free; + + public double getTotal() + { + return BigDecimalUtil.div(total, (1024 * 1024 * 1024), 2); + } + + public void setTotal(long total) + { + this.total = total; + } + + public double getUsed() + { + return BigDecimalUtil.div(used, (1024 * 1024 * 1024), 2); + } + + public void setUsed(long used) + { + this.used = used; + } + + public double getFree() + { + return BigDecimalUtil.div(free, (1024 * 1024 * 1024), 2); + } + + public void setFree(long free) + { + this.free = free; + } + + public double getUsage() + { + return BigDecimalUtil.mul(BigDecimalUtil.div(used, total, 4), 100); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Server.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Server.java new file mode 100644 index 0000000..34a4f6f --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Server.java @@ -0,0 +1,205 @@ +package com.ailanyin.admin.entity.server; + +import com.ailanyin.common.utils.BigDecimalUtil; +import com.ailanyin.common.utils.IpUtil; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.CentralProcessor.TickType; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.Util; + +import java.net.UnknownHostException; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +/** + * 服务器相关信息 + * + * @author ruoyi + */ +public class Server { + private static final int OSHI_WAIT_SECOND = 1000; + + /** + * CPU相关信息 + */ + private Cpu cpu = new Cpu(); + + /** + * 內存相关信息 + */ + private Mem mem = new Mem(); + + /** + * JVM相关信息 + */ + private Jvm jvm = new Jvm(); + + /** + * 服务器相关信息 + */ + private Sys sys = new Sys(); + + /** + * 磁盘相关信息 + */ + private List sysFiles = new LinkedList(); + + public Cpu getCpu() { + return cpu; + } + + public void setCpu(Cpu cpu) { + this.cpu = cpu; + } + + public Mem getMem() { + return mem; + } + + public void setMem(Mem mem) { + this.mem = mem; + } + + public Jvm getJvm() { + return jvm; + } + + public void setJvm(Jvm jvm) { + this.jvm = jvm; + } + + public Sys getSys() { + return sys; + } + + public void setSys(Sys sys) { + this.sys = sys; + } + + public List getSysFiles() { + return sysFiles; + } + + public void setSysFiles(List sysFiles) { + this.sysFiles = sysFiles; + } + + public void copyTo() throws Exception { + SystemInfo si = new SystemInfo(); + HardwareAbstractionLayer hal = si.getHardware(); + setSysInfo(); + setJvmInfo(); + setCpuInfo(hal.getProcessor()); + setMemInfo(hal.getMemory()); + setSysFiles(si.getOperatingSystem()); + } + + /** + * 设置CPU信息 + */ + private void setCpuInfo(CentralProcessor processor) { + // CPU信息 + long[] prevTicks = processor.getSystemCpuLoadTicks(); + Util.sleep(OSHI_WAIT_SECOND); + long[] ticks = processor.getSystemCpuLoadTicks(); + long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()]; + long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()]; + long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()]; + long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()]; + long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; + long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; + long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; + long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; + long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; + cpu.setCpuNum(processor.getLogicalProcessorCount()); + cpu.setTotal(totalCpu); + cpu.setSys(cSys); + cpu.setUsed(user); + cpu.setWait(iowait); + cpu.setFree(idle); + } + + /** + * 设置内存信息 + */ + private void setMemInfo(GlobalMemory memory) { + mem.setTotal(memory.getTotal()); + mem.setUsed(memory.getTotal() - memory.getAvailable()); + mem.setFree(memory.getAvailable()); + } + + /** + * 设置服务器信息 + */ + private void setSysInfo() { + Properties props = System.getProperties(); + sys.setComputerName(IpUtil.getHostName()); + sys.setComputerIp(IpUtil.getHostIp()); + sys.setOsName(props.getProperty("os.name")); + sys.setOsArch(props.getProperty("os.arch")); + sys.setUserDir(props.getProperty("user.dir")); + } + + /** + * 设置Java虚拟机 + */ + private void setJvmInfo() throws UnknownHostException { + Properties props = System.getProperties(); + jvm.setTotal(Runtime.getRuntime().totalMemory()); + jvm.setMax(Runtime.getRuntime().maxMemory()); + jvm.setFree(Runtime.getRuntime().freeMemory()); + jvm.setVersion(props.getProperty("java.version")); + jvm.setHome(props.getProperty("java.home")); + } + + /** + * 设置磁盘信息 + */ + private void setSysFiles(OperatingSystem os) { + FileSystem fileSystem = os.getFileSystem(); + List fsArray = fileSystem.getFileStores(); + for (OSFileStore fs : fsArray) { + long free = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + long used = total - free; + SysFile sysFile = new SysFile(); + sysFile.setDirName(fs.getMount()); + sysFile.setSysTypeName(fs.getType()); + sysFile.setTypeName(fs.getName()); + sysFile.setTotal(convertFileSize(total)); + sysFile.setFree(convertFileSize(free)); + sysFile.setUsed(convertFileSize(used)); + sysFile.setUsage(BigDecimalUtil.mul(BigDecimalUtil.div(used, total, 4), 100)); + sysFiles.add(sysFile); + } + } + + /** + * 字节转换 + * + * @param size 字节大小 + * @return 转换后值 + */ + private String convertFileSize(long size) { + long kb = 1024; + long mb = kb * 1024; + long gb = mb * 1024; + if (size >= gb) { + return String.format("%.1f GB", (float) size / gb); + } else if (size >= mb) { + float f = (float) size / mb; + return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); + } else if (size >= kb) { + float f = (float) size / kb; + return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); + } else { + return String.format("%d B", size); + } + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Sys.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Sys.java new file mode 100644 index 0000000..e7bea93 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/Sys.java @@ -0,0 +1,84 @@ +package com.ailanyin.admin.entity.server; + +/** + * 系统相关信息 + * + * @author ruoyi + */ +public class Sys +{ + /** + * 服务器名称 + */ + private String computerName; + + /** + * 服务器Ip + */ + private String computerIp; + + /** + * 项目路径 + */ + private String userDir; + + /** + * 操作系统 + */ + private String osName; + + /** + * 系统架构 + */ + private String osArch; + + public String getComputerName() + { + return computerName; + } + + public void setComputerName(String computerName) + { + this.computerName = computerName; + } + + public String getComputerIp() + { + return computerIp; + } + + public void setComputerIp(String computerIp) + { + this.computerIp = computerIp; + } + + public String getUserDir() + { + return userDir; + } + + public void setUserDir(String userDir) + { + this.userDir = userDir; + } + + public String getOsName() + { + return osName; + } + + public void setOsName(String osName) + { + this.osName = osName; + } + + public String getOsArch() + { + return osArch; + } + + public void setOsArch(String osArch) + { + this.osArch = osArch; + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/SysFile.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/SysFile.java new file mode 100644 index 0000000..4518008 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/entity/server/SysFile.java @@ -0,0 +1,114 @@ +package com.ailanyin.admin.entity.server; + +/** + * 系统文件相关信息 + * + * @author ruoyi + */ +public class SysFile +{ + /** + * 盘符路径 + */ + private String dirName; + + /** + * 盘符类型 + */ + private String sysTypeName; + + /** + * 文件类型 + */ + private String typeName; + + /** + * 总大小 + */ + private String total; + + /** + * 剩余大小 + */ + private String free; + + /** + * 已经使用量 + */ + private String used; + + /** + * 资源的使用率 + */ + private double usage; + + public String getDirName() + { + return dirName; + } + + public void setDirName(String dirName) + { + this.dirName = dirName; + } + + public String getSysTypeName() + { + return sysTypeName; + } + + public void setSysTypeName(String sysTypeName) + { + this.sysTypeName = sysTypeName; + } + + public String getTypeName() + { + return typeName; + } + + public void setTypeName(String typeName) + { + this.typeName = typeName; + } + + public String getTotal() + { + return total; + } + + public void setTotal(String total) + { + this.total = total; + } + + public String getFree() + { + return free; + } + + public void setFree(String free) + { + this.free = free; + } + + public String getUsed() + { + return used; + } + + public void setUsed(String used) + { + this.used = used; + } + + public double getUsage() + { + return usage; + } + + public void setUsage(double usage) + { + this.usage = usage; + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/CommonFileService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/CommonFileService.java new file mode 100644 index 0000000..c3ed15d --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/CommonFileService.java @@ -0,0 +1,19 @@ +package com.ailanyin.admin.service; + +import org.springframework.web.multipart.MultipartFile; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/4 0004 下午 16:04 + */ +public interface CommonFileService { + + /** + * 文件上传 + * + * @param file file + * @return url + */ + String fileUpload(MultipartFile file); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/ExceptionLogService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/ExceptionLogService.java new file mode 100644 index 0000000..4dbede2 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/ExceptionLogService.java @@ -0,0 +1,42 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.ExceptionLog; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/2 0002 下午 17:23 + */ +public interface ExceptionLogService { + + /** + * 查询异常信息列表 + * + * @param exceptionLog exceptionLog + * @return list + */ + List selectExceptionLog(ExceptionLog exceptionLog); + + /** + * 新增异常 + * + * @param exceptionLog exceptionLog + */ + void insertExceptionLog(ExceptionLog exceptionLog); + + /** + * 新增异常 + * + * @param exception exception + */ + void insertExceptionLog(Exception exception); + + /** + * 批量删除异常日志 + * + * @param logIds ids + */ + void removeExceptionLog(List logIds); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysBlacklistUserService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysBlacklistUserService.java new file mode 100644 index 0000000..b27a0da --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysBlacklistUserService.java @@ -0,0 +1,35 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysBlacklistUser; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/1 0001 下午 15:14 + */ +public interface SysBlacklistUserService { + + /** + * 获取黑名单列表 + * + * @param blacklistUser blacklistUser + * @return list + */ + List selectBlackList(SysBlacklistUser blacklistUser); + + /** + * 批量删除日志 + * + * @param ids ids + */ + void removeBlacklistUser(List ids); + + /** + * 新增黑名单 + * + * @param blacklistUser blacklistUser + */ + void insertBlacklistUser(SysBlacklistUser blacklistUser); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysConfigService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysConfigService.java new file mode 100644 index 0000000..0329292 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysConfigService.java @@ -0,0 +1,71 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysConfig; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:44 + */ +public interface SysConfigService { + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + List selectConfigList(SysConfig config); + + /** + * 加载参数缓存数据 + */ + void loadingConfigCache(); + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数键名 + * @return 参数键值 + */ + String selectConfigByKey(String configKey); + + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return SysConfig 参数配置信息 + */ + SysConfig selectConfigById(Long configId); + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + */ + void addSysConfig(SysConfig config); + + /** + * 校验参数键名是否唯一 + * + * @param config 参数信息 + * @return 结果 + */ + boolean checkConfigKeyNotUnique(SysConfig config); + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + */ + void updateSysConfig(SysConfig config); + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + */ + void deleteConfigByIds(Long[] configIds); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysDeptService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysDeptService.java new file mode 100644 index 0000000..869df1d --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysDeptService.java @@ -0,0 +1,106 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysDept; +import com.ailanyin.model.TreeSelect; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:24 + */ +public interface SysDeptService { + + /** + * 添加部门 + * + * @param dept dept + */ + void addDept(SysDept dept); + + /** + * 修改部门 + * + * @param dept dept + */ + void updateDept(SysDept dept); + + /** + * 删除部门 + * + * @param deptId deptId + */ + void removeDept(Long deptId); + + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + List selectDeptList(SysDept dept); + + /** + * 构建前端所需要下拉树结构 + * + * @param deptList 部门列表 + * @return 下拉树结构列表 + */ + List buildDeptTreeSelect(List deptList); + + /** + * 构建前端所需要树结构 + * + * @param deptList 部门列表 + * @return 树结构列表 + */ + List buildDeptTree(List deptList); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + List selectDeptListByRoleId(Long roleId); + + /** + * 是否存在部门子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + boolean hasChildByDeptId(Long deptId); + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + boolean checkDeptExistUser(Long deptId); + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + boolean checkDeptNameNotUnique(SysDept dept); + + /** + * 校验部门是否有数据权限 + * + * @param deptId 部门id + */ + void checkDeptDataScope(Long deptId); + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + SysDept selectDeptById(Long deptId); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysDictDataService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysDictDataService.java new file mode 100644 index 0000000..de0318d --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysDictDataService.java @@ -0,0 +1,50 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysDictData; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 17:03 + */ +public interface SysDictDataService { + + /** + * 获取字典列表 + * + * @param dictData dictData + * @return List + */ + List selectDictDataList(SysDictData dictData); + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode id + * @return 详情 + */ + SysDictData selectDictDataById(Long dictCode); + + /** + * 新增字典 + * + * @param dict dict + */ + void addDictData(SysDictData dict); + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + */ + void deleteDictDataByIds(Long[] dictCodes); + + /** + * 修改保存字典数据信息 + * + * @param dictData 字典数据信息 + */ + void updateDictData(SysDictData dictData); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysDictTypeService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysDictTypeService.java new file mode 100644 index 0000000..0ba1b42 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysDictTypeService.java @@ -0,0 +1,85 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysDictData; +import com.ailanyin.model.SysDictType; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 17:05 + */ +public interface SysDictTypeService { + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + public List selectDictDataByType(String dictType); + + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + List selectDictTypeList(SysDictType dictType); + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + SysDictType selectDictTypeById(Long dictId); + + /** + * 新增保存字典类型信息 + * + * @param dictType 字典类型信息 + */ + void addDictType(SysDictType dictType); + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + boolean checkDictTypeNotUnique(SysDictType dictType); + + /** + * 修改保存字典类型信息 + * + * @param dictType 字典类型信息 + */ + void updateDictType(SysDictType dictType); + + /** + * 批量删除字典信息 + * + * @param dictIds 需要删除的字典ID + */ + void deleteDictTypeByIds(Long[] dictIds); + + /** + * 重置字典缓存数据 + */ + void resetDictCache(); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + List selectDictTypeAll(); + + /** + * 加载字典缓存数据 + */ + void loadingDictCache(); + +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysLogService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysLogService.java new file mode 100644 index 0000000..b916dc2 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysLogService.java @@ -0,0 +1,40 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysLog; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/28 0028 下午 14:46 + */ +public interface SysLogService { + + /** + * 新增日志 + * + * @param sysLog log + */ + void insertLog(SysLog sysLog); + + /** + * 分页获取日志列表 + * + * @param sysLog sysLog + * @return list + */ + List list(SysLog sysLog); + + /** + * 清空日志 + */ + void cleanLog(); + + /** + * 批量删除日志 + * + * @param logIds ids + */ + void removeLog(List logIds); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysLoginService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysLoginService.java new file mode 100644 index 0000000..0dc6860 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysLoginService.java @@ -0,0 +1,37 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.admin.vo.LoginBodyVo; +import com.ailanyin.common.result.AjaxResult; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 15:55 + */ +public interface SysLoginService { + + /** + * 登录接口 + * + * @param username 账号 + * @param password 密码 + * @param code 验证码 + * @param uuid 验证码的随机码 + * @return token + */ + AjaxResult login(String username, String password, String code, String uuid); + + /** + * 生成图片验证码 + * + * @return uuid + base64 + */ + AjaxResult getCaptchaImage(); + + /** + * 用户注册 + * + * @param register register + */ + void register(LoginBodyVo register); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysMenuService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysMenuService.java new file mode 100644 index 0000000..8f90f88 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysMenuService.java @@ -0,0 +1,134 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.admin.vo.RouterVo; +import com.ailanyin.model.SysMenu; +import com.ailanyin.model.TreeSelect; + +import java.util.List; +import java.util.Set; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 11:26 + */ +public interface SysMenuService { + + /** + * 新增菜单 + * + * @param menu menu + */ + void insertMenu(SysMenu menu); + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + boolean checkMenuNameNotUnique(SysMenu menu); + + /** + * 更新菜单 + * + * @param menu menu + */ + void updateMenu(SysMenu menu); + + /** + * 删除菜单 + * + * @param menuId menuId + */ + void removeMenuById(Long menuId); + + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + List selectMenuList(Long userId); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu 菜单信息 + * @param userId 用户ID + * @return 菜单列表 + */ + List selectMenuList(SysMenu menu, Long userId); + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + SysMenu selectMenuById(Long menuId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + List selectMenuListByRoleId(Long roleId); + + /** + * 构建前端所需要树结构 + * + * @param menus 菜单列表 + * @return 树结构列表 + */ + List buildMenuTree(List menus); + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + List buildMenuTreeSelect(List menus); + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + boolean hasChildByMenuId(Long menuId); + + /** + * 查询菜单是否存在角色 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + boolean checkMenuExistRole(Long menuId); + + /** + * 根据用户ID查询菜单树信息 + * + * @param userId 用户ID + * @return 菜单列表 + */ + List selectMenuTreeByUserId(Long userId); + + /** + * 构建前端路由所需要的菜单 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + List buildMenus(List menus); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + Set selectMenuPermsByUserId(Long userId); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysPermissionService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysPermissionService.java new file mode 100644 index 0000000..1668374 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysPermissionService.java @@ -0,0 +1,29 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysUser; + +import java.util.Set; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 15:56 + */ +public interface SysPermissionService { + + /** + * 获取角色权限 + * + * @param user user + * @return 字符串集合 + */ + Set getRolePermission(SysUser user); + + /** + * 获取菜单权限 + * + * @param user user + * @return 字符串集合 + */ + Set getMenuPermission(SysUser user); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysPostService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysPostService.java new file mode 100644 index 0000000..058f139 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysPostService.java @@ -0,0 +1,89 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysPost; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 14:43 + */ +public interface SysPostService { + + /** + * 增加岗位 + * + * @param post post + */ + void insertPost(SysPost post); + + /** + * 校验岗位名称 + * + * @param post 岗位信息 + * @return 结果 + */ + boolean checkPostNameNotUnique(SysPost post); + + /** + * 校验岗位编码 + * + * @param post 岗位信息 + * @return 结果 + */ + boolean checkPostCodeNotUnique(SysPost post); + + /** + * 修改岗位 + * + * @param post post + */ + void updatePost(SysPost post); + + /** + * 批量删除岗位 + * + * @param postIds ids + */ + void deletePostByIds(Long[] postIds); + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + SysPost selectPostById(Long postId); + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + int countUserPostById(Long postId); + + /** + * 查询全部岗位 + * + * @return 全部岗位集合 + */ + List selectPostAll(); + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + List selectPostListByUserId(Long userId); + + /** + * 查询岗位列表 + * + * @param post 查询条件 + * @return List + */ + List selectPostList(SysPost post); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysRoleService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysRoleService.java new file mode 100644 index 0000000..d95ea72 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysRoleService.java @@ -0,0 +1,164 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysRole; +import com.ailanyin.model.SysUserRole; + +import java.util.List; +import java.util.Set; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 13:03 + */ +public interface SysRoleService { + + /** + * 新增角色 + * + * @param role role + */ + void insertRole(SysRole role); + + /** + * 修改角色 + * + * @param role role + */ + void updateRole(SysRole role); + + /** + * 校验角色名称是否不唯一 + * + * @param role 角色信息 + * @return 结果 + */ + boolean checkRoleNameNotUnique(SysRole role); + + /** + * 校验角色权限是否不唯一 + * + * @param role 角色信息 + * @return 结果 + */ + boolean checkRoleKeyNotUnique(SysRole role); + + /** + * 校验角色是否允许操作 + * + * @param role 角色信息 + */ + void checkRoleAllowed(SysRole role); + + /** + * 保存修改数据权限 + * + * @param role role + */ + void authDataScope(SysRole role); + + /** + * 状态修改 + * + * @param role role + */ + void updateRoleStatus(SysRole role); + + /** + * 批量删除角色 + * + * @param roleIds 角色 ids + */ + void deleteRoleByIds(Long[] roleIds); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + SysRole selectRoleById(Long roleId); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + int countUserRoleByRoleId(Long roleId); + + /** + * 查询所有角色 + * + * @return 所有角色 + */ + List selectRoleAll(); + + /** + * 批量选择授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要删除的用户数据ID + */ + void insertAuthUsers(Long roleId, Long[] userIds); + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要取消授权的用户数据ID + */ + void deleteAuthUsers(Long roleId, Long[] userIds); + + /** + * 取消授权用户角色 + * + * @param userRole userRole + */ + void deleteAuthUser(SysUserRole userRole); + + /** + * 查询角色列表 + * + * @param role 查询条件 + * @return 角色集合 + */ + List selectRoleList(SysRole role); + + /** + * 查询用户拥有的所有角色 + * + * @param userId 用户 id + * @return 角色列表 + */ + List selectRolesByUserId(Long userId); + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + List selectRoleListByUserId(Long userId); + + /** + * 根据用户ID查询角色权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + Set selectRolePermissionByUserId(Long userId); + + /** + * 校验角色是否有数据权限 + * + * @param roleId 角色id + */ + void checkRoleDataScope(Long roleId); + + /** + * 重置超级管理员权限 + */ + void refreshRole(); + +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysUserService.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysUserService.java new file mode 100644 index 0000000..16d2aa1 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/SysUserService.java @@ -0,0 +1,196 @@ +package com.ailanyin.admin.service; + +import com.ailanyin.model.SysUser; +import org.springframework.web.multipart.MultipartFile; + + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 11:16 + */ +public interface SysUserService { + + /** + * 获取当前登录的用户信息 + * + * @return sysUser + */ + SysUser getCurrentUser(); + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @param user 查询条件 + * @return 用户集合 + */ + List selectAllocatedList(SysUser user); + + /** + * 新增用户 + * + * @param user user + */ + void insertUser(SysUser user); + + /** + * 校验用户名称是否不唯一 + * + * @param userName 用户名称 + * @return 结果 + */ + boolean checkUserNameNotUnique(String userName); + + + /** + * 更新用户信息 + * + * @param user user + */ + void updateUser(SysUser user); + + /** + * 校验用户是否允许操作 + * + * @param user 用户信息 + */ + void checkUserAllowed(SysUser user); + + /** + * 批量删除用户 + * + * @param userIds ids + */ + void deleteUserByIds(Long[] userIds); + + /** + * 重置密码 + * + * @param user user + */ + void resetPwd(SysUser user); + + /** + * 修改状态 + * + * @param user user + */ + void updateUserStatus(SysUser user); + + /** + * 通过 id 查询 + * + * @param userId + * @return + */ + SysUser selectUserById(Long userId); + + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + void insertUserAuth(Long userId, Long[] roleIds); + + /** + * 校验用户是否有数据权限 + * + * @param userId 用户id + */ + void checkUserDataScope(Long userId); + + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + List selectUserList(SysUser user); + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + List selectUnallocatedList(SysUser user); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + SysUser selectUserByUserName(String userName); + + /** + * 导入用户列表 + * + * @param list 用户列表 + * @param updateSupport 是否更新已经存在的数量 + */ + void importData(List list, boolean updateSupport); + + /** + * 已删除用户列表 + * + * @param user user + * @return list + */ + List selectDeleteUserList(SysUser user); + + /** + * 恢复已删除的用户 + * + * @param ids ids + */ + void recoveryDeleteUser(List ids); + + /** + * 彻底删除用户 + * + * @param ids ids + */ + void realDeleteUser(List ids); + + /** + * 根据 username 查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + String selectUserRoleGroup(String userName); + + /** + * 根据用户ID查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + String selectUserPostGroup(String userName); + + /** + * 用户自主修改基本信息 + * + * @param user user + */ + void updateProfile(SysUser user); + + /** + * 用户自主修改密码 + * + * @param oldPassword 旧密码 + * @param newPassword 新密码 + */ + void updatePwd(String oldPassword, String newPassword); + + /** + * 更新头像 + * + * @param file file + */ + void updateAvatar(MultipartFile file); +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/CommonFileServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/CommonFileServiceImpl.java new file mode 100644 index 0000000..d978d4b --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/CommonFileServiceImpl.java @@ -0,0 +1,36 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.CommonFileService; +import com.ailanyin.common.utils.FileUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/4 0004 下午 16:04 + */ +@Service +public class CommonFileServiceImpl implements CommonFileService { + + @Autowired + private HttpServletRequest request; + + @Value("${upload.path}") + private String path; + /** + * 文件上传 + * + * @param file file + * @return url + */ + @Override + public String fileUpload(MultipartFile file) { + + return FileUtil.upload(file,request,path); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/ExceptionLogServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/ExceptionLogServiceImpl.java new file mode 100644 index 0000000..a62f55a --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/ExceptionLogServiceImpl.java @@ -0,0 +1,75 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.ExceptionLogService; +import com.ailanyin.mapper.ExceptionLogMapper; +import com.ailanyin.model.ExceptionLog; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/2 0002 下午 17:23 + */ +@Service +public class ExceptionLogServiceImpl implements ExceptionLogService { + + @Resource + private ExceptionLogMapper logMapper; + + /** + * 查询异常信息列表 + * + * @param exceptionLog exceptionLog + * @return list + */ + @Override + public List selectExceptionLog(ExceptionLog exceptionLog) { + return logMapper.selectListByParam(exceptionLog); + } + + /** + * 新增异常 + * + * @param exceptionLog exceptionLog + */ + @Override + public void insertExceptionLog(ExceptionLog exceptionLog) { + exceptionLog.setCreateTime(new Date()); + logMapper.insertExceptionLog(exceptionLog); + } + + /** + * 新增异常 + * + * @param exception exception + */ + @Override + public void insertExceptionLog(Exception exception) { + ExceptionLog log = new ExceptionLog(); + log.setExceptionReason(exception.getMessage()); + + StringBuilder builder = new StringBuilder(); + if (exception.getStackTrace().length > 0) { + for (StackTraceElement traceElement : exception.getStackTrace()) { + builder.append(traceElement).append("
"); + } + } + log.setDetailInfo(builder.toString()); + insertExceptionLog(log); + } + + /** + * 批量删除异常日志 + * + * @param logIds ids + */ + @Override + public void removeExceptionLog(List logIds) { + logMapper.deleteBatchIds(logIds); + + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysBlacklistUserServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysBlacklistUserServiceImpl.java new file mode 100644 index 0000000..bbae39c --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysBlacklistUserServiceImpl.java @@ -0,0 +1,78 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.SysBlacklistUserService; +import com.ailanyin.common.constant.UserConstants; +import com.ailanyin.common.service.RedisService; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.common.utils.IpUtil; +import com.ailanyin.mapper.SysBlacklistUserMapper; +import com.ailanyin.model.SysBlacklistUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/1 0001 下午 15:14 + */ +@Service +public class SysBlacklistUserServiceImpl implements SysBlacklistUserService { + + @Autowired + private RedisService redisService; + @Resource + private SysBlacklistUserMapper blacklistUserMapper; + @Value("${redis.database}") + private String database; + + /** + * 获取黑名单列表 + * + * @param blacklistUser blacklistUser + * @return list + */ + @Override + public List selectBlackList(SysBlacklistUser blacklistUser) { + return blacklistUserMapper.selectByParam(blacklistUser); + } + + /** + * 批量删除日志 + * + * @param ids ids + */ + @Override + public void removeBlacklistUser(List ids) { + List idList = new ArrayList<>(); + List ipList = new ArrayList<>(); + ids.forEach( + blacklistUser -> { + idList.add(blacklistUser.getId()); + ipList.add(blacklistUser.getIp()); + } + ); + blacklistUserMapper.deleteBatchIds(idList); + // 从缓存中移除 + redisService.sRemove(database + UserConstants.BLACKLIST_KEY, ipList.toArray()); + } + + /** + * 新增黑名单 + * + * @param blacklistUser blacklistUser + */ + @Override + public void insertBlacklistUser(SysBlacklistUser blacklistUser) { + if (EmptyUtil.isNotEmpty(blacklistUser.getIp())) { + blacklistUser.setAddress(IpUtil.getRealAddressByIp(blacklistUser.getIp())); + } + blacklistUser.setCreateTime(new Date()); + blacklistUserMapper.insertBlacklistUser(blacklistUser); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysConfigServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysConfigServiceImpl.java new file mode 100644 index 0000000..f43e173 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysConfigServiceImpl.java @@ -0,0 +1,177 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.SysConfigService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.constant.UserConstants; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.common.service.RedisService; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.common.utils.StringUtil; +import com.ailanyin.mapper.SysConfigMapper; +import com.ailanyin.model.SysConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:44 + */ +@Service +public class SysConfigServiceImpl implements SysConfigService { + + @Autowired + private SysUserService sysUserService; + @Autowired + private RedisService redisService; + @Resource + private SysConfigMapper configMapper; + + @Value("${redis.database}") + private String database; + + private static final String KEY = ":sys:config:"; + + /** + * 项目启动时,同步配置到缓存 + */ + @PostConstruct + public void init() { + loadingConfigCache(); + } + + @Override + public List selectConfigList(SysConfig config) { + return configMapper.selectConfigList(config); + } + + /** + * 加载参数缓存数据 + */ + @Override + public void loadingConfigCache() { + List configsList = configMapper.selectConfigList(new SysConfig()); + configsList + .stream() + .filter(config -> EmptyUtil.isNotEmpty(config.getConfigKey()) && EmptyUtil.isNotEmpty(config.getConfigValue())) + .forEach(this::addToRedis); + } + + @Override + public String selectConfigByKey(String configKey) { + + if (redisService.get(database + KEY + configKey) != null) { + return redisService.get(database + KEY + configKey).toString(); + } + SysConfig config = new SysConfig(); + config.setConfigKey(configKey); + SysConfig retConfig = configMapper.selectConfig(config); + if (StringUtil.isNotNull(retConfig)) { + addToRedis(retConfig); + return retConfig.getConfigValue(); + } + return StringUtil.EMPTY; + } + + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return SysConfig 参数配置信息 + */ + @Override + public SysConfig selectConfigById(Long configId) { + SysConfig config = new SysConfig(); + config.setConfigId(configId); + return configMapper.selectConfig(config); + } + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void addSysConfig(SysConfig config) { + if (checkConfigKeyNotUnique(config)) { + Asserts.fail("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + + config.setCreateBy(sysUserService.getCurrentUser().getUserName()); + config.setCreateTime(new Date()); + + int row = configMapper.insertConfig(config); + if (row > 0) { + addToRedis(config); + } + } + + /** + * 校验参数键名是否唯一 + * + * @param config 参数信息 + * @return 结果 + */ + @Override + public boolean checkConfigKeyNotUnique(SysConfig config) { + SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey()); + return StringUtil.isNotNull(info) && !info.getConfigId().equals(config.getConfigId()); + + } + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSysConfig(SysConfig config) { + + if (checkConfigKeyNotUnique(config)) { + Asserts.fail("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + int row = configMapper.updateConfig(config); + if (row > 0) { + addToRedis(config); + } + } + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteConfigByIds(Long[] configIds) { + for (Long configId : configIds) { + SysConfig config = selectConfigById(configId); + if (StringUtil.equals(UserConstants.YES, config.getConfigType())) { + if (configId < 9) { + Asserts.fail("系统配置, 禁止删除!"); + } + Asserts.fail(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); + } + configMapper.deleteConfigById(configId); + delFromRedis(config.getConfigKey()); + } + } + + + private void addToRedis(SysConfig config) { + redisService.set(database + KEY + config.getConfigKey(), config.getConfigValue()); + } + + private void delFromRedis(String configKey) { + redisService.del(database + KEY + configKey); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysDeptServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysDeptServiceImpl.java new file mode 100644 index 0000000..1db829e --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,308 @@ +package com.ailanyin.admin.service.impl; + +import cn.hutool.core.convert.Convert; +import com.ailanyin.admin.service.SysDeptService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.annotation.DataScope; +import com.ailanyin.common.constant.UserConstants; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.common.utils.SpringUtil; +import com.ailanyin.mapper.SysDeptMapper; +import com.ailanyin.mapper.SysRoleMapper; +import com.ailanyin.model.SysDept; +import com.ailanyin.model.SysRole; +import com.ailanyin.model.TreeSelect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:24 + */ +@Service +@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) +public class SysDeptServiceImpl implements SysDeptService { + + @Autowired + private SysUserService sysUserService; + + @Resource + private SysDeptMapper deptMapper; + @Resource + private SysRoleMapper roleMapper; + + /** + * 添加部门 + * + * @param dept dept + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void addDept(SysDept dept) { + + if (checkDeptNameNotUnique(dept)) { + Asserts.fail("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + + SysDept info = deptMapper.selectDeptById(dept.getParentId()); + // 如果父节点不为正常状态,则不允许新增子节点 + if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) { + Asserts.fail("部门停用,不允许新增"); + } + dept.setAncestors(info.getAncestors() + "," + dept.getParentId()); + dept.setCreateBy(sysUserService.getCurrentUser().getUserName()); + dept.setCreateTime(new Date()); + deptMapper.insertDept(dept); + } + + /** + * 修改部门 + * + * @param dept dept + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateDept(SysDept dept) { + + if (checkDeptNameNotUnique(dept)) { + Asserts.fail("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + + SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId()); + SysDept oldDept = deptMapper.selectDeptById(dept.getDeptId()); + + if (EmptyUtil.isNotEmpty(newParentDept) && EmptyUtil.isNotEmpty(oldDept)) { + String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId(); + String oldAncestors = oldDept.getAncestors(); + dept.setAncestors(newAncestors); + updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors); + } + + dept.setUpdateBy(sysUserService.getCurrentUser().getUserName()); + dept.setUpdateTime(new Date()); + deptMapper.updateDept(dept); + if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && EmptyUtil.isNotEmpty(dept.getAncestors()) + && !"0".equals(dept.getAncestors())) { + // 如果该部门是启用状态,则启用该部门的所有上级部门 + updateParentDeptStatusNormal(dept); + } + } + + /** + * 删除部门 + * + * @param deptId deptId + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void removeDept(Long deptId) { + + if (hasChildByDeptId(deptId)) { + Asserts.fail("存在下级部门,不允许删除"); + } + + if (checkDeptExistUser(deptId)) { + Asserts.fail("部门存在用户,不允许删除"); + } + deptMapper.deleteDeptById(deptId); + } + + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + @Override + @DataScope(deptAlias = "d") + public List selectDeptList(SysDept dept) { + return deptMapper.selectDeptList(dept); + } + + /** + * 构建前端所需要下拉树结构 + * + * @param deptList 部门列表 + * @return 下拉树结构列表 + */ + @Override + public List buildDeptTreeSelect(List deptList) { + List deptTrees = buildDeptTree(deptList); + return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * 构建前端所需要树结构 + * + * @param deptList 部门列表 + * @return 树结构列表 + */ + @Override + public List buildDeptTree(List deptList) { + List returnList = new ArrayList(); + List tempList = new ArrayList(); + for (SysDept dept : deptList) { + tempList.add(dept.getDeptId()); + } + for (SysDept dept : deptList) { + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(dept.getParentId())) { + recursionFn(deptList, dept); + returnList.add(dept); + } + } + if (returnList.isEmpty()) { + returnList = deptList; + } + return returnList; + } + + /** + * 递归列表 + */ + private void recursionFn(List list, SysDept t) { + // 得到子节点列表 + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysDept tChild : childList) { + if (hasChild(list, tChild)) { + recursionFn(list, tChild); + } + } + } + + + /** + * 是否存在部门子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public boolean hasChildByDeptId(Long deptId) { + return deptMapper.hasChildByDeptId(deptId) > 0; + } + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + @Override + public SysDept selectDeptById(Long deptId) { + return deptMapper.selectDeptById(deptId); + } + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + @Override + public boolean checkDeptExistUser(Long deptId) { + return deptMapper.checkDeptExistUser(deptId) > 0; + } + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public boolean checkDeptNameNotUnique(SysDept dept) { + SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId()); + return EmptyUtil.isNotEmpty(info) && !info.getDeptId().equals(dept.getDeptId()); + } + + /** + * 校验部门是否有数据权限 + * + * @param deptId 部门id + */ + @Override + public void checkDeptDataScope(Long deptId) { + if (!sysUserService.getCurrentUser().isAdmin()) { + SysDept dept = new SysDept(); + dept.setDeptId(deptId); + List deptList = SpringUtil.getAopProxy(this).selectDeptList(dept); + if (EmptyUtil.isEmpty(deptList)) { + Asserts.fail("没有权限访问该部门数据!"); + } + } + } + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + @Override + public List selectDeptListByRoleId(Long roleId) { + SysRole role = roleMapper.selectRoleById(roleId); + return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly()); + } + + /** + * 获取子节点列表 + * + * @param list list + * @param sysDept sysDept + * @return 子节点列表 + */ + private List getChildList(List list, SysDept sysDept) { + return list.stream() + .filter(dept -> EmptyUtil.isNotEmpty(dept.getParentId()) && dept.getParentId().longValue() == sysDept.getDeptId().longValue()) + .collect(Collectors.toList()); + } + + /** + * 判断是否有子节点 + * + * @param list 部门列表 + * @param sysDept 部门 + * @return boolean + */ + private boolean hasChild(List list, SysDept sysDept) { + return getChildList(list, sysDept).size() > 0; + } + + /** + * 修改该部门的父级部门状态 + * + * @param dept 当前部门 + */ + private void updateParentDeptStatusNormal(SysDept dept) { + String ancestors = dept.getAncestors(); + Long[] deptIds = Convert.toLongArray(ancestors); + deptMapper.updateDeptStatusNormal(deptIds); + } + + /** + * 修改子元素关系 + * + * @param deptId 被修改的部门ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + private void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) { + List children = deptMapper.selectChildrenDeptById(deptId); + if (children.size() > 0) { + children.forEach(child -> child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors))); + deptMapper.updateDeptChildren(children); + } + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysDictDataServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 0000000..3d5062f --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysDictDataServiceImpl.java @@ -0,0 +1,99 @@ +package com.ailanyin.admin.service.impl; + + +import com.ailanyin.admin.service.SysDictDataService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.service.RedisService; +import com.ailanyin.mapper.SysDictDataMapper; +import com.ailanyin.model.SysDictData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 17:03 + */ +@Service +public class SysDictDataServiceImpl implements SysDictDataService { + + @Autowired + private SysUserService sysUserService; + @Autowired + private RedisService redisService; + @Resource + private SysDictDataMapper dictDataMapper; + + @Value("${redis.database}") + private String database; + + private static final String KEY = ":sys:dict:"; + /** + * 获取字典列表 + * + * @param dictData dictData + * @return List + */ + @Override + public List selectDictDataList(SysDictData dictData) { + return dictDataMapper.selectDictDataList(dictData); + } + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode id + * @return 详情 + */ + @Override + public SysDictData selectDictDataById(Long dictCode) { + return dictDataMapper.selectDictDataById(dictCode); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void addDictData(SysDictData dict) { + dict.setCreateBy(sysUserService.getCurrentUser().getUserName()); + dict.setCreateTime(new Date()); + int row = dictDataMapper.insertDictData(dict); + if (row > 0) { + List dictDataList = dictDataMapper.selectDictDataByType(dict.getDictType()); + addToRedis(dict.getDictType(), dictDataList); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteDictDataByIds(Long[] dictCodes) { + for (Long dictCode : dictCodes) { + SysDictData dict = selectDictDataById(dictCode); + dictDataMapper.deleteDictDataById(dictCode); + List dictDataList = dictDataMapper.selectDictDataByType(dict.getDictType()); + addToRedis(dict.getDictType(), dictDataList); + + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateDictData(SysDictData dictData) { + dictData.setUpdateBy(sysUserService.getCurrentUser().getUserName()); + dictData.setUpdateTime(new Date()); + int row = dictDataMapper.updateDictData(dictData); + if (row > 0) { + List dictDataList = dictDataMapper.selectDictDataByType(dictData.getDictType()); + addToRedis(dictData.getDictType(), dictDataList); + } + } + + private void addToRedis(String type, List dictDataList) { + redisService.set(database + KEY + type, dictDataList); + } + +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysDictTypeServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysDictTypeServiceImpl.java new file mode 100644 index 0000000..137959d --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysDictTypeServiceImpl.java @@ -0,0 +1,195 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.SysDictTypeService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.common.service.RedisService; +import com.ailanyin.common.utils.StringUtil; +import com.ailanyin.mapper.SysDictDataMapper; +import com.ailanyin.mapper.SysDictTypeMapper; +import com.ailanyin.model.SysDictData; +import com.ailanyin.model.SysDictType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 17:05 + */ +@Service +public class SysDictTypeServiceImpl implements SysDictTypeService { + + @Autowired + private SysUserService sysUserService; + @Autowired + private RedisService redisService; + @Resource + private SysDictDataMapper dictDataMapper; + @Resource + private SysDictTypeMapper dictTypeMapper; + + @Value("${redis.database}") + private String database; + + private static final String KEY = ":sys:dict:"; + private static final String DEL_ALL_KEY = ":sys:dict"; + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + @Override + public List selectDictDataByType(String dictType) { + + if (redisService.get(database + KEY + dictType) != null) { + return (List) redisService.get(database + KEY + dictType); + } + List dictDataList = dictDataMapper.selectDictDataByType(dictType); + if (dictDataList.size() > 0) { + addToRedis(dictType, dictDataList); + } + return dictDataList; + + } + + + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeList(SysDictType dictType) { + return dictTypeMapper.selectDictTypeList(dictType); + } + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + @Override + public SysDictType selectDictTypeById(Long dictId) { + return dictTypeMapper.selectDictTypeById(dictId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void addDictType(SysDictType dictType) { + if (checkDictTypeNotUnique(dictType)) { + Asserts.fail("新增字典'" + dictType.getDictName() + "'失败,字典类型已存在"); + } + + dictType.setCreateBy(sysUserService.getCurrentUser().getUserName()); + dictType.setCreateTime(new Date()); + dictTypeMapper.insertDictType(dictType); + + } + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + @Override + public boolean checkDictTypeNotUnique(SysDictType dictType) { + SysDictType sysDictType = dictTypeMapper.checkDictTypeUnique(dictType.getDictType()); + return StringUtil.isNotNull(sysDictType) && !sysDictType.getDictId().equals(dictType.getDictId()); + } + + /** + * 修改保存字典类型信息 + * + * @param dictType 字典类型信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateDictType(SysDictType dictType) { + + if (checkDictTypeNotUnique(dictType)) { + Asserts.fail("修改字典'" + dictType.getDictName() + "'失败,字典类型已存在"); + } + + SysDictType oldDict = dictTypeMapper.selectDictTypeById(dictType.getDictId()); + dictDataMapper.updateDictDataType(oldDict.getDictType(), dictType.getDictType()); + int row = dictTypeMapper.updateDictType(dictType); + if (row > 0) { + List dictDataList = dictDataMapper.selectDictDataByType(dictType.getDictType()); + addToRedis(dictType.getDictType(), dictDataList); + } + + } + + /** + * 批量删除字典信息 + * + * @param dictIds 需要删除的字典ID + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteDictTypeByIds(Long[] dictIds) { + for (Long dictId : dictIds) { + SysDictType dictType = selectDictTypeById(dictId); + if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0) { + Asserts.fail(String.format("%1$s已分配,不能删除", dictType.getDictName())); + } + dictTypeMapper.deleteDictTypeById(dictId); + delFromRedis(dictType.getDictType()); + } + } + + /** + * 重置字典缓存数据 + */ + @Override + public void resetDictCache() { + Collection keys = redisService.getKeys(database + KEY + "*"); + List keyList = new ArrayList<>(keys); + redisService.del(keyList); + loadingDictCache(); + } + + /** + * 加载字典缓存数据 + */ + @Override + public void loadingDictCache() { + List dictTypeList = dictTypeMapper.selectDictTypeAll(); + for (SysDictType dictType : dictTypeList) { + List dictDataList = dictDataMapper.selectDictDataByType(dictType.getDictType()); + addToRedis(dictType.getDictType(), dictDataList); + } + } + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeAll() { + return dictTypeMapper.selectDictTypeAll(); + } + + private void addToRedis(String dictType, List dictDataList) { + redisService.set(database + KEY + dictType, dictDataList); + } + + private void delFromRedis(String dictType) { + redisService.del(database + KEY + dictType); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysLogServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysLogServiceImpl.java new file mode 100644 index 0000000..d680bce --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysLogServiceImpl.java @@ -0,0 +1,70 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.SysLogService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.mapper.SysLogMapper; +import com.ailanyin.model.SysLog; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/28 0028 下午 14:46 + */ +@Service +public class SysLogServiceImpl implements SysLogService { + + @Autowired + private SysUserService sysUserService; + @Resource + private SysLogMapper logMapper; + + /** + * 新增日志 + * + * @param sysLog log + */ + @Override + public void insertLog(SysLog sysLog) { + logMapper.insertLog(sysLog); + } + + /** + * 分页获取日志列表 + * + * @param sysLog sysLog + * @return list + */ + @Override + public List list(SysLog sysLog) { + return logMapper.selectByParam(sysLog); + } + + @Override + public void cleanLog() { + checkWhetherAllow(); + logMapper.deleteBatchIds(null); + } + + /** + * 批量删除日志 + * + * @param logIds ids + */ + @Override + public void removeLog(List logIds) { + checkWhetherAllow(); + logMapper.deleteBatchIds(logIds); + } + + private void checkWhetherAllow() { + if (!sysUserService.getCurrentUser().isAdmin()) { + Asserts.fail("非超管禁止操作!"); + } + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysLoginServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysLoginServiceImpl.java new file mode 100644 index 0000000..4502b3b --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysLoginServiceImpl.java @@ -0,0 +1,253 @@ +package com.ailanyin.admin.service.impl; + +import cn.hutool.core.codec.Base64; +import cn.hutool.core.lang.UUID; +import com.ailanyin.admin.service.SysBlacklistUserService; +import com.ailanyin.admin.service.SysLoginService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.admin.vo.LoginBodyVo; +import com.ailanyin.common.constant.UserConstants; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.common.result.AjaxResult; +import com.ailanyin.common.service.RedisService; +import com.ailanyin.common.utils.CaptchaUtil; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.common.utils.IpUtil; +import com.ailanyin.mapper.SysUserMapper; +import com.ailanyin.model.SysBlacklistUser; +import com.ailanyin.model.SysUser; +import com.ailanyin.security.service.SecurityUserService; +import com.ailanyin.security.utils.JwtTokenUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.util.FastByteArrayOutputStream; + +import javax.annotation.Resource; +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletRequest; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Date; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 15:55 + */ +@Service +public class SysLoginServiceImpl implements SysLoginService { + + @Autowired + private SecurityUserService securityUserService; + @Autowired + private SysUserService sysUserService; + @Autowired + private SysBlacklistUserService sysBlacklistUserService; + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private RedisService redisService; + @Autowired + private UserDetailsServiceImpl userDetailsService; + @Autowired + private JwtTokenUtil jwtTokenUtil; + @Autowired + private HttpServletRequest request; + + @Resource + private SysUserMapper userMapper; + + @Value("${redis.database}") + private String database; + + + + @Override + public AjaxResult login(String username, String password, String code, String uuid) { + String ip = IpUtil.getIpAddr(request); + //黑名单开关 + boolean checkBlacklistOnOffResult = checkBlacklistOnOff(); + if (checkBlacklistOnOffResult) { + //查看登录ip是否被拉黑 + checkBlacklist(ip); + } + //验证码 + checkCaptcha(code, uuid); + //用户名查询用户信息 + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + //验证密码 + boolean checkPasswordResult = checkPassword(password, userDetails); + //密码错误 + if (!checkPasswordResult) { + securityUserService.delUserDetailsFromMap(username); + //黑名单 + if (checkBlacklistOnOffResult) { + return AjaxResult.error(handleBlacklist(ip)); + } + return AjaxResult.error("账号或密码错误!"); + } + //密码正确 删除错误记录 + if (checkBlacklistOnOffResult) { + deleteBlacklistUserFromRedis(ip); + } + // update this user last login ip and time + updateUserLastLoginIpAndTime(userDetails.getUsername(),ip); + AjaxResult ajax = AjaxResult.success(); + ajax.put("token", jwtTokenUtil.generateToken(userDetails)); + return ajax; + } + + private void updateUserLastLoginIpAndTime(String username, String ip) { + userMapper.updateUserLastLoginIpAndTime(username,ip,new Date()); + } + + + @Override + public AjaxResult getCaptchaImage() { + + AjaxResult ajax = AjaxResult.success(); + + if (!getRegisterConfig()) { + ajax.put("register", false); + } + if (!getCaptchaConfig()) { + ajax.put("captchaOnOff", false); + return ajax; + } + Object[] image = CaptchaUtil.createImage(); + // 转换流信息写出 + FastByteArrayOutputStream os = new FastByteArrayOutputStream(); + try { + ImageIO.write((BufferedImage) image[1], "jpg", os); + } catch (IOException e) { + return AjaxResult.error(); + } finally { + os.close(); + } + + Object uuid = UUID.randomUUID().toString(true); + ajax.put("uuid", uuid); + ajax.put("img", Base64.encode(os.toByteArray())); + redisService.set(database + UserConstants.CAPTCHA_KEY + uuid, image[0], 120); + return ajax; + } + + @Override + public void register(LoginBodyVo register) { + + // 检查是否开启注册 + if (!getRegisterConfig()) { + Asserts.fail("系统暂未开启注册!"); + } + // 检查验证码 + checkCaptcha(register.getCode(),register.getUuid()); + // 新建用户 + SysUser user = new SysUser(); + user.setUserName(register.getUsername()); + user.setNickName(register.getUsername()); + user.setPassword(register.getPassword()); + sysUserService.insertUser(user); + } + + private boolean getCaptchaConfig() { + try { + return UserConstants.CAPTCHA_ON.equals(redisService.get(database + UserConstants.CAPTCHA_ON_OFF_KEY)); + } catch (Exception e) { + Asserts.fail("Redis中验证码配置不存在!"); + return false; + } + } + + private boolean getRegisterConfig() { + try { + return UserConstants.REGISTER_ON.equals(redisService.get(database + UserConstants.REGISTER_ON_OFF_KEY)); + } catch (Exception e) { + Asserts.fail("Redis中注册配置不存在!"); + return false; + } + } + + private boolean checkBlacklistOnOff() { + try { + return UserConstants.BLACKLIST_ON.equals(redisService.get(database + UserConstants.BLACKLIST_ON_OFF_KEY)); + } catch (Exception e) { + Asserts.fail("Redis中黑名单配置不存在!"); + return false; + } + } + + private void checkBlacklist(String ip) { + if (redisService.sIsMember(database + UserConstants.BLACKLIST_KEY, ip)) { + Asserts.fail("IP:["+ip+"]已经被拉黑,请联系管理员!"); + } + } + + private void checkCaptcha(String code, String uuid) { + if (getCaptchaConfig()) { + if (EmptyUtil.isEmpty(code) || EmptyUtil.isEmpty(uuid)) { + Asserts.fail("验证码或uuid获取失败!"); + } + try { + if (!redisService.hasKey(database + UserConstants.CAPTCHA_KEY + uuid)) { + Asserts.fail("验证码已经过期失效!"); + } else { + if (!code.equalsIgnoreCase(redisService.get(database + UserConstants.CAPTCHA_KEY + uuid).toString())) { + Asserts.fail("验证码输入错误!"); + } + } + + } finally { + redisService.del(database + UserConstants.CAPTCHA_KEY + uuid); + } + } + } + + private boolean checkPassword(String password, UserDetails userDetails) { + return passwordEncoder.matches(password, userDetails.getPassword()); + } + + private String handleBlacklist(String ip) { + int errorCount; + StringBuilder builder = new StringBuilder(); + try { + //半小时过期时间 + errorCount = (int) redisService.hGet(database + UserConstants.LOGIN_ERROR_COUNT, ip); + ++errorCount; + if (errorCount < UserConstants.MAX_ERROR_COUNT) { + redisService.hSet(database + UserConstants.LOGIN_ERROR_COUNT, ip, errorCount, 1800); + builder.append("您还有") + .append(UserConstants.MAX_ERROR_COUNT - errorCount) + .append("次输错密码的机会!"); + return builder.toString(); + } else { + // 黑名单进Redis + redisService.sAdd(database + UserConstants.BLACKLIST_KEY, ip); + // 黑名单进Mysql + addBlacklistUser(ip); + return UserConstants.HAS_BEEN_PULLED_BLACK; + } + + } catch (Exception e) { + redisService.hSet(database + UserConstants.LOGIN_ERROR_COUNT, ip, 1, 1800); + builder.append("您还有") + .append(UserConstants.MAX_ERROR_COUNT - 1) + .append("次输错密码的机会!"); + return builder.toString(); + } + } + + private void deleteBlacklistUserFromRedis(String ip) { + redisService.hDel(database + UserConstants.LOGIN_ERROR_COUNT, ip); + } + + private void addBlacklistUser(String ip) { + SysBlacklistUser blacklistUser = new SysBlacklistUser(); + blacklistUser.setIp(ip); + // "1" == "错误密码次数过多" + blacklistUser.setReason("1"); + sysBlacklistUserService.insertBlacklistUser(blacklistUser); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysMenuServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000..0d874f2 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,442 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.SysMenuService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.admin.vo.MetaVo; +import com.ailanyin.admin.vo.RouterVo; +import com.ailanyin.common.constant.Constants; +import com.ailanyin.common.constant.UserConstants; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.common.utils.StringUtil; +import com.ailanyin.mapper.SysMenuMapper; +import com.ailanyin.mapper.SysRoleMapper; +import com.ailanyin.mapper.SysRoleMenuMapper; +import com.ailanyin.model.SysMenu; +import com.ailanyin.model.SysRole; +import com.ailanyin.model.SysUser; +import com.ailanyin.model.TreeSelect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 11:26 + */ +@Service +public class SysMenuServiceImpl implements SysMenuService { + + @Autowired + private SysUserService sysUserService; + + @Resource + private SysMenuMapper menuMapper; + @Resource + private SysRoleMapper roleMapper; + @Resource + private SysRoleMenuMapper roleMenuMapper; + + /** + * 新增菜单 + * + * @param menu menu + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void insertMenu(SysMenu menu) { + if (checkMenuNameNotUnique(menu)) { + Asserts.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + menu.setCreateTime(new Date()); + menu.setCreateBy(sysUserService.getCurrentUser().getUserName()); + menuMapper.insertMenu(menu); + } + + /** + * 修改保存菜单信息 + * + * @param menu 菜单信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateMenu(SysMenu menu) { + + if (checkMenuNameNotUnique(menu)) { + Asserts.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + menu.setUpdateTime(new Date()); + menu.setUpdateBy(sysUserService.getCurrentUser().getUserName()); + menuMapper.updateMenu(menu); + } + + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + @Override + public List selectMenuList(Long userId) { + return selectMenuList(new SysMenu(), userId); + } + + /** + * 查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + @Override + public List selectMenuList(SysMenu menu, Long userId) { + List menuList = null; + // 管理员显示所有菜单信息 + if (SysUser.isAdmin(userId)) { + menuList = menuMapper.selectMenuList(menu); + } else { + menu.getParams().put("userId", userId); + menuList = menuMapper.selectMenuListByUserId(menu); + } + return menuList; + } + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + @Override + public SysMenu selectMenuById(Long menuId) { + return menuMapper.selectMenuById(menuId); + } + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + @Override + public List selectMenuListByRoleId(Long roleId) { + SysRole role = roleMapper.selectRoleById(roleId); + return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly()); + } + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + @Override + public List buildMenuTreeSelect(List menus) { + List menuTrees = buildMenuTree(menus); + return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * 构建前端所需要树结构 + * + * @param menus 菜单列表 + * @return 树结构列表 + */ + @Override + public List buildMenuTree(List menus) { + List returnList = new ArrayList<>(); + List tempList = new ArrayList<>(); + for (SysMenu dept : menus) { + tempList.add(dept.getMenuId()); + } + + for (SysMenu menu : menus) { + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(menu.getParentId())) { + recursionFn(menus, menu); + returnList.add(menu); + } + } + + return returnList.isEmpty() ? menus : returnList; + } + + /** + * 递归列表 + * + * @param list list + * @param sysMenu sysMenu + */ + private void recursionFn(List list, SysMenu sysMenu) { + // 得到子节点列表 + List childList = getChildList(list, sysMenu); + sysMenu.setChildren(childList); + for (SysMenu tChild : childList) { + if (hasChild(list, tChild)) { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + * + * @param list list + * @param sysMenu sysMenu + * @return List + */ + private List getChildList(List list, SysMenu sysMenu) { + + return list.stream() + .filter(menu -> menu.getParentId().equals(sysMenu.getMenuId())) + .collect(Collectors.toList()); + + } + + /** + * 判断是否有子节点 + * + * @param list list + * @param sysMenu sysMenu + * @return boolean + */ + private boolean hasChild(List list, SysMenu sysMenu) { + return getChildList(list, sysMenu).size() > 0; + } + + /** + * 删除菜单 + * + * @param menuId menuId + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void removeMenuById(Long menuId) { + if (hasChildByMenuId(menuId)) { + Asserts.fail("存在子菜单,不允许删除"); + } + if (checkMenuExistRole(menuId)) { + Asserts.fail("菜单已分配,不允许删除"); + } + menuMapper.deleteMenuById(menuId); + } + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public boolean checkMenuNameNotUnique(SysMenu menu) { + SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId()); + return EmptyUtil.isNotEmpty(info) && !info.getMenuId().equals(menu.getMenuId()); + } + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean hasChildByMenuId(Long menuId) { + return menuMapper.hasChildByMenuId(menuId) > 0; + } + + /** + * 查询菜单使用数量 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean checkMenuExistRole(Long menuId) { + return roleMenuMapper.checkMenuExistRole(menuId) > 0; + } + + /** + * 根据用户ID查询菜单树信息 + * + * @param userId 用户ID + * @return 菜单列表 + */ + @Override + public List selectMenuTreeByUserId(Long userId) { + List menus = null; + if (userId != null && 1L == userId) { + menus = menuMapper.selectMenuTreeAll(); + } else { + menus = menuMapper.selectMenuTreeByUserId(userId); + } + return getChildPerms(menus, 0); + } + + @Override + public List buildMenus(List menus) { + List routers = new LinkedList(); + for (SysMenu menu : menus) { + RouterVo router = new RouterVo(); + router.setHidden("1".equals(menu.getVisible())); + router.setName(getRouteName(menu)); + router.setPath(getRouterPath(menu)); + router.setComponent(getComponent(menu)); + router.setQuery(menu.getQuery()); + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtil.equals("1", menu.getIsCache()), menu.getPath())); + List cMenus = menu.getChildren(); + if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { + router.setAlwaysShow(true); + router.setRedirect("noRedirect"); + router.setChildren(buildMenus(cMenus)); + } else if (isMenuFrame(menu)) { + router.setMeta(null); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + children.setPath(menu.getPath()); + children.setComponent(menu.getComponent()); + children.setName(StringUtil.capitalize(menu.getPath())); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtil.equals("1", menu.getIsCache()), menu.getPath())); + children.setQuery(menu.getQuery()); + childrenList.add(children); + router.setChildren(childrenList); + } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) { + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); + router.setPath("/inner"); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + String routerPath = StringUtil.replaceEach(menu.getPath(), new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""}); + children.setPath(routerPath); + children.setComponent(UserConstants.INNER_LINK); + children.setName(StringUtil.capitalize(routerPath)); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); + childrenList.add(children); + router.setChildren(childrenList); + } + routers.add(router); + } + return routers; + } + + @Override + public Set selectMenuPermsByUserId(Long userId) { + List perms = menuMapper.selectMenuPermsByUserId(userId); + Set permsSet = new HashSet<>(); + for (String perm : perms) { + if (StringUtil.isNotEmpty(perm)) { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + + /** + * 获取组件信息 + * + * @param menu 菜单信息 + * @return 组件信息 + */ + public String getComponent(SysMenu menu) { + String component = UserConstants.LAYOUT; + if (StringUtil.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) { + component = menu.getComponent(); + } else if (StringUtil.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) { + component = UserConstants.INNER_LINK; + } else if (StringUtil.isEmpty(menu.getComponent()) && isParentView(menu)) { + component = UserConstants.PARENT_VIEW; + } + return component; + } + + /** + * 是否为parent_view组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + private boolean isParentView(SysMenu menu) { + return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()); + } + + /** + * 获取路由地址 + * + * @param menu 菜单信息 + * @return 路由地址 + */ + private String getRouterPath(SysMenu menu) { + String routerPath = menu.getPath(); + // 内链打开外网方式 + if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) { + routerPath = StringUtil.replaceEach(routerPath, new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""}); + } + // 非外链并且是一级目录(类型为目录) + if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) + && UserConstants.NO_FRAME.equals(menu.getIsFrame())) { + routerPath = "/" + menu.getPath(); + } + // 非外链并且是一级目录(类型为菜单) + else if (isMenuFrame(menu)) { + routerPath = "/"; + } + return routerPath; + } + + /** + * 是否为内链组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + private boolean isInnerLink(SysMenu menu) { + return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtil.ishttp(menu.getPath()); + } + + /** + * 获取路由名称 + * + * @param menu 菜单信息 + * @return 路由名称 + */ + private String getRouteName(SysMenu menu) { + String routerName = StringUtil.capitalize(menu.getPath()); + // 非外链并且是一级目录(类型为目录) + if (isMenuFrame(menu)) { + routerName = StringUtil.EMPTY; + } + return routerName; + } + + /** + * 是否为菜单内部跳转 + * + * @param menu 菜单信息 + * @return 结果 + */ + private boolean isMenuFrame(SysMenu menu) { + return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) + && menu.getIsFrame().equals(UserConstants.NO_FRAME); + } + + /** + * 根据父节点的ID获取所有子节点 + * + * @param list 分类表 + * @param parentId 父节点ID + * @return List 所有子节点 + */ + private List getChildPerms(List list, int parentId) { + List returnList = new ArrayList<>(); + for (SysMenu t : list) { + // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点 + if (t.getParentId() == parentId) { + recursionFn(list, t); + returnList.add(t); + } + } + return returnList; + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysPermissionServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysPermissionServiceImpl.java new file mode 100644 index 0000000..c2582db --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysPermissionServiceImpl.java @@ -0,0 +1,35 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.SysMenuService; +import com.ailanyin.admin.service.SysPermissionService; +import com.ailanyin.admin.service.SysRoleService; +import com.ailanyin.model.SysUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 15:56 + */ +@Service +public class SysPermissionServiceImpl implements SysPermissionService { + + @Autowired + private SysRoleService sysRoleService; + @Autowired + private SysMenuService sysMenuService; + + @Override + public Set getRolePermission(SysUser user) { + return sysRoleService.selectRolePermissionByUserId(user.getUserId()); + } + + @Override + public Set getMenuPermission(SysUser user) { + return sysMenuService.selectMenuPermsByUserId(user.getUserId()); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysPostServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysPostServiceImpl.java new file mode 100644 index 0000000..4da39ff --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysPostServiceImpl.java @@ -0,0 +1,164 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.SysPostService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.mapper.SysPostMapper; +import com.ailanyin.mapper.SysUserPostMapper; +import com.ailanyin.model.SysPost; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 14:43 + */ +@Service +public class SysPostServiceImpl implements SysPostService { + + @Autowired + private SysUserService sysUserService; + + @Resource + private SysPostMapper postMapper; + @Resource + private SysUserPostMapper userPostMapper; + + /** + * 增加岗位 + * + * @param post post + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void insertPost(SysPost post) { + if (checkPostNameNotUnique(post)) { + Asserts.fail("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } else if (checkPostCodeNotUnique(post)) { + Asserts.fail("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + post.setCreateBy(sysUserService.getCurrentUser().getUserName()); + post.setCreateTime(new Date()); + postMapper.insertPost(post); + } + + /** + * 修改岗位 + * + * @param post post + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePost(SysPost post) { + if (checkPostNameNotUnique(post)) { + Asserts.fail("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } else if (checkPostCodeNotUnique(post)) { + Asserts.fail("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + post.setUpdateBy(sysUserService.getCurrentUser().getUserName()); + post.setUpdateTime(new Date()); + postMapper.updatePost(post); + } + + /** + * 批量删除岗位 + * + * @param postIds ids + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePostByIds(Long[] postIds) { + for (Long postId : postIds) { + SysPost post = selectPostById(postId); + if (countUserPostById(postId) > 0) { + Asserts.fail(String.format("%1$s已分配,不能删除", post.getPostName())); + } + } + postMapper.deletePostByIds(postIds); + } + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + @Override + public SysPost selectPostById(Long postId) { + return postMapper.selectPostById(postId); + } + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + @Override + public int countUserPostById(Long postId) { + return userPostMapper.countUserPostById(postId); + } + + /** + * 查询全部岗位 + * + * @return 全部岗位集合 + */ + @Override + public List selectPostAll() { + return postMapper.selectPostAll(); + } + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + @Override + public List selectPostListByUserId(Long userId) { + return postMapper.selectPostListByUserId(userId); + } + + /** + * 查询岗位列表 + * + * @param post 查询条件 + * @return List + */ + @Override + public List selectPostList(SysPost post) { + return postMapper.selectPostList(post); + } + + /** + * 校验岗位名称 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public boolean checkPostNameNotUnique(SysPost post) { + SysPost info = postMapper.checkPostNameUnique(post.getPostName()); + return EmptyUtil.isNotEmpty(info) && !info.getPostId().equals(post.getPostId()); + } + + /** + * 校验岗位编码 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public boolean checkPostCodeNotUnique(SysPost post) { + SysPost info = postMapper.checkPostCodeUnique(post.getPostCode()); + return EmptyUtil.isNotEmpty(info) && !info.getPostId().equals(post.getPostId()); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysRoleServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..d02d04b --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,391 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.SysRoleService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.common.annotation.DataScope; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.common.utils.SpringUtil; +import com.ailanyin.common.utils.StringUtil; +import com.ailanyin.mapper.*; +import com.ailanyin.model.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.*; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 13:03 + */ +@Service +@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) +public class SysRoleServiceImpl implements SysRoleService { + + @Autowired + private SysUserService sysUserService; + + @Resource + private SysMenuMapper menuMapper; + @Resource + private SysRoleMapper roleMapper; + @Resource + private SysRoleMenuMapper roleMenuMapper; + @Resource + private SysRoleDeptMapper roleDeptMapper; + @Resource + private SysUserRoleMapper userRoleMapper; + + + /** + * 新增角色 + * + * @param role role + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void insertRole(SysRole role) { + if (checkRoleNameNotUnique(role)) { + Asserts.fail("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } else if (checkRoleKeyNotUnique(role)) { + Asserts.fail("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + + role.setCreateBy(sysUserService.getCurrentUser().getUserName()); + role.setCreateTime(new Date()); + roleMapper.insertRole(role); + insertRoleMenu(role); + } + + /** + * 修改角色 + * + * @param role role + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateRole(SysRole role) { + checkRoleAllowed(role); + if (checkRoleNameNotUnique(role)) { + Asserts.fail("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } else if (checkRoleKeyNotUnique(role)) { + Asserts.fail("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + + role.setUpdateBy(sysUserService.getCurrentUser().getUserName()); + role.setUpdateTime(new Date()); + // 修改角色信息 + roleMapper.updateRole(role); + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId()); + // 重新建立关系 + insertRoleMenu(role); + } + + /** + * 校验角色名称是否不唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public boolean checkRoleNameNotUnique(SysRole role) { + SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName()); + return EmptyUtil.isNotEmpty(info) && !info.getRoleId().equals(role.getRoleId()); + } + + /** + * 校验角色权限是否不唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public boolean checkRoleKeyNotUnique(SysRole role) { + SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey()); + return EmptyUtil.isNotEmpty(info) && !info.getRoleId().equals(role.getRoleId()); + } + + /** + * 校验角色是否允许操作 + * + * @param role 角色信息 + */ + @Override + public void checkRoleAllowed(SysRole role) { + if (EmptyUtil.isNotEmpty(role.getRoleId()) && role.isAdmin()) { + Asserts.fail("不允许操作超级管理员角色"); + } + } + + /** + * 保存修改数据权限 + * + * @param role role + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void authDataScope(SysRole role) { + // 修改角色信息 + roleMapper.updateRole(role); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId()); + // 新增角色和部门信息(数据权限) + insertRoleDept(role); + } + + /** + * 状态修改 + * + * @param role role + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateRoleStatus(SysRole role) { + roleMapper.updateRole(role); + } + + /** + * 批量删除角色 + * + * @param roleIds 角色 ids + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteRoleByIds(Long[] roleIds) { + for (Long roleId : roleIds) { + checkRoleAllowed(new SysRole(roleId)); + SysRole role = selectRoleById(roleId); + if (countUserRoleByRoleId(roleId) > 0) { + Asserts.fail(String.format("%1$s已分配,不能删除", role.getRoleName())); + } + } + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenu(roleIds); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDept(roleIds); + roleMapper.deleteRoleByIds(roleIds); + } + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + @Override + public SysRole selectRoleById(Long roleId) { + checkRoleDataScope(roleId); + return roleMapper.selectRoleById(roleId); + } + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + public int countUserRoleByRoleId(Long roleId) { + return userRoleMapper.countUserRoleByRoleId(roleId); + } + + /** + * 查询所有角色 + * + * @return 所有角色 + */ + @Override + public List selectRoleAll() { + return SpringUtil.getAopProxy(this).selectRoleList(new SysRole()); + } + + /** + * 批量选择授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要删除的用户数据ID + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void insertAuthUsers(Long roleId, Long[] userIds) { + // 新增用户与角色管理 + List list = new ArrayList<>(); + for (Long userId : userIds) { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + userRoleMapper.batchUserRole(list); + } + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要取消授权的用户数据ID + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteAuthUsers(Long roleId, Long[] userIds) { + userRoleMapper.deleteUserRoleInfos(roleId, userIds); + } + + /** + * 取消授权用户角色 + * + * @param userRole userRole + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteAuthUser(SysUserRole userRole) { + userRoleMapper.deleteUserRoleInfo(userRole); + } + + /** + * 查询角色列表 + * + * @param role 查询条件 + * @return 角色集合 + */ + @Override + @DataScope(deptAlias = "d") + public List selectRoleList(SysRole role) { + return roleMapper.selectRoleList(role); + } + + /** + * 查询用户拥有的所有角色 + * + * @param userId 用户 id + * @return 角色列表 + */ + @Override + public List selectRolesByUserId(Long userId) { + List userRoles = roleMapper.selectRolePermissionByUserId(userId); + List roles = selectRoleAll(); + for (SysRole role : roles) { + for (SysRole userRole : userRoles) { + if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) { + role.setFlag(true); + break; + } + } + } + return roles; + } + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + @Override + public List selectRoleListByUserId(Long userId) { + return roleMapper.selectRoleListByUserId(userId); + } + + /** + * 根据用户ID查询角色权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + @Override + public Set selectRolePermissionByUserId(Long userId) { + List perms = roleMapper.selectRolePermissionByUserId(userId); + Set permsSet = new HashSet<>(); + for (SysRole perm : perms) { + if (StringUtil.isNotNull(perm)) { + permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(","))); + } + } + return permsSet; + } + + /** + * 新增角色菜单信息 + * + * @param role 角色对象 + */ + @Transactional(rollbackFor = Exception.class) + public void insertRoleMenu(SysRole role) { + // 新增用户与角色管理 + List list = new ArrayList<>(); + for (Long menuId : role.getMenuIds()) { + SysRoleMenu rm = new SysRoleMenu(); + rm.setRoleId(role.getRoleId()); + rm.setMenuId(menuId); + list.add(rm); + } + if (list.size() > 0) { + roleMenuMapper.batchRoleMenu(list); + } + + } + + /** + * 新增角色部门信息(数据权限) + * + * @param role 角色对象 + */ + @Transactional(rollbackFor = Exception.class) + public void insertRoleDept(SysRole role) { + // 新增角色与部门(数据权限)管理 + List list = new ArrayList<>(); + for (Long deptId : role.getDeptIds()) { + SysRoleDept rd = new SysRoleDept(); + rd.setRoleId(role.getRoleId()); + rd.setDeptId(deptId); + list.add(rd); + } + if (list.size() > 0) { + roleDeptMapper.batchRoleDept(list); + } + + } + + /** + * 校验角色是否有数据权限 + * + * @param roleId 角色id + */ + @Override + public void checkRoleDataScope(Long roleId) { + if (!sysUserService.getCurrentUser().isAdmin()) { + SysRole role = new SysRole(); + role.setRoleId(roleId); + List roles = SpringUtil.getAopProxy(this).selectRoleList(role); + if (StringUtil.isEmpty(roles)) { + Asserts.fail("没有权限访问角色数据!"); + } + } + } + + /** + * 重置超级管理员权限 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void refreshRole() { + //查询所有菜单 + List sysMenus = menuMapper.selectMenuList(new SysMenu()); + Long[] menuIds = new Long[sysMenus.size()]; + for (int i = 0; i < sysMenus.size(); i++) { + menuIds[i] = sysMenus.get(i).getMenuId(); + } + SysRole role = new SysRole(); + role.setRoleId(1L); + role.setMenuIds(menuIds); + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId()); + // 重新建立关系 + insertRoleMenu(role); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysUserServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..fe02e9e --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/SysUserServiceImpl.java @@ -0,0 +1,538 @@ +package com.ailanyin.admin.service.impl; + +import com.ailanyin.admin.service.CommonFileService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.admin.vo.LoginUser; +import com.ailanyin.common.annotation.DataScope; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.common.utils.EmptyUtil; +import com.ailanyin.common.utils.SpringUtil; +import com.ailanyin.mapper.*; +import com.ailanyin.model.*; +import com.ailanyin.security.service.SecurityUserService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 14:23 + */ +@Service +@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) +public class SysUserServiceImpl implements SysUserService { + + + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private SecurityUserService securityUserService; + @Autowired + private CommonFileService commonFileService; + @Resource + private SysUserMapper userMapper; + @Resource + private SysRoleMapper roleMapper; + @Resource + private SysPostMapper postMapper; + @Resource + private SysUserPostMapper userPostMapper; + @Resource + private SysUserRoleMapper userRoleMapper; + + + /** + * 获取当前登录的用户信息 + * + * @return sysUser + */ + @Override + public SysUser getCurrentUser() { + try { + SecurityContext ctx = SecurityContextHolder.getContext(); + Authentication auth = ctx.getAuthentication(); + LoginUser adminUserDetails = (LoginUser) auth.getPrincipal(); + return adminUserDetails.getUser(); + } catch (Exception e) { + return null; + } + } + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @param user 查询条件 + * @return 用户集合 + */ + @Override + public List selectAllocatedList(SysUser user) { + return userMapper.selectAllocatedList(user); + } + + /** + * 新增用户 + * + * @param user user + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void insertUser(SysUser user) { + if (checkUserNameNotUnique(user.getUserName())) { + Asserts.fail("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); + } + + if (EmptyUtil.isNotEmpty(user.getPassword())) { + //加密密码 + user.setPassword(passwordEncoder.encode(user.getPassword())); + } + + user.setCreateTime(new Date()); + if (EmptyUtil.isNotEmpty(getCurrentUser())) { + user.setCreateBy(getCurrentUser().getUserName()); + } + // 新增用户信息 + userMapper.insertUser(user); + + if (EmptyUtil.isNotEmpty(user.getPostIds())) { + // 新增用户岗位关联 + insertUserPost(user); + } + + if (EmptyUtil.isNotEmpty(user.getRoleIds())) { + // 新增用户与角色管理 + insertUserRole(user); + } + + } + + /** + * 新增用户岗位信息 + * + * @param user user + */ + @Transactional(rollbackFor = Exception.class) + public void insertUserPost(SysUser user) { + Long[] posts = user.getPostIds(); + if (EmptyUtil.isNotEmpty(posts)) { + // 新增用户与岗位管理 + List list = new ArrayList<>(); + for (Long postId : posts) { + SysUserPost up = new SysUserPost(); + up.setUserId(user.getUserId()); + up.setPostId(postId); + list.add(up); + } + if (list.size() > 0) { + userPostMapper.batchUserPost(list); + } + } + } + + /** + * 新增用户角色信息 + * + * @param user 用户对象 + */ + @Transactional(rollbackFor = Exception.class) + public void insertUserRole(SysUser user) { + Long[] roles = user.getRoleIds(); + if (EmptyUtil.isNotEmpty(roles)) { + // 新增用户与角色管理 + List list = new ArrayList<>(); + for (Long roleId : roles) { + SysUserRole ur = new SysUserRole(); + ur.setUserId(user.getUserId()); + ur.setRoleId(roleId); + list.add(ur); + } + if (list.size() > 0) { + userRoleMapper.batchUserRole(list); + } + } + } + + /** + * 校验用户名称是否不唯一 + * + * @param userName 用户名称 + * @return 结果 + */ + @Override + public boolean checkUserNameNotUnique(String userName) { + return userMapper.checkUserNameUnique(userName) > 0; + } + + /** + * 更新用户信息 + * + * @param user user + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUser(SysUser user) { + checkUserAllowed(user); + + Long userId = user.getUserId(); + + if (EmptyUtil.isNotEmpty(user.getPostIds())) { + // 删除用户与岗位关联 + userPostMapper.deleteUserPostByUserId(userId); + // 新增用户与岗位管理 + insertUserPost(user); + } + + if (EmptyUtil.isNotEmpty(user.getRoleIds())) { + // 删除用户与角色关联 + userRoleMapper.deleteUserRoleByUserId(userId); + // 新增用户与角色管理 + insertUserRole(user); + } + + delUserDetails(user); + user.setUpdateTime(new Date()); + if (EmptyUtil.isNotEmpty(getCurrentUser())) { + user.setUpdateBy(getCurrentUser().getUserName()); + } + userMapper.updateUser(user); + } + + /** + * 校验用户是否允许操作 + * + * @param user 用户信息 + */ + @Override + public void checkUserAllowed(SysUser user) { + if (EmptyUtil.isNotEmpty(user.getUserId()) && user.isAdmin()) { + Asserts.fail("不允许操作超级管理员用户"); + } + } + + /** + * 批量删除用户 + * + * @param userIds ids + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteUserByIds(Long[] userIds) { + for (Long userId : userIds) { + checkUserAllowed(new SysUser(userId)); + } + // 删除用户与角色关联 + userRoleMapper.deleteUserRole(userIds); + // 删除用户与岗位关联 + userPostMapper.deleteUserPost(userIds); + // 删除用户 + userMapper.deleteUserByIds(userIds); + // 删除userDetailsMap中的数据 + for (Long userId : userIds) { + SysUser sysUser = userMapper.selectUserById(userId); + delUserDetails(sysUser); + } + } + + /** + * 重置密码 + * + * @param user user + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void resetPwd(SysUser user) { + user.setPassword(passwordEncoder.encode(user.getPassword())); + userMapper.updateUser(user); + delUserDetails(user); + } + + /** + * 修改状态 + * + * @param user user + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserStatus(SysUser user) { + checkUserAllowed(user); + delUserDetails(user); + userMapper.updateUser(user); + } + + /** + * 通过 id 查询 + * + * @param userId userId + * @return return + */ + @Override + public SysUser selectUserById(Long userId) { + return userMapper.selectUserById(userId); + } + + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void insertUserAuth(Long userId, Long[] roleIds) { + userRoleMapper.deleteUserRoleByUserId(userId); + insertUserRole(userId, roleIds); + } + + /** + * 校验用户是否有数据权限 + * + * @param userId 用户id + */ + @Override + public void checkUserDataScope(Long userId) { + if (!getCurrentUser().isAdmin()) { + SysUser user = new SysUser(); + user.setUserId(userId); + List users = SpringUtil.getAopProxy(this).selectUserList(user); + if (EmptyUtil.isEmpty(users)) { + Asserts.fail("没有权限访问用户数据!"); + } + } + } + + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUserList(SysUser user) { + return userMapper.selectUserList(user); + } + + /** + * 新增用户角色信息 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + @Transactional(rollbackFor = Exception.class) + public void insertUserRole(Long userId, Long[] roleIds) { + if (EmptyUtil.isNotEmpty(roleIds)) { + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long roleId : roleIds) { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + if (list.size() > 0) { + userRoleMapper.batchUserRole(list); + } + } + } + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUnallocatedList(SysUser user) { + return userMapper.selectUnallocatedList(user); + } + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + @Override + public SysUser selectUserByUserName(String userName) { + return userMapper.selectUserByUserName(userName); + } + + /** + * 导入用户列表 + * + * @param list 用户列表 + * @param updateSupport 是否更新已经存在的数量 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void importData(List list, boolean updateSupport) { + list.stream() + .filter(sysUser -> EmptyUtil.isNotEmpty(sysUser.getUserName())) + .forEach(sysUser -> { + //更新已经存在的用户 + if (updateSupport) { + //说明存在 + SysUser userByUserName = userMapper.selectUserByUserName(sysUser.getUserName()); + if (EmptyUtil.isNotEmpty(userByUserName)) { + sysUser.setUserId(userByUserName.getUserId()); + updateUser(sysUser); + } else { + insertUser(sysUser); + } + } else { + if (checkUserNameNotUnique(sysUser.getUserName())) { + Asserts.fail("登录账号: " + sysUser.getUserName() + " 已经存在,导入失败!"); + } + + insertUser(sysUser); + } + }); + + } + + /** + * 已删除用户列表 + * + * @param user user + * @return list + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectDeleteUserList(SysUser user) { + return userMapper.selectDeleteUserList(user); + } + + /** + * 恢复已删除的用户 + * + * @param ids ids + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void recoveryDeleteUser(List ids) { + userMapper.recoveryDeleteUser(ids); + } + + /** + * 彻底删除用户 + * + * @param ids ids + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void realDeleteUser(List ids) { + userMapper.realDeleteUser(ids); + } + + /** + * 查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserRoleGroup(String userName) { + List list = roleMapper.selectRolesByUserName(userName); + StringBuilder idsStr = new StringBuilder(); + for (SysRole role : list) { + idsStr.append(role.getRoleName()).append(","); + } + if (StringUtils.isNotEmpty(idsStr.toString())) { + return idsStr.substring(0, idsStr.length() - 1); + } + return idsStr.toString(); + } + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserPostGroup(String userName) { + List list = postMapper.selectPostsByUserName(userName); + StringBuilder idsStr = new StringBuilder(); + for (SysPost post : list) { + idsStr.append(post.getPostName()).append(","); + } + if (StringUtils.isNotEmpty(idsStr.toString())) { + return idsStr.substring(0, idsStr.length() - 1); + } + return idsStr.toString(); + } + + /** + * 用户自主修改基本信息 + * + * @param user user + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateProfile(SysUser user) { + SysUser currentUser = getCurrentUser(); + user.setUserId(currentUser.getUserId()); + user.setUpdateTime(new Date()); + user.setUpdateBy(currentUser.getUserName()); + userMapper.updateUser(user); + delUserDetails(user); + } + + /** + * 用户自主修改密码 + * + * @param oldPassword 旧密码 + * @param newPassword 新密码 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePwd(String oldPassword, String newPassword) { + SysUser user = getCurrentUser(); + if (!passwordEncoder.matches(oldPassword, user.getPassword())) { + Asserts.fail("旧密码错误!"); + } + user.setPassword(passwordEncoder.encode(newPassword)); + userMapper.resetUserPwd(user.getUserName(), user.getPassword()); + delUserDetails(user); + } + + /** + * 更新头像 + * + * @param file file + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateAvatar(MultipartFile file) { + String fileUrl = commonFileService.fileUpload(file); + SysUser user = getCurrentUser(); + user.setAvatar(fileUrl); + userMapper.updateUserAvatar(user.getUserName(), user.getAvatar()); + delUserDetails(user); + } + + /** + * 删除UserDetailsMap中的数据 + * + * @param user user + */ + private void delUserDetails(SysUser user) { + if (EmptyUtil.isEmpty(user.getUserName())) { + user.setUserName(userMapper.selectUserById(user.getUserId()).getUserName()); + } + securityUserService.delUserDetailsFromMap(user.getUserName()); + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/UserDetailsServiceImpl.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/UserDetailsServiceImpl.java new file mode 100644 index 0000000..4e899c8 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/service/impl/UserDetailsServiceImpl.java @@ -0,0 +1,56 @@ +package com.ailanyin.admin.service.impl; + + +import com.ailanyin.admin.service.SysPermissionService; +import com.ailanyin.admin.service.SysUserService; +import com.ailanyin.admin.vo.LoginUser; +import com.ailanyin.common.enums.UserEnum; +import com.ailanyin.common.exception.Asserts; +import com.ailanyin.common.utils.StringUtil; +import com.ailanyin.model.SysUser; +import com.ailanyin.security.service.SecurityUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +/** + * 用户验证处理 + * + * @author ruoyi + */ +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + + @Autowired + private SysUserService userService; + @Autowired + private SysPermissionService permissionService; + @Autowired + private SecurityUserService securityUserService; + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + + if (securityUserService.getUserDetailsFromMap(username) != null) { + return securityUserService.getUserDetailsFromMap(username); + } + + SysUser user = userService.selectUserByUserName(username); + if (StringUtil.isNull(user)) { + Asserts.fail("登录用户:" + username + " 不存在"); + } else if (UserEnum.DELETED.getCode().equals(user.getDelFlag())) { + Asserts.fail("对不起,您的账号:" + username + " 已被删除"); + } else if (UserEnum.DISABLE.getCode().equals(user.getStatus())) { + Asserts.fail("对不起,您的账号:" + username + " 已停用"); + } + UserDetails userDetails = createUserDetails(user); + securityUserService.addUserDetailsToMap(username,userDetails); + return userDetails; + } + + private UserDetails createUserDetails(SysUser user) { + return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user)); + } + +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/LoginBodyVo.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/LoginBodyVo.java new file mode 100644 index 0000000..7a1731b --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/LoginBodyVo.java @@ -0,0 +1,69 @@ +package com.ailanyin.admin.vo; + +/** + * 用户登录对象 + * + * @author ruoyi + */ +public class LoginBodyVo +{ + /** + * 用户名 + */ + private String username; + + /** + * 用户密码 + */ + private String password; + + /** + * 验证码 + */ + private String code; + + /** + * 唯一标识 + */ + private String uuid = ""; + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getCode() + { + return code; + } + + public void setCode(String code) + { + this.code = code; + } + + public String getUuid() + { + return uuid; + } + + public void setUuid(String uuid) + { + this.uuid = uuid; + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/LoginUser.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/LoginUser.java new file mode 100644 index 0000000..25f0eb3 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/LoginUser.java @@ -0,0 +1,236 @@ +package com.ailanyin.admin.vo; + +import com.ailanyin.model.SysUser; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 登录用户身份权限 + * + * @author ruoyi + */ +public class LoginUser implements UserDetails { + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + private Long userId; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户唯一标识 + */ + private String token; + + /** + * 登录时间 + */ + private Long loginTime; + + /** + * 过期时间 + */ + private Long expireTime; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 权限列表 + */ + private Set permissions; + + /** + * 用户信息 + */ + private SysUser user; + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getDeptId() { + return deptId; + } + + public void setDeptId(Long deptId) { + this.deptId = deptId; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public LoginUser() { + } + + public LoginUser(SysUser user, Set permissions) { + this.user = user; + this.permissions = permissions; + } + + public LoginUser(Long userId, Long deptId, SysUser user, Set permissions) { + this.userId = userId; + this.deptId = deptId; + this.user = user; + this.permissions = permissions; + } + + @Override + public String getPassword() { + return user.getPassword(); + } + + @Override + public String getUsername() { + return user.getUserName(); + } + + /** + * 账户是否未过期,过期无法验证 + */ + @Override + public boolean isAccountNonExpired() { + return true; + } + + /** + * 指定用户是否解锁,锁定的用户无法进行身份验证 + * + */ + @Override + public boolean isAccountNonLocked() { + return true; + } + + /** + * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证 + * + * @return boolean + */ + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + /** + * 是否可用 ,禁用的用户不能身份验证 + * + * @return boolean + */ + @Override + public boolean isEnabled() { + return true; + } + + public Long getLoginTime() { + return loginTime; + } + + public void setLoginTime(Long loginTime) { + this.loginTime = loginTime; + } + + public String getIpaddr() { + return ipaddr; + } + + public void setIpaddr(String ipaddr) { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) { + this.loginLocation = loginLocation; + } + + public String getBrowser() { + return browser; + } + + public void setBrowser(String browser) { + this.browser = browser; + } + + public String getOs() { + return os; + } + + public void setOs(String os) { + this.os = os; + } + + public Long getExpireTime() { + return expireTime; + } + + public void setExpireTime(Long expireTime) { + this.expireTime = expireTime; + } + + public Set getPermissions() { + return permissions; + } + + public void setPermissions(Set permissions) { + this.permissions = permissions; + } + + public SysUser getUser() { + return user; + } + + public void setUser(SysUser user) { + this.user = user; + } + + + @Override + public Collection getAuthorities() { + //返回当前用户的权限 + return permissions.stream() + .filter(permission -> permission != null && !"".equals(permission) ) + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + } + + +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/MetaVo.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/MetaVo.java new file mode 100644 index 0000000..ceadbe7 --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/MetaVo.java @@ -0,0 +1,107 @@ +package com.ailanyin.admin.vo; + + +import com.ailanyin.common.utils.StringUtil; + +/** + * 路由显示信息 + * + * @author ruoyi + */ +public class MetaVo +{ + /** + * 设置该路由在侧边栏和面包屑中展示的名字 + */ + private String title; + + /** + * 设置该路由的图标,对应路径src/assets/icons/svg + */ + private String icon; + + /** + * 设置为true,则不会被 缓存 + */ + private boolean noCache; + + /** + * 内链地址(http(s)://开头) + */ + private String link; + + public MetaVo() + { + } + + public MetaVo(String title, String icon) + { + this.title = title; + this.icon = icon; + } + + public MetaVo(String title, String icon, boolean noCache) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + } + + public MetaVo(String title, String icon, String link) + { + this.title = title; + this.icon = icon; + this.link = link; + } + + public MetaVo(String title, String icon, boolean noCache, String link) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + if (StringUtil.ishttp(link)) + { + this.link = link; + } + } + + public boolean isNoCache() + { + return noCache; + } + + public void setNoCache(boolean noCache) + { + this.noCache = noCache; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public String getLink() + { + return link; + } + + public void setLink(String link) + { + this.link = link; + } +} diff --git a/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/RouterVo.java b/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/RouterVo.java new file mode 100644 index 0000000..c37a7de --- /dev/null +++ b/ailanyin-admin/src/main/java/com/ailanyin/admin/vo/RouterVo.java @@ -0,0 +1,146 @@ +package com.ailanyin.admin.vo; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:02 + */ +public class RouterVo { + + /** + * 路由名字 + */ + private String name; + + /** + * 路由地址 + */ + private String path; + + /** + * 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现 + */ + private boolean hidden; + + /** + * 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + */ + private String redirect; + + /** + * 组件地址 + */ + private String component; + + /** + * 路由参数:如 {"id": 1, "name": "ry"} + */ + private String query; + + /** + * 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + */ + private Boolean alwaysShow; + + /** + * 其他元素 + */ + private MetaVo meta; + + /** + * 子路由 + */ + private List children; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public boolean getHidden() + { + return hidden; + } + + public void setHidden(boolean hidden) + { + this.hidden = hidden; + } + + public String getRedirect() + { + return redirect; + } + + public void setRedirect(String redirect) + { + this.redirect = redirect; + } + + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public String getQuery() + { + return query; + } + + public void setQuery(String query) + { + this.query = query; + } + + public Boolean getAlwaysShow() + { + return alwaysShow; + } + + public void setAlwaysShow(Boolean alwaysShow) + { + this.alwaysShow = alwaysShow; + } + + public MetaVo getMeta() + { + return meta; + } + + public void setMeta(MetaVo meta) + { + this.meta = meta; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/ailanyin-admin/src/main/resources/META-INF/MANIFEST.MF b/ailanyin-admin/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..9b63240 --- /dev/null +++ b/ailanyin-admin/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: com.ailanyin.admin.AdminApplication + diff --git a/ailanyin-admin/src/main/resources/application-dev.yml b/ailanyin-admin/src/main/resources/application-dev.yml new file mode 100644 index 0000000..b0a3ace --- /dev/null +++ b/ailanyin-admin/src/main/resources/application-dev.yml @@ -0,0 +1,24 @@ +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + druid: + url: jdbc:dm://127.0.0.1:5236/AITEST?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: ROOT + password: root12345 + driver-class-name: dm.jdbc.driver.DmDriver + validation-query: SELECT 1 + + + redis: + host: localhost # Redis服务器地址 + database: 0 # Redis数据库索引(默认为0) + port: 6379 # Redis服务器连接端口 + password: # Redis服务器连接密码(默认为空) + timeout: 10s + +logging: + level: + com.ailanyin.mapper : debug + +upload: + path: D:/${spring.application.name}/uploadPath/ diff --git a/ailanyin-admin/src/main/resources/application-prod.yml b/ailanyin-admin/src/main/resources/application-prod.yml new file mode 100644 index 0000000..8fa24e2 --- /dev/null +++ b/ailanyin-admin/src/main/resources/application-prod.yml @@ -0,0 +1,19 @@ +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + druid: + url: jdbc:dm://localhost:5236/AITEST?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: ROOT + password: root12345 + driver-class-name: dm.jdbc.driver.DmDriver + + redis: + host: localhost # Redis服务器地址 + database: 0 # Redis数据库索引(默认为0) + port: 6379 # Redis服务器连接端口 + password: # Redis服务器连接密码(默认为空) + timeout: 10s + +upload: + path: /opt/${spring.application.name}/uploadPath + diff --git a/ailanyin-admin/src/main/resources/application.yml b/ailanyin-admin/src/main/resources/application.yml new file mode 100644 index 0000000..806a128 --- /dev/null +++ b/ailanyin-admin/src/main/resources/application.yml @@ -0,0 +1,35 @@ +server: + port: 1818 +spring: + application: + # name 是整个项目【文件服务】根路径的名称 也是【redis】根目录的名称 + name: vis389-boot + profiles: + active: prod # dev == windows == 开发, prod == linux == 线上 + servlet: + multipart: + enabled: true #开启文件上传 + max-file-size: 10MB #限制文件上传大小为10M + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + + resources: + static-locations: classpath:/META-INF/resources/, + classpath:/resources/, + classpath:/static/, + classpath:/public/, + file:${upload.path} +# MyBatis配置 +mybatis: + # 搜索指定包别名 + typeAliasesPackage: com.ailanyin.model + +redis: + database: ${spring.application.name} + +jwt: + tokenHeader: Authorization #JWT存储的请求头 + secret: vsBxki3ZRgp6zCpwCltuGTIaTpZPBTeZdahuidiuaduibauidauidbaiu #JWT加解密使用的密钥 + expiration: 604800 #JWT的超期限时间(60*60*24*7) + tokenHead: 'Bearer ' #JWT负载中拿到开头 diff --git a/ailanyin-admin/src/test/java/com/ailanyin/test/RoleTest.java b/ailanyin-admin/src/test/java/com/ailanyin/test/RoleTest.java new file mode 100644 index 0000000..5f8c7b9 --- /dev/null +++ b/ailanyin-admin/src/test/java/com/ailanyin/test/RoleTest.java @@ -0,0 +1,23 @@ +package com.ailanyin.test; + +import com.ailanyin.admin.AdminApplication; +import com.ailanyin.admin.service.SysRoleService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/26 0026 下午 14:45 + */ +@SpringBootTest(classes = AdminApplication.class) +public class RoleTest { + + @Autowired + private SysRoleService roleService; + @Test + public void testRefreshRole() { + roleService.refreshRole(); + } +} diff --git a/ailanyin-common/pom.xml b/ailanyin-common/pom.xml new file mode 100644 index 0000000..a31a650 --- /dev/null +++ b/ailanyin-common/pom.xml @@ -0,0 +1,82 @@ + + + + vis389_backend + com.ailanyin + 1.0-SNAPSHOT + + 4.0.0 + + ailanyin-common + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.data + spring-data-commons + + + + org.apache.commons + commons-lang3 + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + com.github.xiaoymin + knife4j-spring-boot-starter + + + + io.springfox + springfox-spring-web + + + + com.alibaba + fastjson + + + + cn.afterturn + easypoi-spring-boot-starter + + + + com.aliyun + aliyun-java-sdk-core + + + + com.aliyun + aliyun-java-sdk-dysmsapi + + + + com.tencentcloudapi + tencentcloud-sdk-java + + + + diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/annotation/DataScope.java b/ailanyin-common/src/main/java/com/ailanyin/common/annotation/DataScope.java new file mode 100644 index 0000000..6b5432f --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/annotation/DataScope.java @@ -0,0 +1,25 @@ +package com.ailanyin.common.annotation; + +import java.lang.annotation.*; + +/** + * 数据权限过滤注解 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 17:44 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataScope { + /** + * 部门表的别名 + */ + public String deptAlias() default ""; + + /** + * 用户表的别名 + */ + public String userAlias() default ""; +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/config/BaseRedisConfig.java b/ailanyin-common/src/main/java/com/ailanyin/common/config/BaseRedisConfig.java new file mode 100644 index 0000000..334d09a --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/config/BaseRedisConfig.java @@ -0,0 +1,76 @@ +package com.ailanyin.common.config; + +import com.ailanyin.common.service.RedisService; +import com.ailanyin.common.service.impl.RedisServiceImpl; +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +/** + * Redis 基础配置 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 17:44 + */ +@Configuration +public class BaseRedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisSerializer serializer = redisSerializer(); + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(serializer); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(serializer); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + @Bean + public RedisSerializer redisSerializer() { + //创建JSON序列化器 + Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + //实体类存在子类继承父类,必须设置 + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + //必须设置,否则无法将JSON转化为对象,会转化成Map类型 + objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); + serializer.setObjectMapper(objectMapper); + return serializer; + } + + @Bean + public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) { + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory); + //设置Redis缓存有效期为1天 + RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1)); + return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); + } + + + @Bean + public RedisService redisService() { + return new RedisServiceImpl(); + } + +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/config/BaseSwaggerConfig.java b/ailanyin-common/src/main/java/com/ailanyin/common/config/BaseSwaggerConfig.java new file mode 100644 index 0000000..d707d23 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/config/BaseSwaggerConfig.java @@ -0,0 +1,87 @@ +package com.ailanyin.common.config; + + +import com.ailanyin.common.model.SwaggerProperties; +import org.springframework.context.annotation.Bean; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.*; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; + +import java.util.ArrayList; +import java.util.List; + +/** + * Swagger 基础配置 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0004 下午 17:46 + */ +public abstract class BaseSwaggerConfig { + + @Bean + public Docket createRestApi() { + SwaggerProperties swaggerProperties = swaggerProperties(); + Docket docket = new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo(swaggerProperties)) + .select() + .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getApiBasePackage())) + .paths(PathSelectors.any()) + .build(); + if (swaggerProperties.isEnableSecurity()) { + docket.securitySchemes(securitySchemes()).securityContexts(securityContexts()); + } + return docket; + } + + private ApiInfo apiInfo(SwaggerProperties swaggerProperties) { + return new ApiInfoBuilder() + .title(swaggerProperties.getTitle()) + .description(swaggerProperties.getDescription()) + .contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail())) + .version(swaggerProperties.getVersion()) + .build(); + } + + private List securitySchemes() { + //设置请求头信息 + List result = new ArrayList<>(); + ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header"); + result.add(apiKey); + return result; + } + + private List securityContexts() { + //设置需要登录认证的路径 + List result = new ArrayList<>(); + result.add(getContextByPath()); + return result; + } + + private SecurityContext getContextByPath() { + return SecurityContext.builder() + .securityReferences(defaultAuth()) + .forPaths(PathSelectors.regex("/*/.*")) + .build(); + } + + private List defaultAuth() { + List result = new ArrayList<>(); + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + result.add(new SecurityReference("Authorization", authorizationScopes)); + return result; + } + + /** + * 自定义配置 + * + * @return Swagger自定义配置 + */ + public abstract SwaggerProperties swaggerProperties(); +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/constant/Constants.java b/ailanyin-common/src/main/java/com/ailanyin/common/constant/Constants.java new file mode 100644 index 0000000..92e4d50 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/constant/Constants.java @@ -0,0 +1,145 @@ +package com.ailanyin.common.constant; + +/** + * 通用常量信息 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0004 下午 17:46 + */ +public class Constants { + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + public static final String GBK = "GBK"; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 通用成功标识 + */ + public static final String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 注册 + */ + public static final String REGISTER = "Register"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 验证码 redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 登录用户 redis key + */ + public static final String LOGIN_TOKEN_KEY = "login_tokens:"; + + /** + * 防重提交 redis key + */ + public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; + + /** + * 限流 redis key + */ + public static final String RATE_LIMIT_KEY = "rate_limit:"; + + /** + * 验证码有效期(分钟) + */ + public static final Integer CAPTCHA_EXPIRATION = 2; + + /** + * 令牌 + */ + public static final String TOKEN = "token"; + + /** + * 令牌前缀 + */ + public static final String TOKEN_PREFIX = "Bearer "; + + /** + * 令牌前缀 + */ + public static final String LOGIN_USER_KEY = "login_user_key"; + + /** + * 用户ID + */ + public static final String JWT_USER_ID = "userid"; + + /** + * 用户头像 + */ + public static final String JWT_AVATAR = "avatar"; + + /** + * 创建时间 + */ + public static final String JWT_CREATED = "created"; + + /** + * 用户权限 + */ + public static final String JWT_AUTHORITIES = "authorities"; + + /** + * 参数管理 cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 字典管理 cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * 资源映射路径 前缀 + */ + public static final String RESOURCE_PREFIX = "/profile"; + + /** + * RMI 远程方法调用 + */ + public static final String LOOKUP_RMI = "rmi://"; + + /** + * LDAP 远程方法调用 + */ + public static final String LOOKUP_LDAP = "ldap://"; +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/constant/IErrorCode.java b/ailanyin-common/src/main/java/com/ailanyin/common/constant/IErrorCode.java new file mode 100644 index 0000000..badc624 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/constant/IErrorCode.java @@ -0,0 +1,25 @@ +package com.ailanyin.common.constant; + +/** + * 错误码 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0006 下午 17:56 + */ +public interface IErrorCode { + + /** + * 获取code + * + * @return code + */ + long getCode(); + + /** + * code的具体含义 + * + * @return msg + */ + String getMessage(); +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/constant/UserConstants.java b/ailanyin-common/src/main/java/com/ailanyin/common/constant/UserConstants.java new file mode 100644 index 0000000..c174f55 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/constant/UserConstants.java @@ -0,0 +1,128 @@ +package com.ailanyin.common.constant; + +/** + * 用户常量信息 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0006 下午 17:56 + */ +public class UserConstants { + /** + * 平台内系统用户的唯一标志 + */ + public static final String SYS_USER = "SYS_USER"; + + /** + * 正常状态 + */ + public static final String NORMAL = "0"; + + /** + * 异常状态 + */ + public static final String EXCEPTION = "1"; + + /** + * 用户封禁状态 + */ + public static final String USER_DISABLE = "1"; + + /** + * 角色封禁状态 + */ + public static final String ROLE_DISABLE = "1"; + + /** + * 部门正常状态 + */ + public static final String DEPT_NORMAL = "0"; + + /** + * 部门停用状态 + */ + public static final String DEPT_DISABLE = "1"; + + /** + * 字典正常状态 + */ + public static final String DICT_NORMAL = "0"; + + /** + * 是否为系统默认(是) + */ + public static final String YES = "Y"; + + /** + * 是否菜单外链(是) + */ + public static final String YES_FRAME = "0"; + + /** + * 是否菜单外链(否) + */ + public static final String NO_FRAME = "1"; + + /** + * 菜单类型(目录) + */ + public static final String TYPE_DIR = "M"; + + /** + * 菜单类型(菜单) + */ + public static final String TYPE_MENU = "C"; + + /** + * 菜单类型(按钮) + */ + public static final String TYPE_BUTTON = "F"; + + /** + * Layout组件标识 + */ + public final static String LAYOUT = "Layout"; + + /** + * ParentView组件标识 + */ + public final static String PARENT_VIEW = "ParentView"; + + /** + * InnerLink组件标识 + */ + public final static String INNER_LINK = "InnerLink"; + + /** + * 校验返回结果码 + */ + public final static String UNIQUE = "0"; + public final static String NOT_UNIQUE = "1"; + + /** + * 用户名长度限制 + */ + public static final int USERNAME_MIN_LENGTH = 2; + public static final int USERNAME_MAX_LENGTH = 20; + + /** + * 密码长度限制 + */ + public static final int PASSWORD_MIN_LENGTH = 5; + public static final int PASSWORD_MAX_LENGTH = 20; + + /** + * 登录相关 + */ + public static final int MAX_ERROR_COUNT = 5; + public static final String HAS_BEEN_PULLED_BLACK = "您的IP已经被系统拉黑"; + public static final String BLACKLIST_KEY = ":login:blacklist"; + public static final String LOGIN_ERROR_COUNT = ":login:errorCount:"; + public static final String BLACKLIST_ON = "true"; + public static final String BLACKLIST_ON_OFF_KEY = ":sys:config:sys.account.blacklistOnOff"; + public static final String CAPTCHA_KEY = ":login:captcha:"; + public static final String CAPTCHA_ON_OFF_KEY = ":sys:config:sys.account.captchaOnOff"; + public static final String CAPTCHA_ON = "true"; + public static final String REGISTER_ON_OFF_KEY = ":sys:config:sys.account.registerUser"; + public static final String REGISTER_ON = "true"; +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/enums/UserEnum.java b/ailanyin-common/src/main/java/com/ailanyin/common/enums/UserEnum.java new file mode 100644 index 0000000..e789e7d --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/enums/UserEnum.java @@ -0,0 +1,31 @@ +package com.ailanyin.common.enums; + +/** + * 用户状态枚举 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0004 下午 17:46 + */ +public enum UserEnum { + /** + * OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除") + */ + OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除"); + + private final String code; + private final String info; + + UserEnum(String code, String info) { + this.code = code; + this.info = info; + } + + public String getCode() { + return code; + } + + public String getInfo() { + return info; + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/exception/ApiException.java b/ailanyin-common/src/main/java/com/ailanyin/common/exception/ApiException.java new file mode 100644 index 0000000..892ca79 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/exception/ApiException.java @@ -0,0 +1,47 @@ +package com.ailanyin.common.exception; + + +import com.ailanyin.common.constant.IErrorCode; + +/** + * 自定义 API异常 + * + * @author ailanyin + * @version 1.0 + * @since 2021-08-31 + */ +public class ApiException extends RuntimeException { + private IErrorCode errorCode; + + public ApiException(IErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } + + public ApiException(String message) { + super(message); + } + + public ApiException(Throwable cause) { + super(cause); + } + + public ApiException(String message, Throwable cause) { + super(message, cause); + } + + public IErrorCode getErrorCode() { + return errorCode; + } + + + /** + * 不打印堆栈信息, 提高性能 + * + * @return this + */ + @Override + public Throwable fillInStackTrace() { + return this; + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/exception/Asserts.java b/ailanyin-common/src/main/java/com/ailanyin/common/exception/Asserts.java new file mode 100644 index 0000000..d2cdd38 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/exception/Asserts.java @@ -0,0 +1,21 @@ +package com.ailanyin.common.exception; + + +import com.ailanyin.common.constant.IErrorCode; + +/** + * 用于抛出各种异常 + * + * @author ailanyin + * @version 1.0 + * @since 2021-08-31 + */ +public class Asserts { + public static void fail(String message) { + throw new ApiException(message); + } + + public static void fail(IErrorCode errorCode) { + throw new ApiException(errorCode); + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/model/BaseEntity.java b/ailanyin-common/src/main/java/com/ailanyin/common/model/BaseEntity.java new file mode 100644 index 0000000..4d500e8 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/model/BaseEntity.java @@ -0,0 +1,115 @@ +package com.ailanyin.common.model; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 所有实体基类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:00 + */ +public class BaseEntity implements Serializable +{ + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "搜索值") + private String searchValue; + + @ApiModelProperty(value = "创建人") + private String createBy; + + @ApiModelProperty(value = "创建时间") + private Date createTime; + + @ApiModelProperty(value = "更新人") + private String updateBy; + + @ApiModelProperty(value = "更新时间") + private Date updateTime; + + @ApiModelProperty(value = "备注") + private String remark; + + @ApiModelProperty(value = "查询参数") + private Map params; + + public String getSearchValue() + { + return searchValue; + } + + public void setSearchValue(String searchValue) + { + this.searchValue = searchValue; + } + + public String getCreateBy() + { + return createBy; + } + + public void setCreateBy(String createBy) + { + this.createBy = createBy; + } + + public Date getCreateTime() + { + return createTime; + } + + public void setCreateTime(Date createTime) + { + this.createTime = createTime; + } + + public String getUpdateBy() + { + return updateBy; + } + + public void setUpdateBy(String updateBy) + { + this.updateBy = updateBy; + } + + public Date getUpdateTime() + { + return updateTime; + } + + public void setUpdateTime(Date updateTime) + { + this.updateTime = updateTime; + } + + public String getRemark() + { + return remark; + } + + public void setRemark(String remark) + { + this.remark = remark; + } + + public Map getParams() + { + if (params == null) + { + params = new HashMap<>(16); + } + return params; + } + + public void setParams(Map params) + { + this.params = params; + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/model/IdWorker.java b/ailanyin-common/src/main/java/com/ailanyin/common/model/IdWorker.java new file mode 100644 index 0000000..576a897 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/model/IdWorker.java @@ -0,0 +1,171 @@ +package com.ailanyin.common.model; + + +import java.lang.management.ManagementFactory; +import java.net.InetAddress; +import java.net.NetworkInterface; + +/** + * 分布式雪花ID + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0008 下午 18:07 + */ +public class IdWorker { + /** + * 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) + */ + private final static long BASE_TIME = 1288834974657L; + /** + * 机器标识位数 + */ + private final static long WORKER_ID_BITS = 5L; + /** + * 数据中心标识位数 + */ + private final static long DATA_CENTER_ID_BITS = 5L; + /** + * 机器ID最大值 + */ + private final static long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS); + /** + * 数据中心ID最大值 + */ + private final static long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS); + /** + * 毫秒内自增位 + */ + private final static long SEQUENCE_BITS = 12L; + /** + * 机器ID偏左移12位 + */ + private final static long WORKER_ID_LEFT = SEQUENCE_BITS; + /** + * 数据中心ID左移17位 + */ + private final static long DATA_CENTER_ID_LEFT = SEQUENCE_BITS + WORKER_ID_BITS; + /** + * 时间毫秒左移22位 + */ + private final static long TIME_STAMP_LEFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS; + /** + * 序列掩码 + */ + private final static long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS); + /** + * 上次生产id时间戳 + */ + private static long LAST_TIME_STAMP = -1L; + /** + * 并发控制 + */ + private long sequence = 0L; + + /** + * 雪花id + */ + private final long workerId; + /** + * 数据标识id部分 + */ + private final long dataCenterId; + + public IdWorker() { + this.dataCenterId = getDataCenterId(); + this.workerId = getMaxWorkerId(dataCenterId); + } + + /** + * @param workerId 工作机器ID + * @param dataCenterId 序列号 + */ + public IdWorker(long workerId, long dataCenterId) { + if (workerId > MAX_WORKER_ID || workerId < 0) { + throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", MAX_WORKER_ID)); + } + if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) { + throw new IllegalArgumentException(String.format("data center Id can't be greater than %d or less than 0", MAX_DATA_CENTER_ID)); + } + this.workerId = workerId; + this.dataCenterId = dataCenterId; + } + + /** + * 获取下一个ID + * + * @return Long id + */ + public synchronized Long nextId() { + long timestamp = timeGen(); + if (timestamp < LAST_TIME_STAMP) { + throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", LAST_TIME_STAMP - timestamp)); + } + + if (LAST_TIME_STAMP == timestamp) { + // 当前毫秒内,则+1 + sequence = (sequence + 1) & SEQUENCE_MASK; + if (sequence == 0) { + // 当前毫秒内计数满了,则等待下一秒 + timestamp = tilNextMillis(); + } + } else { + sequence = 0L; + } + LAST_TIME_STAMP = timestamp; + // ID偏移组合生成最终的ID,并返回ID + return ((timestamp - BASE_TIME) << TIME_STAMP_LEFT) + | (dataCenterId << DATA_CENTER_ID_LEFT) + | (workerId << WORKER_ID_LEFT) | sequence; + } + + private long tilNextMillis() { + long timestamp = this.timeGen(); + while (timestamp <= LAST_TIME_STAMP) { + timestamp = this.timeGen(); + } + return timestamp; + } + + private long timeGen() { + return System.currentTimeMillis(); + } + + /** + * 获取 MAX_WORKER_ID + */ + private static long getMaxWorkerId(long dataCenterId) { + StringBuffer mpId = new StringBuffer(); + mpId.append(dataCenterId); + String name = ManagementFactory.getRuntimeMXBean().getName(); + if (!name.isEmpty()) { + // GET jvmPid + mpId.append(name.split("@")[0]); + } + // MAC + PID 的 hashcode 获取16个低位 + return (mpId.toString().hashCode() & 0xffff) % (MAX_WORKER_ID + 1); + } + + /** + * 数据标识id部分 + */ + private static long getDataCenterId() { + long id = 0L; + try { + InetAddress ip = InetAddress.getLocalHost(); + NetworkInterface network = NetworkInterface.getByInetAddress(ip); + if (network == null) { + id = 1L; + } else { + byte[] mac = network.getHardwareAddress(); + id = ((0x000000FF & (long) mac[mac.length - 1]) + | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6; + id = id % (MAX_DATA_CENTER_ID + 1); + } + } catch (Exception e) { + System.out.println(" getDataCenterId: " + e.getMessage()); + } + return id; + } + +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/model/SwaggerProperties.java b/ailanyin-common/src/main/java/com/ailanyin/common/model/SwaggerProperties.java new file mode 100644 index 0000000..db66c1a --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/model/SwaggerProperties.java @@ -0,0 +1,50 @@ +package com.ailanyin.common.model; + +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * Swagger自定义配置 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 17:50 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Builder +public class SwaggerProperties { + /** + * API文档生成基础路径 + */ + private String apiBasePackage; + /** + * 是否要启用登录认证 + */ + private boolean enableSecurity; + /** + * 文档标题 + */ + private String title; + /** + * 文档描述 + */ + private String description; + /** + * 文档版本 + */ + private String version; + /** + * 文档联系人姓名 + */ + private String contactName; + /** + * 文档联系人网址 + */ + private String contactUrl; + /** + * 文档联系人邮箱 + */ + private String contactEmail; +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/result/AjaxResult.java b/ailanyin-common/src/main/java/com/ailanyin/common/result/AjaxResult.java new file mode 100644 index 0000000..95d91d2 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/result/AjaxResult.java @@ -0,0 +1,144 @@ +package com.ailanyin.common.result; + +import cn.hutool.http.HttpStatus; +import com.ailanyin.common.utils.EmptyUtil; + + +import java.util.HashMap; + +/** + * 通用返回对象 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:00 + */ +public class AjaxResult extends HashMap { + private static final long serialVersionUID = 1L; + + /** + * 状态码 + */ + private static final String CODE_TAG = "code"; + + /** + * 返回内容 + */ + private static final String MSG_TAG = "msg"; + + /** + * 数据对象 + */ + public static final String DATA_TAG = "data"; + + /** + * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 + */ + public AjaxResult() { + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + */ + public AjaxResult(int code, String msg) { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + * @param data 数据对象 + */ + public AjaxResult(int code, String msg, Object data) { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + if (EmptyUtil.isNotEmpty(data)) { + super.put(DATA_TAG, data); + } + } + + /** + * 返回成功消息 + * + * @return 成功消息 + */ + public static AjaxResult success() { + return AjaxResult.success("操作成功"); + } + + /** + * 返回成功数据 + * + * @return 成功消息 + */ + public static AjaxResult success(Object data) { + return AjaxResult.success("操作成功", data); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @return 成功消息 + */ + public static AjaxResult success(String msg) { + return AjaxResult.success(msg, null); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 成功消息 + */ + public static AjaxResult success(String msg, Object data) { + return new AjaxResult(HttpStatus.HTTP_OK, msg, data); + } + + /** + * 返回错误消息 + * + */ + public static AjaxResult error() { + return AjaxResult.error("操作失败"); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @return 警告消息 + */ + public static AjaxResult error(String msg) { + return AjaxResult.error(msg, null); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 警告消息 + */ + public static AjaxResult error(String msg, Object data) { + return new AjaxResult(HttpStatus.HTTP_INTERNAL_ERROR, msg, data); + } + + /** + * 返回错误消息 + * + * @param code 状态码 + * @param msg 返回内容 + * @return 警告消息 + */ + public static AjaxResult error(int code, String msg) { + return new AjaxResult(code, msg, null); + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/result/CommonPage.java b/ailanyin-common/src/main/java/com/ailanyin/common/result/CommonPage.java new file mode 100644 index 0000000..bd59af3 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/result/CommonPage.java @@ -0,0 +1,102 @@ +package com.ailanyin.common.result; + +import cn.hutool.http.HttpStatus; +import com.github.pagehelper.PageInfo; + +import java.io.Serializable; +import java.util.List; + +/** + * 通用分页对象 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:00 + */ +public class CommonPage implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 总记录数 */ + private long total; + + /** 列表数据 */ + private List rows; + + /** 消息状态码 */ + private int code; + + /** 消息内容 */ + private String msg; + + /** + * 将PageHelper分页后的list转为分页信息 + */ + public static CommonPage restPage(List list) { + CommonPage result = new CommonPage(); + PageInfo pageInfo = new PageInfo(list); + result.setTotal(pageInfo.getTotal()); + result.setRows(pageInfo.getList()); + result.setCode(HttpStatus.HTTP_OK); + return result; + } + + /** + * 表格数据对象 + */ + public CommonPage() + { + } + + /** + * 分页 + * + * @param list 列表数据 + * @param total 总记录数 + */ + public CommonPage(List list, int total) + { + this.rows = list; + this.total = total; + } + + public long getTotal() + { + return total; + } + + public void setTotal(long total) + { + this.total = total; + } + + public List getRows() + { + return rows; + } + + public void setRows(List rows) + { + this.rows = rows; + } + + public int getCode() + { + return code; + } + + public void setCode(int code) + { + this.code = code; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/service/RedisService.java b/ailanyin-common/src/main/java/com/ailanyin/common/service/RedisService.java new file mode 100644 index 0000000..59e17de --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/service/RedisService.java @@ -0,0 +1,341 @@ +package com.ailanyin.common.service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 自定义Redis接口 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0002 下午 17:41 + */ +public interface RedisService { + + /** + * 保存为 Set + * + * @param key key + * @param value value + * @param time 存活时间 单位秒 + */ + void set(String key, Object value, long time); + + /** + * 保存为 Set, 永久 + * + * @param key key + * @param value value + */ + void set(String key, Object value); + + /** + * 通过 key 获取值 + * + * @param key key + * @return Object + */ + Object get(String key); + + /** + * 删除 key + * + * @param key key + * @return Boolean + */ + Boolean del(String key); + + /** + * 批量删除 + * + * @param keys List keys + * @return Long 成功删除的个数 + */ + Long del(List keys); + + /** + * 设置过期时间 + * + * @param key key + * @param time 存活时间 单位秒 + * @return Boolean + */ + Boolean expire(String key, long time); + + /** + * 获取过期时间 + * + * @param key key + * @return long 单位秒 + */ + Long getExpire(String key); + + /** + * 判断是否有该属性 + * + * @param key key + * @return Boolean + */ + Boolean hasKey(String key); + + /** + * 按 delta 递增 + * + * value = value + delta + * @param key key + * @param delta 值 + * @return Long 操作后的值 + */ + Long incr(String key, long delta); + + /** + * 按 delta 递减 + * + * value = value - delta + * @param key key + * @param delta 值 + * @return Long 操作后的值 + */ + Long decr(String key, long delta); + + /** + * 获取Hash结构中的属性 + * + * @param key key + * @param hashKey hashKey + * @return Object + */ + Object hGet(String key, String hashKey); + + /** + * 向Hash结构中放入一个属性 + * + * @param key key + * @param hashKey hashKey + * @param value value + * @param time 存活时间 单位秒 + * @return Boolean + */ + Boolean hSet(String key, String hashKey, Object value, long time); + + /** + * 向Hash结构中放入一个属性 永久 + * + * @param key key + * @param hashKey hashKey + * @param value value + */ + void hSet(String key, String hashKey, Object value); + + /** + * 直接获取整个Hash结构 + * + * @param key key + * @return Map + */ + Map hGetAll(String key); + + /** + * 直接设置整个Hash结构 + * + * @param key key + * @param map map + * @param time 存活时间 单位秒 + * @return Boolean + */ + Boolean hSetAll(String key, Map map, long time); + + /** + * 直接设置整个Hash结构 + * + * @param key key + * @param map map + */ + void hSetAll(String key, Map map); + + /** + * 删除Hash结构中的属性 + * + * @param key key + * @param hashKey hashKey + */ + void hDel(String key, Object... hashKey); + + /** + * 判断Hash结构中是否有该属性 + * + * @param key key + * @param hashKey hashKey + * @return Boolean + */ + Boolean hHasKey(String key, String hashKey); + + /** + * Hash结构中属性递增 + * + * @param key key + * @param hashKey hashKey + * @param delta 数值 + * @return 操作后最终的值 + */ + Long hIncr(String key, String hashKey, Long delta); + + /** + * Hash结构中属性递减 + * + * @param key key + * @param hashKey hashKey + * @param delta 数值 + * @return 操作后最终的值 + */ + Long hDecr(String key, String hashKey, Long delta); + + /** + * 获取Set结构 + * + * @param key key + * @return Set + */ + Set sMembers(String key); + + /** + * 向Set结构中添加属性 + * + * @param key key + * @param values values + * @return 被添加到集合中的新元素的数量,不包括被忽略的元素 + */ + Long sAdd(String key, Object... values); + + /** + * 向Set结构中添加属性 + * + * @param key key + * @param time 存活时间 单位秒 + * @param values values + * @return 被添加到集合中的新元素的数量,不包括被忽略的元素 + */ + Long sAdd(String key, long time, Object... values); + + /** + * 是否为Set中的属性 + * + * @param key key + * @param value value + * @return Boolean + */ + Boolean sIsMember(String key, Object value); + + /** + * 获取Set结构的长度 + * + * @param key key + * @return Set结构的长度 + */ + Long sSize(String key); + + /** + * 删除Set结构中的属性 + * + * @param key key + * @param values values + * @return 被成功移除的元素的数量,不包括被忽略的元素 + */ + Long sRemove(String key, Object... values); + + /** + * 获取List结构中的属性 + * + * @param key key + * @param start 开始索引 + * @param end 结束索引 + * @return List + */ + List lRange(String key, long start, long end); + + /** + * 获取List结构的长度 + * + * @param key key + * @return list.size + */ + Long lSize(String key); + + /** + * 根据索引获取List中的属性 + * + * @param key key + * @param index 索引 + * @return Object + */ + Object lIndex(String key, long index); + + /** + * 向List结构中添加属性 + * @param key key + * @param value value + * @return 执行命令后,列表的长度 + */ + Long lPush(String key, Object value); + + /** + * 向List结构中添加属性 + * + * @param key key + * @param value value + * @param time 存活时间 单位秒 + * @return 执行命令后,列表的长度 + */ + Long lPush(String key, Object value, long time); + + /** + * 向List结构中批量添加属性 + * + * @param key key + * @param values values + * @return 执行命令后,列表的长度 + */ + Long lPushAll(String key, Object... values); + + /** + * 向List结构中批量添加属性 + * + * @param key key + * @param time 存活时间 单位秒 + * @param values values + * @return 执行命令后,列表的长度 + */ + Long lPushAll(String key, Long time, Object... values); + + /** + * 从List结构中移除属性 + * + * @param key key + * @param count 数量 + * count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。 + * count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。 + * count = 0 : 移除表中所有与 VALUE 相等的值。 + * @param value value + * @return 被移除元素的数量 + */ + Long lRemove(String key, long count, Object value); + + /** + * 批量添加StringList到Set集合 + * + * @param key key + * @param list List list + */ + void addStringListToSet(String key, final List list); + + /** + * 模糊查询所有key + * + * @param key key + * @return keys + */ + Collection getKeys(String key); + +} \ No newline at end of file diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/service/impl/RedisServiceImpl.java b/ailanyin-common/src/main/java/com/ailanyin/common/service/impl/RedisServiceImpl.java new file mode 100644 index 0000000..86c1ab8 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/service/impl/RedisServiceImpl.java @@ -0,0 +1,234 @@ +package com.ailanyin.common.service.impl; + + +import com.ailanyin.common.service.RedisService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * 自定义Redis接口实现类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 17:44 + */ +public class RedisServiceImpl implements RedisService { + @Autowired + private RedisTemplate redisTemplate; + + @Override + public void set(String key, Object value, long time) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } + + @Override + public void set(String key, Object value) { + redisTemplate.opsForValue().set(key, value); + } + + @Override + public Object get(String key) { + return redisTemplate.opsForValue().get(key); + } + + @Override + public Boolean del(String key) { + return redisTemplate.delete(key); + } + + @Override + public Long del(List keys) { + return redisTemplate.delete(keys); + } + + @Override + public Boolean expire(String key, long time) { + return redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + + @Override + public Long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + @Override + public Boolean hasKey(String key) { + return redisTemplate.hasKey(key); + } + + @Override + public Long incr(String key, long delta) { + return redisTemplate.opsForValue().increment(key, delta); + } + + @Override + public Long decr(String key, long delta) { + return redisTemplate.opsForValue().increment(key, -delta); + } + + @Override + public Object hGet(String key, String hashKey) { + return redisTemplate.opsForHash().get(key, hashKey); + } + + @Override + public Boolean hSet(String key, String hashKey, Object value, long time) { + redisTemplate.opsForHash().put(key, hashKey, value); + return expire(key, time); + } + + @Override + public void hSet(String key, String hashKey, Object value) { + redisTemplate.opsForHash().put(key, hashKey, value); + } + + @Override + public Map hGetAll(String key) { + return redisTemplate.opsForHash().entries(key); + } + + @Override + public Boolean hSetAll(String key, Map map, long time) { + redisTemplate.opsForHash().putAll(key, map); + return expire(key, time); + } + + @Override + public void hSetAll(String key, Map map) { + redisTemplate.opsForHash().putAll(key, map); + } + + @Override + public void hDel(String key, Object... hashKey) { + redisTemplate.opsForHash().delete(key, hashKey); + } + + @Override + public Boolean hHasKey(String key, String hashKey) { + return redisTemplate.opsForHash().hasKey(key, hashKey); + } + + @Override + public Long hIncr(String key, String hashKey, Long delta) { + return redisTemplate.opsForHash().increment(key, hashKey, delta); + } + + @Override + public Long hDecr(String key, String hashKey, Long delta) { + return redisTemplate.opsForHash().increment(key, hashKey, -delta); + } + + @Override + public Set sMembers(String key) { + return redisTemplate.opsForSet().members(key); + } + + @Override + public Long sAdd(String key, Object... values) { + return redisTemplate.opsForSet().add(key, values); + } + + @Override + public Long sAdd(String key, long time, Object... values) { + Long count = redisTemplate.opsForSet().add(key, values); + expire(key, time); + return count; + } + + @Override + public Boolean sIsMember(String key, Object value) { + return redisTemplate.opsForSet().isMember(key, value); + } + + @Override + public Long sSize(String key) { + return redisTemplate.opsForSet().size(key); + } + + @Override + public Long sRemove(String key, Object... values) { + return redisTemplate.opsForSet().remove(key, values); + } + + @Override + public List lRange(String key, long start, long end) { + return redisTemplate.opsForList().range(key, start, end); + } + + @Override + public Long lSize(String key) { + return redisTemplate.opsForList().size(key); + } + + @Override + public Object lIndex(String key, long index) { + return redisTemplate.opsForList().index(key, index); + } + + @Override + public Long lPush(String key, Object value) { + return redisTemplate.opsForList().rightPush(key, value); + } + + @Override + public Long lPush(String key, Object value, long time) { + Long index = redisTemplate.opsForList().rightPush(key, value); + expire(key, time); + return index; + } + + @Override + public Long lPushAll(String key, Object... values) { + return redisTemplate.opsForList().rightPushAll(key, values); + } + + @Override + public Long lPushAll(String key, Long time, Object... values) { + Long count = redisTemplate.opsForList().rightPushAll(key, values); + expire(key, time); + return count; + } + + @Override + public Long lRemove(String key, long count, Object value) { + return redisTemplate.opsForList().remove(key, count, value); + } + + @Override + public void addStringListToSet(String key, final List list) { + // 获取key编码方式 + final StringRedisSerializer stringRedisSerializer = (StringRedisSerializer) redisTemplate.getKeySerializer(); + final RedisSerializer valueSerializer = (RedisSerializer) redisTemplate.getValueSerializer(); + //获取key对应的byte[] + final byte[] rawKey = stringRedisSerializer.serialize(key); + redisTemplate.executePipelined(new RedisCallback() { + @Override + public Object doInRedis(RedisConnection connection) + throws DataAccessException { + for (String str : list) { + byte[] rawStr = valueSerializer.serialize(str); + connection.sAdd(rawKey, rawStr); + } + connection.closePipeline(); + return null; + } + }); + + } + + @Override + public Collection getKeys(String key) { + return redisTemplate.keys(key); + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/BigDecimalUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/BigDecimalUtil.java new file mode 100644 index 0000000..116d03d --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/BigDecimalUtil.java @@ -0,0 +1,115 @@ +package com.ailanyin.common.utils; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 精确的浮点数运算 + * + * @author ruoyi + */ +public class BigDecimalUtil +{ + + /** 默认除法运算精度 */ + private static final int DEF_DIV_SCALE = 10; + + /** 这个类不能实例化 */ + private BigDecimalUtil() + { + } + + /** + * 提供精确的加法运算。 + * @param v1 被加数 + * @param v2 加数 + * @return 两个参数的和 + */ + public static double add(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(v1); + BigDecimal b2 = new BigDecimal(v2); + return b1.add(b2).doubleValue(); + } + + /** + * 提供精确的减法运算。 + * @param v1 被减数 + * @param v2 减数 + * @return 两个参数的差 + */ + public static double sub(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(v1); + BigDecimal b2 = new BigDecimal(v2); + return b1.subtract(b2).doubleValue(); + } + + /** + * 提供精确的乘法运算。 + * @param v1 被乘数 + * @param v2 乘数 + * @return 两个参数的积 + */ + public static double mul(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(v1); + BigDecimal b2 = new BigDecimal(v2); + return b1.multiply(b2).doubleValue(); + } + + /** + * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 + * 小数点以后10位,以后的数字四舍五入。 + * @param v1 被除数 + * @param v2 除数 + * @return 两个参数的商 + */ + public static double div(double v1, double v2) + { + return div(v1, v2, DEF_DIV_SCALE); + } + + /** + * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 + * 定精度,以后的数字四舍五入。 + * @param v1 被除数 + * @param v2 除数 + * @param scale 表示表示需要精确到小数点以后几位。 + * @return 两个参数的商 + */ + public static double div(double v1, double v2, int scale) + { + if (scale < 0) + { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b1 = new BigDecimal(v1); + BigDecimal b2 = new BigDecimal(v2); + if (b1.compareTo(BigDecimal.ZERO) == 0) + { + return BigDecimal.ZERO.doubleValue(); + } + return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); + } + + /** + * 提供精确的小数位四舍五入处理。 + * @param v 需要四舍五入的数字 + * @param scale 小数点后保留几位 + * @return 四舍五入后的结果 + */ + public static double round(double v, int scale) + { + if (scale < 0) + { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b = new BigDecimal(v); + BigDecimal one = BigDecimal.ONE; + return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); + } + +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/CaptchaUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/CaptchaUtil.java new file mode 100644 index 0000000..8cc0dd4 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/CaptchaUtil.java @@ -0,0 +1,82 @@ +package com.ailanyin.common.utils; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.Random; + +/** + * 生成图片验证码工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/27 0027 上午 9:58 + */ +public class CaptchaUtil { + + private static final char[] CHARS = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z' + }; + + private static final int SIZE = 5; + + /** + * 干扰线数量 + */ + private static final int LINES = 10; + + private static final int WIDTH = 150; + + private static final int HEIGHT = 50; + + /** + * 字体大小 + */ + private static final int FONT_SIZE = 50; + + private static Color getRandomColor() { + Random ran = new Random(); + return new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256)); + } + + /** + * 生成随机验证码及图片 + */ + public static Object[] createImage() { + StringBuffer sb = new StringBuffer(); + // 1.创建一个空白图片 + BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); + // 获取图片画笔 + Graphics graphic = image.getGraphics(); + // 设置画笔颜色 + graphic.setColor(Color.LIGHT_GRAY); + // 绘制矩形背景 + graphic.fillRect(0, 0, WIDTH, HEIGHT); + // 5.画随机字符 + Random ran = new Random(); + for (int i = 0; i < SIZE; i++) { + // 取随机字符索引 + int n = ran.nextInt(CHARS.length); + // 设置随机颜色 + graphic.setColor(getRandomColor()); + // 设置字体大小 + graphic.setFont(new Font(null, Font.BOLD + Font.ITALIC, FONT_SIZE)); + // 画字符 + graphic.drawString(CHARS[n] + "", i * WIDTH / SIZE, HEIGHT); + // 记录字符 + sb.append(CHARS[n]); + } + // 6.画干扰线 + for (int i = 0; i < LINES; i++) { + // 设置随机颜色 + graphic.setColor(getRandomColor()); + // 随机画线 + graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT), ran.nextInt(WIDTH), ran.nextInt(HEIGHT)); + } + // 7.返回验证码和图片 + return new Object[]{sb.toString(), image}; + } + +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/ConvertUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/ConvertUtil.java new file mode 100644 index 0000000..11d30b6 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/ConvertUtil.java @@ -0,0 +1,801 @@ +package com.ailanyin.common.utils; + + +import org.springframework.util.StringUtils; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.text.NumberFormat; +import java.util.Set; + +/** + * 类型转换器 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0012 下午 22:30 + */ +public class ConvertUtil { + /** + * 转换为字符串 + * 如果给定的值为null,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static String toStr(Object value, String defaultValue) { + if (null == value) { + return defaultValue; + } + if (value instanceof String) { + return (String) value; + } + return value.toString(); + } + + /** + * 转换为字符串 + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static String toStr(Object value) { + return toStr(value, null); + } + + /** + * 转换为字符 + * 如果给定的值为null,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Character toChar(Object value, Character defaultValue) { + if (null == value) { + return defaultValue; + } + if (value instanceof Character) { + return (Character) value; + } + + final String valueStr = toStr(value, null); + return EmptyUtil.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); + } + + /** + * 转换为字符 + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Character toChar(Object value) { + return toChar(value, null); + } + + /** + * 转换为byte + * 如果给定的值为null,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Byte toByte(Object value, Byte defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Byte) { + return (Byte) value; + } + if (value instanceof Number) { + return ((Number) value).byteValue(); + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Byte.parseByte(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为byte + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Byte toByte(Object value) { + return toByte(value, null); + } + + /** + * 转换为Short + * 如果给定的值为null,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Short toShort(Object value, Short defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Short) { + return (Short) value; + } + if (value instanceof Number) { + return ((Number) value).shortValue(); + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Short.parseShort(valueStr.trim()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Short + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Short toShort(Object value) { + return toShort(value, null); + } + + /** + * 转换为Number + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Number toNumber(Object value, Number defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Number) { + return (Number) value; + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + return NumberFormat.getInstance().parse(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Number + * 如果给定的值为空,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Number toNumber(Object value) { + return toNumber(value, null); + } + + /** + * 转换为int + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Integer toInt(Object value, Integer defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Integer) { + return (Integer) value; + } + if (value instanceof Number) { + return ((Number) value).intValue(); + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Integer.parseInt(valueStr.trim()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为int + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Integer toInt(Object value) { + return toInt(value, null); + } + + /** + * 转换为Integer数组 + * + * @param str 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String str) { + return toIntArray(",", str); + } + + /** + * 转换为Long数组 + * + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String str) { + return toLongArray(",", str); + } + + /** + * 转换为Integer数组 + * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String split, String str) { + if (EmptyUtil.isEmpty(str)) { + return new Integer[]{}; + } + String[] arr = str.split(split); + final Integer[] ints = new Integer[arr.length]; + for (int i = 0; i < arr.length; i++) { + final Integer v = toInt(arr[i], 0); + ints[i] = v; + } + return ints; + } + + /** + * 转换为Long数组 + * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String split, String str) { + if (EmptyUtil.isEmpty(str)) { + return new Long[]{}; + } + String[] arr = str.split(split); + final Long[] longs = new Long[arr.length]; + for (int i = 0; i < arr.length; i++) { + final Long v = toLong(arr[i], null); + longs[i] = v; + } + return longs; + } + + /** + * 转换为String数组 + * + * @param str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String str) { + return toStrArray(",", str); + } + + /** + * 转换为String数组 + * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) { + return str.split(split); + } + + /** + * 转换为long + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Long toLong(Object value, Long defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Long) { + return (Long) value; + } + if (value instanceof Number) { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为long + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Long toLong(Object value) { + return toLong(value, null); + } + + /** + * 转换为double + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Double toDouble(Object value, Double defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Double) { + return (Double) value; + } + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为double + * 如果给定的值为空,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Double toDouble(Object value) { + return toDouble(value, null); + } + + /** + * 转换为Float + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Float toFloat(Object value, Float defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Float) { + return (Float) value; + } + if (value instanceof Number) { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Float.parseFloat(valueStr.trim()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Float + * 如果给定的值为空,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Float toFloat(Object value) { + return toFloat(value, null); + } + + + /** + * 转换为Enum对象 + * 如果给定的值为空,或者转换失败,返回默认值 + * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value, E defaultValue) { + if (value == null) { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Enum.valueOf(clazz, valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Enum对象 + * 如果给定的值为空,或者转换失败,返回默认值null + * + * @param clazz Enum的Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof BigInteger) { + return (BigInteger) value; + } + if (value instanceof Long) { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + return new BigInteger(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为BigInteger + * 如果给定的值为空,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof BigDecimal) { + return (BigDecimal) value; + } + if (value instanceof Long) { + return new BigDecimal((Long) value); + } + if (value instanceof Double) { + return new BigDecimal((Double) value); + } + if (value instanceof Integer) { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (EmptyUtil.isEmpty(valueStr)) { + return defaultValue; + } + try { + return new BigDecimal(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为BigDecimal + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串 + * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) { + return str(obj, Charset.forName("UTF-8")); + } + + /** + * 将对象转为字符串 + * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串 + * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(Object obj, Charset charset) { + if (null == obj) { + return null; + } + + if (obj instanceof String) { + return (String) obj; + } else if (obj instanceof byte[] || obj instanceof Byte[]) { + return str((Byte[]) obj, charset); + } else if (obj instanceof ByteBuffer) { + return str((ByteBuffer) obj, charset); + } + return obj.toString(); + } + + /** + * 将byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(byte[] bytes, String charset) { + return str(bytes, EmptyUtil.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 解码后的字符串 + */ + public static String str(byte[] data, Charset charset) { + if (data == null) { + return null; + } + + if (null == charset) { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, String charset) { + if (data == null) { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, Charset charset) { + if (null == charset) { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + // ----------------------------------------------------------------------- 全角半角转换 + + /** + * 半角转全角 + * + * @param input String. + * @return 全角字符串. + */ + public static String toSbc(String input) { + return toSbc(input, null); + } + + /** + * 半角转全角 + * + * @param input String + * @param notConvertSet 不替换的字符集合 + * @return 全角字符串. + */ + public static String toSbc(String input, Set notConvertSet) { + char[] c = input.toCharArray(); + for (int i = 0; i < c.length; i++) { + if (null != notConvertSet && notConvertSet.contains(c[i])) { + // 跳过不替换的字符 + continue; + } + + if (c[i] == ' ') { + c[i] = '\u3000'; + } else if (c[i] < '\177') { + c[i] = (char) (c[i] + 65248); + + } + } + return new String(c); + } + + /** + * 全角转半角 + * + * @param input String. + * @return 半角字符串 + */ + public static String toDbc(String input) { + return toDbc(input, null); + } + + /** + * 替换全角为半角 + * + * @param text 文本 + * @param notConvertSet 不替换的字符集合 + * @return 替换后的字符 + */ + public static String toDbc(String text, Set notConvertSet) { + char[] c = text.toCharArray(); + for (int i = 0; i < c.length; i++) { + if (null != notConvertSet && notConvertSet.contains(c[i])) { + // 跳过不替换的字符 + continue; + } + + if (c[i] == '\u3000') { + c[i] = ' '; + } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') { + c[i] = (char) (c[i] - 65248); + } + } + + return new String(c); + } + + /** + * 数字金额大写转换 先写个完整的然后将如零拾替换成零 + * + * @param n 数字 + * @return 中文大写数字 + */ + public static String digitUppercase(double n) { + String[] fraction = {"角", "分"}; + String[] digit = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}; + String[][] unit = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}}; + + String head = n < 0 ? "负" : ""; + n = Math.abs(n); + + String s = ""; + for (int i = 0; i < fraction.length; i++) { + s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); + } + if (s.length() < 1) { + s = "整"; + } + int integerPart = (int) Math.floor(n); + + for (int i = 0; i < unit[0].length && integerPart > 0; i++) { + String p = ""; + for (int j = 0; j < unit[1].length && n > 0; j++) { + p = digit[integerPart % 10] + unit[1][j] + p; + integerPart = integerPart / 10; + } + s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; + } + return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整"); + } + +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/DateUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/DateUtil.java new file mode 100644 index 0000000..38f716d --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/DateUtil.java @@ -0,0 +1,198 @@ +package com.ailanyin.common.utils; + +import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.poi.util.LocaleUtil; + +import java.lang.management.ManagementFactory; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +/** + * 时间工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0011 下午 18:30 + */ +public class DateUtil extends org.apache.commons.lang3.time.DateUtils { + public static String YYYY = "yyyy"; + + public static String YYYY_MM = "yyyy-MM"; + + public static String YYYY_MM_DD = "yyyy-MM-dd"; + + public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + + private static String[] parsePatterns = { + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", + "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", + "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; + + /** + * 获取当前Date型日期 + * + * @return Date() 当前日期 + */ + public static Date getNowDate() { + return new Date(); + } + + + /** + * 获取当前日期, 默认格式为yyyy-MM-dd + * + * @return String + */ + public static String getDate(String format) { + return EmptyUtil.isEmpty(format) ? dateTimeNow(YYYY_MM_DD_HH_MM_SS) : dateTimeNow(format); + } + + public static String getTime() { + return dateTimeNow(YYYY_MM_DD_HH_MM_SS); + } + + public static String dateTimeNow(final String format) { + return parseDateToStr(format, new Date()); + } + + public static String dateTime(final Date date) { + return parseDateToStr(YYYY_MM_DD, date); + } + + public static String parseDateToStr(final String format, final Date date) { + return new SimpleDateFormat(format).format(date); + } + + public static final Date dateTime(final String format, final String ts) { + try { + return new SimpleDateFormat(format).parse(ts); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * 日期路径 即年/月/日 如2018/08/08 + */ + public static final String datePath() { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyy/MM/dd"); + } + + /** + * 日期路径 即年/月/日 如20180808 + */ + public static final String dateTime() { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyyMMdd"); + } + + /** + * 日期型字符串转化为日期 格式 + */ + public static Date parseDate(Object str) { + if (str == null) { + return null; + } + try { + return parseDate(str.toString(), parsePatterns); + } catch (ParseException e) { + return null; + } + } + + /** + * 获取服务器启动时间 + */ + public static Date getServerStartDate() { + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + return new Date(time); + } + + /** + * 计算相差天数 + */ + public static int differentDaysByMillisecond(Date date1, Date date2) { + return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24))); + } + + /** + * 计算两个时间差 + */ + public static String getDatePoor(Date endDate, Date nowDate) { + long nd = 1000 * 24 * 60 * 60; + long nh = 1000 * 60 * 60; + long nm = 1000 * 60; + // long ns = 1000; + // 获得两个时间的毫秒时间差异 + long diff = endDate.getTime() - nowDate.getTime(); + // 计算差多少天 + long day = diff / nd; + // 计算差多少小时 + long hour = diff % nd / nh; + // 计算差多少分钟 + long min = diff % nd % nh / nm; + // 计算差多少秒//输出结果 + // long sec = diff % nd % nh % nm / ns; + return day + "天" + hour + "小时" + min + "分钟"; + } + + public static Date getJavaDate(double date) { + return getJavaDate(date, false, (TimeZone)null, false); + } + public static Date getJavaDate(double date, boolean use1904windowing, TimeZone tz, boolean roundSeconds) { + Calendar calendar = getJavaCalendar(date, use1904windowing, tz, roundSeconds); + return calendar == null ? null : calendar.getTime(); + } + + public static Calendar getJavaCalendar(double date, boolean use1904windowing, TimeZone timeZone, boolean roundSeconds) { + if (!isValidExcelDate(date)) { + return null; + } else { + int wholeDays = (int)Math.floor(date); + int millisecondsInDay = (int)((date - (double)wholeDays) * 8.64E7D + 0.5D); + Calendar calendar; + if (timeZone != null) { + calendar = LocaleUtil.getLocaleCalendar(timeZone); + } else { + calendar = LocaleUtil.getLocaleCalendar(); + } + + setCalendar(calendar, wholeDays, millisecondsInDay, use1904windowing, roundSeconds); + return calendar; + } + } + + public static boolean isValidExcelDate(double value) { + return value > -4.9E-324D; + } + public static void setCalendar(Calendar calendar, int wholeDays, int millisecondsInDay, boolean use1904windowing, boolean roundSeconds) { + int startYear = 1900; + int dayAdjust = -1; + int paramO = 61; + int paramW = 14; + if (use1904windowing) { + startYear = 1904; + dayAdjust = 1; + } else if (wholeDays < paramO) { + dayAdjust = 0; + } + + calendar.set(startYear, 0, wholeDays + dayAdjust, 0, 0, 0); + calendar.set(14, millisecondsInDay); + if (calendar.get(paramW) == 0) { + calendar.clear(14); + } + + if (roundSeconds) { + calendar.add(14, 500); + calendar.clear(14); + } + + } + + +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/EmptyUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/EmptyUtil.java new file mode 100644 index 0000000..bd15bb2 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/EmptyUtil.java @@ -0,0 +1,73 @@ +package com.ailanyin.common.utils; + +import java.util.List; + +/** + * 判空工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0002 下午 13:30 + */ +public class EmptyUtil { + + /** + * 对字符串进行判空 + * + * @param str 字符串 + * @return true or false + */ + public static boolean isEmpty(String str) { + return str == null || "".equals(str.trim()); + } + + /** + * 对对象进行判空 + * + * @param obj 对象 + * @return true or false + */ + public static boolean isEmpty(Object obj) { + return obj == null; + } + + /** + * 对象非空 + * + * @param obj 对象 + * @return true or false + */ + public static boolean isNotEmpty(Object obj) { + return !isEmpty(obj); + } + + /** + * 字符串非空 + * + * @param str 对象 + * @return true or false + */ + public static boolean isNotEmpty(String str) { + return !isEmpty(str); + } + + /** + * 对List集合进行判空 int[] array + * + * @param objectList 集合 + * @return true or false + */ + public static boolean isEmpty(List objectList) { + return objectList == null || objectList.size() == 0; + } + + /** + * 对一维数组进行判空 + * + * @param objectArray 一维数组 + * @return true or false + */ + public static boolean isEmpty(Object[] objectArray) { + return objectArray == null || objectArray.length == 0; + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/ExcelUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/ExcelUtil.java new file mode 100644 index 0000000..8dc0bf6 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/ExcelUtil.java @@ -0,0 +1,231 @@ +package com.ailanyin.common.utils; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.ExcelImportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.ImportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.util.IOUtils; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +/** + * Excel 工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/25 0025 上午 9:15 + */ +public class ExcelUtil { + + /** + * excel 导出 + * + * @param list 数据 + * @param title 标题 + * @param sheetName sheet名称 + * @param pojoClass pojo类型 + * @param fileName 文件名称 + */ + public static String exportExcel(List list, String title, String sheetName, Class pojoClass, String fileName) throws IOException { + return defaultExport(list, pojoClass, fileName, new ExportParams(title, sheetName, ExcelType.XSSF)); + } + + /** + * excel 导出 + * + * @param list 数据 + * @param pojoClass pojo类型 + * @param fileName 文件名称 + * @param response + * @param exportParams 导出参数 + */ + public static void exportExcel(List list, Class pojoClass, String fileName, ExportParams exportParams, HttpServletResponse response) throws IOException { + defaultExport(list, pojoClass, fileName, exportParams); + } + + /** + * excel 导出 + * + * @param list 数据 + * @param fileName 文件名称 + * @param response + */ + public static void exportExcel(List> list, String fileName, HttpServletResponse response) throws IOException { + defaultExport(list, fileName, response); + } + + /** + * 默认的 excel 导出 + * + * @param list 数据 + * @param pojoClass pojo类型 + * @param fileName 文件名称 + * @param exportParams 导出参数 + */ + private static String defaultExport(List list, Class pojoClass, String fileName, ExportParams exportParams) throws IOException { + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list); + OutputStream out = null; + try { + String encodingFilename = fileName + "(" + DateUtil.dateTimeNow("yyyyMMddHHmmss") + ")" + "." + ExcelTypeEnum.XLSX.getValue(); + out = new FileOutputStream(getAbsoluteFile(encodingFilename)); + workbook.write(out); + return encodingFilename; + + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("导出Excel失败,请联系网站管理员!"); + } finally { + IOUtils.closeQuietly(workbook); + IOUtils.closeQuietly(out); + } + } + + /** + * 默认的 excel 导出 + * + * @param list 数据 + * @param fileName 文件名称 + * @param response + */ + private static void defaultExport(List> list, String fileName, HttpServletResponse response) throws IOException { + Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF); + downLoadExcel(fileName, response, workbook); + } + + /** + * 获取下载路径 + * + * @param filename 文件名称 + */ + private static String getAbsoluteFile(String filename) { + String downloadPath = getDownloadPath() + filename; + File desc = new File(downloadPath); + if (!desc.getParentFile().exists()) { + desc.getParentFile().mkdirs(); + } + return downloadPath; + } + + private static String getDownloadPath() { + return System.getProperty("java.io.tmpdir") + File.separator + "download" + File.separator; + } + + /** + * 下载 + * + * @param fileName 文件名称 + * @param response + * @param workbook excel数据 + */ + private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) throws IOException { + try { + response.setCharacterEncoding("UTF-8"); + response.setHeader("content-Type", "application/vnd.ms-excel"); + response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + "." + ExcelTypeEnum.XLSX.getValue(), "UTF-8")); + workbook.write(response.getOutputStream()); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + /** + * excel 导入 + * + * @param filePath excel文件路径 + * @param titleRows 标题行 + * @param headerRows 表头行 + * @param pojoClass pojo类型 + * @param + * @return + */ + public static List importExcel(String filePath, Integer titleRows, Integer headerRows, Class pojoClass) throws IOException { + if (StringUtils.isBlank(filePath)) { + return null; + } + ImportParams params = new ImportParams(); + params.setTitleRows(titleRows); + params.setHeadRows(headerRows); + params.setNeedSave(true); + params.setSaveUrl("/excel/"); + try { + return ExcelImportUtil.importExcel(new File(filePath), pojoClass, params); + } catch (NoSuchElementException e) { + throw new IOException("模板不能为空"); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + + /** + * excel 导入 + * + * @param file excel文件 + * @param pojoClass pojo类型 + * @param + * @return + */ + public static List importExcel(MultipartFile file, Class pojoClass) throws IOException { + return importExcel(file.getInputStream(), 1, 1, pojoClass); + } + + + /** + * excel 导入 + * + * @param inputStream 文件输入流 + * @param titleRows 标题行 + * @param headerRows 表头行 + * @param pojoClass pojo类型 + * @param + * @return + */ + private static List importExcel(InputStream inputStream, Integer titleRows, Integer headerRows, Class pojoClass) throws IOException { + if (inputStream == null) { + return null; + } + ImportParams params = new ImportParams(); + params.setTitleRows(titleRows); + params.setHeadRows(headerRows); + params.setSaveUrl("/excel/"); + try { + return ExcelImportUtil.importExcel(inputStream, pojoClass, params); + } catch (NoSuchElementException e) { + throw new IOException("excel文件不能为空"); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + /** + * Excel 类型枚举 + */ + enum ExcelTypeEnum { + /** + * Excel 格式 + */ + XLS("xls"), XLSX("xlsx"); + private String value; + + ExcelTypeEnum(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/FileUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/FileUtil.java new file mode 100644 index 0000000..6c08736 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/FileUtil.java @@ -0,0 +1,250 @@ +package com.ailanyin.common.utils; + +import cn.hutool.core.lang.UUID; +import com.ailanyin.common.exception.Asserts; +import com.alibaba.fastjson.util.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * 文件工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/25 0025 上午 9:15 + */ +public class FileUtil { + private static final String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; + + private static final String AGENT_MSIE = "MSIE"; + + private static final String AGENT_FIREFOX = "Firefox"; + + private static final String AGENT_CHROME = "Chrome"; + + private static final String[] DEFAULT_ALLOWED_EXTENSION = { + // 图片 + "bmp", "gif", "jpg", "jpeg", "png", + // word excel powerpoint + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", + // 压缩文件 + "rar", "zip", "gz", "bz2", + // 视频格式 + "mp4", "avi", "rmvb", "blob", + // pdf + "pdf"}; + + + /** + * @param file 上传的文件 + * @return 文件全路径名称 + */ + public static String upload(MultipartFile file, HttpServletRequest request, String path) { + + // 获取文件后缀名 + String extension = getExtension(file); + // 判断是否允许上传 + if (!isAllowedExtension(extension)) { + Asserts.fail("不允许上传该类型文件!"); + } + // 重命名文件 + String fileName = extractFilename(extension); + // 新建文件 + File newFile = getAbsoluteFile(fileName, path); + try { + file.transferTo(newFile); + return getUrl(request) + getPathFileName(fileName, path); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /** + * 输出指定文件的byte数组 + * + * @param filePath 文件路径 + * @param os 输出流 + * @return + */ + public static void writeBytes(String filePath, OutputStream os) throws IOException { + FileInputStream fis = null; + try { + File file = new File(filePath); + if (!file.exists()) { + throw new FileNotFoundException(filePath); + } + fis = new FileInputStream(file); + byte[] b = new byte[1024]; + int length; + while ((length = fis.read(b)) > 0) { + os.write(b, 0, length); + } + } catch (IOException e) { + throw e; + } finally { + IOUtils.close(os); + IOUtils.close(fis); + } + } + + public static String getDownloadPath() { + return System.getProperty("java.io.tmpdir") + File.separator + "download" + File.separator; + } + + /** + * 删除文件 + * + * @param filePath 文件 + * @return + */ + public static boolean deleteFile(String filePath) { + boolean flag = false; + File file = new File(filePath); + // 路径为文件且不为空则进行删除 + if (file.isFile() && file.exists()) { + file.delete(); + flag = true; + } + return flag; + } + + /** + * 文件名称验证 + * + * @param filename 文件名称 + * @return true 正常 false 非法 + */ + public static boolean isValidFilename(String filename) { + return filename.matches(FILENAME_PATTERN); + } + + + /** + * 下载文件名重新编码 + * + * @param request 请求对象 + * @param fileName 文件名 + * @return 编码后的文件名 + */ + public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException { + final String agent = request.getHeader("USER-AGENT"); + String filename = fileName; + if (agent.contains(AGENT_MSIE)) { + // IE浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + filename = filename.replace("+", " "); + } else if (agent.contains(AGENT_FIREFOX)) { + // 火狐浏览器 + filename = new String(fileName.getBytes(), "ISO8859-1"); + } else if (agent.contains(AGENT_CHROME)) { + // google浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + } else { + // 其它浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + } + return filename; + } + + /** + * 下载文件名重新编码 + * + * @param response 响应对象 + * @param realFileName 真实文件名 + * @return + */ + public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException { + String percentEncodedFileName = percentEncode(realFileName); + + StringBuilder contentDispositionValue = new StringBuilder(); + contentDispositionValue.append("attachment; filename=") + .append(percentEncodedFileName) + .append(";") + .append("filename*=") + .append("utf-8''") + .append(percentEncodedFileName); + + response.setHeader("Content-disposition", contentDispositionValue.toString()); + } + + /** + * 百分号编码工具方法 + * + * @param s 需要百分号编码的字符串 + * @return 百分号编码后的字符串 + */ + public static String percentEncode(String s) throws UnsupportedEncodingException { + String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); + return encode.replaceAll("\\+", "%20"); + } + + /** + * 判断文件类型是否是允许上传的类型 + * + * @param extension 文件类型 + * @return Boolean + */ + public static boolean isAllowedExtension(String extension) { + + for (String str : DEFAULT_ALLOWED_EXTENSION) { + if (str.equalsIgnoreCase(extension)) { + return true; + } + } + return false; + } + + /** + * 获取文件名的后缀 + * + * @param file 表单文件 + * @return 后缀名 + */ + public static String getExtension(MultipartFile file) { + String fileName = file.getOriginalFilename(); + return fileName.substring(fileName.lastIndexOf(".") + 1); + } + + /** + * 编码文件名 + */ + public static String extractFilename(String extension) { + return UUID.fastUUID().toString(true) + "." + extension; + } + + /** + * 创建文件 + * + * @param fileName 文件名 + * @return file + */ + public static File getAbsoluteFile(String fileName, String path) { + File desc = new File(path + File.separator + fileName); + + if (!desc.exists()) { + if (!desc.getParentFile().exists()) { + desc.getParentFile().mkdirs(); + } + } + return desc; + } + + public static String getPathFileName(String fileName, String path) { + int dirLastIndex = path.length() + 1; + String currentDir = StringUtils.substring(path, dirLastIndex); + return currentDir + "/" + fileName; + } + + public static String getUrl(HttpServletRequest request) { + StringBuffer url = request.getRequestURL(); + String contextPath = request.getServletContext().getContextPath(); + return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString(); + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/HttpUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/HttpUtil.java new file mode 100644 index 0000000..d39c187 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/HttpUtil.java @@ -0,0 +1,259 @@ +package com.ailanyin.common.utils; + +import com.ailanyin.common.constant.Constants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.*; +import java.io.*; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.security.cert.X509Certificate; + + +/** + * 通用http发送方法 + * + * @author ruoyi + */ +public class HttpUtil +{ + private static final Logger log = LoggerFactory.getLogger(HttpUtil.class); + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param) + { + return sendGet(url, param, Constants.UTF8); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param contentType 编码类型 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param, String contentType) + { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try + { + String urlNameString = url + "?" + param; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (in != null) + { + in.close(); + } + } + catch (Exception ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param) + { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try + { + String urlNameString = url; + log.info("sendPost - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (out != null) + { + out.close(); + } + if (in != null) + { + in.close(); + } + } + catch (IOException ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + public static String sendSslPost(String url, String param) + { + StringBuilder result = new StringBuilder(); + String urlNameString = url + "?" + param; + try + { + log.info("sendSSLPost - {}", urlNameString); + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); + URL console = new URL(urlNameString); + HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); + setHeader(conn); + + conn.setSSLSocketFactory(sc.getSocketFactory()); + conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); + conn.connect(); + InputStream is = conn.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String ret = ""; + while ((ret = br.readLine()) != null) + { + if (ret != null && !"".equals(ret.trim())) + { + result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8")); + } + } + log.info("recv - {}", result); + conn.disconnect(); + br.close(); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + } + return result.toString(); + } + + private static void setHeader(HttpsURLConnection conn) { + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + } + + private static class TrustAnyTrustManager implements X509TrustManager + { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public X509Certificate[] getAcceptedIssuers() + { + return new X509Certificate[] {}; + } + } + + private static class TrustAnyHostnameVerifier implements HostnameVerifier + { + @Override + public boolean verify(String hostname, SSLSession session) + { + return true; + } + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/IpUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/IpUtil.java new file mode 100644 index 0000000..5772e63 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/IpUtil.java @@ -0,0 +1,100 @@ +package com.ailanyin.common.utils; + +import com.ailanyin.common.constant.Constants; +import com.alibaba.fastjson.JSONObject; + +import javax.servlet.http.HttpServletRequest; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * 获取IP工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 14:10 + */ +public class IpUtil { + + private final static String UNKNOWN = "unknown"; + private final static String CHINESE_UNKNOWN = "未知"; + private final static String X_FORWARDED_FOR_LOWERCASE = "x-forwarded-for"; + private final static String X_FORWARDED_FOR_CAPITALIZE = "X-Forwarded-For"; + private final static String PROXY_CLIENT_IP = "Proxy-Client-IP"; + private final static String WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP"; + private final static String X_REAL_IP = "X-Real-IP"; + private final static String LOCALHOST = "127.0.0.1"; + private final static String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1"; + public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; + + /** + * 获取请求的ip地址 + * + * @param request HttpServletRequest + * @return 请求对应的ip + */ + public static String getIpAddr(HttpServletRequest request) { + if (request == null) { + return UNKNOWN; + } + String ip = request.getHeader(X_FORWARDED_FOR_LOWERCASE); + if (EmptyUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader(PROXY_CLIENT_IP); + } + if (EmptyUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader(X_FORWARDED_FOR_CAPITALIZE); + } + if (EmptyUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader(WL_PROXY_CLIENT_IP); + } + if (EmptyUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader(X_REAL_IP); + } + + if (EmptyUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + return LOCALHOST_IPV6.equals(ip) ? LOCALHOST : ip; + } + + public static String getHostIp() { + try { + return InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException ignored) { + } + return LOCALHOST; + } + + public static String getHostName() { + try { + return InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException ignored) { + } + return CHINESE_UNKNOWN; + } + + /** + * 获取公网ip的实际位置 + * + * @param ip 公网ip + * @return eg:安徽省合肥市 电信 + */ + public static String getRealAddressByIp(String ip) { + // 内网不查询 + if (LOCALHOST.equals(ip)) { + return "内网IP"; + } + try { + String rspStr = HttpUtil.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK); + if (EmptyUtil.isEmpty(rspStr)) { + return UNKNOWN; + } + JSONObject obj = JSONObject.parseObject(rspStr); + return obj.getString("addr"); + } catch (Exception e) { + e.printStackTrace(); + } + return CHINESE_UNKNOWN; + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/ReflectUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/ReflectUtil.java new file mode 100644 index 0000000..6d99fed --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/ReflectUtil.java @@ -0,0 +1,403 @@ +package com.ailanyin.common.utils; + + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.*; +import java.util.Date; + +/** + * 反射工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 14:10 + */ +@SuppressWarnings("rawtypes") +public class ReflectUtil +{ + private static final String SETTER_PREFIX = "set"; + + private static final String GETTER_PREFIX = "get"; + + private static final String CGLIB_CLASS_SEPARATOR = "$$"; + + private static final String MATH_POINT = "."; + + private static Logger logger = LoggerFactory.getLogger(ReflectUtil.class); + + /** + * 调用Getter方法. + * 支持多级,如:对象名.对象名.方法 + */ + @SuppressWarnings("unchecked") + public static E invokeGetter(Object obj, String propertyName) + { + Object object = obj; + for (String name : StringUtils.split(propertyName, MATH_POINT)) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + return (E) object; + } + + /** + * 调用Setter方法, 仅匹配方法名。 + * 支持多级,如:对象名.对象名.方法 + */ + public static void invokeSetter(Object obj, String propertyName, E value) + { + Object object = obj; + String[] names = StringUtils.split(propertyName, "."); + for (int i = 0; i < names.length; i++) + { + if (i < names.length - 1) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + else + { + String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); + invokeMethodByName(object, setterMethodName, new Object[] { value }); + } + } + } + + /** + * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. + */ + @SuppressWarnings("unchecked") + public static E getFieldValue(final Object obj, final String fieldName) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return null; + } + E result = null; + try + { + result = (E) field.get(obj); + } + catch (IllegalAccessException e) + { + logger.error("不可能抛出的异常{}", e.getMessage()); + } + return result; + } + + /** + * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. + */ + public static void setFieldValue(final Object obj, final String fieldName, final E value) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return; + } + try + { + field.set(obj, value); + } + catch (IllegalAccessException e) + { + logger.error("不可能抛出的异常: {}", e.getMessage()); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符. + * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. + * 同时匹配方法名+参数类型, + */ + @SuppressWarnings("unchecked") + public static E invokeMethod(final Object obj, final String methodName, final Class[] parameterTypes, + final Object[] args) + { + if (obj == null || methodName == null) + { + return null; + } + Method method = getAccessibleMethod(obj, methodName, parameterTypes); + if (method == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符, + * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. + * 只匹配函数名,如果有多个同名函数调用第一个。 + */ + @SuppressWarnings("unchecked") + public static E invokeMethodByName(final Object obj, final String methodName, final Object[] args) + { + Method method = getAccessibleMethodByName(obj, methodName, args.length); + if (method == null) + { + // 如果为空不报错,直接返回空。 + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + // 类型转换(将参数数据类型转换为目标方法参数类型) + Class[] cs = method.getParameterTypes(); + for (int i = 0; i < cs.length; i++) + { + if (args[i] != null && !args[i].getClass().equals(cs[i])) + { + if (cs[i] == String.class) + { + args[i] = ConvertUtil.toStr(args[i]); + if (StringUtils.endsWith((String) args[i], ".0")) + { + args[i] = StringUtils.substringBefore((String) args[i], ".0"); + } + } + else if (cs[i] == Integer.class) + { + args[i] = ConvertUtil.toInt(args[i]); + } + else if (cs[i] == Long.class) + { + args[i] = ConvertUtil.toLong(args[i]); + } + else if (cs[i] == Double.class) + { + args[i] = ConvertUtil.toDouble(args[i]); + } + else if (cs[i] == Float.class) + { + args[i] = ConvertUtil.toFloat(args[i]); + } + else if (cs[i] == Date.class) + { + if (args[i] instanceof String) + { + args[i] = DateUtil.parseDate(args[i]); + } + else + { + args[i] = DateUtil.getJavaDate((Double) args[i]); + } + } + } + } + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + */ + public static Field getAccessibleField(final Object obj, final String fieldName) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(fieldName, "fieldName can't be blank"); + for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) + { + try + { + Field field = superClass.getDeclaredField(fieldName); + makeAccessible(field); + return field; + } + catch (NoSuchFieldException e) + { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 匹配函数名+参数类型。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethod(final Object obj, final String methodName, + final Class... parameterTypes) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + try + { + Method method = searchType.getDeclaredMethod(methodName, parameterTypes); + makeAccessible(method); + return method; + } + catch (NoSuchMethodException e) + { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 只匹配函数名。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + Method[] methods = searchType.getDeclaredMethods(); + for (Method method : methods) + { + if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) + { + makeAccessible(method); + return method; + } + } + } + return null; + } + + /** + * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Method method) + { + if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))) + { + method.setAccessible(true); + } + } + + /** + * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Field field) + { + if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) + || Modifier.isFinal(field.getModifiers()))) + { + field.setAccessible(true); + } + } + + /** + * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 + * 如无法找到, 返回Object.class. + */ + @SuppressWarnings("unchecked") + public static Class getClassGenricType(final Class clazz) + { + return getClassGenricType(clazz, 0); + } + + /** + * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. + * 如无法找到, 返回Object.class. + */ + public static Class getClassGenricType(final Class clazz, final int index) + { + Type genType = clazz.getGenericSuperclass(); + + if (!(genType instanceof ParameterizedType)) + { + logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); + return Object.class; + } + + Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); + + if (index >= params.length || index < 0) + { + logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + + params.length); + return Object.class; + } + if (!(params[index] instanceof Class)) + { + logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); + return Object.class; + } + + return (Class) params[index]; + } + + public static Class getUserClass(Object instance) + { + if (instance == null) + { + throw new RuntimeException("Instance must not be null"); + } + Class clazz = instance.getClass(); + if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) + { + Class superClass = clazz.getSuperclass(); + if (superClass != null && !Object.class.equals(superClass)) + { + return superClass; + } + } + return clazz; + + } + + /** + * 将反射时的checked exception转换为unchecked exception. + */ + public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) + { + if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException + || e instanceof NoSuchMethodException) + { + return new IllegalArgumentException(msg, e); + } + else if (e instanceof InvocationTargetException) + { + return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); + } + return new RuntimeException(msg, e); + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/SmsUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/SmsUtil.java new file mode 100644 index 0000000..d1b0ea3 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/SmsUtil.java @@ -0,0 +1,192 @@ +package com.ailanyin.common.utils; + + +import com.alibaba.fastjson.JSON; +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.profile.DefaultProfile; +import com.aliyuncs.profile.IClientProfile; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.sms.v20210111.SmsClient; + + +/** + * 短信工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/11/16 0016 上午 9:47 + */ +public class SmsUtil { + + /** + * 阿里云-accessKeyId + */ + private static final String ALIYUN_ACCESSKEY_ID = "============="; + /** + * 阿里云-accessKeySecret + */ + private static final String ALIYUN_ACCESSKEY_SECRET = "============="; + /** + * 阿里云-短信签名 + */ + private static final String ALIYUN_SIGN_NAME = "============="; + /** + * 阿里云-短信模板 + */ + private static final String ALIYUN_TEMPLATE_CODE = "============="; + /** + * 阿里云-短信发送成功 + */ + private static final String ALIYUN_SEND_OK = "OK"; + + /** + * 腾讯云-accessKeyId + */ + private static final String TENCENTYUN_ACCESSKEY_ID = "============="; + /** + * 腾讯云-accessKeySecret + */ + private static final String TENCENTYUN_ACCESSKEY_SECRET = "============="; + /** + * 腾讯云-短信应用ID + */ + private static final String TENCENTYUN_SDK_APP_ID = "============="; + /** + * 腾讯云-短信签名 + */ + private static final String TENCENTYUN_SIGN_NAME = "============="; + /** + * 腾讯云-短信模板 + */ + private static final String TENCENTYUN_TEMPLATE_ID = "============="; + + /** + * 发送腾讯云短信 + * + * @param phoneNumberSet phoneList + * @param templateParamSet 模板 + */ + public static void sendTencentYunMsg(String[] phoneNumberSet, String[] templateParamSet) { + try { + + Credential cred = new Credential(TENCENTYUN_ACCESSKEY_ID, TENCENTYUN_ACCESSKEY_SECRET); + // 实例化一个http选项,可选,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + // 设置请求方式 + httpProfile.setReqMethod("POST"); + /* SDK有默认的超时时间,非必要请不要进行调整 + * 如有需要请在代码中查阅以获取最新的默认值 */ + httpProfile.setConnTimeout(60); + /* SDK会自动指定域名。通常是不需要特地指定域名的,但是如果你访问的是金融区的服务 + * 则必须手动指定域名,例如sms的上海金融区域名: sms.ap-shanghai-fsi.tencentcloudapi.com */ + httpProfile.setEndpoint("sms.tencentcloudapi.com"); + /* 非必要步骤: + * 实例化一个客户端配置对象,可以指定超时时间等配置 */ + ClientProfile clientProfile = new ClientProfile(); + /* SDK默认用TC3-HMAC-SHA256进行签名 + * 非必要请不要修改这个字段 */ + clientProfile.setSignMethod("HmacSHA256"); + clientProfile.setHttpProfile(httpProfile); + /* 实例化要请求产品(以sms为例)的client对象 + * 第二个参数是地域信息,可以直接填写字符串ap-guangzhou,或者引用预设的常量 */ + SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile); + /* 实例化一个请求对象,根据调用的接口和实际情况,可以进一步设置请求参数 + * 你可以直接查询SDK源码确定接口有哪些属性可以设置 + * 属性可能是基本类型,也可能引用了另一个数据结构 + * 推荐使用IDE进行开发,可以方便的跳转查阅各个接口和数据结构的文档说明 */ + com.tencentcloudapi.sms.v20210111.models.SendSmsRequest req = new com.tencentcloudapi.sms.v20210111.models.SendSmsRequest(); + + /* 填充请求参数,这里request对象的成员变量即对应接口的入参 + * 你可以通过官网接口文档或跳转到request对象的定义处查看请求参数的定义 + * 基本类型的设置: + * 帮助链接: + * 短信控制台: https://console.cloud.tencent.com/smsv2 + * sms helper: https://cloud.tencent.com/document/product/382/3773 */ + + /* 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId,示例如1400006666 */ + req.setSmsSdkAppId(TENCENTYUN_SDK_APP_ID); + + /* 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名,签名信息可登录 [短信控制台] 查看 */ + req.setSignName(TENCENTYUN_SIGN_NAME); + + /* 国际/港澳台短信 SenderId: 国内短信填空,默认未开通,如需开通请联系 [sms helper] */ + String senderid = ""; + req.setSenderId(senderid); + + /* 用户的 session 内容: 可以携带用户侧 ID 等上下文信息,server 会原样返回 */ + String sessionContext = "xxx"; + req.setSessionContext(sessionContext); + + /* 短信号码扩展号: 默认未开通,如需开通请联系 [sms helper] */ + String extendCode = ""; + req.setExtendCode(extendCode); + + /* 模板 ID: 必须填写已审核通过的模板 ID。模板ID可登录 [短信控制台] 查看 */ + req.setTemplateId(TENCENTYUN_TEMPLATE_ID); + + /* 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号] + * 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号 */ + req.setPhoneNumberSet(phoneNumberSet); + + /* 模板参数: 若无模板参数,则设置为空 */ + req.setTemplateParamSet(templateParamSet); + + /* 通过 client 对象调用 SendSms 方法发起请求。注意请求方法名与请求对象是对应的 + * 返回的 res 是一个 SendSmsResponse 类的实例,与请求对象对应 */ + com.tencentcloudapi.sms.v20210111.models.SendSmsResponse res = client.SendSms(req); + + // 输出json格式的字符串回包 + System.out.println(JSON.toJSONString(res)); + + // 也可以取出单个值,你可以通过官网接口文档或跳转到response对象的定义处查看返回字段的定义 + System.out.println(res.getRequestId()); + + } catch (TencentCloudSDKException e) { + e.printStackTrace(); + } + } + + /** + * 发送阿里云短信验证码 + * + * @param phone 目标手机号 + * @param msgCode 验证码 + */ + public static void sendAliYunMsg(String phone, String msgCode) { + try { + //设置超时时间-可自行调整 + System.setProperty("sun.net.client.defaultConnectTimeout", "10000"); + System.setProperty("sun.net.client.defaultReadTimeout", "10000"); + //初始化ascClient,暂时不支持多region(请勿修改) + IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", ALIYUN_ACCESSKEY_ID, ALIYUN_ACCESSKEY_SECRET); + IAcsClient acsClient = new DefaultAcsClient(profile); + //组装请求对象 + SendSmsRequest request = new SendSmsRequest(); + //必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000” + request.setPhoneNumbers(phone); + //必填:短信签名-可在短信控制台中找到*************************** + request.setSignName(ALIYUN_SIGN_NAME); + //必填:短信模板-可在短信控制台中找到,发送国际/港澳台消息时,请使用国际/港澳台短信模版************************** + request.setTemplateCode(ALIYUN_TEMPLATE_CODE); + //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为 + //友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败 + request.setTemplateParam("{\"code\":\"" + msgCode + "\"}"); + //请求失败这里会抛ClientException异常 + SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request); + if (sendSmsResponse.getCode() == null || !ALIYUN_SEND_OK.equals(sendSmsResponse.getCode())) { + System.out.println(phone + "=====fail===="); + } + } catch (ClientException e) { + e.printStackTrace(); + } + + } + +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/SpringUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/SpringUtil.java new file mode 100644 index 0000000..33086ce --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/SpringUtil.java @@ -0,0 +1,147 @@ +package com.ailanyin.common.utils; + +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * Spring 工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 14:10 + */ +@Component +public final class SpringUtil implements BeanFactoryPostProcessor, ApplicationContextAware +{ + /** Spring应用上下文环境 */ + private static ConfigurableListableBeanFactory beanFactory; + + private static ApplicationContext applicationContext; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException + { + SpringUtil.beanFactory = beanFactory; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + SpringUtil.applicationContext = applicationContext; + } + + /** + * 获取对象 + * + * @param name + * @return Object 一个以所给名字注册的bean的实例 + * @throws org.springframework.beans.BeansException + * + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException + { + return (T) beanFactory.getBean(name); + } + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws org.springframework.beans.BeansException + * + */ + public static T getBean(Class clz) throws BeansException + { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true + * + * @param name + * @return boolean + */ + public static boolean containsBean(String name) + { + return beanFactory.containsBean(name); + } + + /** + * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + * + * @param name + * @return + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getAliases(name); + } + + /** + * 获取aop代理对象 + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) + { + return (T) AopContext.currentProxy(); + } + + /** + * 获取当前的环境配置,无配置返回null + * + * @return 当前的环境配置 + */ + public static String[] getActiveProfiles() + { + return applicationContext.getEnvironment().getActiveProfiles(); + } + + /** + * 获取当前的环境配置,当有多个环境配置时,只获取第一个 + * + * @return 当前的环境配置 + */ + public static String getActiveProfile() + { + final String[] activeProfiles = getActiveProfiles(); + return EmptyUtil.isNotEmpty(activeProfiles) ? activeProfiles[0] : null; + } +} diff --git a/ailanyin-common/src/main/java/com/ailanyin/common/utils/StringUtil.java b/ailanyin-common/src/main/java/com/ailanyin/common/utils/StringUtil.java new file mode 100644 index 0000000..4018037 --- /dev/null +++ b/ailanyin-common/src/main/java/com/ailanyin/common/utils/StringUtil.java @@ -0,0 +1,535 @@ +package com.ailanyin.common.utils; + +import cn.hutool.core.text.StrFormatter; +import org.springframework.util.AntPathMatcher; +import com.ailanyin.common.constant.*; + +import java.util.*; + +/** + * 字符串工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 14:10 + */ +public class StringUtil extends org.apache.commons.lang3.StringUtils +{ + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** 下划线 */ + private static final String SEPARATOR = "_"; + + /** + * 获取参数不为空值 + * + * @param value defaultValue 要判断的value + * @return value 返回值 + */ + public static T nvl(T value, T defaultValue) + { + return value != null ? value : defaultValue; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是否非空,包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Collection coll) + { + return !isEmpty(coll); + } + + /** + * * 判断一个对象数组是否为空 + * + * @param objects 要判断的对象数组 + ** @return true:为空 false:非空 + */ + public static boolean isEmpty(Object[] objects) + { + return isNull(objects) || (objects.length == 0); + } + + /** + * * 判断一个对象数组是否非空 + * + * @param objects 要判断的对象数组 + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Object[] objects) + { + return !isEmpty(objects); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Map map) + { + return isNull(map) || map.isEmpty(); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Map map) + { + return !isEmpty(map); + } + + /** + * * 判断一个字符串是否为空串 + * + * @param str String + * @return true:为空 false:非空 + */ + public static boolean isEmpty(String str) + { + return isNull(str) || NULLSTR.equals(str.trim()); + } + + /** + * * 判断一个字符串是否为非空串 + * + * @param str String + * @return true:非空串 false:空串 + */ + public static boolean isNotEmpty(String str) + { + return !isEmpty(str); + } + + /** + * * 判断一个对象是否为空 + * + * @param object Object + * @return true:为空 false:非空 + */ + public static boolean isNull(Object object) + { + return object == null; + } + + /** + * * 判断一个对象是否非空 + * + * @param object Object + * @return true:非空 false:空 + */ + public static boolean isNotNull(Object object) + { + return !isNull(object); + } + + /** + * * 判断一个对象是否是数组类型(Java基本型别的数组) + * + * @param object 对象 + * @return true:是数组 false:不是数组 + */ + public static boolean isArray(Object object) + { + return isNotNull(object) && object.getClass().isArray(); + } + + /** + * 去空格 + */ + public static String trim(String str) + { + return (str == null ? "" : str.trim()); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @return 结果 + */ + public static String substring(final String str, int start) + { + if (str == null) + { + return NULLSTR; + } + + if (start < 0) + { + start = str.length() + start; + } + + if (start < 0) + { + start = 0; + } + if (start > str.length()) + { + return NULLSTR; + } + + return str.substring(start); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end 结束 + * @return 结果 + */ + public static String substring(final String str, int start, int end) + { + if (str == null) + { + return NULLSTR; + } + + if (end < 0) + { + end = str.length() + end; + } + if (start < 0) + { + start = str.length() + start; + } + + if (end > str.length()) + { + end = str.length(); + } + + if (start > end) + { + return NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param template 文本模板,被替换的部分用 {} 表示 + * @param params 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... params) + { + if (isEmpty(params) || isEmpty(template)) + { + return template; + } + return StrFormatter.format(template, params); + } + + /** + * 是否为http(s)://开头 + * + * @param link 链接 + * @return 结果 + */ + public static boolean ishttp(String link) + { + return StringUtil.startsWithAny(link, Constants.HTTP, Constants.HTTPS); + } + + /** + * 字符串转set + * + * @param str 字符串 + * @param sep 分隔符 + * @return set集合 + */ + public static final Set str2Set(String str, String sep) + { + return new HashSet(str2List(str, sep, true, false)); + } + + /** + * 字符串转list + * + * @param str 字符串 + * @param sep 分隔符 + * @param filterBlank 过滤纯空白 + * @param trim 去掉首尾空白 + * @return list集合 + */ + public static final List str2List(String str, String sep, boolean filterBlank, boolean trim) + { + List list = new ArrayList(); + if (StringUtil.isEmpty(str)) + { + return list; + } + + // 过滤空白字符串 + if (filterBlank && StringUtil.isBlank(str)) + { + return list; + } + String[] split = str.split(sep); + for (String string : split) + { + if (filterBlank && StringUtil.isBlank(string)) + { + continue; + } + if (trim) + { + string = string.trim(); + } + list.add(string); + } + + return list; + } + + /** + * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 + * + * @param cs 指定字符串 + * @param searchCharSequences 需要检查的字符串数组 + * @return 是否包含任意一个字符串 + */ + public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) + { + if (isEmpty(cs) || isEmpty(searchCharSequences)) + { + return false; + } + for (CharSequence testStr : searchCharSequences) + { + if (containsIgnoreCase(cs, testStr)) + { + return true; + } + } + return false; + } + + /** + * 驼峰转下划线命名 + */ + public static String toUnderScoreCase(String str) + { + if (str == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + // 前置字符是否大写 + boolean preCharIsUpperCase = true; + // 当前字符是否大写 + boolean curreCharIsUpperCase = true; + // 下一字符是否大写 + boolean nexteCharIsUpperCase = true; + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (i > 0) + { + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); + } + else + { + preCharIsUpperCase = false; + } + + curreCharIsUpperCase = Character.isUpperCase(c); + + if (i < (str.length() - 1)) + { + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); + } + + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) + { + sb.append(SEPARATOR); + } + else if ((i != 0) && curreCharIsUpperCase) + { + if (!preCharIsUpperCase) { + sb.append(SEPARATOR); + + } + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必要转换 + return ""; + } + else if (!name.contains(SEPARATOR)) + { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) + { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + /** + * 驼峰式命名法 例如:user_name->userName + */ + public static String toCamelCase(String s) + { + if (s == null) + { + return null; + } + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + if (String.valueOf(c).equals(SEPARATOR)) + { + upperCase = true; + } + else if (upperCase) + { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } + else + { + sb.append(c); + } + } + return sb.toString(); + } + + /** + * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, List strs) + { + if (isEmpty(str) || isEmpty(strs)) + { + return false; + } + for (String pattern : strs) + { + if (isMatch(pattern, str)) + { + return true; + } + } + return false; + } + + /** + * 判断url是否与规则配置: + * ? 表示单个字符; + * * 表示一层路径内的任意字符串,不可跨层级; + * ** 表示任意层路径; + * + * @param pattern 匹配规则 + * @param url 需要匹配的url + * @return + */ + public static boolean isMatch(String pattern, String url) + { + AntPathMatcher matcher = new AntPathMatcher(); + return matcher.match(pattern, url); + } + + @SuppressWarnings("unchecked") + public static T cast(Object obj) + { + return (T) obj; + } +} \ No newline at end of file diff --git a/ailanyin-model-mapper/pom.xml b/ailanyin-model-mapper/pom.xml new file mode 100644 index 0000000..1f688ff --- /dev/null +++ b/ailanyin-model-mapper/pom.xml @@ -0,0 +1,32 @@ + + + + vis389_backend + com.ailanyin + 1.0-SNAPSHOT + + 4.0.0 + + ailanyin-model-mapper + + + + com.ailanyin + ailanyin-common + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + + + com.alibaba + druid-spring-boot-starter + + + com.dameng + Dm7JdbcDriver17 + + + diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/ExceptionLogMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/ExceptionLogMapper.java new file mode 100644 index 0000000..8102cf8 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/ExceptionLogMapper.java @@ -0,0 +1,37 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.ExceptionLog; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/2 0002 下午 17:21 + */ +public interface ExceptionLogMapper { + + /** + * 新增异常 + * + * @param exceptionLog exceptionLog + */ + void insertExceptionLog(ExceptionLog exceptionLog); + + /** + * 批量删除异常 + * + * @param logIds ids + */ + void deleteBatchIds(@Param("ids") List logIds); + + /** + * 条件查询 + * + * @param exceptionLog exceptionLog + * @return list + */ + List selectListByParam(ExceptionLog exceptionLog); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysBlacklistUserMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysBlacklistUserMapper.java new file mode 100644 index 0000000..0f04778 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysBlacklistUserMapper.java @@ -0,0 +1,37 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysBlacklistUser; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/1 0001 下午 15:08 + */ +public interface SysBlacklistUserMapper { + + /** + * 新增黑名单 + * + * @param blacklistUser 黑名单 + */ + void insertBlacklistUser(SysBlacklistUser blacklistUser); + + /** + * 批量删除黑名单 + * + * @param idList idList + */ + void deleteBatchIds(@Param("ids") List idList); + + /** + * 条件查询 + * + * @param blacklistUser blacklistUser + * @return list + */ + List selectByParam(SysBlacklistUser blacklistUser); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysConfigMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysConfigMapper.java new file mode 100644 index 0000000..d2861d7 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysConfigMapper.java @@ -0,0 +1,68 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysConfig; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:44 + */ +public interface SysConfigMapper { + /** + * 查询参数配置信息 + * + * @param config 参数配置信息 + * @return 参数配置信息 + */ + SysConfig selectConfig(SysConfig config); + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + List selectConfigList(SysConfig config); + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数键名 + * @return 参数配置信息 + */ + SysConfig checkConfigKeyUnique(String configKey); + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + int insertConfig(SysConfig config); + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + int updateConfig(SysConfig config); + + /** + * 删除参数配置 + * + * @param configId 参数ID + */ + void deleteConfigById(Long configId); + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + * @return 结果 + */ + int deleteConfigByIds(Long[] configIds); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysDeptMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysDeptMapper.java new file mode 100644 index 0000000..3ef6106 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysDeptMapper.java @@ -0,0 +1,115 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysDept; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:03 + */ +public interface SysDeptMapper { + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + List selectDeptList(SysDept dept); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @param deptCheckStrictly 部门树选择项是否关联显示 + * @return 选中部门列表 + */ + List selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly); + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + SysDept selectDeptById(Long deptId); + + /** + * 根据ID查询所有子部门 + * + * @param deptId 部门ID + * @return 部门列表 + */ + List selectChildrenDeptById(Long deptId); + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + int selectNormalChildrenDeptById(Long deptId); + + /** + * 是否存在子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + int hasChildByDeptId(Long deptId); + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 + */ + int checkDeptExistUser(Long deptId); + + /** + * 校验部门名称是否唯一 + * + * @param deptName 部门名称 + * @param parentId 父部门ID + * @return 结果 + */ + SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId); + + /** + * 新增部门信息 + * + * @param dept 部门信息 + */ + void insertDept(SysDept dept); + + /** + * 修改部门信息 + * + * @param dept 部门信息 + */ + void updateDept(SysDept dept); + + /** + * 修改所在部门正常状态 + * + * @param deptIds 部门ID组 + */ + void updateDeptStatusNormal(Long[] deptIds); + + /** + * 修改子元素关系 + * + * @param deptList 子元素 + */ + void updateDeptChildren(@Param("deptList") List deptList); + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + */ + void deleteDeptById(Long deptId); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysDictDataMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysDictDataMapper.java new file mode 100644 index 0000000..e581a52 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysDictDataMapper.java @@ -0,0 +1,96 @@ +package com.ailanyin.mapper; + +import com.ailanyin.model.SysDictData; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 字典表 数据层 + * + * @author ruoyi + */ +public interface SysDictDataMapper +{ + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + public List selectDictDataList(SysDictData dictData); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + public List selectDictDataByType(String dictType); + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + public String selectDictLabel(@Param("dictType") String dictType, @Param("dictValue") String dictValue); + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + public SysDictData selectDictDataById(Long dictCode); + + /** + * 查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据 + */ + public int countDictDataByType(String dictType); + + /** + * 通过字典ID删除字典数据信息 + * + * @param dictCode 字典数据ID + * @return 结果 + */ + public int deleteDictDataById(Long dictCode); + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + * @return 结果 + */ + public int deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int insertDictData(SysDictData dictData); + + /** + * 修改字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int updateDictData(SysDictData dictData); + + /** + * 同步修改字典类型 + * + * @param oldDictType 旧字典类型 + * @param newDictType 新旧字典类型 + * @return 结果 + */ + public int updateDictDataType(@Param("oldDictType") String oldDictType, @Param("newDictType") String newDictType); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysDictTypeMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysDictTypeMapper.java new file mode 100644 index 0000000..5b982a8 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysDictTypeMapper.java @@ -0,0 +1,86 @@ +package com.ailanyin.mapper; + +import com.ailanyin.model.SysDictType; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 字典表 数据层 + * + * @author ruoyi + */ +@Mapper +public interface SysDictTypeMapper +{ + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + public List selectDictTypeList(SysDictType dictType); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + public List selectDictTypeAll(); + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + public SysDictType selectDictTypeById(Long dictId); + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + public SysDictType selectDictTypeByType(String dictType); + + /** + * 通过字典ID删除字典信息 + * + * @param dictId 字典ID + * @return 结果 + */ + public int deleteDictTypeById(Long dictId); + + /** + * 批量删除字典类型信息 + * + * @param dictIds 需要删除的字典ID + * @return 结果 + */ + public int deleteDictTypeByIds(Long[] dictIds); + + /** + * 新增字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int insertDictType(SysDictType dictType); + + /** + * 修改字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int updateDictType(SysDictType dictType); + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + public SysDictType checkDictTypeUnique(String dictType); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysLogMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysLogMapper.java new file mode 100644 index 0000000..aef640e --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysLogMapper.java @@ -0,0 +1,38 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysLog; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/28 0028 下午 14:51 + */ +public interface SysLogMapper { + + /** + * 批量删除日志 + * + * @param logIds logIds + */ + void deleteBatchIds(@Param("ids") List logIds); + + /** + * 条件查询 + * + * @param sysLog sysLog + * @return list + */ + List selectByParam(SysLog sysLog); + + /** + * 新增日志 + * + * @param sysLog log + */ + void insertLog(SysLog sysLog); + +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysMenuMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysMenuMapper.java new file mode 100644 index 0000000..921cb7e --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysMenuMapper.java @@ -0,0 +1,122 @@ +package com.ailanyin.mapper; + +import com.ailanyin.model.SysMenu; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:03 + */ +public interface SysMenuMapper +{ + /** + * 查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + List selectMenuList(SysMenu menu); + + /** + * 查询用户所有权限 + * + * @return 权限列表 + */ + List selectMenuPerms(); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + List selectMenuListByUserId(SysMenu menu); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + List selectMenuPermsByUserId(Long userId); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + List selectSysMenuPermsByUserId(Long userId); + /** + * 根据用户ID查询菜单 + * + * @return 菜单列表 + */ + List selectMenuTreeAll(); + + /** + * 根据用户ID查询菜单 + * + * @param userId 用户ID + * @return 菜单列表 + */ + List selectMenuTreeByUserId(Long userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @param menuCheckStrictly 菜单树选择项是否关联显示 + * @return 选中菜单列表 + */ + List selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly); + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + SysMenu selectMenuById(Long menuId); + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 + */ + int hasChildByMenuId(Long menuId); + + /** + * 新增菜单信息 + * + * @param menu 菜单信息 + */ + void insertMenu(SysMenu menu); + + /** + * 修改菜单信息 + * + * @param menu 菜单信息 + */ + void updateMenu(SysMenu menu); + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + */ + void deleteMenuById(Long menuId); + + /** + * 校验菜单名称是否唯一 + * + * @param menuName 菜单名称 + * @param parentId 父菜单ID + * @return 结果 + */ + SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysPostMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysPostMapper.java new file mode 100644 index 0000000..9c211c2 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysPostMapper.java @@ -0,0 +1,97 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysPost; + +import java.util.List; + +/** + * 岗位信息 数据层 + * + * @author ruoyi + */ +public interface SysPostMapper { + /** + * 查询岗位数据集合 + * + * @param post 岗位信息 + * @return 岗位数据集合 + */ + List selectPostList(SysPost post); + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + List selectPostAll(); + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + SysPost selectPostById(Long postId); + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + List selectPostListByUserId(Long userId); + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + List selectPostsByUserName(String userName); + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + int deletePostById(Long postId); + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + */ + void deletePostByIds(Long[] postIds); + + /** + * 修改岗位信息 + * + * @param post 岗位信息 + */ + void updatePost(SysPost post); + + /** + * 新增岗位信息 + * + * @param post 岗位信息 + */ + void insertPost(SysPost post); + + /** + * 校验岗位名称 + * + * @param postName 岗位名称 + * @return 结果 + */ + SysPost checkPostNameUnique(String postName); + + /** + * 校验岗位编码 + * + * @param postCode 岗位编码 + * @return 结果 + */ + SysPost checkPostCodeUnique(String postCode); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysRoleDeptMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysRoleDeptMapper.java new file mode 100644 index 0000000..b6ac1b2 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysRoleDeptMapper.java @@ -0,0 +1,46 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysRoleDept; + +import java.util.List; + +/** + * 角色与部门关联表 数据层 + * + * @author ruoyi + */ +public interface SysRoleDeptMapper +{ + /** + * 通过角色ID删除角色和部门关联 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleDeptByRoleId(Long roleId); + + /** + * 批量删除角色部门关联信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteRoleDept(Long[] ids); + + /** + * 查询部门使用数量 + * + * @param deptId 部门ID + * @return 结果 + */ + public int selectCountRoleDeptByDeptId(Long deptId); + + /** + * 批量新增角色部门信息 + * + * @param roleDeptList 角色部门列表 + * @return 结果 + */ + public int batchRoleDept(List roleDeptList); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysRoleMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysRoleMapper.java new file mode 100644 index 0000000..5fa5ac1 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysRoleMapper.java @@ -0,0 +1,105 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysRole; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:03 + */ +public interface SysRoleMapper { + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + List selectRoleList(SysRole role); + + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + List selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + List selectRoleAll(); + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + SysRole selectRoleById(Long roleId); + + /** + * 根据用户ID查询角色 + * + * @param userName 用户名 + * @return 角色列表 + */ + List selectRolesByUserName(String userName); + + /** + * 校验角色名称是否唯一 + * + * @param roleName 角色名称 + * @return 角色信息 + */ + SysRole checkRoleNameUnique(String roleName); + + /** + * 校验角色权限是否唯一 + * + * @param roleKey 角色权限 + * @return 角色信息 + */ + SysRole checkRoleKeyUnique(String roleKey); + + /** + * 修改角色信息 + * + * @param role 角色信息 + */ + void updateRole(SysRole role); + + /** + * 新增角色信息 + * + * @param role 角色信息 + */ + void insertRole(SysRole role); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + int deleteRoleById(Long roleId); + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + */ + void deleteRoleByIds(Long[] roleIds); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysRoleMenuMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysRoleMenuMapper.java new file mode 100644 index 0000000..cb86a7a --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysRoleMenuMapper.java @@ -0,0 +1,46 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysRoleMenu; + +import java.util.List; + +/** + * 角色与菜单关联表 数据层 + * + * @author ruoyi + */ +public interface SysRoleMenuMapper +{ + /** + * 查询菜单使用数量 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int checkMenuExistRole(Long menuId); + + /** + * 通过角色ID删除角色和菜单关联 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleMenuByRoleId(Long roleId); + + /** + * 批量删除角色菜单关联信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteRoleMenu(Long[] ids); + + /** + * 批量新增角色菜单信息 + * + * @param roleMenuList 角色菜单列表 + * @return 结果 + */ + public int batchRoleMenu(List roleMenuList); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysUserMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysUserMapper.java new file mode 100644 index 0000000..aeb48f0 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysUserMapper.java @@ -0,0 +1,155 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysUser; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:03 + */ +public interface SysUserMapper { + /** + * 根据条件分页查询用户列表 + * + * @param sysUser 用户信息 + * @return 用户信息集合信息 + */ + List selectUserList(SysUser sysUser); + + /** + * 根据条件分页查询未已配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + List selectAllocatedList(SysUser user); + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + List selectUnallocatedList(SysUser user); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + SysUser selectUserByUserName(String userName); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + SysUser selectUserById(Long userId); + + /** + * 新增用户信息 + * + * @param user 用户信息 + */ + void insertUser(SysUser user); + + /** + * 修改用户信息 + * + * @param user 用户信息 + */ + void updateUser(SysUser user); + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + */ + void updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar); + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + */ + void resetUserPwd(@Param("userName") String userName, @Param("password") String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + int deleteUserById(Long userId); + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + */ + void deleteUserByIds(Long[] userIds); + + /** + * 校验用户名称是否唯一 + * + * @param userName 用户名称 + * @return 结果 + */ + int checkUserNameUnique(String userName); + + /** + * 校验手机号码是否唯一 + * + * @param phonenumber 手机号码 + * @return 结果 + */ + SysUser checkPhoneUnique(String phonenumber); + + /** + * 校验email是否唯一 + * + * @param email 用户邮箱 + * @return 结果 + */ + SysUser checkEmailUnique(String email); + + /** + * 已删除用户列表 + * + * @param user user + * @return list + */ + List selectDeleteUserList(SysUser user); + + /** + * 恢复已删除的用户 + * + * @param userIds ids + */ + void recoveryDeleteUser(List userIds); + + /** + * 彻底删除用户 + * + * @param userId ids + */ + void realDeleteUser(List userId); + + /** + * 更新用户最后登录的ip和时间 + * + * @param username username + * @param ip 最后登录位置 + * @param time 最后登录时间 + */ + void updateUserLastLoginIpAndTime(@Param("userName") String username, @Param("ip") String ip, @Param("time") Date time); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysUserPostMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysUserPostMapper.java new file mode 100644 index 0000000..84ac609 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysUserPostMapper.java @@ -0,0 +1,46 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysUserPost; + +import java.util.List; + +/** + * 用户与岗位关联表 数据层 + * + * @author ruoyi + */ +public interface SysUserPostMapper +{ + /** + * 通过用户ID删除用户和岗位关联 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserPostByUserId(Long userId); + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + public int countUserPostById(Long postId); + + /** + * 批量删除用户和岗位关联 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteUserPost(Long[] ids); + + /** + * 批量新增用户岗位信息 + * + * @param userPostList 用户角色列表 + * @return 结果 + */ + public int batchUserPost(List userPostList); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysUserRoleMapper.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysUserRoleMapper.java new file mode 100644 index 0000000..eb25dcd --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/mapper/SysUserRoleMapper.java @@ -0,0 +1,58 @@ +package com.ailanyin.mapper; + + +import com.ailanyin.model.SysUserRole; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 13:01 + */ +public interface SysUserRoleMapper { + /** + * 通过用户ID删除用户和角色关联 + * + * @param userId 用户ID + */ + void deleteUserRoleByUserId(Long userId); + + /** + * 批量删除用户和角色关联 + * + * @param ids 需要删除的数据ID + */ + void deleteUserRole(Long[] ids); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + int countUserRoleByRoleId(Long roleId); + + /** + * 批量新增用户角色信息 + * + * @param userRoleList 用户角色列表 + */ + void batchUserRole(List userRoleList); + + /** + * 删除用户和角色关联信息 + * + * @param userRole 用户和角色关联信息 + */ + void deleteUserRoleInfo(SysUserRole userRole); + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要删除的用户数据ID + */ + void deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds); +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/ExceptionLog.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/ExceptionLog.java new file mode 100644 index 0000000..6e255d2 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/ExceptionLog.java @@ -0,0 +1,30 @@ +package com.ailanyin.model; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/11/2 0002 下午 17:08 + */ +@Data +public class ExceptionLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "序号") + private String exceptionId; + + @ApiModelProperty(value = "异常原因") + private String exceptionReason; + + @ApiModelProperty(value = "堆栈信息") + private String detailInfo; + + @ApiModelProperty(value = "异常时间") + private Date createTime; +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysBlacklistUser.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysBlacklistUser.java new file mode 100644 index 0000000..8cce1f4 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysBlacklistUser.java @@ -0,0 +1,40 @@ +package com.ailanyin.model; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.Map; + +/** + * 黑名单 + * + * @author ailanyin + * @version 1.0 + * @since 2021/11/1 0001 下午 15:05 + */ +@Data +public class SysBlacklistUser implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "序号") + @Excel(name = "名单编号", width = 25) + private String id; + @ApiModelProperty(value = "IP地址") + @Excel(name = "IP地址", width = 20) + private String ip; + @ApiModelProperty(value = "具体位置") + @Excel(name = "具体位置", width = 30) + private String address; + @ApiModelProperty(value = "拉黑原因") + @Excel(name = "拉黑原因", width = 25) + private String reason; + @ApiModelProperty(value = "拉黑时间") + @Excel(name = "拉黑时间", format = "yyyy-MM-dd HH:mm:ss", width = 25) + private Date createTime; + @ApiModelProperty(value = "查询参数") + private Map params; +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysConfig.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysConfig.java new file mode 100644 index 0000000..229898f --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysConfig.java @@ -0,0 +1,105 @@ +package com.ailanyin.model; + +import com.ailanyin.common.model.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 参数配置表 sys_config + * + * @author ruoyi + */ +public class SysConfig extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 参数主键 */ + private Long configId; + + /** 参数名称 */ + private String configName; + + /** 参数键名 */ + private String configKey; + + /** 参数键值 */ + private String configValue; + + /** 系统内置(Y是 N否) */ + private String configType; + + public Long getConfigId() + { + return configId; + } + + public void setConfigId(Long configId) + { + this.configId = configId; + } + + @NotBlank(message = "参数名称不能为空") + @Size(min = 0, max = 100, message = "参数名称不能超过100个字符") + public String getConfigName() + { + return configName; + } + + public void setConfigName(String configName) + { + this.configName = configName; + } + + @NotBlank(message = "参数键名长度不能为空") + @Size(min = 0, max = 100, message = "参数键名长度不能超过100个字符") + public String getConfigKey() + { + return configKey; + } + + public void setConfigKey(String configKey) + { + this.configKey = configKey; + } + + @NotBlank(message = "参数键值不能为空") + @Size(min = 0, max = 500, message = "参数键值长度不能超过500个字符") + public String getConfigValue() + { + return configValue; + } + + public void setConfigValue(String configValue) + { + this.configValue = configValue; + } + + public String getConfigType() + { + return configType; + } + + public void setConfigType(String configType) + { + this.configType = configType; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("configId", getConfigId()) + .append("configName", getConfigName()) + .append("configKey", getConfigKey()) + .append("configValue", getConfigValue()) + .append("configType", getConfigType()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysDept.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysDept.java new file mode 100644 index 0000000..5d62285 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysDept.java @@ -0,0 +1,173 @@ +package com.ailanyin.model; + +import com.ailanyin.common.model.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.ArrayList; +import java.util.List; + +/** + * 部门 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:05 + */ +public class SysDept extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "部门ID") + private Long deptId; + + @ApiModelProperty(value = "父部门ID") + private Long parentId; + + @ApiModelProperty(value = "祖级列表") + private String ancestors; + + @ApiModelProperty(value = "部门名称") + private String deptName; + + @ApiModelProperty(value = "显示顺序") + private String orderNum; + + @ApiModelProperty(value = "负责人") + private String leader; + + @ApiModelProperty(value = "联系电话") + private String phone; + + @ApiModelProperty(value = "邮箱") + private String email; + + @ApiModelProperty(value = "部门状态:0正常,1停用") + private String status; + + @ApiModelProperty(value = "删除标志(0代表存在 2代表删除)") + private String delFlag; + + @ApiModelProperty(value = "父部门名称") + private String parentName; + + @ApiModelProperty(value = "子部门") + private List children = new ArrayList(); + + public Long getDeptId() { + return deptId; + } + + public void setDeptId(Long deptId) { + this.deptId = deptId; + } + + public Long getParentId() { + return parentId; + } + + public void setParentId(Long parentId) { + this.parentId = parentId; + } + + public String getAncestors() { + return ancestors; + } + + public void setAncestors(String ancestors) { + this.ancestors = ancestors; + } + + public String getDeptName() { + return deptName; + } + + public void setDeptName(String deptName) { + this.deptName = deptName; + } + + public String getOrderNum() { + return orderNum; + } + + public void setOrderNum(String orderNum) { + this.orderNum = orderNum; + } + + public String getLeader() { + return leader; + } + + public void setLeader(String leader) { + this.leader = leader; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getDelFlag() { + return delFlag; + } + + public void setDelFlag(String delFlag) { + this.delFlag = delFlag; + } + + public String getParentName() { + return parentName; + } + + public void setParentName(String parentName) { + this.parentName = parentName; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("deptId", getDeptId()) + .append("parentId", getParentId()) + .append("ancestors", getAncestors()) + .append("deptName", getDeptName()) + .append("orderNum", getOrderNum()) + .append("leader", getLeader()) + .append("phone", getPhone()) + .append("email", getEmail()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} \ No newline at end of file diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysDictData.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysDictData.java new file mode 100644 index 0000000..9b17c9b --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysDictData.java @@ -0,0 +1,166 @@ +package com.ailanyin.model; + +import com.ailanyin.common.constant.UserConstants; +import com.ailanyin.common.model.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 字典数据表 sys_dict_data + * + * @author ruoyi + */ +public class SysDictData extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 字典编码 + */ + private Long dictCode; + + /** + * 字典排序 + */ + private Long dictSort; + + /** + * 字典标签 + */ + private String dictLabel; + + /** + * 字典键值 + */ + private String dictValue; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 样式属性(其他样式扩展) + */ + private String cssClass; + + /** + * 表格字典样式 + */ + private String listClass; + + /** + * 是否默认(Y是 N否) + */ + private String isDefault; + + /** + * 状态(0正常 1停用) + */ + private String status; + + public Long getDictCode() { + return dictCode; + } + + public void setDictCode(Long dictCode) { + this.dictCode = dictCode; + } + + public Long getDictSort() { + return dictSort; + } + + public void setDictSort(Long dictSort) { + this.dictSort = dictSort; + } + + @NotBlank(message = "字典标签不能为空") + @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") + public String getDictLabel() { + return dictLabel; + } + + public void setDictLabel(String dictLabel) { + this.dictLabel = dictLabel; + } + + @NotBlank(message = "字典键值不能为空") + @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") + public String getDictValue() { + return dictValue; + } + + public void setDictValue(String dictValue) { + this.dictValue = dictValue; + } + + @NotBlank(message = "字典类型不能为空") + @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") + public String getDictType() { + return dictType; + } + + public void setDictType(String dictType) { + this.dictType = dictType; + } + + @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") + public String getCssClass() { + return cssClass; + } + + public void setCssClass(String cssClass) { + this.cssClass = cssClass; + } + + public String getListClass() { + return listClass; + } + + public void setListClass(String listClass) { + this.listClass = listClass; + } + + public boolean getDefault() { + return UserConstants.YES.equals(this.isDefault) ? true : false; + } + + public String getIsDefault() { + return isDefault; + } + + public void setIsDefault(String isDefault) { + this.isDefault = isDefault; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("dictCode", getDictCode()) + .append("dictSort", getDictSort()) + .append("dictLabel", getDictLabel()) + .append("dictValue", getDictValue()) + .append("dictType", getDictType()) + .append("cssClass", getCssClass()) + .append("listClass", getListClass()) + .append("isDefault", getIsDefault()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysDictType.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysDictType.java new file mode 100644 index 0000000..1123e26 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysDictType.java @@ -0,0 +1,89 @@ +package com.ailanyin.model; + +import com.ailanyin.common.model.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 字典类型表 sys_dict_type + * + * @author ruoyi + */ +public class SysDictType extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 字典主键 */ + private Long dictId; + + /** 字典名称 */ + private String dictName; + + /** 字典类型 */ + private String dictType; + + /** 状态(0正常 1停用) */ + private String status; + + public Long getDictId() + { + return dictId; + } + + public void setDictId(Long dictId) + { + this.dictId = dictId; + } + + @NotBlank(message = "字典名称不能为空") + @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符") + public String getDictName() + { + return dictName; + } + + public void setDictName(String dictName) + { + this.dictName = dictName; + } + + @NotBlank(message = "字典类型不能为空") + @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") + public String getDictType() + { + return dictType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("dictId", getDictId()) + .append("dictName", getDictName()) + .append("dictType", getDictType()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysLog.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysLog.java new file mode 100644 index 0000000..158281c --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysLog.java @@ -0,0 +1,57 @@ +package com.ailanyin.model; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.Map; + + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:05 + */ +@Data +public class SysLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "id") + @Excel(name = "日志编号", width = 30) + private String id; + + @ApiModelProperty(value = "操作描述") + @Excel(name = "操作描述", width = 30) + private String description; + + @ApiModelProperty(value = "操作用户") + @Excel(name = "请求人员") + private String username; + + @ApiModelProperty(value = "访问时间") + @Excel(name = "请求时间", format = "yyyy-MM-dd HH:mm:ss", width = 30) + private Date startTime; + + @ApiModelProperty(value = "执行时间") + @Excel(name = "请求耗时") + private Integer spendTime; + + @ApiModelProperty(value = "请求类型") + @Excel(name = "请求方式") + private String method; + + @ApiModelProperty(value = "IP地址") + @Excel(name = "请求地址") + private String ip; + + @ApiModelProperty(value = "请求路径") + private String uri; + + @ApiModelProperty(value = "请求参数") + private String parameter; + + private Map params; +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysMenu.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysMenu.java new file mode 100644 index 0000000..4a82f0d --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysMenu.java @@ -0,0 +1,251 @@ +package com.ailanyin.model; + +import com.ailanyin.common.model.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:08 + */ +public class SysMenu extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "菜单ID") + private Long menuId; + + @ApiModelProperty(value = "菜单名称") + private String menuName; + + @ApiModelProperty(value = "父菜单名称") + private String parentName; + + @ApiModelProperty(value = "父菜单ID") + private Long parentId; + + @ApiModelProperty(value = "显示顺序") + private String orderNum; + + @ApiModelProperty(value = "路由地址") + private String path; + + @ApiModelProperty(value = "组件路径") + private String component; + + @ApiModelProperty(value = "路由参数") + private String query; + + @ApiModelProperty(value = "是否为外链(0->是,1->否)") + private String isFrame; + + @ApiModelProperty(value = "是否缓存(0->是,1->否)") + private String isCache; + + @ApiModelProperty(value = "类型(M目录 C菜单 F按钮)") + private String menuType; + + @ApiModelProperty(value = "显示状态(0显示 1隐藏)") + private String visible; + + @ApiModelProperty(value = "菜单状态(0显示 1隐藏)") + private String status; + + @ApiModelProperty(value = "权限字符串") + private String perms; + + @ApiModelProperty(value = "菜单图标") + private String icon; + + @ApiModelProperty(value = "子菜单") + private List children = new ArrayList(); + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + public String getMenuName() + { + return menuName; + } + + public void setMenuName(String menuName) + { + this.menuName = menuName; + } + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + public String getOrderNum() + { + return orderNum; + } + + public void setOrderNum(String orderNum) + { + this.orderNum = orderNum; + } + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public String getQuery() + { + return query; + } + + public void setQuery(String query) + { + this.query = query; + } + + public String getIsFrame() + { + return isFrame; + } + + public void setIsFrame(String isFrame) + { + this.isFrame = isFrame; + } + + public String getIsCache() + { + return isCache; + } + + public void setIsCache(String isCache) + { + this.isCache = isCache; + } + + public String getMenuType() + { + return menuType; + } + + public void setMenuType(String menuType) + { + this.menuType = menuType; + } + + public String getVisible() + { + return visible; + } + + public void setVisible(String visible) + { + this.visible = visible; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getPerms() + { + return perms; + } + + public void setPerms(String perms) + { + this.perms = perms; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("menuId", getMenuId()) + .append("menuName", getMenuName()) + .append("parentId", getParentId()) + .append("orderNum", getOrderNum()) + .append("path", getPath()) + .append("component", getComponent()) + .append("isFrame", getIsFrame()) + .append("IsCache", getIsCache()) + .append("menuType", getMenuType()) + .append("visible", getVisible()) + .append("status ", getStatus()) + .append("perms", getPerms()) + .append("icon", getIcon()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysPost.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysPost.java new file mode 100644 index 0000000..f02f103 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysPost.java @@ -0,0 +1,121 @@ +package com.ailanyin.model; + + +import com.ailanyin.common.model.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 岗位实体 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:00 + */ +public class SysPost extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "岗位序号") + private Long postId; + + @ApiModelProperty(value = "岗位编码") + private String postCode; + + @ApiModelProperty(value = "岗位名称") + private String postName; + + @ApiModelProperty(value = "岗位排序") + private String postSort; + + @ApiModelProperty(value = "状态(0正常 1停用)") + private String status; + + @ApiModelProperty(value = "用户是否存在此岗位标识 默认不存在") + private boolean flag = false; + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @NotBlank(message = "岗位编码不能为空") + @Size(min = 0, max = 64, message = "岗位编码长度不能超过64个字符") + public String getPostCode() + { + return postCode; + } + + public void setPostCode(String postCode) + { + this.postCode = postCode; + } + + @NotBlank(message = "岗位名称不能为空") + @Size(min = 0, max = 50, message = "岗位名称长度不能超过50个字符") + public String getPostName() + { + return postName; + } + + public void setPostName(String postName) + { + this.postName = postName; + } + + @NotBlank(message = "显示顺序不能为空") + public String getPostSort() + { + return postSort; + } + + public void setPostSort(String postSort) + { + this.postSort = postSort; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public boolean isFlag() + { + return flag; + } + + public void setFlag(boolean flag) + { + this.flag = flag; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("postId", getPostId()) + .append("postCode", getPostCode()) + .append("postName", getPostName()) + .append("postSort", getPostSort()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysRole.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysRole.java new file mode 100644 index 0000000..7a63859 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysRole.java @@ -0,0 +1,182 @@ +package com.ailanyin.model; + +import com.ailanyin.common.model.BaseEntity; +import io.swagger.annotations.ApiModelProperty; + +import java.util.Arrays; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:06 + */ +public class SysRole extends BaseEntity { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "角色ID") + private Long roleId; + + @ApiModelProperty(value = "角色名称") + private String roleName; + + @ApiModelProperty(value = "角色权限") + private String roleKey; + + @ApiModelProperty(value = "角色排序") + private String roleSort; + + @ApiModelProperty(value = "数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)") + private String dataScope; + + @ApiModelProperty(value = "菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)") + private boolean menuCheckStrictly; + + @ApiModelProperty(value = "部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 )") + private boolean deptCheckStrictly; + + @ApiModelProperty(value = "角色状态(0正常 1停用)") + private String status; + + @ApiModelProperty(value = "删除标志(0代表存在 2代表删除)") + private String delFlag; + + @ApiModelProperty(value = "用户是否存在此角色标识 默认不存在") + private boolean flag = false; + + @ApiModelProperty(value = "菜单组") + private Long[] menuIds; + + @ApiModelProperty(value = "部门组(数据权限)") + private Long[] deptIds; + + public SysRole() { + + } + + public SysRole(Long roleId) { + this.roleId = roleId; + } + + public Long getRoleId() { + return roleId; + } + + public void setRoleId(Long roleId) { + this.roleId = roleId; + } + + public boolean isAdmin() { + return isAdmin(this.roleId); + } + + public static boolean isAdmin(Long roleId) { + return roleId != null && 1L == roleId; + } + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public String getRoleKey() { + return roleKey; + } + + public void setRoleKey(String roleKey) { + this.roleKey = roleKey; + } + + public String getRoleSort() { + return roleSort; + } + + public void setRoleSort(String roleSort) { + this.roleSort = roleSort; + } + + public String getDataScope() { + return dataScope; + } + + public void setDataScope(String dataScope) { + this.dataScope = dataScope; + } + + public boolean isMenuCheckStrictly() { + return menuCheckStrictly; + } + + public void setMenuCheckStrictly(boolean menuCheckStrictly) { + this.menuCheckStrictly = menuCheckStrictly; + } + + public boolean isDeptCheckStrictly() { + return deptCheckStrictly; + } + + public void setDeptCheckStrictly(boolean deptCheckStrictly) { + this.deptCheckStrictly = deptCheckStrictly; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getDelFlag() { + return delFlag; + } + + public void setDelFlag(String delFlag) { + this.delFlag = delFlag; + } + + public boolean isFlag() { + return flag; + } + + public void setFlag(boolean flag) { + this.flag = flag; + } + + public Long[] getMenuIds() { + return menuIds; + } + + public void setMenuIds(Long[] menuIds) { + this.menuIds = menuIds; + } + + public Long[] getDeptIds() { + return deptIds; + } + + public void setDeptIds(Long[] deptIds) { + this.deptIds = deptIds; + } + + @Override + public String toString() { + return "SysRole{" + + "roleId=" + roleId + + ", roleName='" + roleName + '\'' + + ", roleKey='" + roleKey + '\'' + + ", roleSort='" + roleSort + '\'' + + ", dataScope='" + dataScope + '\'' + + ", menuCheckStrictly=" + menuCheckStrictly + + ", deptCheckStrictly=" + deptCheckStrictly + + ", status='" + status + '\'' + + ", delFlag='" + delFlag + '\'' + + ", flag=" + flag + + ", menuIds=" + Arrays.toString(menuIds) + + ", deptIds=" + Arrays.toString(deptIds) + + '}'; + } +} + diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysRoleDept.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysRoleDept.java new file mode 100644 index 0000000..94bb969 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysRoleDept.java @@ -0,0 +1,46 @@ +package com.ailanyin.model; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色和部门关联 sys_role_dept + * + * @author ruoyi + */ +public class SysRoleDept +{ + /** 角色ID */ + private Long roleId; + + /** 部门ID */ + private Long deptId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("deptId", getDeptId()) + .toString(); + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysRoleMenu.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysRoleMenu.java new file mode 100644 index 0000000..dac38a8 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysRoleMenu.java @@ -0,0 +1,46 @@ +package com.ailanyin.model; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色和菜单关联 sys_role_menu + * + * @author ruoyi + */ +public class SysRoleMenu +{ + /** 角色ID */ + private Long roleId; + + /** 菜单ID */ + private Long menuId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("menuId", getMenuId()) + .toString(); + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysUser.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysUser.java new file mode 100644 index 0000000..51ed078 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysUser.java @@ -0,0 +1,270 @@ +package com.ailanyin.model; + + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.ailanyin.common.model.BaseEntity; +import io.swagger.annotations.ApiModelProperty; + + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 上午 10:03 + */ +public class SysUser extends BaseEntity { + + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "用户ID") + @Excel(name = "用户序号", width = 20) + private Long userId; + + @ApiModelProperty(value = "部门ID") + @Excel(name = "部门编号", width = 20) + private Long deptId; + + @ApiModelProperty(value = "用户账号") + @Excel(name = "登录账号", width = 20) + private String userName; + + @ApiModelProperty(value = "用户昵称") + @Excel(name = "用户昵称", width = 20) + private String nickName; + + @ApiModelProperty(value = "用户邮箱") + @Excel(name = "用户邮箱", width = 20) + private String email; + + @ApiModelProperty(value = "手机号码") + @Excel(name = "手机号码", width = 20) + private String phonenumber; + + @ApiModelProperty(value = "用户性别") + @Excel(name = "用户性别", replace = {"男_0", "女_1","未知_2"}) + private String sex; + + @ApiModelProperty(value = "用户头像") + private String avatar; + + @ApiModelProperty(value = "密码") + private String password; + + @ApiModelProperty(value = "帐号状态(0正常 1停用)") + @Excel(name = "帐号状态", replace = {"正常_0", "停用_1"}) + private String status; + + @ApiModelProperty(value = "删除标志(0代表存在 2代表删除)") + private String delFlag; + + @ApiModelProperty(value = "最后登录IP") + @Excel(name = "最后登录IP", width = 20) + private String loginIp; + + @ApiModelProperty(value = "最后登录时间") + @Excel(name = "最后登录时间", format = "yyyy-MM-dd HH:mm:ss", width = 30) + private Date loginDate; + + @ApiModelProperty(value = "部门对象") + private SysDept dept; + + @ApiModelProperty(value = "角色对象") + private List roles; + + @ApiModelProperty(value = "角色组") + private Long[] roleIds; + + @ApiModelProperty(value = "岗位组") + private Long[] postIds; + + @ApiModelProperty(value = "角色ID") + private Long roleId; + + public SysUser() { + + } + + public SysUser(Long userId) { + this.userId = userId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public boolean isAdmin() { + return isAdmin(this.userId); + } + + public static boolean isAdmin(Long userId) { + return userId != null && 1L == userId; + } + + public Long getDeptId() { + return deptId; + } + + public void setDeptId(Long deptId) { + this.deptId = deptId; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhonenumber() { + return phonenumber; + } + + public void setPhonenumber(String phonenumber) { + this.phonenumber = phonenumber; + } + + public String getSex() { + return sex; + } + + public void setSex(String sex) { + this.sex = sex; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getDelFlag() { + return delFlag; + } + + public void setDelFlag(String delFlag) { + this.delFlag = delFlag; + } + + public String getLoginIp() { + return loginIp; + } + + public void setLoginIp(String loginIp) { + this.loginIp = loginIp; + } + + public Date getLoginDate() { + return loginDate; + } + + public void setLoginDate(Date loginDate) { + this.loginDate = loginDate; + } + + public SysDept getDept() { + return dept; + } + + public void setDept(SysDept dept) { + this.dept = dept; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public Long[] getRoleIds() { + return roleIds; + } + + public void setRoleIds(Long[] roleIds) { + this.roleIds = roleIds; + } + + public Long[] getPostIds() { + return postIds; + } + + public void setPostIds(Long[] postIds) { + this.postIds = postIds; + } + + public Long getRoleId() { + return roleId; + } + + public void setRoleId(Long roleId) { + this.roleId = roleId; + } + + @Override + public String toString() { + return "SysUser{" + + "userId=" + userId + + ", deptId=" + deptId + + ", userName='" + userName + '\'' + + ", nickName='" + nickName + '\'' + + ", email='" + email + '\'' + + ", phonenumber='" + phonenumber + '\'' + + ", sex='" + sex + '\'' + + ", avatar='" + avatar + '\'' + + ", password='" + password + '\'' + + ", status='" + status + '\'' + + ", delFlag='" + delFlag + '\'' + + ", loginIp='" + loginIp + '\'' + + ", loginDate=" + loginDate + + ", dept=" + dept + + ", roles=" + roles + + ", roleIds=" + Arrays.toString(roleIds) + + ", postIds=" + Arrays.toString(postIds) + + ", roleId=" + roleId + + '}'; + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysUserPost.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysUserPost.java new file mode 100644 index 0000000..3564666 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysUserPost.java @@ -0,0 +1,46 @@ +package com.ailanyin.model; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户和岗位关联 sys_user_post + * + * @author ruoyi + */ +public class SysUserPost +{ + /** 用户ID */ + private Long userId; + + /** 岗位ID */ + private Long postId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("postId", getPostId()) + .toString(); + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysUserRole.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysUserRole.java new file mode 100644 index 0000000..77fc5d5 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/SysUserRole.java @@ -0,0 +1,46 @@ +package com.ailanyin.model; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户和角色关联 sys_user_role + * + * @author ruoyi + */ +public class SysUserRole +{ + /** 用户ID */ + private Long userId; + + /** 角色ID */ + private Long roleId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("roleId", getRoleId()) + .toString(); + } +} diff --git a/ailanyin-model-mapper/src/main/java/com/ailanyin/model/TreeSelect.java b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/TreeSelect.java new file mode 100644 index 0000000..312ced4 --- /dev/null +++ b/ailanyin-model-mapper/src/main/java/com/ailanyin/model/TreeSelect.java @@ -0,0 +1,76 @@ +package com.ailanyin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Treeselect树结构实体类 + * + * @author ruoyi + */ +public class TreeSelect implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 节点ID */ + private Long id; + + /** 节点名称 */ + private String label; + + /** 子节点 */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + public TreeSelect() + { + + } + + public TreeSelect(SysDept dept) + { + this.id = dept.getDeptId(); + this.label = dept.getDeptName(); + this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public TreeSelect(SysMenu menu) + { + this.id = menu.getMenuId(); + this.label = menu.getMenuName(); + this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public Long getId() + { + return id; + } + + public void setId(Long id) + { + this.id = id; + } + + public String getLabel() + { + return label; + } + + public void setLabel(String label) + { + this.label = label; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/ExceptionLogMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/ExceptionLogMapper.xml new file mode 100644 index 0000000..a20ef7c --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/ExceptionLogMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + insert into ROOT."exception_log" + + + "exception_id", + + + "create_time", + + + "exception_reason", + + + "detail_info", + + + + + #{exceptionId}, + + + #{createTime}, + + + #{exceptionReason}, + + + #{detailInfo}, + + + + + + delete from ROOT."exception_log" + where "exception_id" in + + #{item} + + + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysBlacklistUserMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysBlacklistUserMapper.xml new file mode 100644 index 0000000..fd87f24 --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysBlacklistUserMapper.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + "id", "ip", "address", "reason", "create_time" + + + + insert into ROOT."sys_blacklist_user" + + + "id", + + + "ip", + + + "address", + + + "reason", + + + "create_time", + + + + + #{id,jdbcType=BIGINT}, + + + #{ip,jdbcType=VARCHAR}, + + + #{address,jdbcType=VARCHAR}, + + + #{reason,jdbcType=VARCHAR}, + + + #{createTime,jdbcType=TIMESTAMP}, + + + + + + delete from ROOT."sys_blacklist_user" + where "id" in + + #{item} + + + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysConfigMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysConfigMapper.xml new file mode 100644 index 0000000..a2e6058 --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysConfigMapper.xml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + select "config_id", "config_name", "config_key", "config_value", "config_type", "create_by", "create_time", "update_by", "update_time", "remark" + from ROOT."sys_config" + + + + + + + and "config_id" = #{configId} + + + and "config_key" = #{configKey} + + + + + + + + + + + + insert into ROOT."sys_config" ( + "config_name", + "config_key", + "config_value", + "config_type", + "create_by", + "remark", + "create_time" + )values( + #{configName}, + #{configKey}, + #{configValue}, + #{configType}, + #{createBy}, + #{remark}, + sysdate + ) + + + + update ROOT."sys_config" + + "config_name" = #{configName}, + "config_key" = #{configKey}, + "config_value" = #{configValue}, + "config_type" = #{configType}, + "update_by" = #{updateBy}, + "remark" = #{remark}, + "update_time" = sysdate + + where "config_id" = #{configId} + + + + delete from ROOT."sys_config" where "config_id" in + + #{configId} + + + + + delete from ROOT."sys_config" where "config_id" = #{configId} + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysDeptMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysDeptMapper.xml new file mode 100644 index 0000000..12a7d50 --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysDeptMapper.xml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + select d."dept_id", d."parent_id", d."ancestors", d."dept_name", d."order_num", d."leader", d."phone", d."email", d."status", d."del_flag", d."create_by", d."create_time" + from ROOT."sys_dept" d + + + + + + + + + + + + + + + + + + + + insert into ROOT."sys_dept"( + "parent_id", + "dept_name", + "ancestors", + "order_num", + "leader", + "phone", + "email", + "status", + "create_by", + "create_time" + )values( + #{parentId}, + #{deptName}, + #{ancestors}, + #{orderNum}, + #{leader}, + #{phone}, + #{email}, + #{status}, + #{createBy}, + sysdate + ) + + + + update ROOT."sys_dept" + + "parent_id" = #{parentId}, + "dept_name" = #{deptName}, + "ancestors" = #{ancestors}, + "order_num" = #{orderNum}, + "leader" = #{leader}, + "phone" = #{phone}, + "email" = #{email}, + "status" = #{status}, + "update_by" = #{updateBy}, + "update_time" = sysdate + + where "dept_id" = #{deptId} + + + + update ROOT."sys_dept" set "ancestors" = + + when #{item.deptId} then #{item.ancestors} + + where "dept_id" in + + #{item.deptId} + + + + + update ROOT."sys_dept" set "del_flag" = '2' where "dept_id" = #{deptId} + + + + update ROOT."sys_dept" + + "status" = #{status}, + "update_by" = #{updateBy}, + "update_time" = sysdate + + where "dept_id" in (${"ancestors"}) + + + + + + + + update ROOT."sys_dept" set "status" = '0' where "dept_id" in + + #{deptId} + + + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysDictDataMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysDictDataMapper.xml new file mode 100644 index 0000000..808a88a --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysDictDataMapper.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + select "dict_code", "dict_sort", "dict_label", "dict_value", "dict_type", "css_class", "list_class", "is_default", "status", "create_by", "create_time", "remark" + from ROOT."sys_dict_data" + + + + + + + + + + + + + + delete from ROOT."sys_dict_data" where "dict_code" = #{dictCode} + + + + delete from ROOT."sys_dict_data" where "dict_code" in + + #{dictCode} + + + + + update ROOT."sys_dict_data" + + "dict_sort" = #{dictSort}, + "dict_label" = #{dictLabel}, + "dict_value" = #{dictValue}, + "dict_type" = #{dictType}, + "css_class" = #{cssClass}, + "list_class" = #{listClass}, + "is_default" = #{isDefault}, + "status" = #{status}, + "remark" = #{remark}, + "update_by" = #{updateBy}, + "update_time" = sysdate + + where "dict_code" = #{dictCode} + + + + update ROOT."sys_dict_data" set "dict_type" = #{newDictType} where "dict_type" = #{oldDictType} + + + + insert into ROOT."sys_dict_data"( + "dict_sort", + "dict_label", + "dict_value", + "dict_type", + "css_class", + "list_class", + "is_default", + "status", + "remark", + "create_by", + "create_time" + )values( + #{dictSort}, + #{dictLabel}, + #{dictValue}, + #{dictType}, + #{cssClass}, + #{listClass}, + #{isDefault}, + #{status}, + #{remark}, + #{createBy}, + sysdate + ) + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysDictTypeMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysDictTypeMapper.xml new file mode 100644 index 0000000..a9ea88c --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysDictTypeMapper.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + select "dict_id", "dict_name", "dict_type", "status", "create_by", "create_time", "remark" + from ROOT."sys_dict_type" + + + + + + + + + + + + + + delete from ROOT."sys_dict_type" where "dict_id" = #{dictId} + + + + delete from ROOT."sys_dict_type" where "dict_id" in + + #{dictId} + + + + + update ROOT."sys_dict_type" + + "dict_name" = #{dictName}, + "dict_type" = #{dictType}, + "status" = #{status}, + "remark" = #{remark}, + "update_by" = #{updateBy}, + "update_time" = sysdate + + where "dict_id" = #{dictId} + + + + insert into ROOT."sys_dict_type"( + "dict_name", + "dict_type", + "status", + "remark", + "create_by", + "create_time" + )values( + #{dictName}, + #{dictType}, + #{status}, + #{remark}, + #{createBy}, + sysdate + ) + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysLogMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysLogMapper.xml new file mode 100644 index 0000000..b318b90 --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysLogMapper.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + "id", "description", "username", "start_time", "spend_time", "method", "ip", "uri" + + + "parameter" + + + + + + delete from ROOT."sys_log" + + + "id" in + + #{item} + + + + + + + insert into ROOT."sys_log" + + + "id", + + + "description", + + + "username", + + + "start_time", + + + "spend_time", + + + "method", + + + "ip", + + + "uri", + + + "parameter", + + + + + #{id}, + + + #{description}, + + + #{username}, + + + #{startTime}, + + + #{spendTime}, + + + #{method}, + + + #{ip}, + + + #{uri}, + + + #{parameter}, + + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysMenuMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysMenuMapper.xml new file mode 100644 index 0000000..75fb18a --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysMenuMapper.xml @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select "menu_id", "menu_name", "parent_id", "order_num", "path", "component", "query", "is_frame", "is_cache", "menu_type", "visible", "status", ifnull("perms",'') as "perms", "icon", "create_time" + from ROOT."sys_menu" + + + + + + + + + + + + + + + + + + + + + + + + + + update ROOT."sys_menu" + + "menu_name" = #{menuName}, + "parent_id" = #{parentId}, + "order_num" = #{orderNum}, + "path" = #{path}, + "component" = #{component}, + "query" = #{query}, + "is_frame" = #{isFrame}, + "is_cache" = #{isCache}, + "menu_type" = #{menuType}, + "visible" = #{visible}, + "status" = #{status}, + "perms" = #{perms}, + "icon" = #{icon}, + "remark" = #{remark}, + "update_by" = #{updateBy}, + "update_time" = sysdate() + + where "menu_id" = #{menuId} + + + + insert into ROOT."sys_menu"( + "menu_id", + "parent_id", + "menu_name", + "order_num", + "path", + "component", + "query", + "is_frame", + "is_cache", + "menu_type", + "visible", + "status", + "perms", + "icon", + "remark", + "create_by", + "create_time" + )values( + #{menuId}, + #{parentId}, + #{menuName}, + #{orderNum}, + #{path}, + #{component}, + #{query}, + #{isFrame}, + #{isCache}, + #{menuType}, + #{visible}, + #{status}, + #{perms}, + #{icon}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + delete from ROOT."sys_menu" where "menu_id" = #{menuId} + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysPostMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysPostMapper.xml new file mode 100644 index 0000000..ef9361e --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysPostMapper.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + select "post_id", "post_code", "post_name", "post_sort", "status", "create_by", "create_time", "remark" + from ROOT."sys_post" + + + + + + + + + + + + + + + + + + update ROOT."sys_post" + + "post_code" = #{postCode}, + "post_name" = #{postName}, + "post_sort" = #{postSort}, + "status" = #{status}, + "remark" = #{remark}, + "update_by" = #{updateBy}, + "update_time" = sysdate() + + where "post_id" = #{postId} + + + + insert into ROOT."sys_post"( + "post_id", + "post_code", + "post_name", + "post_sort", + "status", + "remark", + "create_by", + "create_time" + )values( + #{postId}, + #{postCode}, + #{postName}, + #{postSort}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + delete from ROOT."sys_post" where "post_id" = #{postId} + + + + delete from ROOT."sys_post" where "post_id" in + + #{postId} + + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysRoleDeptMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysRoleDeptMapper.xml new file mode 100644 index 0000000..1e836c0 --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysRoleDeptMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from ROOT."sys_role_dept" where "role_id" = #{roleId} + + + + + + delete from ROOT."sys_role_dept" where "role_id" in + + #{roleId} + + + + + insert into ROOT."sys_role_dept"("role_id", "dept_id") values + + (#{item.roleId},#{item.deptId}) + + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysRoleMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysRoleMapper.xml new file mode 100644 index 0000000..3b5ef4b --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysRoleMapper.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + select distinct r."role_id", r."role_name", r."role_key", r."role_sort", r."data_scope", r."menu_check_strictly", r."dept_check_strictly", + r."status", r."del_flag", r."create_time", r."remark" + from ROOT."sys_role" r + left join ROOT."sys_user_role" ur on ur."role_id" = r."role_id" + left join ROOT."sys_user" u on u."user_id" = ur."user_id" + left join ROOT."sys_dept" d on u."dept_id" = d."dept_id" + + + + + + + + + + + + + + + + + + + + insert into ROOT."sys_role"( + "role_id", + "role_name", + "role_key", + "role_sort", + "data_scope", + "menu_check_strictly", + "dept_check_strictly", + "status", + "remark", + "create_by", + "create_time" + )values( + #{roleId}, + #{roleName}, + #{roleKey}, + #{roleSort}, + #{dataScope}, + #{menuCheckStrictly}, + #{deptCheckStrictly}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update ROOT."sys_role" + + "role_name" = #{roleName}, + "role_key" = #{roleKey}, + "role_sort" = #{roleSort}, + "data_scope" = #{dataScope}, + "menu_check_strictly" = #{menuCheckStrictly}, + "dept_check_strictly" = #{deptCheckStrictly}, + "status" = #{status}, + "remark" = #{remark}, + "update_by" = #{updateBy}, + "update_time" = sysdate() + + where "role_id" = #{roleId} + + + + update ROOT."sys_role" set "del_flag" = '2' where "role_id" = #{roleId} + + + + update ROOT."sys_role" set "del_flag" = '2' where "role_id" in + + #{roleId} + + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysRoleMenuMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysRoleMenuMapper.xml new file mode 100644 index 0000000..bef145e --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysRoleMenuMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + delete from ROOT."sys_role_menu" where "role_id"=#{roleId} + + + + delete from ROOT."sys_role_menu" where "role_id" in + + #{roleId} + + + + + insert into ROOT."sys_role_menu"("role_id", "menu_id") values + + (#{item.roleId},#{item.menuId}) + + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysUserMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysUserMapper.xml new file mode 100644 index 0000000..8e4f86e --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysUserMapper.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select u."user_id", u."dept_id", u."user_name", u."nick_name", u."email", u."avatar", u."phonenumber", u."password", u."sex", u."status", u."del_flag", u."login_ip", u."login_date", u."create_by", u."create_time", u."remark", + d."dept_id", d."parent_id", d."dept_name", d."order_num", d."leader", d."status" as "dept_status", + r."role_id", r."role_name", r."role_key", r."role_sort", r."data_scope", r."status" as "role_status" + from ROOT."sys_user" u + left join ROOT."sys_dept" d on u."dept_id" = d."dept_id" + left join ROOT."sys_user_role" ur on u."user_id" = ur."user_id" + left join ROOT."sys_role" r on r."role_id" = ur."role_id" + + + + + + + + + + + + + + + + + + + + + + insert into ROOT."sys_user"( + "user_id", + "dept_id", + "user_name", + "nick_name", + "email", + "avatar", + "phonenumber", + "sex", + "password", + "status", + "create_by", + "remark", + "create_time" + )values( + #{userId}, + #{deptId}, + #{userName}, + #{nickName}, + #{email}, + #{avatar}, + #{phonenumber}, + #{sex}, + #{password}, + #{status}, + #{createBy}, + #{remark}, + sysdate() + ) + + + + update ROOT."sys_user" + + "dept_id" = #{deptId}, + "user_name" = #{userName}, + "nick_name" = #{nickName}, + "email" = #{email}, + "phonenumber" = #{phonenumber}, + "sex" = #{sex}, + "avatar" = #{avatar}, + "password" = #{password}, + "status" = #{status}, + "login_ip" = #{loginIp}, + "login_date" = #{loginDate}, + "update_by" = #{updateBy}, + "remark" = #{remark}, + "update_time" = sysdate() + + where "user_id" = #{userId} + + + + update ROOT."sys_user" set "status" = #{status} where "user_id" = #{userId} + + + + update ROOT."sys_user" set "avatar" = #{avatar} where "user_name" = #{userName} + + + + update ROOT."sys_user" set "password" = #{password} where "user_name" = #{userName} + + + + update ROOT."sys_user" set "del_flag" = '2' where "user_id" = #{userId} + + + + update ROOT."sys_user" set "del_flag" = '2' where "user_id" in + + #{userId} + + + + + update ROOT."sys_user" set "del_flag" = '0' where "user_id" in + + #{userId} + + + + + delete from ROOT."sys_user" where "user_id" in + + #{userId} + + + + + update ROOT."sys_user" set "login_ip" = #{ip},"login_date" = #{time} where "user_name" = #{userName} + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysUserPostMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysUserPostMapper.xml new file mode 100644 index 0000000..eeaf046 --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysUserPostMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from ROOT."sys_user_post" where "user_id" = #{userId} + + + + + + delete from ROOT."sys_user_post" where "user_id" in + + #{userId} + + + + + insert into ROOT."sys_user_post"("user_id", "post_id") values + + (#{item.userId},#{item.postId}) + + + + diff --git a/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysUserRoleMapper.xml b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysUserRoleMapper.xml new file mode 100644 index 0000000..c28ae41 --- /dev/null +++ b/ailanyin-model-mapper/src/main/resources/com/ailanyin/mapper/SysUserRoleMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + delete from ROOT."sys_user_role" where "user_id" = #{userId} + + + + + + delete from ROOT."sys_user_role" where "user_id" in + + #{userId} + + + + + insert into ROOT."sys_user_role"("user_id", "role_id") values + + (#{item.userId},#{item.roleId}) + + + + + delete from ROOT."sys_user_role" where "user_id" = #{userId} and "role_id" = #{roleId} + + + + delete from ROOT."sys_user_role" where "role_id" = #{roleId} and "user_id" in + + #{userId} + + + diff --git a/ailanyin-security/pom.xml b/ailanyin-security/pom.xml new file mode 100644 index 0000000..441f939 --- /dev/null +++ b/ailanyin-security/pom.xml @@ -0,0 +1,41 @@ + + + + vis389_backend + com.ailanyin + 1.0-SNAPSHOT + + 4.0.0 + + ailanyin-security + + + + + com.ailanyin + ailanyin-common + + + + org.springframework.boot + spring-boot-starter-security + + + + io.jsonwebtoken + jjwt-api + + + + io.jsonwebtoken + jjwt-impl + + + + io.jsonwebtoken + jjwt-jackson + + + diff --git a/ailanyin-security/src/main/java/com/ailanyin/security/config/BaseSecurityConfig.java b/ailanyin-security/src/main/java/com/ailanyin/security/config/BaseSecurityConfig.java new file mode 100644 index 0000000..e4a37b2 --- /dev/null +++ b/ailanyin-security/src/main/java/com/ailanyin/security/config/BaseSecurityConfig.java @@ -0,0 +1,128 @@ +package com.ailanyin.security.config; + +import com.ailanyin.security.filter.JwtAuthenticationTokenFilter; +import com.ailanyin.security.filter.XssFilter; +import com.ailanyin.security.handle.NoPermissionResult; +import com.ailanyin.security.handle.NoTokenResult; +import com.ailanyin.security.service.SecurityUserService; +import com.ailanyin.security.utils.JwtTokenUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/21 0021 下午 14:06 + */ + +public class BaseSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private NoTokenResult noTokenResult; + @Autowired + private NoPermissionResult noPermissionResult; + + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + // 由于使用的是JWT,我们这里不需要csrf + httpSecurity.csrf() + .disable() + //添加自定义未授权和未登录结果返回 + .exceptionHandling() + .authenticationEntryPoint(noTokenResult) + .accessDeniedHandler(noPermissionResult) + .and() + // 基于token,所以不需要session + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .authorizeRequests() + // 允许对于网站静态资源的无授权访问 + .antMatchers(HttpMethod.GET, + "/", + "/*.*", + "/favicon.ico", + "/**/*.html", + "/**/*.css", + "/**/*.js", + "/swagger-resources/**", + "/v2/api-docs/**", + "/druid/**" + ) + .permitAll() + // 对以下允许匿名访问(不带token) + .antMatchers("/login", + "/register", + "/captchaImage", + "/getRouters") + .permitAll() + //跨域请求会先进行一次options请求 + .antMatchers(HttpMethod.OPTIONS) + .permitAll() + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest() + .authenticated(); + // 禁用缓存 + httpSecurity.headers().cacheControl(); + // 添加JWT filter + httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); + + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService()) + .passwordEncoder(passwordEncoder()); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + + @Bean + public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){ + return new JwtAuthenticationTokenFilter(); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Bean + public JwtTokenUtil jwtTokenUtil() { + return new JwtTokenUtil(); + } + + @Bean + public NoTokenResult noTokenResult() { + return new NoTokenResult(); + } + + @Bean + public NoPermissionResult noPermissionResult() { + return new NoPermissionResult(); + } + + @Bean + public SecurityUserService securityUserService() { + return new SecurityUserService(); + } + + @Bean + public XssFilter xssFilter() { + return new XssFilter(); + } +} diff --git a/ailanyin-security/src/main/java/com/ailanyin/security/filter/HtmlFilter.java b/ailanyin-security/src/main/java/com/ailanyin/security/filter/HtmlFilter.java new file mode 100644 index 0000000..c15cda5 --- /dev/null +++ b/ailanyin-security/src/main/java/com/ailanyin/security/filter/HtmlFilter.java @@ -0,0 +1,419 @@ +package com.ailanyin.security.filter; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 强迫症不要试图去优化这个类, + * 百度来的代码, + * 也不要试着用 HuTool 提供的 HtmlUtil, + * 因为那个xss过滤是有问题的, + * 就这样吧, 强迫症。 + * + * @author ruoyi + */ +public final class HtmlFilter { + + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); + private static final Pattern P_END_ARROW = Pattern.compile("^>"); + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_AMP = Pattern.compile("&"); + private static final Pattern P_QUOTE = Pattern.compile("\""); + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); + private static final String SPECIAL_STR = "#//"; + + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(16); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(16); + + private final Map> vAllowed; + private final Map vTagCounts = new HashMap<>(16); + + private final String[] vSelfClosingTags; + private final String[] vNeedClosingTags; + private final String[] vDisallowed; + private final String[] vProtocolAtts; + private final String[] vAllowedProtocols; + private final String[] vRemoveBlanks; + private final String[] vAllowedEntities; + + private final boolean stripComment; + private final boolean encodeQuotes; + private final boolean alwaysMakeTags; + + + public HtmlFilter() { + vAllowed = new HashMap<>(); + + final ArrayList aAtts = new ArrayList<>(); + aAtts.add("href"); + aAtts.add("target"); + vAllowed.put("a", aAtts); + + final ArrayList imgAtts = new ArrayList<>(); + imgAtts.add("src"); + imgAtts.add("width"); + imgAtts.add("height"); + imgAtts.add("alt"); + vAllowed.put("img", imgAtts); + + final ArrayList noAtts = new ArrayList<>(); + vAllowed.put("b", noAtts); + vAllowed.put("strong", noAtts); + vAllowed.put("i", noAtts); + vAllowed.put("em", noAtts); + + vSelfClosingTags = new String[]{"img"}; + vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"}; + vDisallowed = new String[]{}; + vAllowedProtocols = new String[]{"http", "mailto", "https"}; + vProtocolAtts = new String[]{"src", "href"}; + vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"}; + vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"}; + stripComment = true; + encodeQuotes = true; + alwaysMakeTags = false; + } + + /** + * Map-parameter configurable constructor. + * + * @param conf map containing configuration. keys match field names. + */ + @SuppressWarnings("unchecked") + public HtmlFilter(final Map conf) { + + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; + + vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); + vDisallowed = (String[]) conf.get("vDisallowed"); + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; + } + + private void reset() { + vTagCounts.clear(); + } + + public static String chr(final int decimal) { + return String.valueOf((char) decimal); + } + + public static String htmlSpecialChars(final String s) { + String result = s; + result = regexReplace(P_AMP, "&", result); + result = regexReplace(P_QUOTE, """, result); + result = regexReplace(P_LEFT_ARROW, "<", result); + result = regexReplace(P_RIGHT_ARROW, ">", result); + return result; + } + + public String filter(final String input) { + reset(); + String s = input; + + s = escapeComments(s); + + s = balanceHtml(s); + + s = checkTags(s); + + s = processRemoveBlanks(s); + + return s; + } + + private String escapeComments(final String s) { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) { + final String match = m.group(1); + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHtml(String s) { + if (alwaysMakeTags) { + s = regexReplace(P_END_ARROW, "", s); + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } else { + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + final StringBuilder sBuilder = new StringBuilder(buf.toString()); + for (String key : vTagCounts.keySet()) { + for (int ii = 0; ii < vTagCounts.get(key); ii++) { + sBuilder.append(""); + } + } + s = sBuilder.toString(); + + return s; + } + + private String processRemoveBlanks(final String s) { + String result = s; + for (String tag : vRemoveBlanks) { + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) { + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) { + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private static String regexReplace(final Pattern regexPattern, final String replacement, final String s) { + Matcher m = regexPattern.matcher(s); + return m.replaceAll(replacement); + } + + private String processTag(final String s) { + Matcher m = P_END_TAG.matcher(s); + if (m.find()) { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) { + if (false == inArray(name, vSelfClosingTags)) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } + + m = P_START_TAG.matcher(s); + if (m.find()) { + final String name = m.group(1).toLowerCase(); + final String body = m.group(2); + String ending = m.group(3); + + if (allowed(name)) { + final StringBuilder params = new StringBuilder(); + + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); + final List paramNames = new ArrayList<>(); + final List paramValues = new ArrayList<>(); + while (m2.find()) { + paramNames.add(m2.group(1)); + paramValues.add(m2.group(3)); + } + while (m3.find()) { + paramNames.add(m3.group(1)); + paramValues.add(m3.group(3)); + } + + String paramName, paramValue; + for (int ii = 0; ii < paramNames.size(); ii++) { + paramName = paramNames.get(ii).toLowerCase(); + paramValue = paramValues.get(ii); + + if (allowedAttribute(name, paramName)) { + if (inArray(paramName, vProtocolAtts)) { + paramValue = processParamProtocol(paramValue); + } + params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\""); + } + } + + if (inArray(name, vSelfClosingTags)) { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) { + ending = ""; + } + + if (ending == null || ending.length() < 1) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } else { + vTagCounts.put(name, 1); + } + } else { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } else { + return ""; + } + } + + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) { + s = "#" + s.substring(protocol.length() + 1); + if (s.startsWith(SPECIAL_STR)) { + s = "#" + s.substring(3); + } + } + } + + return s; + } + + private String decodeEntities(String s) { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.decode(match).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) { + + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) { + final String one = m.group(1); + final String two = m.group(2); + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } + + private String encodeQuotes(final String s) { + if (encodeQuotes) { + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_QUOTES.matcher(s); + while (m.find()) { + final String one = m.group(1); + final String two = m.group(2); + final String three = m.group(3); + // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) + m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); + } + m.appendTail(buf); + return buf.toString(); + } else { + return s; + } + } + + private String checkEntity(final String preamble, final String term) { + + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; + } + + private boolean isValidEntity(final String entity) { + return inArray(entity, vAllowedEntities); + } + + private static boolean inArray(final String s, final String[] array) { + for (String item : array) { + if (item != null && item.equals(s)) { + return true; + } + } + return false; + } + + private boolean allowed(final String name) { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } + + private boolean allowedAttribute(final String name, final String paramName) { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } +} \ No newline at end of file diff --git a/ailanyin-security/src/main/java/com/ailanyin/security/filter/JwtAuthenticationTokenFilter.java b/ailanyin-security/src/main/java/com/ailanyin/security/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..d444069 --- /dev/null +++ b/ailanyin-security/src/main/java/com/ailanyin/security/filter/JwtAuthenticationTokenFilter.java @@ -0,0 +1,55 @@ +package com.ailanyin.security.filter; + +import com.ailanyin.security.utils.JwtTokenUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/21 0021 下午 14:13 + */ +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + @Autowired + private UserDetailsService userDetailsService; + @Autowired + private JwtTokenUtil jwtTokenUtil; + @Value("${jwt.tokenHeader}") + private String tokenHeader; + @Value("${jwt.tokenHead}") + private String tokenHead; + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain chain) throws ServletException, IOException { + // The part after "Bearer " + String authHeader = request.getHeader(this.tokenHeader); + if (authHeader != null && authHeader.startsWith(this.tokenHead)) { + String authToken = authHeader.substring(this.tokenHead.length()); + String username = jwtTokenUtil.getUserNameFromToken(authToken); + if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); + if (jwtTokenUtil.validateToken(authToken, userDetails)) { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + } + chain.doFilter(request, response); + } +} diff --git a/ailanyin-security/src/main/java/com/ailanyin/security/filter/XssFilter.java b/ailanyin-security/src/main/java/com/ailanyin/security/filter/XssFilter.java new file mode 100644 index 0000000..a1711e0 --- /dev/null +++ b/ailanyin-security/src/main/java/com/ailanyin/security/filter/XssFilter.java @@ -0,0 +1,42 @@ +package com.ailanyin.security.filter; + +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 防止XSS攻击的过滤器 + * + * @author ruoyi + */ +@Component +public class XssFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + if (handleExcludeUrl(req, resp)) { + chain.doFilter(request, response); + return; + } + XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); + chain.doFilter(xssRequest, response); + } + + private boolean handleExcludeUrl(HttpServletRequest request, HttpServletResponse response) { + String method = request.getMethod(); + // GET DELETE 不过滤 + return method == null || method.matches(HttpMethod.GET.toString()) || method.matches(HttpMethod.DELETE.toString()); + } + + @Override + public void destroy() { + + } +} \ No newline at end of file diff --git a/ailanyin-security/src/main/java/com/ailanyin/security/filter/XssHttpServletRequestWrapper.java b/ailanyin-security/src/main/java/com/ailanyin/security/filter/XssHttpServletRequestWrapper.java new file mode 100644 index 0000000..ae820d9 --- /dev/null +++ b/ailanyin-security/src/main/java/com/ailanyin/security/filter/XssHttpServletRequestWrapper.java @@ -0,0 +1,95 @@ +package com.ailanyin.security.filter; + +import com.ailanyin.common.utils.StringUtil; +import io.micrometer.core.instrument.util.IOUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +/** + * XSS过滤处理 + * + * @author ruoyi + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + + private final static HtmlFilter HTMLFILTER = new HtmlFilter(); + + public XssHttpServletRequestWrapper(HttpServletRequest request) { + super(request); + } + + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (values != null) { + int length = values.length; + String[] escapeValues = new String[length]; + for (int i = 0; i < length; i++) { + // 防xss攻击和过滤前后空格 + escapeValues[i] = HTMLFILTER.filter(values[i]).trim(); + } + return escapeValues; + } + return super.getParameterValues(name); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + // 非json类型,直接返回 + if (!isJsonRequest()) { + return super.getInputStream(); + } + + // 为空,直接返回 + String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8); + if (StringUtil.isEmpty(json)) { + return super.getInputStream(); + } + + // xss过滤 + json = HTMLFILTER.filter(json).trim(); + byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8); + final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public int available() throws IOException { + return jsonBytes.length; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + + @Override + public int read() throws IOException { + return bis.read(); + } + }; + } + + /** + * 是否是Json请求 + */ + private boolean isJsonRequest() { + String header = super.getHeader(HttpHeaders.CONTENT_TYPE); + return StringUtil.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); + } +} \ No newline at end of file diff --git a/ailanyin-security/src/main/java/com/ailanyin/security/handle/NoPermissionResult.java b/ailanyin-security/src/main/java/com/ailanyin/security/handle/NoPermissionResult.java new file mode 100644 index 0000000..02144b7 --- /dev/null +++ b/ailanyin-security/src/main/java/com/ailanyin/security/handle/NoPermissionResult.java @@ -0,0 +1,32 @@ +package com.ailanyin.security.handle; + +import cn.hutool.json.JSONUtil; +import com.ailanyin.common.result.AjaxResult; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 当访问接口没有权限时,自定义的返回结果 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/21 0021 下午 14:08 + */ +@Component +public class NoPermissionResult implements AccessDeniedHandler { + @Override + public void handle(HttpServletRequest request, + HttpServletResponse response, + AccessDeniedException e) throws IOException, ServletException { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + response.getWriter().println(JSONUtil.parse(AjaxResult.error(403,e.getMessage()))); + response.getWriter().flush(); + } +} diff --git a/ailanyin-security/src/main/java/com/ailanyin/security/handle/NoTokenResult.java b/ailanyin-security/src/main/java/com/ailanyin/security/handle/NoTokenResult.java new file mode 100644 index 0000000..57a08d9 --- /dev/null +++ b/ailanyin-security/src/main/java/com/ailanyin/security/handle/NoTokenResult.java @@ -0,0 +1,30 @@ +package com.ailanyin.security.handle; + +import cn.hutool.json.JSONUtil; +import com.ailanyin.common.result.AjaxResult; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 当未登录或者token失效访问接口时,自定义的返回结果 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/21 0021 下午 14:09 + */ +@Component +public class NoTokenResult implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest httpServletRequest, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + response.getWriter().println(JSONUtil.parse(AjaxResult.error(401,"未登录或登录过期"))); + response.getWriter().flush(); + } +} diff --git a/ailanyin-security/src/main/java/com/ailanyin/security/service/SecurityUserService.java b/ailanyin-security/src/main/java/com/ailanyin/security/service/SecurityUserService.java new file mode 100644 index 0000000..895e7d7 --- /dev/null +++ b/ailanyin-security/src/main/java/com/ailanyin/security/service/SecurityUserService.java @@ -0,0 +1,61 @@ +package com.ailanyin.security.service; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author ailanyin + * @version 1.0 + * @since 2021/10/26 0026 下午 17:32 + */ +@Service +public class SecurityUserService { + + /** + * 存放登录用户的 UserDetails, 用作缓存 + */ + private final Map userDetailsMap = new ConcurrentHashMap<>(128); + + /** + * 添加登录用户的 UserDetails + * + * @param username key + * @param userDetails value + */ + public void addUserDetailsToMap(String username, UserDetails userDetails) { + userDetailsMap.put(username, userDetails); + } + + /** + * 删除登录用户的 UserDetails + * + * @param username key + */ + public void delUserDetailsFromMap(String username) { + userDetailsMap.remove(username); + SecurityContextHolder.clearContext(); + } + + /** + * 获取登录用户的 UserDetails + * + * @param username key + * @return UserDetails + */ + public UserDetails getUserDetailsFromMap(String username) { + return userDetailsMap.get(username); + } + + /** + * 每天凌晨 1点钟 清空 map + */ + @Scheduled(cron = "0 0 1 * * ?") + public void clearUserDetailsMap() { + userDetailsMap.clear(); + } +} diff --git a/ailanyin-security/src/main/java/com/ailanyin/security/utils/JwtTokenUtil.java b/ailanyin-security/src/main/java/com/ailanyin/security/utils/JwtTokenUtil.java new file mode 100644 index 0000000..cf8bc0d --- /dev/null +++ b/ailanyin-security/src/main/java/com/ailanyin/security/utils/JwtTokenUtil.java @@ -0,0 +1,175 @@ +package com.ailanyin.security.utils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.security.Keys; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.userdetails.UserDetails; + +import javax.crypto.SecretKey; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * Jwt工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2021-08-31 + */ +public class JwtTokenUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class); + private static final String CLAIM_KEY_USERNAME = "sub"; + private static final String CLAIM_KEY_CREATED = "created"; + private static final int REFRESH_TIME = 1800; + @Value("${jwt.secret}") + private String secret; + @Value("${jwt.expiration}") + private Long expiration; + @Value("${jwt.tokenHead}") + private String tokenHead; + + /** + * 根据负责生成JWT的token + */ + private String generateToken(Map claims) { + + return Jwts.builder() + //添加自定义参数 + .addClaims(claims) + //设置过期时间 + .setExpiration(generateExpirationDate()) + .signWith(getSecretKey()) + .compact(); + } + + private SecretKey getSecretKey() { + byte[] encodeKey = Decoders.BASE64.decode(secret); + return Keys.hmacShaKeyFor(encodeKey); + } + + /** + * 从token中获取JWT中的负载 + */ + private Claims getClaimsFromToken(String token) { + Claims claims; + try { + claims = Jwts.parserBuilder().setSigningKey(secret).build().parseClaimsJws(token).getBody(); + } catch (Exception e) { + claims = null; + } + return claims; + } + + /** + * 生成token的过期时间 + */ + private Date generateExpirationDate() { + return new Date(System.currentTimeMillis() + expiration * 1000); + } + + /** + * 从token中获取登录用户名 + */ + public String getUserNameFromToken(String token) { + String username; + try { + Claims claims = getClaimsFromToken(token); + username = claims.getSubject(); + } catch (Exception e) { + username = null; + } + return username; + } + + /** + * 验证token是否还有效 + * + * @param token 客户端传入的token + * @param userDetails 从数据库中查询出来的用户信息 + */ + public boolean validateToken(String token, UserDetails userDetails) { + String username = getUserNameFromToken(token); + return username.equals(userDetails.getUsername()) && !isTokenExpired(token); + } + + /** + * 判断token是否已经失效 + */ + private boolean isTokenExpired(String token) { + Date expiredDate = getExpiredDateFromToken(token); + return expiredDate.before(new Date()); + } + + /** + * 从token中获取过期时间 + */ + private Date getExpiredDateFromToken(String token) { + Claims claims = getClaimsFromToken(token); + return claims.getExpiration(); + } + + /** + * 根据用户信息生成token + */ + public String generateToken(UserDetails userDetails) { + Map claims = new HashMap<>(16); + claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername()); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + + /** + * 当原来的token没过期时是可以刷新的 + * + * @param oldToken 带tokenHead的token + */ + public String refreshHeadToken(String oldToken) { + if (StrUtil.isEmpty(oldToken)) { + return null; + } + String token = oldToken.substring(tokenHead.length()); + if (StrUtil.isEmpty(token)) { + return null; + } + //token校验不通过 + Claims claims = getClaimsFromToken(token); + if (claims == null) { + return null; + } + //如果token已经过期,不支持刷新 + if (isTokenExpired(token)) { + return null; + } + //如果token在30分钟之内刚刷新过,返回原token + if (tokenRefreshJustBefore(token, REFRESH_TIME)) { + return token; + } else { + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + } + + /** + * 判断token在指定时间内是否刚刚刷新过 + * + * @param token 原token + * @param time 指定时间(秒) + */ + private boolean tokenRefreshJustBefore(String token, int time) { + Claims claims = getClaimsFromToken(token); + Date created = claims.get(CLAIM_KEY_CREATED, Date.class); + Date refreshDate = new Date(); + //刷新时间在创建时间的指定时间内 + if (refreshDate.after(created) && refreshDate.before(DateUtil.offsetSecond(created, time))) { + return true; + } + return false; + } +} diff --git a/doc/FIND_IN_SET.sql b/doc/FIND_IN_SET.sql new file mode 100644 index 0000000..e37910b --- /dev/null +++ b/doc/FIND_IN_SET.sql @@ -0,0 +1,49 @@ +create or replace FUNCTION ROOT.FIND_IN_SET(piv_str1 varchar2, piv_str2 varchar2, p_sep varchar2 := ',') + RETURN NUMBER IS + l_idx number:=0; -- ڼpiv_str2зָλ + str varchar2(500); -- ݷָȡַ + piv_str varchar2(500) := piv_str2; -- piv_str2ֵpiv_str + res number:=0; -- ؽ + res_place number:=0;-- ԭַĿַеλ + BEGIN + -- ֶnull 򷵻0 + IF piv_str2 IS NULL THEN + RETURN res; + END IF; + -- piv_strûзֱָжpiv_str1piv_strǷȣ res_place=1 + IF instr(piv_str, p_sep, 1) = 0 THEN + IF piv_str = piv_str1 THEN + res_place:=1; + res:= res_place; + END IF; + ELSE + -- ѭָȡpiv_str + LOOP + l_idx := instr(piv_str,p_sep); + -- + res_place := res_place + 1; + -- piv_strлзָʱ + IF l_idx > 0 THEN + -- ȡһָǰֶstr + str:= substr(piv_str,1,l_idx-1); + -- ж str piv_str1 Ƿȣѭж + IF str = piv_str1 THEN + res:= res_place; + EXIT; + END IF; + piv_str := substr(piv_str,l_idx+length(p_sep)); + ELSE + -- ȡpiv_str вڷָʱжpiv_strpiv_str1Ƿȣ res=res_path + IF piv_str = piv_str1 THEN + res:= res_place; + END IF; + -- Ƿȣѭ + EXIT; + END IF; + END LOOP; + -- ѭ + END IF; + -- res + RETURN res; + END FIND_IN_SET; + diff --git a/doc/ailanyin-boot-mysql5.7.sql b/doc/ailanyin-boot-mysql5.7.sql new file mode 100644 index 0000000..0518435 --- /dev/null +++ b/doc/ailanyin-boot-mysql5.7.sql @@ -0,0 +1,621 @@ +/* + Navicat Premium Data Transfer + + Source Server : 本地mysql + Source Server Type : MySQL + Source Server Version : 80026 + Source Host : localhost:3306 + Source Schema : ailanyin-boot + + Target Server Type : MySQL + Target Server Version : 80026 + File Encoding : 65001 + + Date: 15/11/2021 11:15:08 +*/ + +SET NAMES utf8; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for exception_log +-- ---------------------------- +DROP TABLE IF EXISTS `exception_log`; +CREATE TABLE `exception_log` ( + `exception_id` bigint NOT NULL AUTO_INCREMENT, + `exception_reason` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '异常原因', + `detail_info` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '堆栈信息', + `create_time` datetime NULL DEFAULT NULL, + PRIMARY KEY (`exception_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of exception_log +-- ---------------------------- +INSERT INTO `exception_log` VALUES (1, 'Invalid bound statement (not found): com.ailanyin.mapper.SysUserMapper.updateUser', 'org.apache.ibatis.binding.MapperMethod$SqlCommand.(MapperMethod.java:235)
com.baomidou.mybatisplus.core.override.MybatisMapperMethod.(MybatisMapperMethod.java:50)
com.baomidou.mybatisplus.core.override.MybatisMapperProxy.lambda$cachedInvoker$0(MybatisMapperProxy.java:111)
java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
com.baomidou.mybatisplus.core.toolkit.CollectionUtils.computeIfAbsent(CollectionUtils.java:115)
com.baomidou.mybatisplus.core.override.MybatisMapperProxy.cachedInvoker(MybatisMapperProxy.java:98)
com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
jdk.proxy2/jdk.proxy2.$Proxy113.updateUser(Unknown Source)
com.ailanyin.admin.service.impl.SysUserServiceImpl.resetPwd(SysUserServiceImpl.java:237)
com.ailanyin.admin.service.impl.SysUserServiceImpl$$FastClassBySpringCGLIB$$d327fb1f.invoke()
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
com.ailanyin.admin.service.impl.SysUserServiceImpl$$EnhancerBySpringCGLIB$$c95cc101.resetPwd()
com.ailanyin.admin.controller.SysUserController.resetPwd(SysUserController.java:71)
com.ailanyin.admin.controller.SysUserController$$FastClassBySpringCGLIB$$cac1195.invoke()
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:61)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
com.ailanyin.admin.controller.SysUserController$$EnhancerBySpringCGLIB$$48441a6c.resetPwd()
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:568)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:920)
javax.servlet.http.HttpServlet.service(HttpServlet.java:684)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
com.ailanyin.security.filter.XssFilter.doFilter(XssFilter.java:29)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
com.ailanyin.security.filter.JwtAuthenticationTokenFilter.doFilterInternal(JwtAuthenticationTokenFilter.java:53)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1726)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:833)
', '2021-11-02 17:35:14'); +INSERT INTO `exception_log` VALUES (2, 'Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 300 millisecond(s)', 'org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:70)
org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:41)
org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)
org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:271)
org.springframework.data.redis.connection.lettuce.LettuceConnection.await(LettuceConnection.java:1062)
org.springframework.data.redis.connection.lettuce.LettuceConnection.lambda$doInvoke$4(LettuceConnection.java:919)
org.springframework.data.redis.connection.lettuce.LettuceInvoker$Synchronizer.invoke(LettuceInvoker.java:665)
org.springframework.data.redis.connection.lettuce.LettuceInvoker.just(LettuceInvoker.java:94)
org.springframework.data.redis.connection.lettuce.LettuceStringCommands.get(LettuceStringCommands.java:55)
org.springframework.data.redis.connection.DefaultedRedisConnection.get(DefaultedRedisConnection.java:267)
org.springframework.data.redis.core.DefaultValueOperations$1.inRedis(DefaultValueOperations.java:57)
org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:60)
org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:222)
org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:189)
org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96)
org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:53)
com.ailanyin.common.service.impl.RedisServiceImpl.get(RedisServiceImpl.java:42)
com.ailanyin.admin.service.impl.SysDictTypeServiceImpl.selectDictDataByType(SysDictTypeServiceImpl.java:54)
com.ailanyin.admin.controller.SysDictDataController.dictType(SysDictDataController.java:64)
com.ailanyin.admin.controller.SysDictDataController$$FastClassBySpringCGLIB$$3643950a.invoke()
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
com.ailanyin.admin.controller.SysDictDataController$$EnhancerBySpringCGLIB$$d6ad9ea1.dictType()
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:568)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
com.ailanyin.security.filter.XssFilter.doFilter(XssFilter.java:25)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
com.ailanyin.security.filter.JwtAuthenticationTokenFilter.doFilterInternal(JwtAuthenticationTokenFilter.java:53)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1726)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:833)
', '2021-11-03 09:24:11'); + +-- ---------------------------- +-- Table structure for sys_blacklist_user +-- ---------------------------- +DROP TABLE IF EXISTS `sys_blacklist_user`; +CREATE TABLE `sys_blacklist_user` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'ip地址', + `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '具体地址', + `reason` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '拉黑原因(具体见字典)', + `create_time` datetime NULL DEFAULT NULL COMMENT '拉黑时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_blacklist_user +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_config +-- ---------------------------- +DROP TABLE IF EXISTS `sys_config`; +CREATE TABLE `sys_config` ( + `config_id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键', + `config_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '参数名称', + `config_key` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '参数键名', + `config_value` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '参数键值', + `config_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'N' COMMENT '系统内置(Y是 N否)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`config_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 105 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '参数配置表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_config +-- ---------------------------- +INSERT INTO `sys_config` VALUES (1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', '2021-10-12 11:26:31', '', '2021-10-22 14:06:52', '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow'); +INSERT INTO `sys_config` VALUES (2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', '2021-10-12 11:26:31', '', NULL, '初始化密码 123456'); +INSERT INTO `sys_config` VALUES (3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', '2021-10-12 11:26:31', '', NULL, '深色主题theme-dark,浅色主题theme-light'); +INSERT INTO `sys_config` VALUES (4, '验证码开关', 'sys.account.captchaOnOff', 'false', 'Y', 'admin', '2021-10-12 11:26:31', '', '2021-11-08 17:24:23', '是否开启验证码功能(true开启,false关闭)'); +INSERT INTO `sys_config` VALUES (5, '用户注册开关', 'sys.account.registerUser', 'true', 'Y', 'admin', '2021-10-12 11:26:31', '', '2021-11-01 11:32:15', '是否开启注册用户功能(true开启,false关闭)'); +INSERT INTO `sys_config` VALUES (6, '登录黑名单开关', 'sys.account.blacklistOnOff', 'true', 'Y', 'admin', '2021-11-01 11:35:38', '', '2021-11-03 09:53:27', 'true:开,false:关'); +INSERT INTO `sys_config` VALUES (7, '系统日志开关', 'sys.log.switch', 'off', 'Y', 'admin', '2021-11-03 10:15:14', '', '2021-11-15 11:06:48', 'on(开) off(关)'); +INSERT INTO `sys_config` VALUES (8, '系统日志级别', 'sys.log.level', 'PUT-DELETE', 'Y', 'admin', '2021-11-03 10:24:23', '', '2021-11-15 11:06:43', '全部:GET-POST-PUT-DELETE\n仅删:DELETE\n删改:PUT-DELETE\n增删改:POST-PUT-DELETE\n'); + +-- ---------------------------- +-- Table structure for sys_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dept`; +CREATE TABLE `sys_dept` ( + `dept_id` bigint NOT NULL AUTO_INCREMENT COMMENT '部门id', + `parent_id` bigint NULL DEFAULT 0 COMMENT '父部门id', + `ancestors` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '祖级列表', + `dept_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '部门名称', + `order_num` int NULL DEFAULT 0 COMMENT '显示顺序', + `leader` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '负责人', + `phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '部门状态(0正常 1停用)', + `del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`dept_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 201 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '部门表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_dept +-- ---------------------------- +INSERT INTO `sys_dept` VALUES (100, 0, '0', '集团总部', 0, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', 'admin', '2021-10-21 16:17:07'); +INSERT INTO `sys_dept` VALUES (101, 100, '0,100', '深圳总公司', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', '', NULL); +INSERT INTO `sys_dept` VALUES (102, 100, '0,100', '长沙分公司', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', '', NULL); +INSERT INTO `sys_dept` VALUES (103, 101, '0,100,101', '研发部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', '', NULL); +INSERT INTO `sys_dept` VALUES (104, 101, '0,100,101', '市场部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', '', NULL); +INSERT INTO `sys_dept` VALUES (105, 101, '0,100,101', '测试部门', 3, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', '', NULL); +INSERT INTO `sys_dept` VALUES (106, 101, '0,100,101', '财务部门', 4, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', '', '2021-10-15 17:21:07'); +INSERT INTO `sys_dept` VALUES (107, 101, '0,100,101', '运维部门', 5, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', '', NULL); +INSERT INTO `sys_dept` VALUES (108, 102, '0,100,102', '市场部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', '', NULL); +INSERT INTO `sys_dept` VALUES (109, 102, '0,100,102', '技术部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-10-12 11:26:30', 'admin', '2021-10-29 17:25:51'); +INSERT INTO `sys_dept` VALUES (200, 100, '0,100', '橘子科技', 3, '橘子', '15166778899', 'juzi@admin.com', '0', '2', 'admin', '2021-10-21 16:13:59', 'admin', '2021-10-21 16:16:16'); + +-- ---------------------------- +-- Table structure for sys_dict_data +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict_data`; +CREATE TABLE `sys_dict_data` ( + `dict_code` bigint NOT NULL AUTO_INCREMENT COMMENT '字典编码', + `dict_sort` int NULL DEFAULT 0 COMMENT '字典排序', + `dict_label` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典标签', + `dict_value` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典键值', + `dict_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典类型', + `css_class` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '样式属性(其他样式扩展)', + `list_class` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表格回显样式', + `is_default` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'N' COMMENT '是否默认(Y是 N否)', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`dict_code`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 107 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字典数据表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_dict_data +-- ---------------------------- +INSERT INTO `sys_dict_data` VALUES (1, 1, '男', '0', 'sys_user_sex', '', '', 'Y', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '性别男'); +INSERT INTO `sys_dict_data` VALUES (2, 2, '女', '1', 'sys_user_sex', '', '', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '性别女'); +INSERT INTO `sys_dict_data` VALUES (3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '性别未知'); +INSERT INTO `sys_dict_data` VALUES (4, 1, '显示', '0', 'sys_show_hide', '', 'primary', 'Y', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '显示菜单'); +INSERT INTO `sys_dict_data` VALUES (5, 2, '隐藏', '1', 'sys_show_hide', '', 'danger', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '隐藏菜单'); +INSERT INTO `sys_dict_data` VALUES (6, 1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (7, 2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '停用状态'); +INSERT INTO `sys_dict_data` VALUES (8, 1, '正常', '0', 'sys_job_status', '', 'primary', 'Y', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (9, 2, '暂停', '1', 'sys_job_status', '', 'danger', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '停用状态'); +INSERT INTO `sys_dict_data` VALUES (10, 1, '默认', 'DEFAULT', 'sys_job_group', '', '', 'Y', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '默认分组'); +INSERT INTO `sys_dict_data` VALUES (11, 2, '系统', 'SYSTEM', 'sys_job_group', '', '', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '系统分组'); +INSERT INTO `sys_dict_data` VALUES (12, 1, '是', 'Y', 'sys_yes_no', '', 'primary', 'Y', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '系统默认是'); +INSERT INTO `sys_dict_data` VALUES (13, 2, '否', 'N', 'sys_yes_no', '', 'danger', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '系统默认否'); +INSERT INTO `sys_dict_data` VALUES (14, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '通知'); +INSERT INTO `sys_dict_data` VALUES (15, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '公告'); +INSERT INTO `sys_dict_data` VALUES (16, 1, '正常', '0', 'sys_notice_status', '', 'primary', 'Y', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (17, 2, '关闭', '1', 'sys_notice_status', '', 'danger', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '关闭状态'); +INSERT INTO `sys_dict_data` VALUES (18, 1, '新增', '1', 'sys_oper_type', '', 'info', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '新增操作'); +INSERT INTO `sys_dict_data` VALUES (19, 2, '修改', '2', 'sys_oper_type', '', 'info', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '修改操作'); +INSERT INTO `sys_dict_data` VALUES (20, 3, '删除', '3', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '删除操作'); +INSERT INTO `sys_dict_data` VALUES (21, 4, '授权', '4', 'sys_oper_type', '', 'primary', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '授权操作'); +INSERT INTO `sys_dict_data` VALUES (22, 5, '导出', '5', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '导出操作'); +INSERT INTO `sys_dict_data` VALUES (23, 6, '导入', '6', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '导入操作'); +INSERT INTO `sys_dict_data` VALUES (24, 7, '强退', '7', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '强退操作'); +INSERT INTO `sys_dict_data` VALUES (25, 8, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '生成操作'); +INSERT INTO `sys_dict_data` VALUES (26, 9, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '清空操作'); +INSERT INTO `sys_dict_data` VALUES (27, 1, '成功', '0', 'sys_common_status', '', 'primary', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (28, 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '停用状态'); +INSERT INTO `sys_dict_data` VALUES (100, 0, '系统开', 'sys_on', 'system_off', NULL, 'default', 'N', '0', 'admin', '2021-10-22 13:40:54', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (101, 1, '系统关', 'sys_off', 'system_off', NULL, 'default', 'N', '0', 'admin', '2021-10-22 13:41:12', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (102, 0, 'GET请求', 'GET', 'sys_http_mothod', NULL, 'default', 'N', '0', 'admin', '2021-10-29 10:56:28', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (103, 1, 'POST请求', 'POST', 'sys_http_mothod', NULL, 'default', 'N', '0', 'admin', '2021-10-29 10:56:42', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (104, 2, 'PUT请求', 'PUT', 'sys_http_mothod', NULL, 'default', 'N', '0', 'admin', '2021-10-29 10:56:59', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (105, 3, 'DELETE请求', 'DELETE', 'sys_http_mothod', NULL, 'default', 'N', '0', 'admin', '2021-10-29 10:57:16', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (106, 0, '密码错误次数过多', '1', 'sys_blacklist_reason', NULL, 'default', 'N', '0', 'admin', '2021-11-02 11:22:45', 'admin', '2021-11-02 11:28:38', NULL); +INSERT INTO `sys_dict_data` VALUES (107, 1, '上传木马文件', '2', 'sys_blacklist_reason', NULL, 'default', 'N', '0', 'admin', '2021-11-02 11:24:09', 'admin', '2021-11-02 13:00:33', NULL); + +-- ---------------------------- +-- Table structure for sys_dict_type +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict_type`; +CREATE TABLE `sys_dict_type` ( + `dict_id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典主键', + `dict_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典名称', + `dict_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典类型', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`dict_id`) USING BTREE, + UNIQUE INDEX `dict_type`(`dict_type`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 102 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字典类型表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_dict_type +-- ---------------------------- +INSERT INTO `sys_dict_type` VALUES (1, '用户性别', 'sys_user_sex', '0', 'admin', '2021-10-12 11:26:31', '', '2021-10-22 13:38:51', '用户性别列表'); +INSERT INTO `sys_dict_type` VALUES (2, '菜单状态', 'sys_show_hide', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '菜单状态列表'); +INSERT INTO `sys_dict_type` VALUES (3, '系统开关', 'sys_normal_disable', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '系统开关列表'); +INSERT INTO `sys_dict_type` VALUES (4, '任务状态', 'sys_job_status', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '任务状态列表'); +INSERT INTO `sys_dict_type` VALUES (5, '任务分组', 'sys_job_group', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '任务分组列表'); +INSERT INTO `sys_dict_type` VALUES (6, '系统是否', 'sys_yes_no', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '系统是否列表'); +INSERT INTO `sys_dict_type` VALUES (7, '通知类型', 'sys_notice_type', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '通知类型列表'); +INSERT INTO `sys_dict_type` VALUES (8, '通知状态', 'sys_notice_status', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '通知状态列表'); +INSERT INTO `sys_dict_type` VALUES (9, '操作类型', 'sys_oper_type', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '操作类型列表'); +INSERT INTO `sys_dict_type` VALUES (10, '系统状态', 'sys_common_status', '0', 'admin', '2021-10-12 11:26:31', '', NULL, '登录状态列表'); +INSERT INTO `sys_dict_type` VALUES (100, '系统开关', 'system_off', '1', 'admin', '2021-10-22 13:39:55', '', '2021-10-22 13:40:14', '系统开关'); +INSERT INTO `sys_dict_type` VALUES (101, '网络请求方式', 'sys_http_mothod', '0', 'admin', '2021-10-29 10:56:07', '', NULL, 'GET,POST,PUT,DELETE'); +INSERT INTO `sys_dict_type` VALUES (102, '拉黑原因', 'sys_blacklist_reason', '0', 'admin', '2021-11-02 11:12:15', '', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_log`; +CREATE TABLE `sys_log` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `description` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作描述', + `username` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `start_time` datetime NULL DEFAULT NULL, + `spend_time` bigint NULL DEFAULT NULL, + `method` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ip` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `parameter` json NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_log +-- ---------------------------- +INSERT INTO `sys_log` VALUES (1, '分页获取日志列表', 'admin', '2021-11-15 11:05:29', 4, 'GET', '127.0.0.1', '/system/log/list', '[{\"pageSize\": 10}, {\"pageNum\": 1}]'); +INSERT INTO `sys_log` VALUES (1457981682114654233, '获取用户信息', 'admin', '2021-11-15 11:05:57', 18, 'GET', '127.0.0.1', '/getInfo', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654234, '获取路由信息', 'admin', '2021-11-15 11:05:57', 4, 'GET', '127.0.0.1', '/getRouters', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654235, '根据字典类型查询字典数据信息', 'admin', '2021-11-15 11:05:57', 8, 'GET', '127.0.0.1', '/system/dict/data/type/sys_http_mothod', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654236, '根据参数键名查询参数值', 'admin', '2021-11-15 11:05:57', 3, 'GET', '127.0.0.1', '/system/config/configKey/sys.log.switch', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654237, '分页获取日志列表', 'admin', '2021-11-15 11:05:57', 7, 'GET', '127.0.0.1', '/system/log/list', '[{\"pageSize\": 10}, {\"pageNum\": 1}]'); +INSERT INTO `sys_log` VALUES (1457981682114654238, '根据参数键名查询参数值', 'admin', '2021-11-15 11:05:57', 2, 'GET', '127.0.0.1', '/system/config/configKey/sys.log.level', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654239, '根据字典类型查询字典数据信息', 'admin', '2021-11-15 11:06:31', 3, 'GET', '127.0.0.1', '/system/dict/data/type/sys_blacklist_reason', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654240, '获取黑名单列表', 'admin', '2021-11-15 11:06:31', 6, 'GET', '127.0.0.1', '/system/blacklist/list', '[{\"pageSize\": 10}, {\"pageNum\": 1}]'); +INSERT INTO `sys_log` VALUES (1457981682114654241, '根据字典类型查询字典数据信息', 'admin', '2021-11-15 11:06:34', 3, 'GET', '127.0.0.1', '/system/dict/data/type/sys_http_mothod', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654242, '根据参数键名查询参数值', 'admin', '2021-11-15 11:06:34', 2, 'GET', '127.0.0.1', '/system/config/configKey/sys.log.switch', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654243, '分页获取日志列表', 'admin', '2021-11-15 11:06:34', 7, 'GET', '127.0.0.1', '/system/log/list', '[{\"pageSize\": 10}, {\"pageNum\": 1}]'); +INSERT INTO `sys_log` VALUES (1457981682114654244, '根据参数键名查询参数值', 'admin', '2021-11-15 11:06:34', 2, 'GET', '127.0.0.1', '/system/config/configKey/sys.log.level', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654245, '根据字典类型查询字典数据信息', 'admin', '2021-11-15 11:06:39', 2, 'GET', '127.0.0.1', '/system/dict/data/type/sys_yes_no', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654246, '获取参数配置列表', 'admin', '2021-11-15 11:06:39', 15, 'GET', '127.0.0.1', '/system/config/list', '[{\"pageSize\": 10}, {\"pageNum\": 1}]'); +INSERT INTO `sys_log` VALUES (1457981682114654247, '根据参数编号获取详细信息', 'admin', '2021-11-15 11:06:40', 2, 'GET', '127.0.0.1', '/system/config/8', 'null'); +INSERT INTO `sys_log` VALUES (1457981682114654248, '修改参数配置', 'admin', '2021-11-15 11:06:43', 12, 'PUT', '127.0.0.1', '/system/config', '{\"params\": {}, \"remark\": \"全部:GET-POST-PUT-DELETE\\n仅删:DELETE\\n删改:PUT-DELETE\\n增删改:POST-PUT-DELETE\\n\", \"configId\": 8, \"createBy\": \"admin\", \"updateBy\": \"\", \"configKey\": \"sys.log.level\", \"configName\": \"系统日志级别\", \"configType\": \"Y\", \"createTime\": 1635906263000, \"updateTime\": 1636945440000, \"configValue\": \"PUT-DELETE\"}'); +INSERT INTO `sys_log` VALUES (1457981682114654249, '修改参数配置', 'admin', '2021-11-15 11:06:48', 18, 'PUT', '127.0.0.1', '/system/config', '{\"params\": {}, \"remark\": \"on(开) off(关)\", \"configId\": 7, \"createBy\": \"admin\", \"updateBy\": \"\", \"configKey\": \"sys.log.switch\", \"configName\": \"系统日志开关\", \"configType\": \"Y\", \"createTime\": 1635905714000, \"updateTime\": 1636945325000, \"configValue\": \"off\"}'); + +-- ---------------------------- +-- Table structure for sys_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_menu`; +CREATE TABLE `sys_menu` ( + `menu_id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单ID', + `menu_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单名称', + `parent_id` bigint NULL DEFAULT 0 COMMENT '父菜单ID', + `order_num` int NULL DEFAULT 0 COMMENT '显示顺序', + `path` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '路由地址', + `component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件路径', + `query` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '路由参数', + `is_frame` int NULL DEFAULT 1 COMMENT '是否为外链(0是 1否)', + `is_cache` int NULL DEFAULT 0 COMMENT '是否缓存(0缓存 1不缓存)', + `menu_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '菜单类型(M目录 C菜单 F按钮)', + `visible` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '菜单状态(0显示 1隐藏)', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '菜单状态(0正常 1停用)', + `perms` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限标识', + `icon` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '#' COMMENT '菜单图标', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '备注', + PRIMARY KEY (`menu_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 2008 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '菜单权限表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_menu +-- ---------------------------- +INSERT INTO `sys_menu` VALUES (1, '系统管理', 0, 1, 'system', NULL, '', 1, 0, 'M', '0', '0', '', 'system', 'admin', '2021-10-12 11:26:30', '', NULL, '系统管理目录'); +INSERT INTO `sys_menu` VALUES (2, '系统监控', 0, 2, 'monitor', NULL, '', 1, 0, 'M', '0', '0', '', 'monitor', 'admin', '2021-10-12 11:26:30', '', NULL, '系统监控目录'); +INSERT INTO `sys_menu` VALUES (100, '用户管理', 1, 1, 'user', 'system/user/index', '', 1, 0, 'C', '0', '0', 'system:user:list', 'user', 'admin', '2021-10-12 11:26:30', 'admin', '2021-10-12 13:31:12', '用户管理菜单'); +INSERT INTO `sys_menu` VALUES (101, '角色管理', 1, 2, 'role', 'system/role/index', '', 1, 0, 'C', '0', '0', 'system:role:list', 'peoples', 'admin', '2021-10-12 11:26:30', '', NULL, '角色管理菜单'); +INSERT INTO `sys_menu` VALUES (102, '菜单管理', 1, 3, 'menu', 'system/menu/index', '', 1, 0, 'C', '0', '0', 'system:menu:list', 'tree-table', 'admin', '2021-10-12 11:26:30', '', NULL, '菜单管理菜单'); +INSERT INTO `sys_menu` VALUES (103, '部门管理', 1, 4, 'dept', 'system/dept/index', '', 1, 0, 'C', '0', '0', 'system:dept:list', 'tree', 'admin', '2021-10-12 11:26:30', '', NULL, '部门管理菜单'); +INSERT INTO `sys_menu` VALUES (104, '岗位管理', 1, 5, 'post', 'system/post/index', '', 1, 0, 'C', '0', '0', 'system:post:list', 'post', 'admin', '2021-10-12 11:26:30', '', NULL, '岗位管理菜单'); +INSERT INTO `sys_menu` VALUES (105, '字典管理', 1, 6, 'dict', 'system/dict/index', '', 1, 0, 'C', '0', '0', 'system:dict:list', 'dict', 'admin', '2021-10-12 11:26:30', '', NULL, '字典管理菜单'); +INSERT INTO `sys_menu` VALUES (106, '参数设置', 1, 7, 'config', 'system/config/index', '', 1, 0, 'C', '0', '0', 'system:config:list', 'edit', 'admin', '2021-10-12 11:26:30', '', '2021-10-15 17:20:32', '参数设置菜单'); +INSERT INTO `sys_menu` VALUES (112, '服务监控', 2, 2, 'server', 'monitor/server/index', '', 1, 1, 'C', '0', '0', 'monitor:server:list', 'server', 'admin', '2021-10-12 11:26:30', '', '2021-11-03 09:16:24', '服务监控菜单'); +INSERT INTO `sys_menu` VALUES (113, '缓存监控', 2, 3, 'cache', 'monitor/cache/index', '', 1, 1, 'C', '0', '0', 'monitor:cache:list', 'redis', 'admin', '2021-10-12 11:26:30', '', '2021-11-03 09:16:20', '缓存监控菜单'); +INSERT INTO `sys_menu` VALUES (500, '操作日志', 1, 9, 'operlog', 'monitor/operlog/index', '', 1, 1, 'C', '0', '0', 'system:log:list', 'form', 'admin', '2021-10-12 11:26:30', '', '2021-10-29 17:26:50', '操作日志菜单'); +INSERT INTO `sys_menu` VALUES (1001, '用户查询', 100, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:user:query', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1002, '用户新增', 100, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:user:add', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1003, '用户修改', 100, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:user:edit', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1004, '用户删除', 100, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:user:remove', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1005, '用户导出', 100, 5, '', '', '', 1, 0, 'F', '0', '0', 'system:user:export', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1006, '用户导入', 100, 6, '', '', '', 1, 0, 'F', '0', '0', 'system:user:import', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1007, '重置密码', 100, 7, '', '', '', 1, 0, 'F', '0', '0', 'system:user:resetPwd', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1008, '角色查询', 101, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:role:query', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1009, '角色新增', 101, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:role:add', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1010, '角色修改', 101, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:role:edit', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1011, '角色删除', 101, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:role:remove', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1012, '权限重置', 101, 5, '', '', '', 1, 0, 'F', '0', '0', 'system:role:refresh', '#', 'admin', '2021-10-12 11:26:30', '', '2021-10-26 14:53:55', ''); +INSERT INTO `sys_menu` VALUES (1013, '菜单查询', 102, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:menu:query', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1014, '菜单新增', 102, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:menu:add', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1015, '菜单修改', 102, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:menu:edit', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1016, '菜单删除', 102, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:menu:remove', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1017, '部门查询', 103, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:dept:query', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1018, '部门新增', 103, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:dept:add', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1019, '部门修改', 103, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:dept:edit', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1020, '部门删除', 103, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:dept:remove', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1021, '岗位查询', 104, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:post:query', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1022, '岗位新增', 104, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:post:add', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1023, '岗位修改', 104, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:post:edit', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1024, '岗位删除', 104, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:post:remove', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1025, '岗位导出', 104, 5, '', '', '', 1, 0, 'F', '0', '0', 'system:post:export', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1026, '字典查询', 105, 1, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:query', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1027, '字典新增', 105, 2, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:add', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1028, '字典修改', 105, 3, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:edit', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1029, '字典删除', 105, 4, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:remove', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1030, '字典导出', 105, 5, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:export', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1031, '参数查询', 106, 1, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:query', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1032, '参数新增', 106, 2, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:add', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1033, '参数修改', 106, 3, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:edit', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1034, '参数删除', 106, 4, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:remove', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1035, '参数导出', 106, 5, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:export', '#', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1040, '操作查询', 500, 1, '#', '', '', 1, 0, 'F', '0', '0', 'system:log:query', '#', 'admin', '2021-10-12 11:26:30', '', '2021-10-29 13:27:44', ''); +INSERT INTO `sys_menu` VALUES (1041, '操作删除', 500, 2, '#', '', '', 1, 0, 'F', '0', '0', 'system:log:remove', '#', 'admin', '2021-10-12 11:26:30', '', '2021-10-29 13:27:49', ''); +INSERT INTO `sys_menu` VALUES (1042, '日志导出', 500, 3, '#', '', '', 1, 0, 'F', '0', '0', 'system:log:export', '#', 'admin', '2021-10-12 11:26:30', '', '2021-11-02 10:55:10', ''); +INSERT INTO `sys_menu` VALUES (2002, '黑名单管理', 1, 10, 'blacklist', 'system/blacklist/index', NULL, 1, 1, 'C', '0', '0', '', 'user', '', '2021-11-01 16:08:18', '', '2021-11-01 17:30:08', ''); +INSERT INTO `sys_menu` VALUES (2003, '黑名单查询', 2002, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'system:blacklist:query', '#', '', '2021-11-02 10:52:47', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2004, '黑名单删除', 2002, 2, '', NULL, NULL, 1, 0, 'F', '0', '0', 'system:blacklist:remove', '#', '', '2021-11-02 10:53:51', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2005, '黑名单导出', 2002, 3, '', NULL, NULL, 1, 0, 'F', '0', '0', 'system:blacklist:export', '#', '', '2021-11-02 10:54:21', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2006, '异常监控', 2, 1, 'exception', 'monitor/exception/index', NULL, 1, 1, 'C', '0', '0', '', 'bug', '', '2021-11-02 21:51:00', '', '2021-11-03 09:16:54', ''); +INSERT INTO `sys_menu` VALUES (2007, '回收站', 100, 10, '', NULL, NULL, 1, 0, 'F', '0', '0', 'system:user:recovery', '#', '', '2021-11-03 17:00:17', '', '2021-11-03 17:00:38', ''); + +-- ---------------------------- +-- Table structure for sys_post +-- ---------------------------- +DROP TABLE IF EXISTS `sys_post`; +CREATE TABLE `sys_post` ( + `post_id` bigint NOT NULL AUTO_INCREMENT COMMENT '岗位ID', + `post_code` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '岗位编码', + `post_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '岗位名称', + `post_sort` int NOT NULL COMMENT '显示顺序', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '状态(0正常 1停用)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`post_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '岗位信息表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_post +-- ---------------------------- +INSERT INTO `sys_post` VALUES (1, 'ceo', '董事长', 1, '0', 'admin', '2021-10-12 11:26:30', '', '2021-10-22 14:22:23', ''); +INSERT INTO `sys_post` VALUES (2, 'se', '项目经理', 2, '0', 'admin', '2021-10-12 11:26:30', '', NULL, ''); +INSERT INTO `sys_post` VALUES (3, 'hr', '人力资源', 3, '0', 'admin', '2021-10-12 11:26:30', '', '2021-10-22 14:22:26', ''); + +-- ---------------------------- +-- Table structure for sys_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role`; +CREATE TABLE `sys_role` ( + `role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID', + `role_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称', + `role_key` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色权限字符串', + `role_sort` int NOT NULL COMMENT '显示顺序', + `data_scope` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', + `menu_check_strictly` tinyint(1) NULL DEFAULT 1 COMMENT '菜单树选择项是否关联显示', + `dept_check_strictly` tinyint(1) NULL DEFAULT 1 COMMENT '部门树选择项是否关联显示', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色状态(0正常 1停用)', + `del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`role_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 101 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色信息表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_role +-- ---------------------------- +INSERT INTO `sys_role` VALUES (1, '超级管理员', 'admin', 1, '1', 0, 0, '0', '0', 'admin', '2021-10-12 11:26:30', '', '2021-10-25 14:36:55', '超级管理员'); +INSERT INTO `sys_role` VALUES (2, '普通角色', 'common', 2, '2', 1, 0, '0', '0', 'admin', '2021-10-12 11:26:30', 'admin', '2021-11-03 09:18:08', '普通角色'); +INSERT INTO `sys_role` VALUES (100, '经理', '/add/list', 3, '5', 0, 0, '0', '2', '', '2021-10-18 08:54:17', '', '2021-10-18 09:02:51', '测试add角色123'); + +-- ---------------------------- +-- Table structure for sys_role_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role_dept`; +CREATE TABLE `sys_role_dept` ( + `role_id` bigint NOT NULL COMMENT '角色ID', + `dept_id` bigint NOT NULL COMMENT '部门ID', + PRIMARY KEY (`role_id`, `dept_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色和部门关联表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_role_dept +-- ---------------------------- +INSERT INTO `sys_role_dept` VALUES (2, 100); +INSERT INTO `sys_role_dept` VALUES (2, 101); +INSERT INTO `sys_role_dept` VALUES (2, 103); +INSERT INTO `sys_role_dept` VALUES (2, 104); +INSERT INTO `sys_role_dept` VALUES (2, 105); + +-- ---------------------------- +-- Table structure for sys_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role_menu`; +CREATE TABLE `sys_role_menu` ( + `role_id` bigint NOT NULL COMMENT '角色ID', + `menu_id` bigint NOT NULL COMMENT '菜单ID', + PRIMARY KEY (`role_id`, `menu_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色和菜单关联表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_role_menu +-- ---------------------------- +INSERT INTO `sys_role_menu` VALUES (1, 1); +INSERT INTO `sys_role_menu` VALUES (1, 2); +INSERT INTO `sys_role_menu` VALUES (1, 100); +INSERT INTO `sys_role_menu` VALUES (1, 101); +INSERT INTO `sys_role_menu` VALUES (1, 102); +INSERT INTO `sys_role_menu` VALUES (1, 103); +INSERT INTO `sys_role_menu` VALUES (1, 104); +INSERT INTO `sys_role_menu` VALUES (1, 105); +INSERT INTO `sys_role_menu` VALUES (1, 106); +INSERT INTO `sys_role_menu` VALUES (1, 112); +INSERT INTO `sys_role_menu` VALUES (1, 113); +INSERT INTO `sys_role_menu` VALUES (1, 500); +INSERT INTO `sys_role_menu` VALUES (1, 1001); +INSERT INTO `sys_role_menu` VALUES (1, 1002); +INSERT INTO `sys_role_menu` VALUES (1, 1003); +INSERT INTO `sys_role_menu` VALUES (1, 1004); +INSERT INTO `sys_role_menu` VALUES (1, 1005); +INSERT INTO `sys_role_menu` VALUES (1, 1006); +INSERT INTO `sys_role_menu` VALUES (1, 1007); +INSERT INTO `sys_role_menu` VALUES (1, 1008); +INSERT INTO `sys_role_menu` VALUES (1, 1009); +INSERT INTO `sys_role_menu` VALUES (1, 1010); +INSERT INTO `sys_role_menu` VALUES (1, 1011); +INSERT INTO `sys_role_menu` VALUES (1, 1012); +INSERT INTO `sys_role_menu` VALUES (1, 1013); +INSERT INTO `sys_role_menu` VALUES (1, 1014); +INSERT INTO `sys_role_menu` VALUES (1, 1015); +INSERT INTO `sys_role_menu` VALUES (1, 1016); +INSERT INTO `sys_role_menu` VALUES (1, 1017); +INSERT INTO `sys_role_menu` VALUES (1, 1018); +INSERT INTO `sys_role_menu` VALUES (1, 1019); +INSERT INTO `sys_role_menu` VALUES (1, 1020); +INSERT INTO `sys_role_menu` VALUES (1, 1021); +INSERT INTO `sys_role_menu` VALUES (1, 1022); +INSERT INTO `sys_role_menu` VALUES (1, 1023); +INSERT INTO `sys_role_menu` VALUES (1, 1024); +INSERT INTO `sys_role_menu` VALUES (1, 1025); +INSERT INTO `sys_role_menu` VALUES (1, 1026); +INSERT INTO `sys_role_menu` VALUES (1, 1027); +INSERT INTO `sys_role_menu` VALUES (1, 1028); +INSERT INTO `sys_role_menu` VALUES (1, 1029); +INSERT INTO `sys_role_menu` VALUES (1, 1030); +INSERT INTO `sys_role_menu` VALUES (1, 1031); +INSERT INTO `sys_role_menu` VALUES (1, 1032); +INSERT INTO `sys_role_menu` VALUES (1, 1033); +INSERT INTO `sys_role_menu` VALUES (1, 1034); +INSERT INTO `sys_role_menu` VALUES (1, 1035); +INSERT INTO `sys_role_menu` VALUES (1, 1040); +INSERT INTO `sys_role_menu` VALUES (1, 1041); +INSERT INTO `sys_role_menu` VALUES (1, 1042); +INSERT INTO `sys_role_menu` VALUES (1, 2002); +INSERT INTO `sys_role_menu` VALUES (1, 2003); +INSERT INTO `sys_role_menu` VALUES (1, 2004); +INSERT INTO `sys_role_menu` VALUES (1, 2005); +INSERT INTO `sys_role_menu` VALUES (1, 2006); +INSERT INTO `sys_role_menu` VALUES (1, 2007); +INSERT INTO `sys_role_menu` VALUES (2, 1); +INSERT INTO `sys_role_menu` VALUES (2, 2); +INSERT INTO `sys_role_menu` VALUES (2, 100); +INSERT INTO `sys_role_menu` VALUES (2, 101); +INSERT INTO `sys_role_menu` VALUES (2, 102); +INSERT INTO `sys_role_menu` VALUES (2, 103); +INSERT INTO `sys_role_menu` VALUES (2, 104); +INSERT INTO `sys_role_menu` VALUES (2, 105); +INSERT INTO `sys_role_menu` VALUES (2, 106); +INSERT INTO `sys_role_menu` VALUES (2, 112); +INSERT INTO `sys_role_menu` VALUES (2, 113); +INSERT INTO `sys_role_menu` VALUES (2, 500); +INSERT INTO `sys_role_menu` VALUES (2, 1001); +INSERT INTO `sys_role_menu` VALUES (2, 1002); +INSERT INTO `sys_role_menu` VALUES (2, 1003); +INSERT INTO `sys_role_menu` VALUES (2, 1004); +INSERT INTO `sys_role_menu` VALUES (2, 1005); +INSERT INTO `sys_role_menu` VALUES (2, 1006); +INSERT INTO `sys_role_menu` VALUES (2, 1007); +INSERT INTO `sys_role_menu` VALUES (2, 1008); +INSERT INTO `sys_role_menu` VALUES (2, 1009); +INSERT INTO `sys_role_menu` VALUES (2, 1010); +INSERT INTO `sys_role_menu` VALUES (2, 1011); +INSERT INTO `sys_role_menu` VALUES (2, 1012); +INSERT INTO `sys_role_menu` VALUES (2, 1013); +INSERT INTO `sys_role_menu` VALUES (2, 1014); +INSERT INTO `sys_role_menu` VALUES (2, 1015); +INSERT INTO `sys_role_menu` VALUES (2, 1016); +INSERT INTO `sys_role_menu` VALUES (2, 1017); +INSERT INTO `sys_role_menu` VALUES (2, 1018); +INSERT INTO `sys_role_menu` VALUES (2, 1019); +INSERT INTO `sys_role_menu` VALUES (2, 1020); +INSERT INTO `sys_role_menu` VALUES (2, 1021); +INSERT INTO `sys_role_menu` VALUES (2, 1022); +INSERT INTO `sys_role_menu` VALUES (2, 1023); +INSERT INTO `sys_role_menu` VALUES (2, 1024); +INSERT INTO `sys_role_menu` VALUES (2, 1025); +INSERT INTO `sys_role_menu` VALUES (2, 1026); +INSERT INTO `sys_role_menu` VALUES (2, 1027); +INSERT INTO `sys_role_menu` VALUES (2, 1028); +INSERT INTO `sys_role_menu` VALUES (2, 1029); +INSERT INTO `sys_role_menu` VALUES (2, 1030); +INSERT INTO `sys_role_menu` VALUES (2, 1031); +INSERT INTO `sys_role_menu` VALUES (2, 1032); +INSERT INTO `sys_role_menu` VALUES (2, 1033); +INSERT INTO `sys_role_menu` VALUES (2, 1034); +INSERT INTO `sys_role_menu` VALUES (2, 1035); +INSERT INTO `sys_role_menu` VALUES (2, 1040); +INSERT INTO `sys_role_menu` VALUES (2, 1041); +INSERT INTO `sys_role_menu` VALUES (2, 1042); +INSERT INTO `sys_role_menu` VALUES (2, 2002); +INSERT INTO `sys_role_menu` VALUES (2, 2003); +INSERT INTO `sys_role_menu` VALUES (2, 2004); +INSERT INTO `sys_role_menu` VALUES (2, 2005); +INSERT INTO `sys_role_menu` VALUES (2, 2006); + +-- ---------------------------- +-- Table structure for sys_user +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user`; +CREATE TABLE `sys_user` ( + `user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID', + `dept_id` bigint NULL DEFAULT NULL COMMENT '部门ID', + `user_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户账号', + `nick_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户昵称', + `user_type` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '00' COMMENT '用户类型(00系统用户)', + `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '用户邮箱', + `phonenumber` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '手机号码', + `sex` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)', + `avatar` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '头像地址', + `password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '密码', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '帐号状态(0正常 1停用)', + `del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', + `login_ip` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '最后登录IP', + `login_date` datetime NULL DEFAULT NULL COMMENT '最后登录时间', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`user_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 119 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户信息表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user +-- ---------------------------- +INSERT INTO `sys_user` VALUES (1, 103, 'admin', '若依admin', '00', 'ry@163.com', '15888888888', '1', 'http://localhost:1818/17a15f132fe94ed0b5cd4551fc9871e8.blob', '$2a$10$8UOvDMhuZrb9q4qq5qAxx.NLvHOT8RttQP9McvjtN6vkeGR6A9RFG', '0', '0', '127.0.0.1', '2021-11-15 11:10:21', 'admin', '2021-10-12 11:26:30', '', '2021-11-09 14:46:55', '管理员'); +INSERT INTO `sys_user` VALUES (2, 106, 'ry', '若依1234', '00', 'ry1@qq.com', '15666666666', '0', '', '$2a$10$NOUJUSq10hdPo0LM0Lezq.oBUXdo7pQzrcI4UQjIXrfjUD73nuhj.', '0', '0', '127.0.0.1', '2021-10-13 08:47:52', 'admin', '2021-10-12 11:26:30', '', '2021-11-04 10:47:37', '测试员123'); +INSERT INTO `sys_user` VALUES (107, 103, 'woshixiaoming1', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (108, 103, 'woshixiaoming2', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (109, 103, 'woshixiaoming3', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (110, 103, 'woshixiaoming4', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (111, 103, 'woshixiaoming5', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (112, 103, 'woshixiaoming6', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (113, 103, 'woshixiaoming7', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (114, 103, 'woshixiaoming8', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (115, 103, 'woshixiaoming9', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (116, 103, 'woshixiaoming10', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (117, 103, 'woshixiaoming11', 'woshixiaoming', '00', '', '18208762345', '0', '', '$2a$10$fbF0zMkxD.EdIkwVx03TKOrGl55uN77eUd1UJDutsRUnxgFI0ncR.', '0', '2', '', NULL, '', '2021-11-02 15:40:00', '', '2021-11-03 10:02:21', NULL); +INSERT INTO `sys_user` VALUES (118, 100, 'admin36123', '小小黑', '00', 'am@163.com', '17856782345', '1', '', '$2a$10$00r4GhKTXGtNzc4F9TFAFeMXBJ1Ve7iDps0zk2SrlsxTS525U8n5m', '0', '2', '', NULL, 'admin', '2021-11-15 09:18:58', 'admin', '2021-11-15 09:23:33', '133·1·3'); + +-- ---------------------------- +-- Table structure for sys_user_post +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_post`; +CREATE TABLE `sys_user_post` ( + `user_id` bigint NOT NULL COMMENT '用户ID', + `post_id` bigint NOT NULL COMMENT '岗位ID', + PRIMARY KEY (`user_id`, `post_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户与岗位关联表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user_post +-- ---------------------------- +INSERT INTO `sys_user_post` VALUES (1, 1); +INSERT INTO `sys_user_post` VALUES (2, 1); +INSERT INTO `sys_user_post` VALUES (2, 2); + +-- ---------------------------- +-- Table structure for sys_user_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_role`; +CREATE TABLE `sys_user_role` ( + `user_id` bigint NOT NULL COMMENT '用户ID', + `role_id` bigint NOT NULL COMMENT '角色ID', + PRIMARY KEY (`user_id`, `role_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户和角色关联表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user_role +-- ---------------------------- +INSERT INTO `sys_user_role` VALUES (1, 1); +INSERT INTO `sys_user_role` VALUES (2, 2); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/doc/说明(必看!!!).txt b/doc/说明(必看!!!).txt new file mode 100644 index 0000000..330a0fc --- /dev/null +++ b/doc/说明(必看!!!).txt @@ -0,0 +1,6 @@ +1. 装一个mysql5.7 +2. 执行ailanyin-boot-mysql5.7.sql到mysql5.7中 +3. 装dm8 +4. 用达梦数据迁移工具,将mysql迁移到dm8 +5. 复制FIND_IN_SET.sql中的内容并运行 + (将ROOT.FIND_IN_SET中的ROOT改成实际的) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..f10be6d --- /dev/null +++ b/pom.xml @@ -0,0 +1,285 @@ + + + 4.0.0 + + com.ailanyin + vis389_backend + pom + 1.0-SNAPSHOT + + ailanyin-admin + ailanyin-common + ailanyin-model-mapper + ailanyin-security + + + + org.springframework.boot + spring-boot-starter-parent + 2.5.5 + + + + + + UTF-8 + + UTF-8 + + 8 + + 1.0-SNAPSHOT + + true + + 1.3.1 + + 1.2.6 + + 5.7.15 + + 7.6.0.142 + + 2.5.4 + + 0.11.2 + + 8.16 + + 4.5.30 + + 2.1.0 + + 3.1.332 + + 7.1.0 + + 2.2.0 + + 2.0.4 + + 1.2.78 + + 4.4.0 + + 2.9.2 + + 1.4 + + 5.8.0 + + + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper-starter.version} + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + cn.hutool + hutool-all + ${hutool.version} + + + + com.github.xiaoymin + knife4j-spring-boot-starter + ${knife4j.version} + + + + com.dameng + Dm7JdbcDriver17 + ${dm8-connector.version} + + + + org.springframework.data + spring-data-commons + ${spring-data-commons.version} + + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + runtime + + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.version} + runtime + + + + com.nimbusds + nimbus-jose-jwt + ${nimbus-jose-jwt.version} + + + + com.aliyun + aliyun-java-sdk-core + ${aliyun.version} + + + + com.aliyun + aliyun-java-sdk-dysmsapi + ${aliyun-dysmsapi.version} + + + + com.tencentcloudapi + tencentcloud-sdk-java + ${tencentcloud.version} + + + + io.minio + minio + ${minio.version} + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis-spring-boot.version} + + + + com.alibaba + fastjson + ${fastjson.version} + + + + cn.afterturn + easypoi-spring-boot-starter + ${easypoi.version} + + + + io.springfox + springfox-spring-web + ${springfox.version} + + + + commons-fileupload + commons-fileupload + ${commons.fileupload.version} + + + + com.github.oshi + oshi-core + ${oshi.version} + + + + com.ailanyin + ailanyin-common + ${ailanyin.version} + + + + com.ailanyin + ailanyin-model-mapper + ${ailanyin.version} + + + + com.ailanyin + ailanyin-security + ${ailanyin.version} + + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-test + test + + + cn.hutool + hutool-all + + + org.projectlombok + lombok + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + false + + + + +