This commit is contained in:
lijiaqi 2023-02-01 10:37:18 +08:00
commit e388a37454
165 changed files with 4918 additions and 0 deletions

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

19
.idea/compiler.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="ydool-demo" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="ydool-demo" options="-parameters" />
</option>
</component>
</project>

7
.idea/encodings.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

15
.idea/git_toolbox_prj.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GoogleJavaFormatSettings">
<option name="enabled" value="false" />
</component>
</project>

45
.idea/jarRepositories.xml Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="rdd-releases" />
<option name="name" value="rdd-releases" />
<option name="url" value="https://packages.aliyun.com/maven/repository/2226303-release-LbOUW1/" />
</remote-repository>
<remote-repository>
<option name="id" value="rdc-releases" />
<option name="name" value="rdc-releases" />
<option name="url" value="https://packages.aliyun.com/maven/repository/2123695-release-4FLjf1/" />
</remote-repository>
<remote-repository>
<option name="id" value="rdd-snapshots" />
<option name="name" value="rdd-snapshots" />
<option name="url" value="https://packages.aliyun.com/maven/repository/2226303-snapshot-Ktt1JF/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="rdc-snapshots" />
<option name="name" value="rdc-snapshots" />
<option name="url" value="https://packages.aliyun.com/maven/repository/2123695-snapshot-LiQOYE/" />
</remote-repository>
<remote-repository>
<option name="id" value="snapshots" />
<option name="name" value="snapshots" />
<option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="central" />
<option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository>
</component>
</project>

14
.idea/misc.xml Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

29
bin/start.sh Normal file
View File

@ -0,0 +1,29 @@
#!/bin/sh
cd $PWD
pid=$(ps -ef | grep video.jar | grep -v grep | awk '{print $2}')
if [ -n "$pid" ]; then
kill -9 $pid
fi
# 优化JVM参数
JAVA_OPTS="$MAVEN_OPTS -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m"
# 方式一、配置外部自定义的属性文件(建议)
#JAVA_OPTS="$JAVA_OPTS -Dspring.config.location=$PWD\application.yml"
# 方式二、配置环境名称,加载不同的属性文件
# JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=prod"
if [ -z "$JAVA_HOME" ]; then
RUN_JAVA=java
else
RUN_JAVA="$JAVA_HOME"/bin/java
fi
# 根据情况修改 web.war 为您的 war 包名称
nohup $RUN_JAVA $JAVA_OPTS -jar video.jar > system.log 2>&1 &
sleep 1
pid=$(ps -ef | grep video.jar | grep -v grep | awk '{print $2}')
echo $pid

8
bin/update.sh Normal file
View File

@ -0,0 +1,8 @@
_pwd=/mnt/build
_ip=150.158.32.238
cd ../
mvn clean package
scp target/build/*.jar root@${_ip}:${_pwd}
#scp target/build/lib/*.* root@${_ip}:${_pwd}/lib
ssh root@${_ip} "cd ${_pwd}; sh ./start.sh"

382
pom.xml Normal file
View File

@ -0,0 +1,382 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
</parent>
<groupId>com.ydool</groupId>
<artifactId>ydool-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<!-- jdk版本1.8 -->
<java.version>1.8</java.version>
<!-- maven-compiler-plugin插件版本Java代码编译 -->
<maven.plugin.version>3.8.1</maven.plugin.version>
<!-- maven编译时指定编码UTF-8 -->
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<!-- 项目统一字符集编码UTF-8 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 项目统一字符集编码UTF-8 -->
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- 项目统一设置版本号 -->
<gitegg.project.version>1.0-SNAPSHOT</gitegg.project.version>
<!-- SpringBoot版本号 -->
<spring.boot.version>2.3.12.RELEASE</spring.boot.version>
<!-- hutool版本号 -->
<hutool.version>5.8.11</hutool.version>
<!-- sa-token版本号-->
<sa-token.version>1.33.0</sa-token.version>
<!-- mysql数据库驱动 -->
<mysql.connector.version>8.0.17</mysql.connector.version>
<!-- 数据库连接池Druid -->
<druid.version>1.2.15</druid.version>
<!-- Mybatis Plus增强工具 -->
<mybatis.plus.version>3.4.3.1</mybatis.plus.version>
<!-- Knife4j Swagger2文档 -->
<knife4j.version>2.0.9</knife4j.version>
<!-- Lombok -->
<lombok.version>1.18.20</lombok.version>
<!-- Mybatis Plus代码生成器 -->
<mybatis.plus.gen.version>3.3.2</mybatis.plus.gen.version>
<!-- Mybatis Plus多表连接 -->
<mybatis.plus.join.version>1.2.4</mybatis.plus.join.version>
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
<app.build.name>${project.artifactId}-${project.version}</app.build.name>
<app.build.prod>target/build</app.build.prod>
</properties>
<dependencies>
<!-- Lombok 通过简单注解消除冗长代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<artifactId>log4j-api</artifactId>
<groupId>org.apache.logging.log4j</groupId>
</exclusion>
<exclusion>
<artifactId>log4j-to-slf4j</artifactId>
<groupId>org.apache.logging.log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- spring-boot-starter-web 2.3.x开始不再默认引入这里需要手动引入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>3.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.10</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- Mybatis Plus增强工具 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join</artifactId>
<version>${mybatis.plus.join.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis.plus.gen.version}</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Swagger2 knife4j bom方式引入 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!-- hutool工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- sa-token -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${sa-token.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.7</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.0.6</version> <!-- 注:如提示报错,先升级基础包版,无法解决可联系技术支持 -->
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打JAR包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!-- MANIFEST.MF 中 Class-Path 加入前缀 -->
<classpathPrefix>lib/</classpathPrefix>
<!-- jar包不包含唯一版本标识 -->
<useUniqueVersions>false</useUniqueVersions>
<!--指定入口类 需要改名 -->
<mainClass>xyz.grapehub.AppEntry</mainClass>
</manifest>
<manifestEntries>
<!--MANIFEST.MF 中 Class-Path 加入资源文件目录 -->
<Class-Path>./resources/</Class-Path>
</manifestEntries>
</archive>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</plugin>
<!-- 该插件的作用是用于复制依赖的jar包到指定的文件夹里 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- 该插件的作用是用于复制指定的文件 -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<!-- 复制配置文件 -->
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
<include>*.yml</include>
</includes>
<excludes>
<exclude>*.jar</exclude>
</excludes>
</resource>
</resources>
<outputDirectory>${project.build.directory}/resources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.7.RELEASE</version>
<configuration>
<!--重写包含依赖包含不存在的依赖jar里没有pom里的依赖 -->
<includes>
<include>
<groupId>null</groupId>
<artifactId>null</artifactId>
</include>
</includes>
<layout>ZIP</layout>
<!--使用外部配置文件jar包里没有资源文件 -->
<addResources>true</addResources>
<outputDirectory>${project.build.directory}/resources</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<!--配置jar包特殊标识 配置后,保留原文件,生成新文件 *-run.jar -->
<!--配置jar包特殊标识 不配置,原文件命名为 *.jar.original生成新文件 *.jar -->
<!--<classifier>run</classifier> -->
</configuration>
</execution>
</executions>
</plugin>
<!-- 对打包后的文件重新进行组装 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy file="${project.basedir}/target/${app.build.name}.jar"
tofile="${app.build.prod}/xs_building_star.jar"/>
<copy file="${project.basedir}/bin/start.sh" tofile="${app.build.prod}/start.sh"/>
<!-- 复制资源文件 -->
<copy todir="${app.build.prod}">
<fileset dir="target/resources">
<include name="**/*.properties"/>
<include name="**/*.xml"/>
<include name="**/*.yml"/>
</fileset>
</copy>
<!-- 复制包文件 -->
<copy todir="${app.build.prod}/lib">
<fileset dir="target/lib"/>
</copy>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,16 @@
package com.ydool;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableCaching
@EnableAsync
public class YdoolApplication {
public static void main(String[] args) {
SpringApplication.run(YdoolApplication.class, args);
}
}

View File

@ -0,0 +1,96 @@
package com.ydool.common.advice;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.util.SaResult;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.common.exception.ResultException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestControllerAdvice
public class BaseControllerAdvice {
@ExceptionHandler(Exception.class)
public AjaxResult globalException(Exception e, HttpServletResponse response) {
e.printStackTrace();
System.out.println(e.getMessage());
return AjaxResult.fail("服务器错误,请联系管理员");
}
@ExceptionHandler(ConstraintViolationException.class)
public AjaxResult handlerConstraintViolationException(ConstraintViolationException e) {
return AjaxResult.fail(e.getConstraintViolations().iterator().next().getMessage());
}
@ExceptionHandler(BindException.class)
public AjaxResult handlerBindExceptionn(BindException e) {
for (Field field : e.getTarget().getClass().getDeclaredFields()) {
FieldError fieldError = e.getBindingResult().getFieldError(field.getName());
if (fieldError != null) {
return AjaxResult.fail(fieldError.getDefaultMessage());
}
}
return AjaxResult.fail(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public AjaxResult handlerMethodArgumentNotValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
Map<String, Object> maps = null;
if (bindingResult.hasErrors()) {
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
maps = new HashMap<>(fieldErrors.size());
Map<String, Object> finalMaps = maps;
fieldErrors.forEach(error -> finalMaps.put(error.getField(), error.getDefaultMessage()));
return AjaxResult.fail(fieldErrors.get(0).getDefaultMessage());
}
return AjaxResult.fail("参数校验失败");
}
@ExceptionHandler(ResultException.class)
public AjaxResult handlerResultException(ResultException e) {
return e.getResult();
}
// 全局异常拦截拦截项目中的NotLoginException异常
@ExceptionHandler(NotLoginException.class)
public SaResult handlerNotLoginException(NotLoginException nle){
// 判断场景值定制化异常信息
String message = "";
if(nle.getType().equals(NotLoginException.NOT_TOKEN)) {
message = "未提供token";
}
else if(nle.getType().equals(NotLoginException.INVALID_TOKEN)) {
message = "token无效";
}
else if(nle.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
message = "token已过期";
}
else if(nle.getType().equals(NotLoginException.BE_REPLACED)) {
message = "token已被顶下线";
}
else if(nle.getType().equals(NotLoginException.KICK_OUT)) {
message = "token已被踢下线";
}
else {
message = "当前会话未登录";
}
// 返回给前端
return SaResult.error(message).setCode(HttpStatus.UNAUTHORIZED.value());
}
}

View File

@ -0,0 +1,58 @@
package com.ydool.common.base;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.common.exception.ResultException;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author zhouyuan
* @date 2021/8/20 11:21
*/
public class BaseController {
@Autowired
protected HttpServletRequest request;
@Autowired
protected HttpServletResponse response;
protected Integer getPageNum() {
String pageNum = request.getParameter("current");
return StrUtil.isBlank(pageNum) ? 1 : Convert.toInt(pageNum);
}
protected Integer getPageSize() {
String limit = request.getParameter("size");
return StrUtil.isBlank(limit) ? 20 : Convert.toInt(limit);
}
protected Page getPage() {
return new Page<>(getPageNum(), getPageSize());
}
public void renderJson(AjaxResult ajaxResult) {
throw new ResultException(ajaxResult);
}
public void fail(String msg) {
renderJson(AjaxResult.fail(msg));
}
public void ok(String msg) {
renderJson(AjaxResult.ok().msg(msg));
}
public void ok() {
renderJson(AjaxResult.ok());
}
}

View File

@ -0,0 +1,51 @@
package com.ydool.common.base;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class BaseEntity implements Serializable {
@TableId(type = IdType.ASSIGN_UUID)
private String id;
/**
* 创建时间
*/
@TableField(value = "created_at", fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@ApiModelProperty(value = "创建时间")
private LocalDateTime createdAt;
/**
* 创建人
*/
@TableField(value = "created_id", fill = FieldFill.INSERT)
@ApiModelProperty(value = "创建人")
private String createdId;
/**
* 更新时间
*/
@TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@ApiModelProperty(value = "更新时间")
private LocalDateTime updatedAt;
/**
* 更新人
*/
@TableField(value = "updated_id", fill = FieldFill.INSERT_UPDATE)
@ApiModelProperty(value = "更新人")
private String updatedId;
}

View File

@ -0,0 +1,64 @@
package com.ydool.common.base;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ydool.common.data.dto.PageResult;
import com.ydool.common.data.vo.BaseRequest;
import com.ydool.common.exception.ResultException;
import com.ydool.common.factory.PageFactory;
import com.ydool.common.factory.PageResultFactory;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
public class BaseService<M extends BaseMapper<T>, T extends BaseEntity> extends ServiceImpl<M, T> {
@Transactional(rollbackFor = Exception.class)
public void add(T entity) {
this.save(entity);
}
@Transactional(rollbackFor = Exception.class)
public void edit(T entity) {
this.updateById(entity);
}
public void delete(String id) {
this.removeById(id);
}
public T get(Serializable id) {
T result = getById(id);
if(result == null) throw new ResultException("数据不存在");
return result;
}
public PageResult<T> findPage(BaseRequest baseRequest) {
PageResult<T> pageResult = PageResultFactory.createPageResult(this.page(PageFactory.defaultPage(), this.createWrapper(baseRequest)));
return pageResult;
}
public LambdaQueryWrapper<T> createWrapper(BaseRequest baseRequest) {
return new LambdaQueryWrapper<>();
}
@Override
public boolean saveOrUpdate(T entity) {
if (StrUtil.isBlank(entity.getId())) {
entity.setCreatedAt(LocalDateTime.now());
return this.save(entity);
} else {
entity.setUpdatedAt(LocalDateTime.now());
return this.updateById(entity);
}
}
}

View File

@ -0,0 +1,56 @@
package com.ydool.common.base;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ydool.common.utils.TreeSorterUtil;
import java.util.List;
public class BaseTreeService <M extends BaseMapper<T>, T extends TreeEntity> extends BaseService<M, T> {
@Override
public boolean save(T entity) {
setTreePidNames(entity);
return super.save(entity);
}
@Override
public boolean updateById(T entity) {
setTreePidNames(entity);
return super.updateById(entity);
}
public void setTreePidNames(T entity) {
if(entity.getPid().equals("0")) {
entity.setTreeNames(entity.getNamed());
entity.setTreeIds(entity.getPid());
}else {
T parent = baseMapper.selectOne(new QueryWrapper<T>().eq("id", entity.getPid()));
if(parent != null) {
entity.setTreeNames(parent.getTreeNames() + "/" + entity.getNamed());
entity.setTreeIds(parent.getTreeIds() + "," + entity.getPid());
}
}
}
public List<T> treeList() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("sort_no");
List<T> treeList = list(queryWrapper);
TreeSorterUtil.tree(treeList);
return treeList;
}
public List<T> treeList(String informationSheetId) {
QueryWrapper<T> queryWrapper = new QueryWrapper<T>().like(StrUtil.isNotBlank(informationSheetId), "information_sheet_id",
informationSheetId);
queryWrapper.orderByAsc("sort_no");
List<T> treeList = list(queryWrapper);
TreeSorterUtil.tree(treeList);
return treeList;
}
}

View File

@ -0,0 +1,27 @@
package com.ydool.common.base;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
/**
* @author zhouyuan
* @date 2021/8/20 16:44
*/
public interface BaseWrapper<T, D> {
public D toDto(T t);
public List<D> toDto(List<T> list);
default Page<D> toDto(IPage<T> t) {
List<T> list = t.getRecords();
List<D> dtoList = toDto(list);
Page<D> page = new Page<>();
BeanUtil.copyProperties(t, page);
page.setRecords(dtoList);
return page;
}
}

View File

@ -0,0 +1,51 @@
package com.ydool.common.base;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public abstract class TreeEntity extends BaseEntity {
@TableId(type = IdType.ASSIGN_UUID)
private String id;
private String pid;
private Integer sortNo;
@JsonIgnore
private String treeNames;
@JsonIgnore
private String treeIds;
@TableField(exist = false)
private Integer treeLeaf;
@TableField(exist = false)
private Integer treeLevel;
@TableField(exist = false)
private String parentName;
@TableField(exist = false)
private List children;
/**
* 返回树列表显示的值
* @return
*/
public abstract String getNamed();
public void addChild(TreeEntity child) {
if(children == null) this.children = new ArrayList();
this.children.add(child);
}
}

View File

@ -0,0 +1,117 @@
package com.ydool.common.cache;
import cn.hutool.core.lang.Dict;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.extra.spring.SpringUtil;
import com.ydool.common.constant.CacheConst;
import com.ydool.common.constant.GrapeConst;
import com.ydool.common.utils.CacheUtil;
import com.ydool.system.entity.Config;
import com.ydool.system.service.IConfigService;
import com.ydool.system.service.impl.ConfigServiceImpl;
import java.util.List;
public class ConfigCache {
public static final String CONFIG_KEY = "dict";
/**
* 密码是否加密
*/
public static final String USER_PASSWORD_SALT = "sys.user.salt";
/**
* 账号初始化密码
*/
public static final String USER_INIT_PASSWORD = "sys.user.initPassword";
/**
* 图片验证码
*/
public static final String LOGIN_CAPTCHA_CODE = "login_captcha_code";
/**
* 用户TOKEN密钥
*/
public static final String USER_TOKEN_SECRET = "sys.user.tokenSecret";
/**
* 用户TOKEN有效天数
*/
public static final String USER_TOKEN_DAY = "sys.user.tokenDay";
/**
* 手机验证码
*/
public static final String SYS_PHONE_CODE_LOGIN = "sys_phone_code_login";
/**
* 用户登录验证码长度
*/
public static final String LOGIN_CAPTCHA_CODE_LENGTH = "sys.login.captchaCodeLength";
/**
* 用户密码输入错误次数
*/
public static final String LOGIN_FAILED_TIMES = "login_failed_times";
/**
* 用户锁定时间
*/
public static final String LOGIN_FAILED_LOCK_MINUTE = "login_failed_lock_minute";
public static Dict getConfigDict() {
Dict configDict = CacheUtil.get(CacheConst.UPMS_CONFIG_CACHE, CONFIG_KEY, ()->{
ConfigServiceImpl configService = SpringUtil.getBean(ConfigServiceImpl.class);
List<Config> configList = configService.list();
Dict dict = Dict.create();
configList.stream().forEach(config -> {
dict.set(config.getParamKey(), config.getParamValue());
});
return dict;
});
return configDict;
}
public static String getStr(String key) {
Dict dict = getConfigDict();
return dict.getStr(key);
}
public static String getStr(String key, String defaultValue) {
Dict dict = getConfigDict();
String value = dict.getStr(key);
return value == null ? defaultValue : value;
}
public static Integer getInt(String key) {
Dict dict = getConfigDict();
return dict.getInt(key);
}
public static Integer getInt(String key, Integer defaultValue) {
Dict dict = getConfigDict();
Integer value = dict.getInt(key);
return value == null ? defaultValue : value;
}
public static String getDecryptStr(String key) {
String dictStr = getStr(key);
SymmetricCrypto rc2 = new SymmetricCrypto(SymmetricAlgorithm.RC2, GrapeConst.RC2_KEY.getBytes());
try {
return rc2.decryptStr(dictStr);
}catch (Exception e){
return null;
}
}
public static String getDecryptStr(String key, String defaultValue) {
String value = getStr(key);
String decryptStr = getDecryptStr(value);
return decryptStr == null ? defaultValue : value;
}
}

View File

@ -0,0 +1,13 @@
package com.ydool.common.config;
import com.ydool.common.interceptor.SqlLogInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LogConfig {
@Bean
public SqlLogInterceptor sqlLogInterceptor() {
return new SqlLogInterceptor();
}
}

View File

@ -0,0 +1,6 @@
package com.ydool.common.constant;
public interface CacheConst {
String UPMS_CONFIG_CACHE = "upms_config";
}

View File

@ -0,0 +1,7 @@
package com.ydool.common.constant;
public interface GrapeConst {
String RC2_KEY = "kj7967hdiv9sz0jbbps96tw8ikba44z2";
}

View File

@ -0,0 +1,30 @@
package com.ydool.common.constant;
public interface UrlConstant {
/**
* 后台根路径
*/
String API = "/api";
String AUTH = API + "/auth";
String ATTACHMENT = API + "/attachment";
String CONFIG = API + "/config";
String DEPT = API + "/dept";
String ROLE = API + "/role";
/**
* 重要说明该值为项目生成后的缺省密钥
* 在实际的应用中一定要为不同的项目或服务自行生成公钥和私钥并将 PRIVATE_KEY 的引用改为服务的配置项
* 密钥的生成方式com.ydool.common.util.RsaUtil类的main函数动态生成
*/
String APP_PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJwq/96CJLuyjMrcctY0lNrlTIvUikj0bXjmTrY6srwzGA9HiC6saPnwOryrwTqAy/QTCnKW/EeepyJl61r4wlITU0sPbCY7ugPbD2g3cowHPpofb4RJOQfV+EPlLOnDrrYbCP8Z6YhD6P6nltfRxL0kyP/NGX7CUaiMiXZshTMVAgMBAAECgYA6PO7ek7oPJS7MGBnbOBCq8QfyvXg0bLLGe1yvKISvGn7Gc+6dOT6MtsGwynxszMtCYjdrNFMwgkHh2hBDBLGyRM/C1orRpcpCK4CdJNI4GAF/jtIJ1lnrHp11Tt7ng0wGSC00i/oIBIFVRbRhk04SWtLb0C3KaiL9CpBFlFCkAQJBAMm01Opv5V18EZkA7G0Jn0axqNDqKb0OiiXPzzYJ1q3H+VaKYBulQ2V2vlwaO+VJ2any0zbtJrNN+ChiJXO3xzUCQQDGNDXj0NgzAPFGouGhhgjieMCIk1dGfcUT3tdEljqH6XxzgpgGk9WaDcKGi94gcBpw+k4S2K/2Z8BWm0o4VthhAkBElm30DfqTcFXXjj3W0ffMJSs/ZvCsbd5B/0j5mhza2O4LJGCL5gVl4hvW28DUNemC5aQ2wCtxuyiQKteLYsmlAkA9MBES635TAI97xvzw6HgFslF92D6xPFKC9+BtBBO9sY8B+ecE4M6oaGcNMlC4ouMGzb8cgliQMSdnlTkse2MBAkBpy+wkyUvJzLtBq2IPM5vlw9Oxn/6yP2YyBG5AP1dHFDwz3q/pkBcp/ZSmH2FgjXOvjFdSsNdRnOtNiLpFO19l";
}

View File

@ -0,0 +1,146 @@
package com.ydool.common.data.dto;
import java.util.HashMap;
import java.util.Map;
public class AjaxResult extends HashMap {
private static final String STATE = "code";
private static final Integer STATE_OK = 200;
private static final Integer STATE_FAIL = 500;
private static final Integer STATE_UN_AUTHORIZED = 401;
public AjaxResult() { }
public static AjaxResult by(Object key, Object value) {
return new AjaxResult().set(key, value);
}
public static AjaxResult create(Object key, Object value) {
return new AjaxResult().set(key, value);
}
public static AjaxResult flag(boolean flag) {
return flag == true ? AjaxResult.ok() : AjaxResult.fail();
}
public AjaxResult setOk() {
super.put(STATE, STATE_OK);
return this;
}
public static AjaxResult create() {
return new AjaxResult();
}
public static AjaxResult ok() {
return new AjaxResult().setOk();
}
public static AjaxResult ok(Object key, Object value) {
return ok().set(key, value);
}
public static AjaxResult fail() {
return new AjaxResult().setFail();
}
public static AjaxResult fail(String msg) {
return new AjaxResult().setFail().msg(msg);
}
public static AjaxResult state(Integer state) {
return new AjaxResult().set(STATE, state);
}
public static AjaxResult fail(Object key, Object value) {
return fail().set(key, value);
}
public static AjaxResult unauthorized() { return state(STATE_UN_AUTHORIZED); }
public AjaxResult setFail() {
super.put(STATE, STATE_FAIL);
return this;
}
public boolean isOk() {
Object state = get(STATE);
if (STATE_OK.equals(state)) {
return true;
}
if (STATE_FAIL.equals(state)) {
return false;
}
throw new IllegalStateException("调用 isOk() 之前,必须先调用 ok()、fail() 或者 setOk()、setFail() 方法");
}
public boolean isUnauthorized() {
Object state = get(STATE);
if (STATE_UN_AUTHORIZED.equals(state)) {
return true;
}
return false;
}
public boolean isFail() {
Object state = get(STATE);
if (STATE_FAIL.equals(state)) {
return true;
}
if (STATE_OK.equals(state)) {
return false;
}
throw new IllegalStateException("调用 isFail() 之前,必须先调用 ok()、fail() 或者 setOk()、setFail() 方法");
}
public AjaxResult set(Object key, Object value) {
super.put(key, value);
return this;
}
public AjaxResult setData(String key, Object value) {
Map<String, Object> data = (Map<String, Object>) get("data");
if(data == null) data = new HashMap<>();
data.put(key, value);
data(data);
return this;
}
public AjaxResult msg(String msg) {
set("message", msg);
return this;
}
public AjaxResult data(Object data) {
set("data", data);
return this;
}
public AjaxResult page(PageResult pageResult) {
this.put("count", pageResult.getCount());
this.put("data", pageResult.getRows());
return this;
}
public AjaxResult reset(Boolean reset) {
super.put("reset", reset);
return this;
}
public AjaxResult url(String url) {
super.put("url", url);
return this;
}
public AjaxResult func(String func) {
super.put("func", func);
return this;
}
}

View File

@ -0,0 +1,23 @@
package com.ydool.common.data.dto;
import lombok.Data;
import java.util.List;
@Data
public class OptionResult {
private String label;
private String value;
private String key;
private List<OptionResult> children;
public OptionResult(String label, String value) {
this.label = label;
this.value = value;
this.key = value;
}
}

View File

@ -0,0 +1,36 @@
package com.ydool.common.data.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class PageResult<T> implements Serializable {
/**
* 第几页
*/
private Integer pageNo = 1;
/**
* 每页条数
*/
private Integer pageSize = 20;
/**
* 总页数
*/
private Integer totalPage = 0;
/**
* 总记录数
*/
private Integer count = 0;
/**
* 结果集
*/
private List<T> rows;
}

View File

@ -0,0 +1,116 @@
package com.ydool.common.data.vo;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
public class BaseRequest implements Serializable {
private String id;
/**
* 开始时间
*/
private String searchBeginTime;
/**
* 结束时间
*/
private String searchEndTime;
/**
* 分页每页大小默认20
*/
private Integer perPage;
/**
* 分页第几页从1开始
*/
private Integer page;
/**
* 排序字段
*/
private String orderBy;
/**
* 正序或者倒序排列asc desc
*/
private String orderDir;
/**
* 搜索的参数
*/
private List<String> params = new ArrayList<>();
/**
* 唯一请求号
*/
private String requestNo;
/**
* 业务节点id
*/
private String spanId;
/**
* 当前登录用户的token
*/
private String token;
/**
* 参数校验分组分页
*/
public @interface page {
}
/**
* 参数校验分组查询所有
*/
public @interface list {
}
/**
* 参数校验分组增加
*/
public @interface add {
}
/**
* 参数校验分组编辑
*/
public @interface edit {
}
/**
* 参数校验分组删除
*/
public @interface delete {
}
/**
* 参数校验分组详情
*/
public @interface detail {
}
/**
* 参数校验分组导出
*/
public @interface export {
}
/**
* 参数校验分组修改状态
*/
public @interface updateStatus {
}
/**
* 参数校验分组批量删除
*/
public @interface batchDelete {
}
}

View File

@ -0,0 +1,26 @@
package com.ydool.common.exception;
import com.ydool.common.data.dto.AjaxResult;
public class ResultException extends RuntimeException {
private AjaxResult ajaxResult;
public ResultException(){
this.ajaxResult = AjaxResult.ok();
}
public ResultException(String msg) {
this.ajaxResult = AjaxResult.fail(msg);
}
public ResultException(AjaxResult ajaxResult){
this.ajaxResult = ajaxResult;
}
public AjaxResult getResult() {
return ajaxResult;
}
}

View File

@ -0,0 +1,35 @@
package com.ydool.common.factory;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ydool.common.utils.HttpServletUtil;
import javax.servlet.http.HttpServletRequest;
/**
* 分页参数快速获取
*/
public class PageFactory {
private static final String PAGE_NO_PARAM_NAME = "current";
private static final String PAGE_SIZE_PARAM_NAME = "pageSize";
public static <T> Page<T> defaultPage() {
int pageNo = 1;
int pageSize = 20;
HttpServletRequest request = HttpServletUtil.getRequest();
// 第几页
String pageNoStr = request.getParameter(PAGE_NO_PARAM_NAME);
if(ObjectUtil.isNotEmpty(pageNoStr)) pageNo = Integer.parseInt(pageNoStr);
// 每页条数
String pageSizeStr = request.getParameter(PAGE_SIZE_PARAM_NAME);
if(ObjectUtil.isNotEmpty(pageSizeStr)) pageSize = Integer.parseInt(pageSizeStr);
return new Page<>(pageNo, pageSize);
}
}

View File

@ -0,0 +1,38 @@
package com.ydool.common.factory;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.PageUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ydool.common.data.dto.PageResult;
import java.util.List;
public class PageResultFactory {
/**
* 将mybatis-plus的page转成自定义的PageResult,扩展了totalPage总页数
*/
public static PageResult createPageResult(IPage page) {
PageResult<?> pageResult = new PageResult<>();
pageResult.setRows(page.getRecords());
pageResult.setCount(Convert.toInt(page.getTotal()));
pageResult.setPageNo(Convert.toInt(page.getCurrent()));
pageResult.setPageSize(Convert.toInt(page.getSize()));
pageResult.setTotalPage(PageUtil.totalPage(pageResult.getCount(), pageResult.getPageSize()));
return pageResult;
}
/**
* 转成自定义PageResult
*/
public static <T> PageResult<T> createPageResult(List<T> rows, Long count, Integer pageSize, Integer pageNo) {
PageResult<T> pageResult = new PageResult<>();
pageResult.setRows(rows);
pageResult.setCount(Convert.toInt(count));
pageResult.setPageNo(pageNo);
pageResult.setPageSize(pageSize);
pageResult.setTotalPage(PageUtil.totalPage(pageResult.getCount(), pageSize));
return pageResult;
}
}

View File

@ -0,0 +1,135 @@
package com.ydool.common.gen;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.BeetlTemplateEngine;
import com.ydool.common.base.BaseController;
import com.ydool.common.base.BaseEntity;
import com.ydool.common.base.BaseService;
/**
* @author: zhouyuan
* @date: 2021年09月15日16:39:02
* <p>
* 填写表名和表前缀,生成实体类已有情况不会覆盖
*/
public class Generator {
private static String url = "jdbc:mysql://localhost:3306/ydool_demo?useSSL=false&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai";
private static String username = "root";
private static String password = "Wang09211108";
private static String driverName = "com.mysql.cj.jdbc.Driver";
public static void main(String[] args) {
//表名
String tableName = "t_sys_role";
//表前缀
String tablePrefix = "t_sys_";
//作者
String author = "ljq";
generate(tableName, tablePrefix, author);
}
public static void generate(String tableName, String tablePrefix, String author) {
AutoGenerator mpg = new AutoGenerator();
mpg.setTemplateEngine(new BeetlTemplateEngine());
//全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor(author);
gc.setOpen(false);
//是否覆盖
gc.setFileOverride(false);
gc.setDateType(DateType.ONLY_DATE);
//带swagger注解
gc.setSwagger2(true);
//实现类不要Impl后缀
// gc.setServiceImplName("%sService");
mpg.setGlobalConfig(gc);
//数据源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl(url);
dsc.setUsername(username);
dsc.setPassword(password);
dsc.setDriverName(driverName);
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
//包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.ydool.system");
pc.setEntity("entity");
pc.setServiceImpl("service");
pc.setServiceImpl("service.impl");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// if (null == template) {
// this.template = new TemplateConfig();
// } else {
// this.template = template;
// }
//
// if (null == packageConfig) {
// this.handlerPackage(this.template, this.globalConfig.getOutputDir(), new PackageConfig());
// } else {
// this.handlerPackage(this.template, this.globalConfig.getOutputDir(), packageConfig);
// }
// this.pathInfo = new HashMap(10);
// this.setPathInfo(this.pathInfo, template.getEntity(this.getGlobalConfig().isKotlin()), outputDir, "entity_path", "Entity");
// this.setPathInfo(this.pathInfo, template.getMapper(), outputDir, "mapper_path", "Mapper");
// this.setPathInfo(this.pathInfo, template.getXml(), outputDir, "xml_path", "Xml");
// this.setPathInfo(this.pathInfo, template.getService(), outputDir, "service_path", "Service");
// this.setPathInfo(this.pathInfo, template.getServiceImpl(), outputDir, "service_impl_path", "ServiceImpl");
// this.setPathInfo(this.pathInfo, template.getController(), outputDir, "controller_path", "Controller");
// if (StringUtils.isNotBlank(template)) {
// pathInfo.put(path, this.joinPath(outputDir, (String)this.packageInfo.get(module)));
// }
//指定生成模块
//可见不是模块null才会生成指定模块
TemplateConfig templateConfig = new TemplateConfig();
// templateConfig.setController("/templates/controller.java");
templateConfig.setServiceImpl("/templates/serviceImpl.java");
templateConfig.setService("/templates/service.java");
templateConfig.setMapper("/templates/mapper.java");
//只生成实体类mapperService和serviceImpl
templateConfig.setController(null);
// templateConfig.setService(null);
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
//策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude(tableName);
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
//链式操作
strategy.setChainModel(true);
//rest风格
strategy.setRestControllerStyle(true);
//公共父类
strategy.setSuperEntityClass(BaseEntity.class);
strategy.setSuperControllerClass(BaseController.class);
strategy.setSuperServiceImplClass(BaseService.class);
strategy.setSuperMapperClass("com.github.yulichang.base.MPJBaseMapper");
strategy.setTablePrefix(tablePrefix);
strategy.setSkipView(true);
mpg.setStrategy(strategy);
mpg.execute();
System.out.println("创建完成...");
}
}

View File

@ -0,0 +1,130 @@
package com.ydool.common.interceptor;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Statement;
import java.util.*;
@Intercepts({
@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
@Signature(type = StatementHandler.class, method = "update", args = Statement.class),
@Signature(type = StatementHandler.class, method = "batch", args = Statement.class)
})
public class SqlLogInterceptor implements Interceptor {
private Method druidGetSqlMethod;
@Override
public Object intercept(Invocation invocation) throws Throwable {
Statement statement;
Object firstArg = invocation.getArgs()[0];
if (Proxy.isProxyClass(firstArg.getClass())) {
statement = (Statement) SystemMetaObject.forObject(firstArg).getValue("h.statement");
} else {
statement = (Statement) firstArg;
}
MetaObject stmtMetaObj = SystemMetaObject.forObject(statement);
try {
statement = (Statement) stmtMetaObj.getValue("stmt.statement");
} catch (Exception e) {
// do nothing
}
if (stmtMetaObj.hasGetter("delegate")) {
//Hikari
try {
statement = (Statement) stmtMetaObj.getValue("delegate");
} catch (Exception ignored) {
}
}
String originalSql = statement.toString();;
originalSql = originalSql.replaceAll("[\\s]+", StringPool.SPACE);
int index = indexOfSqlStart(originalSql);
if (index > 0) {
originalSql = originalSql.substring(index);
}
// 计算执行 SQL 耗时
long start = SystemClock.now();
Object result = invocation.proceed();
long timing = SystemClock.now() - start;
// SQL 打印执行结果
Object target = PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(target);
MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
// 打印 sql
System.err.println(
StrUtil.format(
"\n============== Sql Start ==============" +
"\nExecute ID {}" +
"\nExecute SQL {}" +
"\nExecute Time{} ms" +
"\n============== Sql End ==============\n",
ms.getId(), originalSql, timing));
return result;
}
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
}
return target;
}
/**
* 获取此方法名的具体 Method
*
* @param clazz class 对象
* @param methodName 方法名
* @return 方法
*/
private Method getMethodRegular(Class<?> clazz, String methodName) {
if (Object.class.equals(clazz)) {
return null;
}
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().equals(methodName)) {
return method;
}
}
return getMethodRegular(clazz.getSuperclass(), methodName);
}
/**
* 获取sql语句开头部分
*
* @param sql ignore
* @return ignore
*/
private int indexOfSqlStart(String sql) {
String upperCaseSql = sql.toUpperCase();
Set<Integer> set = new HashSet<>();
set.add(upperCaseSql.indexOf("SELECT "));
set.add(upperCaseSql.indexOf("UPDATE "));
set.add(upperCaseSql.indexOf("INSERT "));
set.add(upperCaseSql.indexOf("DELETE "));
set.remove(-1);
if (CollectionUtils.isEmpty(set)) {
return -1;
}
List<Integer> list = new ArrayList<>(set);
list.sort(Comparator.naturalOrder());
return list.get(0);
}
}

View File

@ -0,0 +1,178 @@
package com.ydool.common.utils;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.ehcache.EhCacheCache;
import org.springframework.lang.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
public class CacheUtil {
private static CacheManager cacheManager = SpringUtil.getBean(CacheManager.class);
/**
* 获取缓存对象
*
* @param cacheName 缓存名
* @return Cache
*/
public static Cache getCache(String cacheName) {
return cacheManager.getCache(cacheName);
}
public static List<String> getCacheNames() {
Collection<String> cacheNames = cacheManager.getCacheNames();
return cacheNames.stream().collect(Collectors.toList());
}
/**
* 获取缓存
*
* @param cacheName 缓存名
* @param keyPrefix 缓存键前缀
* @param key 缓存键值
* @return
*/
@Nullable
public static Object get(String cacheName, String keyPrefix, Object key) {
if (ObjectUtil.hasEmpty(cacheName, keyPrefix, key)) {
return null;
}
return getCache(cacheName).get(keyPrefix.concat(String.valueOf(key))).get();
}
/**
* 获取缓存
*
* @param cacheName 缓存名
* @param keyPrefix 缓存键前缀
* @param key 缓存键值
* @param type
* @param <T>
* @return
*/
@Nullable
public static <T> T get(String cacheName, String keyPrefix, Object key, @Nullable Class<T> type) {
if (ObjectUtil.hasEmpty(cacheName, keyPrefix, key)) {
return null;
}
return getCache(cacheName).get(keyPrefix.concat(String.valueOf(key)), type);
}
/**
* 获取缓存
*
* @param cacheName 缓存名
* @param keyPrefix 缓存键前缀
* @param key 缓存键值
* @param valueLoader 重载对象
* @param <T>
* @return
*/
@Nullable
public static <T> T get(String cacheName, String keyPrefix, Object key, Callable<T> valueLoader) {
if (ObjectUtil.hasEmpty(cacheName, keyPrefix, key)) {
return null;
}
try {
return getCache(cacheName).get(keyPrefix.concat(String.valueOf(key)), valueLoader);
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* 获取缓存
*
* @param cacheName 缓存名
* @param key 缓存键
* @param valueLoader 重载对象
* @param <T>
* @return
*/
@Nullable
public static <T> T get(String cacheName, String key, Callable<T> valueLoader) {
if (ObjectUtil.hasEmpty(cacheName, key)) {
return null;
}
try {
return getCache(cacheName).get(key, valueLoader);
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* 设置缓存
*
* @param cacheName 缓存名
* @param keyPrefix 缓存键前缀
* @param key 缓存键值
* @param value 缓存值
*/
public static void put(String cacheName, String keyPrefix, Object key, @Nullable Object value) {
getCache(cacheName).put(keyPrefix.concat(String.valueOf(key)), value);
}
/**
* 清除缓存
*
* @param cacheName 缓存名
* @param keyPrefix 缓存键前缀
* @param key 缓存键值
*/
public static void evict(String cacheName, String keyPrefix, Object key) {
if (ObjectUtil.hasEmpty(cacheName, keyPrefix, key)) {
return;
}
evict(cacheName, keyPrefix.concat(String.valueOf(key)));
}
/**
* 清除缓存
*
* @param cacheName 缓存名
* @param key 缓存键前缀
*/
public static void evict(String cacheName, String key) {
if (ObjectUtil.hasEmpty(cacheName, key)) {
return;
}
getCache(cacheName).evict(key);
}
/**
* 清空缓存
*
* @param cacheName 缓存名
*/
public static void clear(String cacheName) {
if (ObjectUtil.isEmpty(cacheName)) {
return;
}
getCache(cacheName).clear();
}
public static List<String> getKeyList(String cacheName) {
if(ObjectUtil.isEmpty(cacheName)) return new ArrayList();
Cache cache = getCache(cacheName);
if(cache == null) return new ArrayList();
List<String> keyList = new ArrayList();
EhCacheCache obj = (EhCacheCache) cache;
obj.getNativeCache().getKeys().stream().forEach(key -> {
keyList.add(key.toString());
});
return keyList;
}
}

View File

@ -0,0 +1,84 @@
package com.ydool.common.utils;
import cn.hutool.core.util.StrUtil;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
/**
* Created with IntelliJ IDEA.
* User: liuj
* Date: 2020/11/18
* Time: 13:27
* Description: No Description
*/
public class CodecUtils {
private static Cipher encryptCipher; // 加密cipher
private static Cipher decryptChipher; // 解密chipher
private static final String ENCODING = "UTF-8";
public static final String KEY = "ydool123ydool123";
static {
try {
encryptCipher = Cipher.getInstance("AES");
decryptChipher = Cipher.getInstance("AES");
encryptCipher.init(Cipher.ENCRYPT_MODE, generateAESKey(KEY, ENCODING));
decryptChipher.init(Cipher.DECRYPT_MODE, generateAESKey(KEY, ENCODING));
} catch (Exception e) {
e.printStackTrace();
}
}
public static SecretKeySpec generateAESKey(final String key, final String encoding) {
try {
byte[] raw = key.getBytes(encoding);
return new SecretKeySpec(raw, "AES");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
/**
* 加密算法
*
* @param encryptString
* @return
*/
public static String encrypt(String encryptString) {
try {
if (StrUtil.isBlank(encryptString)) return "";
return new BASE64Encoder().encode(encryptCipher.doFinal(encryptString.getBytes(ENCODING)));
} catch (BadPaddingException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
}
}
/**
* 解密算法
*
* @param decryptString
* @return
*/
public static String decrypt(String decryptString) {
if (StrUtil.isBlank(decryptString)) return "";
try {
byte[] encryptedByte = new BASE64Decoder().decodeBuffer(decryptString);
return new String(decryptChipher.doFinal(encryptedByte));
} catch (Exception e) {
e.printStackTrace();
return decryptString;
}
}
}

View File

@ -0,0 +1,80 @@
package com.ydool.common.utils;
import cn.hutool.core.util.StrUtil;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.common.exception.ResultException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.function.Predicate;
@Slf4j
public class HttpServletUtil {
private static final String[] IP_HEADER_NAMES = new String[]{
"x-forwarded-for",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_CLIENT_IP",
"HTTP_X_FORWARDED_FOR"
};
private static final Predicate<String> IP_PREDICATE = (ip) -> StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip);
public static String getRemoteAddress() {
return getRemoteAddress(getRequest());
}
public static String getRemoteAddress(HttpServletRequest request) {
if (request == null) {
return "unknown";
}
String ip = null;
for (String ipHeader : IP_HEADER_NAMES) {
ip = request.getHeader(ipHeader);
if (!IP_PREDICATE.test(ip)) {
break;
}
}
if (IP_PREDICATE.test(ip)) {
ip = request.getRemoteAddr();
}
return StrUtil.isBlank(ip) ? null : StrUtil.splitTrim(ip, ",").get(0);
}
/**
* 获取当前请求的request对象
*
* @author fengshuonan
* @date 2020/10/15 17:48
*/
public static HttpServletRequest getRequest() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
throw new ResultException(AjaxResult.fail("获取不到http context请确认当前请求是http请求"));
} else {
return requestAttributes.getRequest();
}
}
/**
* 获取当前请求的response对象
*
* @author fengshuonan
* @date 2020/10/15 17:48
*/
public static HttpServletResponse getResponse() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
throw new ResultException(AjaxResult.fail("获取不到http context请确认当前请求是http请求"));
} else {
return requestAttributes.getResponse();
}
}
}

View File

@ -0,0 +1,46 @@
package com.ydool.common.utils;
import org.springframework.util.DigestUtils;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.Key;
import java.util.regex.Pattern;
public class PasswordUtil {
public static Boolean valid(String password) {
String regexp = "^.*(?=.*\\d)(?=.*[A-Za-z])(?=.*[!@#$%^&*?_]).{6,}$";
return Pattern.matches(regexp, password);
}
public static String password(String salt, String src){
String firstKey = DigestUtils.md5DigestAsHex(salt.getBytes()).substring(0, 8).toUpperCase();
byte[] bs = firstKey.getBytes();
byte[] inputArray = src.getBytes();
try {
DESKeySpec keySpec = new DESKeySpec(bs);
IvParameterSpec iv = new IvParameterSpec(bs);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");// 获得密钥工厂
Key key = keyFactory.generateSecret(keySpec);
Cipher enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");// 得到加密对象Cipher
enCipher.init(Cipher.ENCRYPT_MODE, key, iv);// 设置工作模式为加密模式给出密钥和向量
byte[] pasByte = enCipher.doFinal(inputArray);
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < pasByte.length; i++) {
String plainText = Integer.toHexString(0xff & pasByte[i]);
if (plainText.length() < 2) plainText = "0" + plainText;
hexString.append(plainText);
}
return hexString.toString().toUpperCase();
}catch (Exception e) {
e.printStackTrace();
}
return "";
}
}

View File

@ -0,0 +1,112 @@
package com.ydool.common.utils;
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* Java RSA 加密工具类
*/
public class RsaUtil {
/**
* 密钥长度 于原文长度对应 以及越长速度越慢
*/
private static final int KEY_SIZE = 1024;
/**
* 用于封装随机产生的公钥与私钥
*/
private static final Map<Integer, String> KEY_MAP = new HashMap<>();
/**
* 随机生成密钥对
*/
public static void genKeyPair() throws NoSuchAlgorithmException {
// KeyPairGenerator类用于生成公钥和私钥对基于RSA算法生成对象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器
keyPairGen.initialize(KEY_SIZE, new SecureRandom());
// 生成一个密钥对保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
// 得到私钥字符串
String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
// 将公钥和私钥保存到Map
// 0表示公钥
KEY_MAP.put(0, publicKeyString);
// 1表示私钥
KEY_MAP.put(1, privateKeyString);
}
/**
* RSA公钥加密
*
* @param str 加密字符串
* @param publicKey 公钥
* @return 密文
* @throws Exception 加密过程中的异常信息
*/
public static String encrypt(String str, String publicKey) throws Exception {
// base64编码的公钥
byte[] decoded = Base64.getDecoder().decode(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
// RSA加密后面这个更安全但是SonarQube始终report安全漏洞"RSA/ECB/PKCS1Padding"
// 而浏览器自带的Javascript加密功能目前safari不支持而且用的人也不太多所以暂时都不考虑了
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
}
/**
* RSA私钥解密
*
* @param str 加密字符串
* @param privateKey 私钥
* @return 明文
* @throws Exception 解密过程中的异常信息
*/
public static String decrypt(String str, String privateKey) throws Exception {
// 64位解码加密后的字符串
byte[] inputByte = Base64.getDecoder().decode(str);
// base64编码的私钥
byte[] decoded = Base64.getDecoder().decode(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
// RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
return new String(cipher.doFinal(inputByte));
}
public static void main(String[] args) throws Exception {
long temp = System.currentTimeMillis();
// 生成公钥和私钥
genKeyPair();
// 加密字符串
System.out.println("公钥:" + KEY_MAP.get(0));
System.out.println("私钥:" + KEY_MAP.get(1));
System.out.println("生成密钥消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "");
System.out.println("生成后的公钥前端使用!");
System.out.println("生成后的私钥后台使用!");
String message = "RSA测试ABCD~!@#$";
System.out.println("原文:" + message);
temp = System.currentTimeMillis();
String messageEn = encrypt(message, KEY_MAP.get(0));
System.out.println("密文:" + messageEn);
System.out.println("加密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "");
temp = System.currentTimeMillis();
String messageDe = decrypt(messageEn, KEY_MAP.get(1));
System.out.println("解密:" + messageDe);
System.out.println("解密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "");
}
}

View File

@ -0,0 +1,115 @@
package com.ydool.common.utils;
import cn.hutool.core.util.StrUtil;
import com.ydool.common.data.dto.OptionResult;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class TreeMapUtil {
private String ID = "id";
private String PID = "pid";
public TreeMapUtil() { }
public TreeMapUtil(String ID, String PID) {
this.ID = ID;
this.PID = PID;
}
public void sort(List<Map<String, Object>> tlist) {
sort(tlist, null);
}
public void sort(List<Map<String, Object>> tlist, String parentId) {
if (tlist == null)
return;
List newList = new ArrayList();
sort(tlist, newList, parentId, 0);
tlist.clear();
tlist.addAll(newList);
}
public void sort(List<Map<String, Object>> tlist, List<Map<String, Object>> newlist, String pid, int layer) {
for (Map model : tlist) {
if (StrUtil.isEmpty(pid)) {
newlist.add(model);
sort(tlist, newlist, model.get(ID).toString(), 0);
} else {
if (model.get(PID) != null && pid.equals(model.get(PID).toString())) {
newlist.add(model);
sort(tlist, newlist, model.get(ID).toString(), layer + 1);
}
}
}
}
public void tree(List<Map<String, Object>> tlist) {
if (tlist == null)
return;
List newList = new ArrayList();
tree(tlist, newList, null);
tlist.clear();
tlist.addAll(newList);
}
public void removeTreeBranch(List<Map<String, Object>> treelist, String branchId) {
List<Map<String, Object>> removeModels = new ArrayList<>();
findModelsInBranch(treelist, removeModels, branchId);
if (removeModels.size() > 0) {
for (Map<String, Object> model : removeModels) {
treelist.remove(model);
}
}
}
public void findModelsInBranch(List<Map<String, Object>> treelist, List<Map<String, Object>> removeModels, String branchId) {
for (int i = 0; i < treelist.size(); i++) {
Map<String, Object> model = treelist.get(i);
if (model.get(ID).toString().equals(branchId)) {
removeModels.add(model);
}
if (model.get(PID) != null && branchId.compareTo(model.get(PID).toString()) == 0) {
findModelsInBranch(treelist, removeModels, model.get(PID).toString());
}
}
}
public void tree(List<Map<String, Object>> tlist, List<Map<String, Object>> newlist, Map<String, Object> parent) {
for (Map<String, Object> model : tlist) {
if (parent == null) {
if (model.get(PID) != null && "0".equals(model.get(PID).toString())) {
newlist.add(model);
tree(tlist, newlist, model);
}
} else {
if (parent.get(ID) != null && model.get(PID) != null && parent.get(ID).toString().equals(model.get(PID).toString())) {
List children = parent.containsKey("children") ? (ArrayList) parent.get("children") : new ArrayList();
children.add(model);
parent.put("children", children);
tree(tlist, null, model);
}
}
}
}
public List<OptionResult> toOptionResult(String named, List<Map<String, Object>> tlist) {
List<OptionResult> optionResultList = new ArrayList<>();
for(Map<String, Object> recode: tlist) {
OptionResult optionResult = new OptionResult(recode.get(named).toString(), recode.get(ID).toString());
if(recode.containsKey("children")) {
optionResult.setChildren(toOptionResult(named, (List) recode.get("children")));
}
optionResultList.add(optionResult);
}
return optionResultList;
}
}

View File

@ -0,0 +1,120 @@
package com.ydool.common.utils;
import cn.hutool.core.util.StrUtil;
import com.ydool.common.base.TreeEntity;
import com.ydool.common.data.dto.OptionResult;
import java.util.ArrayList;
import java.util.List;
public class TreeSorterUtil {
public static <M extends TreeEntity> void sort(List<M> tlist) {
sort(tlist, null);
}
public static <M extends TreeEntity> void sort(List<M> tlist, String parentId) {
if (tlist == null)
return;
List<M> newList = new ArrayList<M>();
sort(tlist, newList, parentId, 0);
tlist.clear();
tlist.addAll(newList);
}
public static <M extends TreeEntity> void sort(List<M> tlist, List<M> newlist, String pid, int layer) {
for (M model : tlist) {
if (StrUtil.isEmpty(pid)) {
model.setTreeLevel(0);// 为顶层分类
newlist.add(model);
sort(tlist, newlist, model.getId(), 0);
} else {
if (model.getPid() != null && pid.equals(model.getPid())) {
model.setTreeLevel(layer + 1);
newlist.add(model);
sort(tlist, newlist, model.getId(), layer + 1);
}
}
}
}
public static <M extends TreeEntity> void tree(List<M> tlist) {
if (tlist == null)
return;
List<M> newList = new ArrayList<M>();
tree(tlist, newList, null);
tlist.clear();
tlist.addAll(newList);
}
public static <M extends TreeEntity> void removeTreeBranch(List<M> treelist, String branchId) {
List<TreeEntity> removeModels = new ArrayList<>();
findModelsInBranch(treelist, removeModels, branchId);
if (removeModels.size() > 0) {
for (TreeEntity model : removeModels) {
treelist.remove(model);
}
}
}
public static <M extends TreeEntity> void findModelsInBranch(List<M> treelist, List<TreeEntity> removeModels, String branchId) {
for (int i = 0; i < treelist.size(); i++) {
TreeEntity model = treelist.get(i);
if (model.getId().equals(branchId)) {
removeModels.add(model);
}
if (model.getPid() != null && branchId.compareTo(model.getPid()) == 0) {
findModelsInBranch(treelist, removeModels, model.getId());
}
}
}
public static <M extends TreeEntity> void tree(List<M> tlist, List<M> newlist, M parent) {
for (M model : tlist) {
if (parent == null) {
if (StrUtil.isEmpty(model.getPid()) || "0".equals(model.getPid())) {
newlist.add(model);
tree(tlist, newlist, model);
}
} else {
if (parent.getId() != null && model.getPid() != null && parent.getId().equals(model.getPid())) {
parent.addChild(model);
tree(tlist, null, model);
}
}
}
}
public static <M extends TreeEntity> List<OptionResult> optionTree(List<M> tlist) {
if (tlist == null) return new ArrayList<>();
tree(tlist);
return toOptionList(tlist);
}
public static <M extends TreeEntity> List<OptionResult> toOptionList(List<M> tlist) {
List<OptionResult> optionResultList = new ArrayList<>();
for (M model : tlist) {
OptionResult optionResult = new OptionResult(model.getNamed(), model.getId());
optionResult.setChildren(getOptionResultChildren(model));
optionResultList.add(optionResult);
}
return optionResultList;
}
public static <M extends TreeEntity> List<OptionResult> getOptionResultChildren(M parent) {
List<OptionResult> optionResultList = new ArrayList<>();
if(parent.getChildren() == null) return null;
for(Object obj : parent.getChildren()) {
M model = (M) obj;
OptionResult optionResult = new OptionResult(model.getNamed(), model.getId());
optionResult.setChildren(getOptionResultChildren(model));
optionResultList.add(optionResult);
}
return optionResultList;
}
}

View File

@ -0,0 +1,34 @@
package com.ydool.common.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Date;
public class UploadUtils {
public static String uploadFile(MultipartFile file) {
try {
String fileName = getFileUploadPath() + "/" + IdUtil.simpleUUID() + "." + FileUtil.extName(file.getOriginalFilename());
String fullFilePath = getWebRoot() + fileName;
FileUtil.writeFromStream(file.getInputStream(), fullFilePath);
return fileName;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public static String getFileUploadPath() {
String folder = DateUtil.format(new Date(), "yyyy/MM/dd");
return "/upload/" + folder;
}
public static String getWebRoot() {
return System.getProperty("user.dir");
}
}

View File

@ -0,0 +1,7 @@
package com.ydool.platform.db.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DruidConfig {
}

View File

@ -0,0 +1,44 @@
package com.ydool.platform.mybatis.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.MybatisMapWrapperFactory;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.ydool.**.mapper.**")
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false
* 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
/**
* 解决map 返回 驼峰字段
*
* @return
*/
@Bean
public ConfigurationCustomizer mybatisConfigurationCustomizer() {
return new ConfigurationCustomizer() {
@Override
public void customize(MybatisConfiguration configuration) {
configuration.setObjectWrapperFactory(new MybatisMapWrapperFactory());
configuration.setUseGeneratedShortKey(false);
}
};
}
}

View File

@ -0,0 +1,39 @@
package com.ydool.platform.mybatis.handler;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
@Slf4j
public class CustomMetaObjectHandler implements MetaObjectHandler {
/**
* 插入时的填充策略
*
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createdId", StpUtil.getLoginIdAsString(), metaObject);
this.setFieldValByName("createdAt", LocalDateTime.now(), metaObject);
this.setFieldValByName("updatedId", StpUtil.getLoginIdAsString(), metaObject);
this.setFieldValByName("updatedAt", LocalDateTime.now(), metaObject);
}
/**
* 更新时的填充策略
*
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updatedId", StpUtil.getLoginIdAsString(), metaObject);
this.setFieldValByName("updatedAt", LocalDateTime.now(), metaObject);
}
}

View File

@ -0,0 +1,43 @@
package com.ydool.platform.saToken.config;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import com.ydool.common.constant.UrlConstant;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SaTokenConfig implements WebMvcConfigurer {
// 注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册 Sa-Token 拦截器校验规则为 StpUtil.checkLogin() 登录校验
registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
.addPathPatterns(UrlConstant.API + "/**")
.excludePathPatterns(UrlConstant.AUTH+"/login");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/upload/**").addResourceLocations("file:" + System.getProperty("user.dir") + "/upload/");
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.allowedHeaders("*")
.exposedHeaders("access-control-allow-headers",
"access-control-allow-methods",
"access-control-allow-origin",
"access-control-max-age",
"X-Frame-Options")
.maxAge(3600)
.allowCredentials(false);
}
}

View File

@ -0,0 +1,54 @@
package com.ydool.platform.swagger.config;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import springfox.documentation.service.Contact;
@Configuration
@EnableSwagger2WebMvc
public class SwaggerConfig {
/*引入Knife4j提供的扩展类*/
private final OpenApiExtensionResolver openApiExtensionResolver;
@Autowired
public SwaggerConfig(OpenApiExtensionResolver openApiExtensionResolver) {
this.openApiExtensionResolver = openApiExtensionResolver;
}
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
String groupName="2.X版本";
Docket docket=new Docket(DocumentationType.SWAGGER_2)
.host("http://www.ydool.com/")
.apiInfo(apiInfo())
.groupName(groupName)
.select()
.apis(RequestHandlerSelectors.basePackage("com.ydool.system.controller"))
.paths(PathSelectors.any())
.build()
//赋予插件体系
.extensions(openApiExtensionResolver.buildExtensions(groupName));
return docket;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("接口文档系统")
.description("接口文档系统")
.termsOfServiceUrl("http://www.ydool.com/")
.contact(new Contact("zhujingang", "http://www.ydool.com", "zhujg@ydool.com"))
.version("1.0")
.build();
}
}

View File

@ -0,0 +1,33 @@
package com.ydool.system.controller;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.ydool.common.constant.UrlConstant;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.request.AuthRequest;
import com.ydool.system.service.IAuthService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(UrlConstant.AUTH)
@Api(tags = "登录", value = "登录")
@ApiSupport(order = 1)
public class AuthController {
@Autowired
private IAuthService authService;
@PostMapping("login")
@ApiOperation("登录")
@ApiOperationSupport(order = 1)
public AjaxResult login(@RequestBody @Validated AuthRequest authRequest) {
return authService.login(authRequest.getUserName(), authRequest.getPassword());
}
}

View File

@ -0,0 +1,155 @@
package com.ydool.system.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import com.ydool.common.base.BaseController;
import com.ydool.common.constant.UrlConstant;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.entity.Config;
import com.ydool.system.request.ConfigRequest;
import com.ydool.system.request.IdsRequest;
import com.ydool.system.service.IConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(UrlConstant.CONFIG)
@Api(tags = "参数", value = "参数")
@ApiSupport(order = 3)
public class ConfigController extends BaseController {
@Autowired
private IConfigService configService;
/**
* 参数列表
*
* @param value
* @param column
* @param orderBy
* @return
*/
@GetMapping(value = "list")
@ApiOperation(value = "参数列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "current", value = "当前页", dataType = "Integer"),
@ApiImplicitParam(name = "size", value = "每页条数", dataType = "Integer"),
@ApiImplicitParam(name = "value", value = "搜索框中的内容(只支持字符串类型)"),
@ApiImplicitParam(name = "column", value = "排序字段 字段名"),
@ApiImplicitParam(name = "orderBy", value = "排序顺序 降序desc升序asc"),
})
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = Config.class)
}),
order = 1
)
public AjaxResult configList(String value,
String column,
String orderBy) {
return configService.configList(getPage(), value, column, orderBy);
}
/**
* 参数详情
*
* @param id 参数Id
* @return
*/
@GetMapping(value = "detail")
@ApiOperation(value = "参数详情")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = Config.class)
}), order = 2
)
@ApiImplicitParam(name = "id", value = "参数Id")
public AjaxResult configDetail(String id) {
return configService.configDetail(id);
}
/**
* 保存参数
*
* @param configRequest
* @return
*/
@PostMapping(value = "save")
@ApiOperation(value = "保存参数")
@ApiOperationSupport(order = 3)
public AjaxResult saveConfig(@RequestBody @Validated ConfigRequest configRequest) {
return configService.saveConfig(configRequest);
}
/**
* 编辑参数
*
* @param id
* @param configRequest
* @return
*/
@PutMapping(value = "edit")
@ApiOperation(value = "编辑参数")
@ApiImplicitParam(name = "id", value = "参数Id")
@ApiOperationSupport(order = 4)
public AjaxResult editConfig(String id, @RequestBody @Validated ConfigRequest configRequest) {
return configService.editConfig(id, configRequest);
}
/**
* 单个删除参数
*
* @param id 参数Id
* @return
*/
@DeleteMapping(value = "remove")
@ApiOperation(value = "删除参数")
@ApiImplicitParam(name = "id", value = "参数Id")
@ApiOperationSupport(order = 5)
public AjaxResult removeConfig(String id) {
return configService.removeConfig(id);
}
/**
* 批量删除参数
*
* @param ids 参数Id集合
* @return
*/
@PostMapping(value = "removeBatch")
@ApiOperation(value = "批量删除参数")
@ApiOperationSupport(order = 6)
public AjaxResult removeConfigs(@RequestBody @Validated IdsRequest ids) {
return configService.removeConfigs(ids);
}
/**
* 根据参数键名获取参数
*
* @param paramKey
* @return
*/
@GetMapping(value = "getConfigByParamKey")
@ApiOperation(value = "根据参数键名获取参数")
@ApiImplicitParam(name = "paramKey", value = "参数键名")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = Config.class)
}), order = 7
)
public AjaxResult getConfigByParamKey(String paramKey) {
return configService.getConfigByParamKey(paramKey);
}
}

View File

@ -0,0 +1,136 @@
package com.ydool.system.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import com.ydool.common.base.BaseController;
import com.ydool.common.constant.UrlConstant;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.common.data.dto.OptionResult;
import com.ydool.system.entity.Dept;
import com.ydool.system.request.DeptRequest;
import com.ydool.system.service.IDeptService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(UrlConstant.DEPT)
@Api(tags = "部门", value = "部门")
@ApiSupport(order = 4)
public class DeptController extends BaseController {
@Autowired
private IDeptService deptService;
/**
* 部门列表
*
* @param value
* @param column
* @param orderBy
* @return
*/
@GetMapping(value = "list")
@ApiOperation(value = "部门列表(树形结构不带分页功能)")
@ApiImplicitParams({
@ApiImplicitParam(name = "value", value = "搜索框中的内容(只支持字符串类型)"),
@ApiImplicitParam(name = "column", value = "排序字段 字段名"),
@ApiImplicitParam(name = "orderBy", value = "排序顺序 降序desc升序asc"),
})
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = Dept.class)
}),order = 1
)
public AjaxResult deptList(String value,
String column,
String orderBy) {
return deptService.deptList(value, column, orderBy);
}
/**
* 部门详情
*
* @param id 部门ID
* @return
*/
@GetMapping(value = "detail")
@ApiOperation(value = "部门详情")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = Dept.class)
}),order = 2
)
@ApiImplicitParam(name = "id", value = "部门Id")
public AjaxResult deptDetail(String id) {
return AjaxResult.ok().data(deptService.deptDetail(id));
}
/**
* 保存部门
*
* @param deptRequest
* @return
*/
@PostMapping(value = "save")
@ApiOperation(value = "保存部门")
@ApiOperationSupport(order = 3)
public AjaxResult saveDept(@Validated @RequestBody DeptRequest deptRequest) {
return deptService.saveDept(deptRequest);
}
/**
* 编辑部门
*
* @param id
* @param deptRequest
* @return
*/
@PutMapping(value = "edit")
@ApiOperation(value = "编辑部门")
@ApiImplicitParam(name = "id", value = "部门Id")
@ApiOperationSupport(order = 4)
public AjaxResult editDept(String id, @Validated @RequestBody DeptRequest deptRequest) {
return deptService.editDept(id, deptRequest);
}
/**
* 删除部门
*
* @param id
* @return
*/
@DeleteMapping(value = "remove")
@ApiOperation(value = "删除部门")
@ApiImplicitParam(name = "id", value = "部门Id")
@ApiOperationSupport(order = 5)
public AjaxResult removeDept(String id) {
return deptService.removeDept(id);
}
/**
* 部门树
*
* @return
*/
@GetMapping("tree")
@ApiOperation("部门树")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = OptionResult.class)
}),order = 6
)
public AjaxResult deptTree() {
return AjaxResult.ok().data(deptService.deptTree());
}
}

View File

@ -0,0 +1,137 @@
package com.ydool.system.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import com.ydool.common.base.BaseController;
import com.ydool.common.constant.UrlConstant;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.entity.Config;
import com.ydool.system.entity.Role;
import com.ydool.system.request.IdsRequest;
import com.ydool.system.request.RoleRequest;
import com.ydool.system.service.IRoleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(UrlConstant.ROLE)
@Api(tags = "角色", value = "角色")
@ApiSupport(order = 5)
public class RoleController extends BaseController {
@Autowired
private IRoleService roleService;
/**
* 角色列表
*
* @param value
* @param column
* @param orderBy
* @param status
* @return
*/
@GetMapping(value = "list")
@ApiOperation(value = "角色列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "current", value = "当前页", dataType = "Integer"),
@ApiImplicitParam(name = "size", value = "每页条数", dataType = "Integer"),
@ApiImplicitParam(name = "value", value = "搜索框中的内容(只支持字符串类型)"),
@ApiImplicitParam(name = "column", value = "排序字段 字段名"),
@ApiImplicitParam(name = "orderBy", value = "排序顺序 降序desc升序asc"),
@ApiImplicitParam(name = "status", value = "启用状态", dataType = "Boolean"),
})
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = Config.class)
}),
order = 1
)
public AjaxResult roleList(String value,
String column,
String orderBy,
Boolean status
) {
return roleService.roleList(getPage(), value, column, orderBy, status);
}
/**
* 角色详情
*
* @param id 参数Id
* @return
*/
@GetMapping(value = "detail")
@ApiOperation(value = "角色详情")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = Role.class)
}), order = 2
)
@ApiImplicitParam(name = "id", value = "角色Id")
public AjaxResult roleDetail(String id) {
return roleService.roleDetail(id);
}
/**
* 保存角色
*
* @param roleRequest
* @return
*/
@PostMapping(value = "save")
@ApiOperation(value = "保存角色")
@ApiOperationSupport(order = 3)
public AjaxResult saveRole(@RequestBody @Validated RoleRequest roleRequest) {
return roleService.saveRole(roleRequest);
}
/**
* 编辑角色
*
* @param id
* @param roleRequest
* @return
*/
@PutMapping(value = "edit")
@ApiOperation(value = "编辑角色")
@ApiImplicitParam(name = "id", value = "角色Id")
@ApiOperationSupport(order = 4)
public AjaxResult editRole(String id, @RequestBody @Validated RoleRequest roleRequest) {
return roleService.editRole(id, roleRequest);
}
/**
* 单个删除角色
*
* @param id 参数Id
* @return
*/
@DeleteMapping(value = "remove")
@ApiOperation(value = "删除角色")
@ApiImplicitParam(name = "id", value = "角色Id")
@ApiOperationSupport(order = 5)
public AjaxResult removeRole(String id) {
return roleService.removeRole(id);
}
/**
* 批量删除角色
*
* @param ids 角色Id集合
* @return
*/
@PostMapping(value = "removeBatch")
@ApiOperation(value = "批量删除角色")
@ApiOperationSupport(order = 6)
public AjaxResult removeConfigs(@RequestBody @Validated IdsRequest ids) {
return roleService.removeRoles(ids);
}
}

View File

@ -0,0 +1,60 @@
package com.ydool.system.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Dict;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.ydool.common.constant.UrlConstant;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.common.utils.UploadUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
@RestController
@RequestMapping(value = UrlConstant.ATTACHMENT)
@Api(tags = "文件上传", value = "文件上传")
@ApiSupport(order = 2)
public class UploadController {
@PostMapping("/upload")
@ApiOperation(value = "单文件上传")
@ApiOperationSupport(order = 1)
public AjaxResult upload(@RequestParam(value = "file") MultipartFile file) {
//判断文件类型
String reg = ".+(.exe|.bat|.sh|.java|.php|.js|.py)$";
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
if (Pattern.matches(reg, file.getOriginalFilename())) {
return AjaxResult.fail("不能上传后缀为" + suffix + "的文件");
}
String path = UploadUtils.uploadFile(file);
Dict data = Dict.create().set("path", path).set("name", file.getOriginalFilename());
return AjaxResult.ok().data(data);
}
@PostMapping("/uploadList")
@ApiOperation(value = "多文件上传")
@ApiOperationSupport(order = 2)
public AjaxResult uploadList(@RequestParam(value = "files") MultipartFile[] files) {
List<Dict> list = new ArrayList<>();
for (MultipartFile file : files) {
String reg = ".+(.exe|.bat|.sh|.java|.php|.js|.py)$";
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
if (Pattern.matches(reg, file.getOriginalFilename())) {
return AjaxResult.fail("不能上传后缀为" + suffix + "的文件");
}
String path = UploadUtils.uploadFile(file);
list.add(Dict.create().set("path", path).set("name", file.getOriginalFilename()));
}
return CollectionUtil.isNotEmpty(list) ? AjaxResult.ok("data", list) : AjaxResult.fail().msg("上传失败!!!");
}
}

View File

@ -0,0 +1,41 @@
package com.ydool.system.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ydool.common.base.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 系统参数设置
* </p>
*
* @author ljq
* @since 2023-01-06
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("t_sys_config")
@ApiModel(value="Config对象", description="系统参数设置")
public class Config extends BaseEntity{
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "参数名称")
private String name;
@ApiModelProperty(value = "参数键名")
private String paramKey;
@ApiModelProperty(value = "参数键值")
private String paramValue;
@ApiModelProperty(value = "排序")
private Integer sortNo;
@ApiModelProperty(value = "备注")
private String remarks;
}

View File

@ -0,0 +1,39 @@
package com.ydool.system.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ydool.common.base.TreeEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* <p>
* 部门管理
* </p>
*
* @author ljq
* @since 2023-01-10
*/
@Data
@TableName("t_sys_dept")
@ApiModel(value="Dept对象", description="部门管理")
public class Dept extends TreeEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "部门编码")
private String code;
@ApiModelProperty(value = "部门名称")
private String name;
@ApiModelProperty(value = "排序")
private Integer sortNo;
@ApiModelProperty(value = "备注")
private String remarks;
@Override
public String getNamed() {
return this.name;
}
}

View File

@ -0,0 +1,48 @@
package com.ydool.system.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ydool.common.base.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 系统角色
* </p>
*
* @author ljq
* @since 2023-01-11
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("t_sys_role")
@ApiModel(value = "Role对象", description = "系统角色")
public class Role extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "角色编码")
private String code;
@ApiModelProperty(value = "角色名称")
private String name;
@JsonIgnore
@ApiModelProperty(value = "菜单")
private String menus;
@ApiModelProperty(value = "排序")
private Integer sortNo;
@ApiModelProperty(value = "启用状态")
private Boolean status;
@ApiModelProperty(value = "备注")
private String remarks;
}

View File

@ -0,0 +1,67 @@
package com.ydool.system.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ydool.common.base.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* <p>
* 系统账号表
* </p>
*
* @author ljq
* @since 2023-01-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("t_sys_user")
@ApiModel(value="User对象", description="系统账号表")
public class User extends BaseEntity{
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "登录账号")
private String loginName;
@ApiModelProperty(value = "用户昵称")
private String userName;
@ApiModelProperty(value = "手机号码")
private String phone;
@JsonIgnore
@ApiModelProperty(value = "密码")
private String password;
@JsonIgnore
@ApiModelProperty(value = "加密")
private String salt;
@ApiModelProperty(value = "帐号状态0正常 1停用")
private Boolean status;
@ApiModelProperty(value = "最后修改密码时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private LocalDateTime lastUpdatePwd;
@ApiModelProperty(value = "最后登陆IP")
private String loginIp;
@ApiModelProperty(value = "最后登陆时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private LocalDateTime loginDate;
@ApiModelProperty(value = "备注")
private String remarks;
}

View File

@ -0,0 +1,18 @@
package com.ydool.system.mapper;
import com.ydool.system.entity.Config;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 系统参数设置 Mapper 接口
* </p>
*
* @author ljq
* @since 2023-01-06
*/
@Mapper
public interface ConfigMapper extends MPJBaseMapper<Config> {
}

View File

@ -0,0 +1,18 @@
package com.ydool.system.mapper;
import com.ydool.system.entity.Dept;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 部门管理 Mapper 接口
* </p>
*
* @author ljq
* @since 2023-01-10
*/
@Mapper
public interface DeptMapper extends MPJBaseMapper<Dept> {
}

View File

@ -0,0 +1,18 @@
package com.ydool.system.mapper;
import com.ydool.system.entity.Role;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 系统角色 Mapper 接口
* </p>
*
* @author ljq
* @since 2023-01-11
*/
@Mapper
public interface RoleMapper extends MPJBaseMapper<Role> {
}

View File

@ -0,0 +1,18 @@
package com.ydool.system.mapper;
import com.ydool.system.entity.User;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 系统账号表 Mapper 接口
* </p>
*
* @author ljq
* @since 2023-01-05
*/
@Mapper
public interface UserMapper extends MPJBaseMapper<User> {
}

View File

@ -0,0 +1,19 @@
package com.ydool.system.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class AuthRequest {
@NotBlank(message = "请输入用户名")
@ApiModelProperty(value = "用户名", required = true)
private String userName;
@NotBlank(message = "请输入密码")
@ApiModelProperty(value = "密码", required = true)
private String password;
}

View File

@ -0,0 +1,28 @@
package com.ydool.system.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class ConfigRequest {
@ApiModelProperty(value = "参数名称")
@NotBlank(message = "参数名称不能为空")
private String name;
@ApiModelProperty(value = "参数键名")
@NotBlank(message = "参数键名不能为空")
private String paramKey;
@ApiModelProperty(value = "参数键值")
private String paramValue;
@ApiModelProperty(value = "排序")
@NotNull(message = "排序不能为空")
private Integer sortNo;
@ApiModelProperty(value = "备注")
private String remarks;
}

View File

@ -0,0 +1,30 @@
package com.ydool.system.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class DeptRequest {
@ApiModelProperty(value = "部门编码")
@NotBlank(message = "部门编码不能为空")
private String code;
@ApiModelProperty(value = "上级部门编码")
@NotBlank(message = "上级部门编码不能为空")
private String pid;
@ApiModelProperty(value = "部门名称")
@NotBlank(message = "部门名称不能为空")
private String name;
@ApiModelProperty(value = "排序")
@NotNull(message = "排序不能为空")
private Integer sortNo;
@ApiModelProperty(value = "备注")
private String remarks;
}

View File

@ -0,0 +1,13 @@
package com.ydool.system.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
public class IdsRequest {
@ApiModelProperty(value = "Id集合", required = true)
@NotNull(message = "请输入Id集合")
private String[] ids;
}

View File

@ -0,0 +1,29 @@
package com.ydool.system.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class RoleRequest {
@ApiModelProperty(value = "角色编码")
@NotBlank(message = "角色编码不能为空")
private String code;
@ApiModelProperty(value = "角色名称")
@NotBlank(message = "角色编码不能为空")
private String name;
@ApiModelProperty(value = "排序")
@NotNull(message = "排序不能为空")
private Integer sortNo;
@ApiModelProperty(value = "启用状态")
@NotNull(message = "启用状态不能为空")
private Boolean status;
@ApiModelProperty(value = "备注")
private String remarks;
}

View File

@ -0,0 +1,13 @@
package com.ydool.system.service;
import com.ydool.common.data.dto.AjaxResult;
public interface IAuthService {
/**
* 登录接口
* @param userName 用户名
* @param password 密码
* @return
*/
AjaxResult login(String userName, String password);
}

View File

@ -0,0 +1,75 @@
package com.ydool.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.request.ConfigRequest;
import com.ydool.system.request.IdsRequest;
/**
* <p>
* 系统参数设置 服务类
* </p>
*
* @author ljq
* @since 2023-01-06
*/
public interface IConfigService {
/**
* 删除参数
*
* @param id 参数Id
* @return
*/
AjaxResult removeConfig(String id);
/**
* 批量删除参数
*
* @param ids 参数Id集合
* @return
*/
AjaxResult removeConfigs(IdsRequest ids);
/**
* 参数详情
*
* @param id 参数Id
* @return
*/
AjaxResult configDetail(String id);
/**
* 保存参数
* @param configRequest
* @return
*/
AjaxResult saveConfig(ConfigRequest configRequest);
/**
* 编辑参数
* @param id
* @param configRequest
* @return
*/
AjaxResult editConfig(String id, ConfigRequest configRequest);
/**
* 参数列表
* @param page
* @param value
* @param column
* @param orderBy
* @return
*/
AjaxResult configList(Page page, String value, String column, String orderBy);
/**
* 根据参数键名获取参数
* @param paramKey
* @return
*/
AjaxResult getConfigByParamKey(String paramKey);
}

View File

@ -0,0 +1,67 @@
package com.ydool.system.service;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.request.DeptRequest;
/**
* <p>
* 部门管理 服务类
* </p>
*
* @author ljq
* @since 2023-01-10
*/
public interface IDeptService {
/**
* 删除部门
*
* @param id
* @return
*/
AjaxResult removeDept(String id);
/**
* 保存部门
*
* @param deptRequest
* @return
*/
AjaxResult saveDept(DeptRequest deptRequest);
/**
* 编辑部门
*
* @param id
* @param deptRequest
* @return
*/
AjaxResult editDept(String id, DeptRequest deptRequest);
/**
* 部门详情
*
* @param id
* @return
*/
AjaxResult deptDetail(String id);
/**
* 部门树
*
* @return
*/
AjaxResult deptTree();
/**
* 部门列表
*
* @param value
* @param column
* @param orderBy
* @return
*/
AjaxResult deptList(String value, String column, String orderBy);
}

View File

@ -0,0 +1,71 @@
package com.ydool.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.request.IdsRequest;
import com.ydool.system.request.RoleRequest;
/**
* <p>
* 系统角色 服务类
* </p>
*
* @author ljq
* @since 2023-01-11
*/
public interface IRoleService {
/**
* 保存角色
*
* @param roleRequest
* @return
*/
AjaxResult saveRole(RoleRequest roleRequest);
/**
* 编辑角色
*
* @param id
* @param roleRequest
* @return
*/
AjaxResult editRole(String id, RoleRequest roleRequest);
/**
* 删除角色
*
* @param id
* @return
*/
AjaxResult removeRole(String id);
/**
* 批量删除角色
* @param ids
* @return
*/
AjaxResult removeRoles(IdsRequest ids);
/**
* 角色详情
* @param id
* @return
*/
AjaxResult roleDetail(String id);
/**
* 角色列表
* @param page
* @param value
* @param column
* @param orderBy
* @param status
* @return
*/
AjaxResult roleList(Page page, String value, String column, String orderBy, Boolean status);
}

View File

@ -0,0 +1,14 @@
package com.ydool.system.service;
/**
* <p>
* 系统账号表 服务类
* </p>
*
* @author ljq
* @since 2023-01-05
*/
public interface IUserService {
}

View File

@ -0,0 +1,78 @@
package com.ydool.system.service.impl;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ydool.common.base.BaseService;
import com.ydool.common.constant.UrlConstant;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.common.utils.HttpServletUtil;
import com.ydool.common.utils.PasswordUtil;
import com.ydool.common.utils.RsaUtil;
import com.ydool.system.entity.User;
import com.ydool.system.mapper.UserMapper;
import com.ydool.system.service.IAuthService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
@Service
public class AuthServiceImpl extends BaseService<UserMapper, User> implements IAuthService {
@Value("${sa-token.token-prefix}")
private String tokenPrefix;
/**
* 登录接口
*
* @param userName 用户名
* @param password 密码
* @return
*/
@SneakyThrows
@Override
public AjaxResult login(String userName, String password) {
//用户名密码按照UTF-8编码解密
userName = URLDecoder.decode(userName, StandardCharsets.UTF_8.name());
password = URLDecoder.decode(password, StandardCharsets.UTF_8.name());
//按照Rsa解密用户名密码
// userName = RsaUtil.decrypt(userName, UrlConstant.APP_PRIVATE_KEY);
// password = RsaUtil.decrypt(password, UrlConstant.APP_PRIVATE_KEY);
//根据用户名查询账号是否存在
User loginUser = getOne(new QueryWrapper<User>().lambda().eq(User::getLoginName, userName));
if (ObjectUtil.isNull(loginUser)) return AjaxResult.fail("账号或者密码错误");
//加密密码
String loginPassword = PasswordUtil.password(loginUser.getSalt(), password);
//与数据库的密码进行匹配
if (!loginPassword.equals(loginUser.getPassword())) return AjaxResult.fail("账号或者密码错误");
//判断账号是否停用
if (loginUser.getStatus()) return AjaxResult.fail("当前账号已被停用,请联系管理员");
loginUser.setLoginDate(LocalDateTime.now());
loginUser.setLoginIp(HttpServletUtil.getRemoteAddress());
// 第1步先登录上
StpUtil.login(loginUser.getId());
boolean flag = updateById(loginUser);
if (flag) {
// 第2步获取 Token 相关参数
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
Dict result = Dict.create();
result.set("tokenName", tokenInfo.getTokenName());
result.set("tokenPrefix",tokenPrefix);
result.set("tokenValue", tokenInfo.getTokenValue());
result.set("name", loginUser.getUserName());
return AjaxResult.ok().data(result);
}else {
StpUtil.logout();
}
return AjaxResult.fail("登陆失败");
}
}

View File

@ -0,0 +1,179 @@
package com.ydool.system.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ydool.common.base.BaseService;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.entity.Config;
import com.ydool.system.mapper.ConfigMapper;
import com.ydool.system.request.ConfigRequest;
import com.ydool.system.request.IdsRequest;
import com.ydool.system.service.IConfigService;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 系统参数设置 服务类
* </p>
*
* @author ljq
* @since 2023-01-06
*/
@Service
public class ConfigServiceImpl extends BaseService<ConfigMapper, Config> implements IConfigService {
/**
* 删除参数
*
* @param id 参数Id
* @return
*/
@Override
public AjaxResult removeConfig(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
Config config = getById(id);
if (ObjectUtil.isNull(config)) return AjaxResult.fail("该参数不存在");
return removeById(id) ? AjaxResult.ok().msg("删除成功") : AjaxResult.fail("删除失败");
}
/**
* 批量删除参数
*
* @param ids 参数Id集合
* @return
*/
@Override
public AjaxResult removeConfigs(IdsRequest ids) {
String[] idList = ids.getIds();
if (ArrayUtil.isEmpty(idList)) return AjaxResult.fail("参数Id集合不能为空");
List<Config> configList = listByIds(Arrays.asList(idList));
if (CollUtil.isEmpty(configList)) return AjaxResult.fail("该参数集合全部不存在");
return removeByIds(Arrays.asList(idList)) ? AjaxResult.ok().msg("批量删除成功") : AjaxResult.fail("批量删除失败");
}
/**
* 参数详情
*
* @param id 参数Id
* @return
*/
@Override
public AjaxResult configDetail(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
Config config = getById(id);
if (ObjectUtil.isNull(config)) return AjaxResult.fail("该参数不存在");
return AjaxResult.ok().data(config);
}
/**
* 保存参数
*
* @param configRequest
* @return
*/
@Override
public AjaxResult saveConfig(ConfigRequest configRequest) {
String message = checkConfig("", configRequest);
if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message);
Config config = BeanUtil.copyProperties(configRequest, Config.class);
return save(config) ? AjaxResult.ok().msg("保存成功") : AjaxResult.fail("保存失败");
}
/**
* 编辑参数
*
* @param id
* @param configRequest
* @return
*/
@Override
public AjaxResult editConfig(String id, ConfigRequest configRequest) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
Config config = getById(id);
if (ObjectUtil.isNull(config)) return AjaxResult.fail("该参数不存在");
String message = checkConfig(id, configRequest);
if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message);
BeanUtil.copyProperties(configRequest, config);
return updateById(config) ? AjaxResult.ok().msg("编辑成功") : AjaxResult.fail("编辑失败");
}
/**
* 参数列表
*
* @param page
* @param value
* @param column
* @param orderBy
* @return
*/
@Override
public AjaxResult configList(Page page, String value, String column, String orderBy) {
QueryWrapper<Config> qw = new QueryWrapper<Config>();
if (StrUtil.isNotBlank(value)) {
qw.lambda().like(Config::getName, value)
.or().like(Config::getRemarks, value)
.or().like(Config::getParamKey, value)
.or().like(Config::getParamValue, value);
}
if ("desc".equals(orderBy) && StrUtil.isNotBlank(column)) {
qw.orderByDesc(StrUtil.toUnderlineCase(column));
}
if ("asc".equals(orderBy) && StrUtil.isNotBlank(column)) {
qw.orderByAsc(StrUtil.toUnderlineCase(column));
}
Page<Config> pageList = page(page, qw);
return AjaxResult.ok().data(pageList);
}
/**
* 根据参数键名获取参数
*
* @param paramKey
* @return
*/
@Override
public AjaxResult getConfigByParamKey(String paramKey) {
if (StrUtil.isBlank(paramKey)) return AjaxResult.fail("参数键名不能为空");
Config config = getOne(new QueryWrapper<Config>().lambda()
.eq(Config::getParamKey, paramKey)
.last("limit 1")
);
if (ObjectUtil.isNull(config)) return AjaxResult.fail("参数键名不存在");
return AjaxResult.ok().data(config);
}
/**
* 校验参数
*
* @param id
* @param configRequest
* @return
*/
private String checkConfig(String id, ConfigRequest configRequest) {
Config config = getOne(new QueryWrapper<Config>().lambda()
.eq(Config::getParamKey, configRequest.getParamKey())
.ne(StrUtil.isNotBlank(id), Config::getId, id)
.last("limit 1")
);
if (ObjectUtil.isNotNull(config)) return "参数键名不能重复";
return null;
}
}

View File

@ -0,0 +1,209 @@
package com.ydool.system.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ydool.common.base.BaseTreeService;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.common.data.dto.OptionResult;
import com.ydool.common.utils.TreeMapUtil;
import com.ydool.common.utils.TreeSorterUtil;
import com.ydool.system.entity.Dept;
import com.ydool.system.mapper.DeptMapper;
import com.ydool.system.request.DeptRequest;
import com.ydool.system.service.IDeptService;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.*;
/**
* <p>
* 部门管理 服务类
* </p>
*
* @author ljq
* @since 2023-01-10
*/
@Service
public class DeptServiceImpl extends BaseTreeService<DeptMapper, Dept> implements IDeptService {
/**
* 删除部门
*
* @param id
* @return
*/
@Override
public AjaxResult removeDept(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
Dept dept = getById(id);
if (ObjectUtil.isNull(dept)) return AjaxResult.fail("该部门不存在");
int count = count(new QueryWrapper<Dept>().lambda().eq(Dept::getPid, dept.getId()));
if (count > 0) return AjaxResult.fail("该部门下还有子节点不允许删除");
return removeById(id) ? AjaxResult.ok().msg("删除成功") : AjaxResult.fail("删除失败");
}
/**
* 保存部门
*
* @param deptRequest
* @return
*/
@Override
public AjaxResult saveDept(DeptRequest deptRequest) {
String message = checkDept("", deptRequest);
if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message);
Dept dept = BeanUtil.copyProperties(deptRequest, Dept.class);
boolean flag = save(dept);
return flag ? AjaxResult.ok().msg("保存成功") : AjaxResult.fail("保存失败");
}
/**
* 编辑部门
*
* @param id
* @param deptRequest
* @return
*/
@Override
public AjaxResult editDept(String id, DeptRequest deptRequest) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
Dept dept = dept = getById(id);
if (ObjectUtil.isNull(dept)) return AjaxResult.fail("该部门不存在");
String message = checkDept(id, deptRequest);
if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message);
BeanUtil.copyProperties(deptRequest, dept);
boolean flag = updateById(dept);
return flag ? AjaxResult.ok().msg("编辑成功") : AjaxResult.fail("编辑失败");
}
/**
* 部门详情
*
* @param id
* @return
*/
@Override
public AjaxResult deptDetail(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
Dept dept = dept = getById(id);
if (ObjectUtil.isNull(dept)) return AjaxResult.fail("该部门不存在");
return AjaxResult.ok().data(dept);
}
/**
* 部门树
*
* @return
*/
@Override
public AjaxResult deptTree() {
List<Dept> deptList = treeList();
List<OptionResult> optionResultList = TreeSorterUtil.optionTree(deptList);
return AjaxResult.ok().data(optionResultList);
}
/**
* 部门列表
*
* @param value
* @param column
* @param orderBy
* @return
*/
@Override
public AjaxResult deptList(String value, String column, String orderBy) {
//获取符合条件的部门
QueryWrapper<Dept> qw = new QueryWrapper<Dept>();
if (StrUtil.isNotBlank(value)) {
qw.lambda().like(Dept::getName, value)
.or().like(Dept::getRemarks, value)
.or().like(Dept::getCode, value);
}
if ("desc".equals(orderBy) && StrUtil.isNotBlank(column)) {
qw.orderByDesc(StrUtil.toUnderlineCase(column));
}
if ("asc".equals(orderBy) && StrUtil.isNotBlank(column)) {
qw.orderByAsc(StrUtil.toUnderlineCase(column));
}
List<Map<String, Object>> deptMap = listMaps(qw);
//树结构下搜索,如果子级符合条件,就把父级也放进去,确保其能显示
Iterator<Map<String, Object>> iterator = deptMap.iterator();
List<Map<String, Object>> parentList = new ArrayList<>();
QueryWrapper<Dept> wrapper = new QueryWrapper<Dept>();
if ("desc".equals(orderBy) && StrUtil.isNotBlank(column)) {
wrapper.orderByDesc(StrUtil.toUnderlineCase(column));
}
if ("asc".equals(orderBy) && StrUtil.isNotBlank(column)) {
wrapper.orderByAsc(StrUtil.toUnderlineCase(column));
}
//获取所有部门
List<Map<String, Object>> allDeptMap = listMaps(wrapper);
Map<String, Object> allMap = new HashMap<String, Object>();
allDeptMap.forEach(item -> {
HashMap map = (HashMap) item;
allMap.put(map.get("id").toString(), map);
});
while (iterator.hasNext()) {
Map map = (HashMap) iterator.next();
String pid = map.get("pid").toString();
if (!"0".equals(pid)) {
for (; ; ) {
Map pMap = (HashMap) allMap.get(pid);
if (pMap != null && !deptMap.contains(pMap) && !parentList.contains(pMap)) {
parentList.add(pMap);
pid = pMap.get("pid").toString();
} else {
break;
}
}
}
}
deptMap.addAll(parentList);
TreeMapUtil treeMapUtil = new TreeMapUtil();
treeMapUtil.tree(deptMap);
//转换为集合对象
JSONArray jsonArray = new JSONArray();
jsonArray.addAll(deptMap);
List<Dept> depts = jsonArray.toList(Dept.class);
return AjaxResult.ok().data(depts);
}
/**
* 校验部门
*
* @param id
* @param deptRequest
* @return
*/
private String checkDept(String id, DeptRequest deptRequest) {
Dept dept = getOne(new QueryWrapper<Dept>().lambda()
.eq(Dept::getCode, deptRequest.getCode())
.ne(StrUtil.isNotBlank(id), Dept::getId, id)
.last("limit 1")
);
if (ObjectUtil.isNotNull(dept)) return "部门编码不能重复";
return null;
}
}

View File

@ -0,0 +1,163 @@
package com.ydool.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ydool.common.base.BaseService;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.entity.Role;
import com.ydool.system.mapper.RoleMapper;
import com.ydool.system.request.IdsRequest;
import com.ydool.system.request.RoleRequest;
import com.ydool.system.service.IRoleService;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 系统角色 服务类
* </p>
*
* @author ljq
* @since 2023-01-11
*/
@Service
public class RoleServiceImpl extends BaseService<RoleMapper, Role> implements IRoleService {
/**
* 保存角色
*
* @param roleRequest
* @return
*/
@Override
public AjaxResult saveRole(RoleRequest roleRequest) {
String message = checkRole("", roleRequest);
if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message);
Role role = BeanUtil.copyProperties(roleRequest, Role.class);
boolean flag = save(role);
return flag ? AjaxResult.ok().msg("保存成功") : AjaxResult.fail("保存失败");
}
/**
* 编辑角色
*
* @param id
* @param roleRequest
* @return
*/
@Override
public AjaxResult editRole(String id, RoleRequest roleRequest) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
String message = checkRole(id, roleRequest);
if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message);
Role role = getById(id);
if (ObjectUtil.isNull(role)) return AjaxResult.fail("该角色不存在");
BeanUtil.copyProperties(roleRequest, role);
boolean flag = updateById(role);
return flag ? AjaxResult.ok().msg("编辑成功") : AjaxResult.fail("编辑失败");
}
/**
* 删除角色
*
* @param id
* @return
*/
@Override
public AjaxResult removeRole(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
Role role = getById(id);
if (ObjectUtil.isNull(role)) return AjaxResult.fail("该角色不存在");
return removeById(id) ? AjaxResult.ok().msg("删除成功") : AjaxResult.fail("删除失败");
}
/**
* 批量删除角色
*
* @param ids
* @return
*/
@Override
public AjaxResult removeRoles(IdsRequest ids) {
String[] idList = ids.getIds();
if (ArrayUtil.isEmpty(idList)) return AjaxResult.fail("角色Id集合不能为空");
List<Role> roleList = listByIds(Arrays.asList(idList));
if (CollUtil.isEmpty(roleList)) return AjaxResult.fail("该角色集合全部不存在");
return removeByIds(Arrays.asList(idList)) ? AjaxResult.ok().msg("批量删除成功") : AjaxResult.fail("批量删除失败");
}
/**
* 角色详情
*
* @param id
* @return
*/
@Override
public AjaxResult roleDetail(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
Role role = getById(id);
if (ObjectUtil.isNull(role)) return AjaxResult.fail("该角色不存在");
return AjaxResult.ok().data(role);
}
/**
* 角色列表
* @param page
* @param value
* @param column
* @param orderBy
* @param status
* @return
*/
@Override
public AjaxResult roleList(Page page, String value, String column, String orderBy, Boolean status) {
QueryWrapper<Role> qw = new QueryWrapper<Role>();
if (StrUtil.isNotBlank(value)) {
qw.lambda().like(Role::getName, value)
.or().like(Role::getRemarks, value)
.or().like(Role::getCode, value);
}
qw.lambda().eq(ObjectUtil.isNotNull(status), Role::getStatus, status);
if ("desc".equals(orderBy) && StrUtil.isNotBlank(column)) {
qw.orderByDesc(StrUtil.toUnderlineCase(column));
}
if ("asc".equals(orderBy) && StrUtil.isNotBlank(column)) {
qw.orderByAsc(StrUtil.toUnderlineCase(column));
}
Page<Role> pageList = page(page, qw);
return AjaxResult.ok().data(pageList);
}
/**
* 校验角色
*
* @param id
* @param roleRequest
* @return
*/
private String checkRole(String id, RoleRequest roleRequest) {
Role role = getOne(new QueryWrapper<Role>().lambda()
.eq(Role::getCode, roleRequest.getCode())
.ne(StrUtil.isNotBlank(id), Role::getId, id)
.last("limit 1")
);
if (ObjectUtil.isNotNull(role)) return "角色编码不能重复";
return null;
}
}

View File

@ -0,0 +1,21 @@
package com.ydool.system.service.impl;
import com.ydool.system.entity.User;
import com.ydool.common.base.BaseService;
import com.ydool.system.mapper.UserMapper;
import com.ydool.system.service.IUserService;
import org.springframework.stereotype.Service;
/**
* <p>
* 系统账号表 服务类
* </p>
*
* @author ljq
* @since 2023-01-05
*/
@Service
public class UserServiceImpl extends BaseService<UserMapper, User> implements IUserService {
}

View File

@ -0,0 +1,115 @@
server:
port: 8080
spring:
profiles:
active: dev
servlet:
multipart:
max-file-size: 500MB
max-request-size: 500MB
mvc:
pathmatch:
# 配置策略
matching-strategy: ant-path-matcher
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/ydool_demo?useSSL=false&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: Wang09211108
druid:
# 下面为连接池的补充设置,应用到上面所有数据源中
# 初始化大小,最小,最大
initial-size: 5
min-idle: 5
max-active: 1000
# 配置获取连接等待超时的时间
max-wait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 打开PSCache并且指定每个连接上PSCache的大小
pool-prepared-statements: true
# 配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
max-pool-prepared-statement-per-connection-size: 20
filters: stat,wall
use-global-data-source-stat: true
# 通过connectProperties属性来打开mergeSql功能慢SQL记录
connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 配置监控服务器
stat-view-servlet:
login-username: admin
login-password: 123456
reset-enable: false
url-pattern: /druid/*
# 添加IP白名单
#allow:
# 添加IP黑名单当白名单和黑名单重复时黑名单优先级更高
#deny:
web-stat-filter:
# 添加过滤规则
url-pattern: /*
# 忽略过滤格式
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
thymeleaf:
prefix: classpath:/html/
suffix: .html
mybatis-plus:
global-config:
banner: false
enableSqlRunner: true
mapper-locations: classpath:xml/*.xml
ydool:
sms:
accessKeyId: LTAIlV2ofsSoQe1F
accessKeySecret: SzzGOXLWlH5uMfTzWSjSiXeJRob5Hn
knife4j:
# 开启增强配置
enable: true
# 开启Swagger的Basic认证功能,默认是false
basic:
enable: false
# Basic认证用户名
username: ydool
# Basic认证密码
password: ydool@123
setting:
# 开启调试
enableDebug: true
# 开启搜索框
enableSearch: true
# 开启OpenApi
enableOpenApi: true
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
# token名称 (同时也是cookie名称)
token-name: x-token
# token有效期单位s 默认30天, -1代表永不过期
timeout: 86400
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: 1800
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: true
# token风格
token-style: uuid
# 是否输出操作日志
is-log: false
# token前缀
token-prefix: Bearer

View File

@ -0,0 +1,22 @@
package ${package.Mapper};
import ${package.Entity}.${entity};
import ${superMapperClassPackage};
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* ${table.comment!} Mapper 接口
* </p>
*
* @author ${author}
* @since ${date}
*/
@Mapper
<% if(kotlin){ %>
interface ${table.mapperName} : ${superMapperClass}<${entity}>
<% }else{ %>
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
}
<% } %>

View File

@ -0,0 +1,14 @@
package ${package.Service};
/**
* <p>
* ${table.comment!} 服务类
* </p>
*
* @author ${author}
* @since ${date}
*/
public interface ${table.serviceName} {
}

View File

@ -0,0 +1,21 @@
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import com.ydool.common.base.BaseService;
import com.ydool.system.mapper.${entity}Mapper;
import com.ydool.system.service.${table.serviceName};
import org.springframework.stereotype.Service;
/**
* <p>
* ${table.comment!} 服务类
* </p>
*
* @author ${author}
* @since ${date}
*/
@Service
public class ${table.serviceImplName} extends BaseService<${entity}Mapper, ${entity}> implements ${table.serviceName} {
}

View File

@ -0,0 +1,115 @@
server:
port: 8080
spring:
profiles:
active: dev
servlet:
multipart:
max-file-size: 500MB
max-request-size: 500MB
mvc:
pathmatch:
# 配置策略
matching-strategy: ant-path-matcher
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/ydool_demo?useSSL=false&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: Wang09211108
druid:
# 下面为连接池的补充设置,应用到上面所有数据源中
# 初始化大小,最小,最大
initial-size: 5
min-idle: 5
max-active: 1000
# 配置获取连接等待超时的时间
max-wait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 打开PSCache并且指定每个连接上PSCache的大小
pool-prepared-statements: true
# 配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
max-pool-prepared-statement-per-connection-size: 20
filters: stat,wall
use-global-data-source-stat: true
# 通过connectProperties属性来打开mergeSql功能慢SQL记录
connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 配置监控服务器
stat-view-servlet:
login-username: admin
login-password: 123456
reset-enable: false
url-pattern: /druid/*
# 添加IP白名单
#allow:
# 添加IP黑名单当白名单和黑名单重复时黑名单优先级更高
#deny:
web-stat-filter:
# 添加过滤规则
url-pattern: /*
# 忽略过滤格式
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
thymeleaf:
prefix: classpath:/html/
suffix: .html
mybatis-plus:
global-config:
banner: false
enableSqlRunner: true
mapper-locations: classpath:xml/*.xml
ydool:
sms:
accessKeyId: LTAIlV2ofsSoQe1F
accessKeySecret: SzzGOXLWlH5uMfTzWSjSiXeJRob5Hn
knife4j:
# 开启增强配置
enable: true
# 开启Swagger的Basic认证功能,默认是false
basic:
enable: false
# Basic认证用户名
username: ydool
# Basic认证密码
password: ydool@123
setting:
# 开启调试
enableDebug: true
# 开启搜索框
enableSearch: true
# 开启OpenApi
enableOpenApi: true
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
# token名称 (同时也是cookie名称)
token-name: x-token
# token有效期单位s 默认30天, -1代表永不过期
timeout: 86400
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: 1800
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: true
# token风格
token-style: uuid
# 是否输出操作日志
is-log: false
# token前缀
token-prefix: Bearer

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More