commit b4d88c1e7a352ba41e7062a679b740053ef3aff9
Author: zhanghaijun <1055190269@qq.com>
Date: Thu Jun 19 17:29:12 2025 +0800
init
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c936be6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,65 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/
+*.iws
+*.iml
+*.ipr
+rebel.xml
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
+
+# Compiled class file
+*.class
+
+# Log file
+*.log
+*.log.gz
+
+# flatten
+.flattened-pom.xml
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+target/
+
+### temp ignore ###
+*.cache
+*.diff
+*.patch
+*.tmp
+*.java~
+*.properties~
+*.xml~
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..ac29e3f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,308 @@
+
+ 4.0.0
+ com.gci.boot
+ cdenv-manage
+ 1.0.0-SNAPSHOT
+ jar
+ gci-boot-backend-demo Tapestry 5 Application
+ GCI-Boot3.0样例工程
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.15
+
+
+
+ 1.0.0-SNAPSHOT
+ UTF-8
+ 1.2.7
+ 0.0.39
+ 3.0.0-M5
+ 3.8.1
+ 1.8
+ 1.8
+ 5.8.20
+ 3.4.2
+ 3.5.1
+ 2.3
+ 3.3.2
+ 3.0.0
+ 2.6.15
+ 2021.0.5
+ 2021.1
+ UTF-8
+ 2.3.6.RELEASE
+ 1.1.1.RELEASE
+ 5.6.0
+ 1.8
+ 1.8
+ 2.2.5
+ 0.0.23
+ 1.5.24
+ 0.9.1
+ 2.6.0
+ 1.18.22
+ 2.13.0
+ 2.1.210
+ 3.8.0
+ 3.2.1
+ 1.12.0
+ 2.11.1
+ 1.1.17
+ 42.2.5
+ 3.7.0
+ 6.2.5.Final
+ 4.4.0
+
+
+
+
+ gci-nexus
+ Releases
+ http://10.88.2.69:8081/nexus/content/repositories/releases/
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatis.plus.version}
+
+
+
+ io.swagger
+ swagger-models
+ ${swagger.core.version}
+
+
+ io.swagger
+ swagger-annotations
+ ${swagger.core.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+ org.apache.commons
+ commons-lang3
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ ${jackson.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ ${jackson.version}
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ ${spring.boot.version}
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ com.alibaba
+ easyexcel
+ ${easyexcel.version}
+
+
+
+ org.apache.shiro
+ shiro-spring-boot-starter
+ ${shiro.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.postgresql
+ postgresql
+ runtime
+ ${postgresql.version}
+
+
+
+ com.auth0
+ java-jwt
+ ${java.jwt.version}
+
+
+
+
+
+ com.baomidou
+ mybatis-plus-generator
+ ${mybatis.plus.generator.version}
+
+
+
+ org.apache.velocity
+ velocity-engine-core
+ ${velocity.version}
+
+
+
+ org.freemarker
+ freemarker
+
+
+
+ org.hibernate.validator
+ hibernate-validator
+ ${org.hibernate.validator.version}
+
+
+ io.minio
+ minio
+ 8.2.2
+
+
+ org.aspectj
+ aspectjweaver
+ 1.9.7
+
+
+ org.springframework.statemachine
+ spring-statemachine-core
+ 2.1.3.RELEASE
+
+
+ org.springframework.statemachine
+ spring-statemachine-redis
+ 1.2.9.RELEASE
+
+
+ com.fasterxml.jackson.module
+ jackson-module-jsonSchema
+ 2.13.5
+
+
+ cn.afterturn
+ easypoi-base
+ ${easypoi.version}
+
+
+ cn.afterturn
+ easypoi-web
+ ${easypoi.version}
+
+
+ cn.afterturn
+ easypoi-annotation
+ ${easypoi.version}
+
+
+
+
+
+ dev
+
+ dev
+
+
+ true
+
+
+
+ test
+
+ test
+
+
+
+ prod
+
+ prod
+
+
+
+
+
+
+ ${project.artifactId}
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+
+
+ woff
+ woff2
+ eot
+ ttf
+ svg
+ xls
+ xlsx
+
+
+
+
+
+
+ src/main/resources
+ true
+
+
+ src/main/java
+
+ **/*.xml
+ **/*.json
+ **/*.ftl
+
+
+
+
+
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..8178c76
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1 @@
+readme
diff --git a/src/main/java/com/gci/boot/GciApplication.java b/src/main/java/com/gci/boot/GciApplication.java
new file mode 100644
index 0000000..49487be
--- /dev/null
+++ b/src/main/java/com/gci/boot/GciApplication.java
@@ -0,0 +1,33 @@
+package com.gci.boot;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.Environment;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+@SpringBootApplication
+@EnableScheduling
+@Slf4j
+public class GciApplication {
+
+ public static void main(String[] args) throws UnknownHostException {
+ ConfigurableApplicationContext application = SpringApplication.run(GciApplication.class, args);
+ Environment env = application.getEnvironment();
+ String ip = InetAddress.getLocalHost().getHostAddress();
+ String port = env.getProperty("server.port");
+ String path = env.getProperty("server.servlet.context-path");
+ log.info("\n----------------------------------------------------------\n\t" +
+ "Application Gci-Boot is running! Access URLs:\n\t" +
+ "Local: \t\thttp://localhost:" + port + path + "/\n\t" +
+ "External: \thttp://" + ip + ":" + port + path + "/\n\t" +
+ "swagger-ui: \thttp://" + ip + ":" + port + path + "/swagger-ui.html\n\t" +
+ "Doc: \t\thttp://" + ip + ":" + port + path + "/doc.html\n" +
+ "----------------------------------------------------------");
+ }
+
+}
diff --git a/src/main/java/com/gci/boot/annotation/Query/OrderQuery.java b/src/main/java/com/gci/boot/annotation/Query/OrderQuery.java
new file mode 100644
index 0000000..0beb661
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/Query/OrderQuery.java
@@ -0,0 +1,27 @@
+package com.gci.boot.annotation.Query;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 用于构建排序
+ * @author 24642
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface OrderQuery {
+ /**
+ * 排序顺序
+ */
+ int sort() default 0;
+ /**
+ * 排序规则
+ */
+ boolean IsAsc() default false;
+ /**
+ * 属性名
+ */
+ String PropName() default "";
+}
diff --git a/src/main/java/com/gci/boot/annotation/Query/SelectQuery.java b/src/main/java/com/gci/boot/annotation/Query/SelectQuery.java
new file mode 100644
index 0000000..aa35549
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/Query/SelectQuery.java
@@ -0,0 +1,81 @@
+package com.gci.boot.annotation.Query;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 用于构建查询
+ * @author 24642
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SelectQuery {
+
+ /**
+ * 属性名
+ */
+ String PropName() default "";
+
+
+ /**
+ * 查询类型
+ */
+ SelectType Type() default SelectType.LIKE;
+
+ enum SelectType {
+ /**
+ * 等于
+ */
+ EQ,
+ /**
+ * 不等于
+ */
+ NE,
+ /**
+ * 大于
+ */
+ GT,
+ /**
+ * 大于等于
+ */
+ GE,
+ /**
+ * 小于
+ */
+ LT,
+ /**
+ * 小于等于
+ */
+ LE,
+ /**
+ * 列表中
+ */
+ IN,
+ /**
+ * 列表外
+ */
+ NOT_IN,
+ /**
+ * 区间内
+ */
+ BETWEEN,
+ /**
+ * 区间外
+ */
+ NOT_BETWEEN,
+ /**
+ * 模糊查询
+ */
+ LIKE,
+ /**
+ * 左模糊查询
+ */
+ LIKE_LEFT,
+ /**
+ * 右模糊查询
+ */
+ LIKE_RIGHT
+ }
+}
diff --git a/src/main/java/com/gci/boot/annotation/Query/handle/QueryGenerator.java b/src/main/java/com/gci/boot/annotation/Query/handle/QueryGenerator.java
new file mode 100644
index 0000000..1f1d8c4
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/Query/handle/QueryGenerator.java
@@ -0,0 +1,186 @@
+package com.gci.boot.annotation.Query.handle;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.gci.boot.annotation.Query.OrderQuery;
+import com.gci.boot.annotation.Query.SelectQuery;
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author 24642
+ */
+@Slf4j
+public class QueryGenerator {
+ private static final String COMMA = ",";
+ /**
+ * 生成查询语句
+ * @param entity 数据库实体类
+ * @param query 查询参数实体类或者数据库实体类
+ * @return 生成的查询语句
+ */
+ public static LambdaQueryWrapper initQueryWrapper(Class entity, Q query) {
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ if (query == null) {
+ return queryWrapper.lambda();
+ }
+ common(entity, query, queryWrapper,false);
+ return queryWrapper.lambda();
+ }
+
+ public static LambdaQueryWrapper initQueryWrapper(Class entity, Q query,Boolean ignoreOrder) {
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ if (query == null) {
+ return queryWrapper.lambda();
+ }
+ common(entity, query, queryWrapper, ignoreOrder);
+ return queryWrapper.lambda();
+ }
+
+ private static void common(Class entity, Q query, QueryWrapper queryWrapper, boolean ignoreOrder) {
+ Field[] fields = ReflectUtil.getFields(query.getClass());
+ ArrayList orderList = new ArrayList<>();
+ for (Field field : fields) {
+ boolean accessible = field.isAccessible();
+ //设置后操作速度更快
+ field.setAccessible(true);
+ if (!ignoreOrder) {
+ if (field.isAnnotationPresent(OrderQuery.class)) {
+ orderList.add(field);
+ }
+ }
+ Object fieldValue = ReflectUtil.getFieldValue(query, field);
+ if (ObjectUtil.isEmpty(fieldValue)) {
+ continue;
+ }
+// String simpleName = field.getType().getSimpleName();
+ SelectQuery selectQuery = field.getAnnotation(SelectQuery.class);
+
+
+ if (selectQuery == null) {
+ continue;
+ }
+ String fieldName = StrUtil.toUnderlineCase(!"".equals(selectQuery.PropName()) ? selectQuery.PropName() : field.getName());
+ Class> type = field.getType();
+// SFunction function = LambdaFunctionUtil.getFunctionField(entity, fieldName);
+ switch (selectQuery.Type()) {
+ case EQ:
+ queryWrapper.eq(fieldName,fieldValue);
+ break;
+ case NE:
+ queryWrapper.ne(fieldName,fieldValue);
+ break;
+ case GT:
+ queryWrapper.gt(fieldName,fieldValue);
+ break;
+ case GE:
+ queryWrapper.ge(fieldName,fieldValue);
+ break;
+ case LT:
+ queryWrapper.lt(fieldName,fieldValue);
+ break;
+ case LE:
+ queryWrapper.le(fieldName,fieldValue);
+ break;
+ case IN:
+ if (List.class.equals(type)) {
+ queryWrapper.in(fieldName, (List)fieldValue);
+ } else if (String.class.equals(type)) {
+ Field o = ReflectUtil.getField(entity, StrUtil.toCamelCase(fieldName));
+ String replace = StrUtil.join(",",fieldValue).replace(",,", COMMA);
+ List split = StrUtil.split(replace, COMMA);
+ if (!o.getType().equals(String.class)) {
+ queryWrapper.in(fieldName,Convert.toNumberArray(split));
+ }
+ queryWrapper.in(fieldName,split);
+ }
+ break;
+ case NOT_IN:
+ if (List.class.equals(type)) {
+ queryWrapper.notIn(fieldName, (List)fieldValue);
+ } else if (String.class.equals(type)) {
+ Field o = ReflectUtil.getField(entity, StrUtil.toCamelCase(fieldName));
+ String replace = StrUtil.join(",",fieldValue).replace(",,", COMMA);
+ List split = StrUtil.split(replace, COMMA);
+ if (!o.getType().equals(String.class)) {
+ queryWrapper.notIn(fieldName,Convert.toNumberArray(split));
+ }
+ queryWrapper.notIn(fieldName,split);
+ }
+ break;
+ case BETWEEN:
+ if (List.class.equals(type)) {
+ if (((List)fieldValue).size()<2) {
+ break;
+ }
+ queryWrapper.between(fieldName, ((List)fieldValue).get(0),((List)fieldValue).get(1));
+ } else if (String.class.equals(type)) {
+ Field o = ReflectUtil.getField(entity, StrUtil.toCamelCase(fieldName));
+ String replace = StrUtil.join(",",fieldValue).replace(",,", COMMA);
+ List split = StrUtil.split(replace, COMMA);
+ if (split.size()<2) {
+ break;
+ }
+ if (!o.getType().equals(String.class)) {
+ Number[] numbers = Convert.toNumberArray(split);
+ queryWrapper.between(fieldName,numbers[0],numbers[1]);
+ }
+ queryWrapper.between(fieldName,split.get(0),split.get(1));
+ }
+ break;
+ case NOT_BETWEEN:
+ if (List.class.equals(type)) {
+ if (((List)fieldValue).size()<2) {
+ break;
+ }
+ queryWrapper.notBetween(fieldName, ((List)fieldValue).get(0),((List)fieldValue).get(1));
+ } else if (String.class.equals(type)) {
+ Field o = ReflectUtil.getField(entity, StrUtil.toCamelCase(fieldName));
+ String replace = StrUtil.join(",",fieldValue).replace(",,", COMMA);
+ List split = StrUtil.split(replace, COMMA);
+ if (split.size()<2) {
+ break;
+ }
+ if (!o.getType().equals(String.class)) {
+ Number[] numbers = Convert.toNumberArray(split);
+ queryWrapper.notBetween(fieldName,numbers[0],numbers[1]);
+ }
+ queryWrapper.notBetween(fieldName,split.get(0),split.get(1));
+ }
+ break;
+ case LIKE:
+ queryWrapper.like(fieldName,fieldValue);
+ break;
+ case LIKE_LEFT:
+ queryWrapper.likeLeft(fieldName,fieldValue);
+ break;
+ case LIKE_RIGHT:
+ queryWrapper.likeRight(fieldName,fieldValue);
+ break;
+ default:
+ break;
+ }
+ //恢复原样
+ field.setAccessible(accessible);
+ }
+ if (!ignoreOrder) {
+ if (ObjectUtil.isNotEmpty(orderList)) {
+ orderList.sort(Comparator.comparingInt(f->f.getAnnotation(OrderQuery.class).sort()));
+ for (Field field : orderList) {
+ OrderQuery orderQuery = field.getAnnotation(OrderQuery.class);
+ String fieldName = StrUtil.toUnderlineCase(!"".equals(orderQuery.PropName()) ? orderQuery.PropName() : field.getName());
+// SFunction function = LambdaFunctionUtil.getFunctionField(entity, fieldName);
+ queryWrapper.orderBy(true,orderQuery.IsAsc(),fieldName);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/gci/boot/annotation/fileUrl/FileUrl.java b/src/main/java/com/gci/boot/annotation/fileUrl/FileUrl.java
new file mode 100644
index 0000000..4e38d75
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/fileUrl/FileUrl.java
@@ -0,0 +1,23 @@
+package com.gci.boot.annotation.fileUrl;
+
+import com.gci.boot.annotation.repeat.handle.TableRepeatHandle;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author 24642
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FileUrl {
+ /**
+ * 文件前缀 没有的话就是默认取value
+ * @return
+ */
+ String value() default "";
+}
\ No newline at end of file
diff --git a/src/main/java/com/gci/boot/annotation/fileUrl/handle/FileUrlHandle.java b/src/main/java/com/gci/boot/annotation/fileUrl/handle/FileUrlHandle.java
new file mode 100644
index 0000000..1a9eb9c
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/fileUrl/handle/FileUrlHandle.java
@@ -0,0 +1,57 @@
+package com.gci.boot.annotation.fileUrl.handle;
+
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.StrUtil;
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.gci.boot.common.util.SpringContextUtil;
+import com.gci.boot.constant.CommonConstant;
+import com.gci.boot.exception.GciBootException;
+import org.springframework.beans.factory.annotation.Value;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author 24642
+ */
+public class FileUrlHandle extends JsonDeserializer {
+ @Value("${minio.fileUrl}")
+ private String fileUrl;
+ @Value("${minio.minioUrl}")
+ private String minioUrl;
+
+ @Override
+ public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
+ String inFileUrl;
+ HttpServletRequest request = SpringContextUtil.getHttpServletRequest();
+ String header = request.getHeader(CommonConstant.IS_INNER);
+ if (Convert.toBool(header,false)) {
+ inFileUrl = minioUrl;
+ } else {
+ inFileUrl = fileUrl;
+ }
+ String text = jsonParser.getText();
+ if (StrUtil.isBlank(text)) {
+ return text;
+ }
+ List split = StrUtil.split(text, StrUtil.COMMA);
+ for (int i = 0; i < split.size(); i++) {
+ String s = split.get(i);
+ if (StrUtil.isBlank(s)) {
+ throw new GciBootException("上传文件地址错误!");
+ } else {
+ boolean contains = StrUtil.contains(s, inFileUrl);
+ if (!contains) {
+ throw new GciBootException("上传文件地址未包括域名和端口!");
+ }
+ split.set(i,StrUtil.removeAll(s,inFileUrl));
+ }
+ }
+ return StrUtil.join(StrUtil.COMMA,split);
+ }
+}
diff --git a/src/main/java/com/gci/boot/annotation/importHandler/ExcelTypeHandler.java b/src/main/java/com/gci/boot/annotation/importHandler/ExcelTypeHandler.java
new file mode 100644
index 0000000..7698c30
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/importHandler/ExcelTypeHandler.java
@@ -0,0 +1,95 @@
+package com.gci.boot.annotation.importHandler;
+
+import lombok.Data;
+
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class ExcelTypeHandler {
+ /**
+ * 校验类型
+ * 1-数据库重复校验(excel校验也用这个)
+ * 2-单独字段校验是否在数据内(是否有权限之类的)
+ * 3-联合检验(当对应校验字段为指定值时其他字段不能为空)
+ */
+ private String type;
+
+ /**
+ * 对应校验字段
+ */
+ private List fields;
+
+ /**
+ * 校验字段指定值
+ */
+ private Map specifiedValue;
+
+ /**
+ * 其他字段
+ */
+ private List others;
+ /**
+ * 校验字段是否共同校验
+ */
+ private boolean needAll;
+ /**
+ * 数据集合
+ */
+ private List> record;
+ /**
+ * 自定义校验信息
+ */
+ private String errorMsg;
+
+ /**
+ * 数据库重复校验(excel校验也用这个)
+ * 这个校验感觉有问题 还是注解优先
+ * @param fields
+ * @param needAll
+ * @param record
+ * @param errorMsg
+ * @return
+ */
+ public ExcelTypeHandler(List fields, boolean needAll, List> record, String errorMsg) {
+ this.type = "1";
+ this.fields = fields;
+ this.needAll = needAll;
+ this.record = record;
+ this.errorMsg = errorMsg;
+ }
+
+ /**
+ * 单独字段校验是否在数据内(是否有权限之类的)
+ * @param fields
+ * @param record
+ * @param errorMsg
+ */
+ public ExcelTypeHandler(List fields, List> record, String errorMsg) {
+ this.type = "2";
+ this.fields = fields;
+ this.record = record;
+ this.errorMsg = errorMsg;
+ }
+
+ /**
+ * 联合检验(当对应校验字段为指定值时其他字段不能为空)
+ * @param fields
+ * @param specifiedValue
+ * @param others
+ * @param needAll
+ * @param record
+ * @param errorMsg
+ */
+ public ExcelTypeHandler(List fields, Map specifiedValue, List others, boolean needAll, List> record, String errorMsg) {
+ this.type = "3";
+ this.fields = fields;
+ this.specifiedValue = specifiedValue;
+ this.others = others;
+ this.needAll = needAll;
+ this.record = record;
+ this.errorMsg = errorMsg;
+ }
+
+}
diff --git a/src/main/java/com/gci/boot/annotation/importHandler/MyExcelVerifyHandler.java b/src/main/java/com/gci/boot/annotation/importHandler/MyExcelVerifyHandler.java
new file mode 100644
index 0000000..cb9417d
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/importHandler/MyExcelVerifyHandler.java
@@ -0,0 +1,179 @@
+package com.gci.boot.annotation.importHandler;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.springframework.stereotype.Component;
+
+import cn.afterturn.easypoi.excel.entity.result.ExcelVerifyHandlerResult;
+import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+
+@Component
+public class MyExcelVerifyHandler implements IExcelVerifyHandler {
+
+ private final ThreadLocal> threadLocal = new ThreadLocal<>();
+ private List list;
+ private Map> map;
+
+ public ThreadLocal> getThreadLocal() {
+ return threadLocal;
+ }
+
+ public List getList() {
+ return list;
+ }
+
+ public void setList(List list) {
+ this.list = list;
+ if (!list.isEmpty()) {
+ this.map = list.stream().collect(Collectors.groupingBy(ExcelTypeHandler::getType));
+ }
+ }
+
+ @Override
+ public ExcelVerifyHandlerResult verifyHandler(T t) {
+ Class> aClass = t.getClass();
+
+ return getExcelVerifyHandlerResult(t);
+
+ }
+
+ private ExcelVerifyHandlerResult getExcelVerifyHandlerResult(T t) {
+
+ List objects = threadLocal.get();
+ if (objects == null) {
+ objects = new ArrayList<>();
+ }
+ ArrayList errorMsg = new ArrayList<>();
+
+ List first = map.get("1");
+ if (first != null) {
+ for (ExcelTypeHandler excelTypeHandler : first) {
+ // 获取需要检验的字段
+ List fields = excelTypeHandler.getFields();
+
+ // 获取数据
+ List> record = excelTypeHandler.getRecord();
+
+ // 是否需要共同校验
+ boolean needAll = excelTypeHandler.isNeedAll();
+ if (record != null) {
+ boolean recordAnyMatch = record.stream().anyMatch(i -> {
+ if (needAll) {
+ // 共同校验数据
+ boolean allMatch = true;
+ for (String field : fields) {
+ boolean equal = ObjectUtil.equal(BeanUtil.getFieldValue(i, field),
+ BeanUtil.getFieldValue(t, field));
+ if (!equal) {
+ allMatch = false;
+ }
+ }
+ return allMatch;
+ } else {
+ for (String field : fields) {
+ boolean equal = ObjectUtil.equal(BeanUtil.getFieldValue(i, field),
+ BeanUtil.getFieldValue(t, field));
+ if (equal) {
+ return true;
+ }
+ }
+ return false;
+ }
+ });
+
+ if (recordAnyMatch) {
+ errorMsg.add(excelTypeHandler.getErrorMsg());
+ }
+ }
+
+ // excel内校验
+ List inExcel = new ArrayList<>();
+ objects.forEach(e -> {
+ if (needAll) {
+ // 共同校验数据
+ boolean allMatch = true;
+ for (String field : fields) {
+ boolean equal =
+ ObjectUtil.equal(BeanUtil.getFieldValue(e, field), BeanUtil.getFieldValue(t, field));
+ if (!equal) {
+ allMatch = false;
+ }
+ }
+ if (allMatch) {
+ inExcel.add("与原始excel" + BeanUtil.getFieldValue(e, "rowNum") + "行"
+ + excelTypeHandler.getErrorMsg());
+ }
+ } else {
+ for (String field : fields) {
+ boolean equal =
+ ObjectUtil.equal(BeanUtil.getFieldValue(e, field), BeanUtil.getFieldValue(t, field));
+ if (equal) {
+ inExcel.add("与原始excel" + BeanUtil.getFieldValue(e, "rowNum") + "行"
+ + excelTypeHandler.getErrorMsg());
+ }
+ }
+ }
+ });
+ if (!inExcel.isEmpty()) {
+ errorMsg.addAll(inExcel);
+ }
+ }
+ }
+
+ objects.add(t);
+ threadLocal.set(objects);
+
+ List second = map.get("2");
+ if (second != null) {
+ for (ExcelTypeHandler excelTypeHandler : second) {
+ // 需要校验的字段
+ List fields = excelTypeHandler.getFields();
+ // 获取数据
+ List> record = excelTypeHandler.getRecord();
+ for (String field : fields) {
+ Object fieldValue = BeanUtil.getFieldValue(t, field);
+ if (ObjectUtil.isNotEmpty(fieldValue)) {
+ boolean contains = record.contains(fieldValue);
+ // 不包含就报错
+ if (!contains) {
+ errorMsg.add(excelTypeHandler.getErrorMsg());
+ }
+ }
+ }
+ }
+ }
+ List third = map.get("3");
+ if (third != null) {
+ for (ExcelTypeHandler excelTypeHandler : third) {
+ List fields = excelTypeHandler.getFields();
+ Map specifiedValueMap = excelTypeHandler.getSpecifiedValue();
+ for (String field : fields) {
+ boolean equals = ObjectUtil.equals(BeanUtil.getFieldValue(t, field), specifiedValueMap.get(field));
+ if (equals) {
+ List others = excelTypeHandler.getOthers();
+ for (String other : others) {
+ boolean empty = ObjectUtil.isEmpty(BeanUtil.getFieldValue(t, other));
+ if (empty) {
+ errorMsg.add(excelTypeHandler.getErrorMsg());
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (errorMsg.isEmpty()) {
+ return new ExcelVerifyHandlerResult(true);
+ } else {
+ errorMsg.add(0,"当前行为原始excel"+BeanUtil.getFieldValue(t, "rowNum") + "行");
+ return new ExcelVerifyHandlerResult(false, StrUtil.join(";", errorMsg));
+ }
+ }
+}
diff --git a/src/main/java/com/gci/boot/annotation/permission/DataPermission.java b/src/main/java/com/gci/boot/annotation/permission/DataPermission.java
new file mode 100644
index 0000000..5ceae45
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/permission/DataPermission.java
@@ -0,0 +1,36 @@
+package com.gci.boot.annotation.permission;
+
+import java.lang.annotation.*;
+
+/**
+ * 数据权限注解
+ * @Author taoyan
+ * @Date 2019年4月11日
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE,ElementType.METHOD})
+@Documented
+public @interface DataPermission {
+ /**
+ * 默认字段暂时不用
+ * @return
+ */
+ String value() default "";
+
+
+ /**
+ * 存放作为过滤条件的字段名称:表名.projectId,createBy,repairShop或(createBy,repairShop)
+ */
+ String item() default "projectId";
+
+ /**
+ * 指定sqlId
+ * @return
+ */
+ String[] sqlIds() default {};
+
+ /**
+ * 以逗号隔开的字符串包容
+ */
+ boolean stringIn() default false;
+ }
\ No newline at end of file
diff --git a/src/main/java/com/gci/boot/annotation/repeat/FieldRepeat.java b/src/main/java/com/gci/boot/annotation/repeat/FieldRepeat.java
new file mode 100644
index 0000000..7559b66
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/repeat/FieldRepeat.java
@@ -0,0 +1,25 @@
+package com.gci.boot.annotation.repeat;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 需要结合@TableRepeat使用
+ * @author 24642
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FieldRepeat {
+ /**
+ * 属性名
+ */
+ String PropName() default "";
+
+ /**
+ * 不重复关联属性 --未完成
+ */
+ String other() default "";
+ String message() default "你所输入的内容已存在";
+}
\ No newline at end of file
diff --git a/src/main/java/com/gci/boot/annotation/repeat/TableRepeat.java b/src/main/java/com/gci/boot/annotation/repeat/TableRepeat.java
new file mode 100644
index 0000000..ce41ab8
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/repeat/TableRepeat.java
@@ -0,0 +1,23 @@
+package com.gci.boot.annotation.repeat;
+
+import com.gci.boot.annotation.repeat.handle.TableRepeatHandle;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author 24642
+ */
+@Target({ElementType.TYPE})
+@Constraint(validatedBy = TableRepeatHandle.class)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TableRepeat {
+ Class> aClass() ;
+ String message() default "";
+ Class>[] groups() default {};
+ Class extends Payload>[] payload() default {};
+}
diff --git a/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatHandle.java b/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatHandle.java
new file mode 100644
index 0000000..af3d155
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatHandle.java
@@ -0,0 +1,27 @@
+package com.gci.boot.annotation.repeat.handle;
+
+import com.gci.boot.annotation.repeat.FieldRepeat;
+import com.gci.boot.annotation.repeat.TableRepeat;
+import org.apache.poi.ss.formula.functions.T;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * @author 24642
+ */
+public class TableRepeatHandle implements ConstraintValidator {
+ private Class cClass;
+ /**
+ *
+ */
+ @Override
+ public void initialize(TableRepeat constraintAnnotation) {
+ this.cClass = (Class) constraintAnnotation.aClass();
+ }
+
+ @Override
+ public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
+ return TableRepeatUtils.fieldRepeat(o,cClass,constraintValidatorContext);
+ }
+}
diff --git a/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatUtils.java b/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatUtils.java
new file mode 100644
index 0000000..14d9cb8
--- /dev/null
+++ b/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatUtils.java
@@ -0,0 +1,84 @@
+package com.gci.boot.annotation.repeat.handle;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.gci.boot.annotation.repeat.FieldRepeat;
+import com.gci.boot.common.util.LambdaFunctionUtil;
+import com.gci.boot.common.util.SpringContextUtil;
+import org.apache.poi.ss.formula.functions.T;
+
+import javax.validation.ConstraintValidatorContext;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author 24642
+ */
+public class TableRepeatUtils {
+
+ public static boolean fieldRepeat(Object o, Class cClass, ConstraintValidatorContext context) {
+ HashMap stringObjectHashMap = new HashMap<>();
+ SFunction sFunction = null;
+ Object idValue = null;
+ //去除默认的提示消息
+ context.disableDefaultConstraintViolation();
+ String message = "";
+ Field[] fields = ReflectUtil.getFields(cClass);
+ if (ObjectUtil.isEmpty(fields)) {
+ return true;
+ }
+ LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
+ for (Field field : fields) {
+ queryWrapper.clear();
+ boolean accessible = field.isAccessible();
+ //设置后操作速度更快
+ field.setAccessible(true);
+ Object fieldValue = ReflectUtil.getFieldValue(o, field);
+ if (ObjectUtil.isEmpty(fieldValue)) {
+ continue;
+ }
+ TableId annotation = field.getAnnotation(TableId.class);
+ if (null != annotation && ObjectUtil.isNotEmpty(fieldValue)) {
+ sFunction = LambdaFunctionUtil.getFunctionField(cClass,field.getName());
+ idValue = fieldValue;
+ }
+ FieldRepeat fieldRepeat = field.getAnnotation(FieldRepeat.class);
+ if (null == fieldRepeat) {
+ continue;
+ }
+ String fieldName = !"".equals(fieldRepeat.PropName()) ? fieldRepeat.PropName() : field.getName();
+ queryWrapper.eq(LambdaFunctionUtil.getFunctionField(cClass,fieldName),fieldValue);
+ if (ObjectUtil.isNotEmpty(sFunction)) {
+ queryWrapper.ne(sFunction,idValue);
+ }
+ String other = fieldRepeat.other();
+ if (StrUtil.isNotBlank(other)) {
+ List split = StrUtil.split(other, ',');
+ for (String s : split) {
+ Object orDefault = stringObjectHashMap.getOrDefault(s, null);
+ if (orDefault == null) {
+ orDefault = ReflectUtil.getFieldValue(o,s);
+ }
+ if (ObjectUtil.isNotEmpty(orDefault)) {
+ stringObjectHashMap.put(s,orDefault);
+ queryWrapper.eq(LambdaFunctionUtil.getFunctionField(cClass,s),orDefault);
+ }
+ }
+ }
+ int count = ((IService) SpringContextUtil.getBean(StrUtil.lowerFirst(cClass.getSimpleName()) + "ServiceImpl")).count(queryWrapper);
+ if (count >0) {
+ message = fieldRepeat.message();
+ context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
+ return false;
+ }
+ field.setAccessible(accessible);
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/gci/boot/aspect/DataPermissionAspect.java b/src/main/java/com/gci/boot/aspect/DataPermissionAspect.java
new file mode 100644
index 0000000..3113488
--- /dev/null
+++ b/src/main/java/com/gci/boot/aspect/DataPermissionAspect.java
@@ -0,0 +1,164 @@
+package com.gci.boot.aspect;
+
+import cn.hutool.core.util.StrUtil;
+import com.gci.boot.annotation.permission.DataPermission;
+import com.gci.boot.common.util.SpringContextUtil;
+import com.gci.boot.constant.DataPermissionConstant;
+import com.gci.boot.modules.basedata.entity.TbRepairShopArchives;
+import com.gci.boot.modules.basedata.service.ITbRepairShopArchivesService;
+import com.gci.boot.modules.projects.service.IProjectsService;
+import com.gci.boot.modules.system.entity.SysRole;
+import com.gci.boot.modules.system.service.ISysRoleService;
+import com.gci.boot.modules.system.vo.LoginUser;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.SecurityUtils;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * 数据权限切面处理类
+ * 当被请求的方法有注解PermissionData时,会在往当前request中写入数据权限信息
+ * @Date 2019年4月10日
+ * @Version: 1.0
+ */
+@Aspect
+@Component
+@Slf4j
+public class DataPermissionAspect {
+
+ @Autowired
+ private IProjectsService projectsService;
+ @Autowired
+ private ISysRoleService sysRoleService;
+ @Autowired
+ private ITbRepairShopArchivesService tbRepairShopArchivesService;
+
+ @Pointcut("@annotation(com.gci.boot.annotation.permission.DataPermission)")
+ public void pointCut() {
+
+ }
+
+ @Around("pointCut()")
+ public Object arround(ProceedingJoinPoint point) throws Throwable{
+ HttpServletRequest request = SpringContextUtil.getHttpServletRequest();
+ String requestPath = request.getRequestURI().substring(request.getContextPath().length());
+ String requestMethod = request.getMethod();
+ requestPath = filterUrl(requestPath);
+ log.info("DataPermissionAspect拦截请求 >> "+requestPath+";请求类型 >> "+requestMethod);
+ MethodSignature signature = (MethodSignature) point.getSignature();
+ Method method = signature.getMethod();
+ DataPermission pd = method.getAnnotation(DataPermission.class);
+ String item = pd.item();
+ //处理特定的数据权限:按照项目projectId列表过滤
+ LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+ if(sysUser==null || StringUtils.isEmpty(sysUser.getId())){
+ throw new RuntimeException("用户未登录");
+ }
+ //获取角色:为判断超级管理员准备
+ List listRole = sysRoleService.getRoleByUserId(sysUser.getId());
+ if(CollectionUtils.isEmpty(listRole)){
+ //角色配置为空
+ throw new RuntimeException("角色配置为空");
+ }
+ StringBuilder sbRole = new StringBuilder();
+ listRole.forEach(lRole -> {
+ sbRole.append(","+lRole.getRoleCode());
+ });
+ String strRole = sbRole.toString();
+
+ String sqlConditon = null;
+ if(item.contains("projectId")){
+ //判断用户身份:1_普通部门,2_维修厂,3_司机,4_客户公司其他人员,0、其他身份,并根据身份获取授权的项目列表
+ List listProjectIds = projectsService.queryProjectListOfUser();
+ //超级管理员角色需放通
+ if(strRole.contains("PM0000")){
+ return point.proceed();
+ }
+ if(CollectionUtils.isEmpty(listProjectIds)){
+ //项目清单为空,说明没有任何项目权限,禁止查看视频监控、司机管理等项目类列表
+ sqlConditon = "1 != 1";
+ }else{
+ //组装项目id条件
+ sqlConditon = buildProjectIds(item,listProjectIds,pd.stringIn());
+ }
+ request.setAttribute(DataPermissionConstant.DATA_PERMISSION_CONDITION, sqlConditon);
+ request.setAttribute(DataPermissionConstant.DATA_PERMISSION_SQL_ID, pd.sqlIds());
+ }
+ return point.proceed();
+ }
+
+ private String buildProjectIds(String item, List listProjectIds, boolean stringIn){
+
+ String tableName = item.substring(0,item.lastIndexOf("."));
+
+ StringBuilder sb = new StringBuilder();
+ if (stringIn) {
+ sb.append("string_to_array(").append(tableName).append(".project_id,',') &&");
+ sb.append("string_to_array('").append(StrUtil.join(StrUtil.COMMA, listProjectIds)).append("',',')");
+ return sb.toString();
+ } else {
+ sb.append(tableName+".project_id in (");
+ listProjectIds.forEach(id -> {
+ sb.append("'"+id+"',");
+ });
+ String res = sb.substring(0, sb.length() - 1);
+
+ return res+")";
+ }
+ }
+
+ private String buildCreateBy(String item,String username){
+ String tableName = item.substring(0,item.lastIndexOf("."));
+ StringBuilder sb = new StringBuilder();
+ sb.append(tableName+".create_by='").append(username).append("'");
+ return sb.toString();
+ }
+
+ private String buildRepairShop(String item,String userId){
+ String res = null;
+ String tableName = item.substring(0,item.lastIndexOf("."));
+ List list = tbRepairShopArchivesService.getRepairShopByUserId(userId);
+ if(CollectionUtils.isEmpty(list)){
+ return "1 != 1";
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append(tableName+".repair_shop in (");
+ list.forEach(shop -> {
+ sb.append("'"+shop.getId()+"',");
+ });
+ res = sb.substring(0, sb.length() - 1);
+ return res+")";
+ }
+
+ /**
+ * 过滤url
+ * @param requestPath
+ * @return
+ */
+ private String filterUrl(String requestPath){
+ String url = "";
+ if(requestPath != null && !requestPath.equals("") && !requestPath.equals("null")){
+ url = requestPath.replace("\\", "/");
+ url = requestPath.replace("//", "/");
+ if(url.indexOf("//")>=0){
+ url = filterUrl(url);
+ }
+ /*if(url.startsWith("/")){
+ url=url.substring(1);
+ }*/
+ }
+ return url;
+ }
+
+}
diff --git a/src/main/java/com/gci/boot/common/config/CancelConverter.java b/src/main/java/com/gci/boot/common/config/CancelConverter.java
new file mode 100644
index 0000000..2b7e966
--- /dev/null
+++ b/src/main/java/com/gci/boot/common/config/CancelConverter.java
@@ -0,0 +1,56 @@
+package com.gci.boot.common.config;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.converters.ReadConverterContext;
+import com.alibaba.excel.converters.WriteConverterContext;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.data.WriteCellData;
+
+/**
+ * 状态字符串处理
+ *
+ */
+public class CancelConverter implements Converter {
+ @Override
+ public Class> supportJavaTypeKey() {
+ //对象属性类型
+ return Integer.class;
+ }
+
+ @Override
+ public CellDataTypeEnum supportExcelTypeKey() {
+ //CellData属性类型
+ return CellDataTypeEnum.STRING;
+ }
+
+ @Override
+ public Integer convertToJavaData(ReadConverterContext> context) throws Exception {
+ //CellData转对象属性
+ String cellStr = context.getReadCellData().getStringValue();
+ if (StrUtil.isEmpty(cellStr)) return null;
+ if ("正常".equals(cellStr)) {
+ return 0;
+ } else if ("作废".equals(cellStr)) {
+ return 1;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public WriteCellData> convertToExcelData(WriteConverterContext context) throws Exception {
+ //对象属性转CellData
+ Integer cellValue = context.getValue();
+ if (cellValue == null) {
+ return new WriteCellData<>("");
+ }
+ if (cellValue == 0) {
+ return new WriteCellData<>("正常");
+ } else if (cellValue == 1) {
+ return new WriteCellData<>("作废");
+ } else {
+ return new WriteCellData<>("");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gci/boot/common/config/DictConfig.java b/src/main/java/com/gci/boot/common/config/DictConfig.java
new file mode 100644
index 0000000..06096d9
--- /dev/null
+++ b/src/main/java/com/gci/boot/common/config/DictConfig.java
@@ -0,0 +1,14 @@
+package com.gci.boot.common.config;
+
+import com.gci.boot.common.dict.aspect.DictAspect;
+import com.gci.boot.modules.system.service.ISysDictService;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class DictConfig {
+ @Bean
+ public DictAspect dictAspect(ISysDictService dictService){
+ return new DictAspect(dictService);
+ }
+}
diff --git a/src/main/java/com/gci/boot/common/config/LogConfig.java b/src/main/java/com/gci/boot/common/config/LogConfig.java
new file mode 100644
index 0000000..1b55c04
--- /dev/null
+++ b/src/main/java/com/gci/boot/common/config/LogConfig.java
@@ -0,0 +1,16 @@
+package com.gci.boot.common.config;
+
+import com.gci.boot.common.log.aspect.SysLogAspect;
+import com.gci.boot.modules.system.service.ISysLogService;
+import com.gci.boot.modules.system.service.ISysUserService;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LogConfig {
+
+ @Bean
+ public SysLogAspect sysLogAspect(ISysLogService sysLogService, ISysUserService sysUserService) {
+ return new SysLogAspect(sysLogService, sysUserService);
+ }
+}
diff --git a/src/main/java/com/gci/boot/common/config/UtilsInitializeConfig.java b/src/main/java/com/gci/boot/common/config/UtilsInitializeConfig.java
new file mode 100644
index 0000000..53dccec
--- /dev/null
+++ b/src/main/java/com/gci/boot/common/config/UtilsInitializeConfig.java
@@ -0,0 +1,35 @@
+package com.gci.boot.common.config;
+
+import com.gci.boot.common.util.CacheUtil;
+import com.gci.boot.common.util.RedisUtil;
+import com.gci.boot.common.util.SpringContextUtil;
+import com.gci.boot.common.util.SpringEnvironmentUtil;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.cache.CacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.data.redis.core.RedisTemplate;
+
+@Configuration
+public class UtilsInitializeConfig {
+ @Bean
+ public SpringContextUtil.Initializer springContextUtilInitializer() {
+ return new SpringContextUtil.Initializer();
+ }
+
+ @Bean
+ public SpringEnvironmentUtil.Initializer springEnvironmentUtilInitializer() {
+ return new SpringEnvironmentUtil.Initializer();
+ }
+
+ @Bean
+ public RedisUtil redisUtilInitializer() {
+ return new RedisUtil();
+ }
+
+ @Bean
+ public CacheUtil cacheUtilInitializer() {
+ return new CacheUtil();
+ }
+}
diff --git a/src/main/java/com/gci/boot/common/dict/annotation/Dict.java b/src/main/java/com/gci/boot/common/dict/annotation/Dict.java
new file mode 100644
index 0000000..e3179f2
--- /dev/null
+++ b/src/main/java/com/gci/boot/common/dict/annotation/Dict.java
@@ -0,0 +1,25 @@
+package com.gci.boot.common.dict.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Dict {
+ /**
+ * 方法描述: 字典编码,如果指定了dictTable,则是字典项的值
+ */
+ String dicCode();
+
+ /**
+ * 方法描述: 字典文本
+ */
+ String dicText() default "";
+
+ /**
+ * 数据字典表
+ */
+ String dictTable() default "";
+}
diff --git a/src/main/java/com/gci/boot/common/dict/annotation/ExcelEnum.java b/src/main/java/com/gci/boot/common/dict/annotation/ExcelEnum.java
new file mode 100644
index 0000000..bdc67eb
--- /dev/null
+++ b/src/main/java/com/gci/boot/common/dict/annotation/ExcelEnum.java
@@ -0,0 +1,12 @@
+package com.gci.boot.common.dict.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ExcelEnum {
+ String value() default "";
+}
diff --git a/src/main/java/com/gci/boot/common/dict/aspect/DictAspect.java b/src/main/java/com/gci/boot/common/dict/aspect/DictAspect.java
new file mode 100644
index 0000000..0831837
--- /dev/null
+++ b/src/main/java/com/gci/boot/common/dict/aspect/DictAspect.java
@@ -0,0 +1,251 @@
+package com.gci.boot.common.dict.aspect;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.util.URLUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.gci.boot.annotation.fileUrl.FileUrl;
+import com.gci.boot.common.dict.annotation.Dict;
+import com.gci.boot.common.util.ClassReflectionUtil;
+import com.gci.boot.common.util.JsonUtil;
+import com.gci.boot.common.util.SpringContextUtil;
+import com.gci.boot.common.vo.Result;
+import com.gci.boot.constant.CommonConstant;
+import com.gci.boot.modules.system.service.ISysDictService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Value;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Field;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 字典解析切面
+ */
+@Aspect
+@Slf4j
+@RequiredArgsConstructor
+public class DictAspect {
+ private final ISysDictService dictService;
+ private static final ThreadLocal