@@ -0,0 +1,463 @@ | |||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<parent> | |||||
<groupId>com.hz.pm</groupId> | |||||
<artifactId>hz-project-management</artifactId> | |||||
<version>1.0.0</version> | |||||
</parent> | |||||
<artifactId>hz-pm-api</artifactId> | |||||
<version>1.0.0</version> | |||||
<properties> | |||||
<jjwt.version>0.11.5</jjwt.version> | |||||
</properties> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>com.google.guava</groupId> | |||||
<artifactId>guava</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>cn.hutool</groupId> | |||||
<artifactId>hutool-all</artifactId> | |||||
<version>5.8.5</version> | |||||
</dependency> | |||||
<!--lombok--> | |||||
<dependency> | |||||
<groupId>org.projectlombok</groupId> | |||||
<artifactId>lombok</artifactId> | |||||
</dependency> | |||||
<!-- mybatis plus--> | |||||
<dependency> | |||||
<groupId>com.baomidou</groupId> | |||||
<artifactId>mybatis-plus-boot-starter</artifactId> | |||||
</dependency> | |||||
<!--Spring boot Redis--> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-data-redis</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.baomidou</groupId> | |||||
<artifactId>mybatis-plus-extension</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.session</groupId> | |||||
<artifactId>spring-session-data-redis</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-freemarker</artifactId> | |||||
</dependency> | |||||
<!--spring boot 集成redis所需common-pool2--> | |||||
<dependency> | |||||
<groupId>org.apache.commons</groupId> | |||||
<artifactId>commons-pool2</artifactId> | |||||
<version>${commons-pool2.version}</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.apache.commons</groupId> | |||||
<artifactId>commons-lang3</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba</groupId> | |||||
<artifactId>fastjson</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.apache.tomcat.embed</groupId> | |||||
<artifactId>tomcat-embed-core</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-validation</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-web</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-jdbc</artifactId> | |||||
</dependency> | |||||
<!--实现springboot的热加载--> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-devtools</artifactId> | |||||
<optional>true</optional> | |||||
<scope>true</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-aop</artifactId> | |||||
</dependency> | |||||
<!--cache--> | |||||
<dependency> | |||||
<groupId>com.github.ben-manes.caffeine</groupId> | |||||
<artifactId>caffeine</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.apache.httpcomponents</groupId> | |||||
<artifactId>httpclient</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.apache.poi</groupId> | |||||
<artifactId>poi</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.apache.poi</groupId> | |||||
<artifactId>poi-ooxml</artifactId> | |||||
</dependency> | |||||
<!-- 阿里云oss --> | |||||
<dependency> | |||||
<groupId>com.aliyun.oss</groupId> | |||||
<artifactId>aliyun-sdk-oss</artifactId> | |||||
<version>3.15.0</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>junit</groupId> | |||||
<artifactId>junit</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.aspectj</groupId> | |||||
<artifactId>aspectjweaver</artifactId> | |||||
</dependency> | |||||
<!--Spring boot 测试--> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-test</artifactId> | |||||
</dependency> | |||||
<!--引入jwt--> | |||||
<dependency> | |||||
<groupId>com.auth0</groupId> | |||||
<artifactId>java-jwt</artifactId> | |||||
<version>3.10.3</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-configuration-processor</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.ningdatech</groupId> | |||||
<artifactId>nd-log-starter</artifactId> | |||||
<version>1.0.0</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.ningdatech</groupId> | |||||
<artifactId>nd-basic</artifactId> | |||||
<exclusions> | |||||
<exclusion> | |||||
<groupId>org.slf4j</groupId> | |||||
<artifactId>slf4j-log4j12</artifactId> | |||||
</exclusion> | |||||
</exclusions> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.ningdatech</groupId> | |||||
<artifactId>nd-swagger2-starter</artifactId> | |||||
<exclusions> | |||||
<exclusion> | |||||
<groupId>org.slf4j</groupId> | |||||
<artifactId>slf4j-log4j12</artifactId> | |||||
</exclusion> | |||||
</exclusions> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.ningdatech</groupId> | |||||
<artifactId>nd-zwdd-starter</artifactId> | |||||
<exclusions> | |||||
<exclusion> | |||||
<groupId>org.slf4j</groupId> | |||||
<artifactId>slf4j-log4j12</artifactId> | |||||
</exclusion> | |||||
</exclusions> | |||||
<version>1.0.0</version> | |||||
</dependency> | |||||
<!--KingBase--> | |||||
<dependency> | |||||
<groupId>com.kingbase8</groupId> | |||||
<artifactId>kingbase8-8.2.0</artifactId> | |||||
<version>8.2.0</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/src/lib/kingbase8-8.2.0.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.ningdatech</groupId> | |||||
<artifactId>nd-cache-starter</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.ningdatech</groupId> | |||||
<artifactId>nd-irs-starter</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.ningdatech</groupId> | |||||
<artifactId>nd-yxt-starter</artifactId> | |||||
<version>1.0.0</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba</groupId> | |||||
<artifactId>easyexcel-core</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.ningdatech</groupId> | |||||
<artifactId>nd-file-starter</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.ningdatech</groupId> | |||||
<artifactId>nd-flowable-starter</artifactId> | |||||
<exclusions> | |||||
<exclusion> | |||||
<groupId>com.baomidou</groupId> | |||||
<artifactId>mybatis-plus-boot-starter</artifactId> | |||||
</exclusion> | |||||
<exclusion> | |||||
<groupId>com.alibaba</groupId> | |||||
<artifactId>druid-spring-boot-starter</artifactId> | |||||
</exclusion> | |||||
</exclusions> | |||||
</dependency> | |||||
<!--浙政钉--> | |||||
<dependency> | |||||
<groupId>com.alibaba.xxpt</groupId> | |||||
<artifactId>zwdd</artifactId> | |||||
<version>1.2.0</version> | |||||
<scope>system</scope> | |||||
<systemPath>${basedir}/src/lib/zwdd-sdk-java-1.2.0.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>joda-time</groupId> | |||||
<artifactId>joda-time</artifactId> | |||||
</dependency> | |||||
<!--状态机--> | |||||
<dependency> | |||||
<groupId>org.springframework.statemachine</groupId> | |||||
<artifactId>spring-statemachine-core</artifactId> | |||||
</dependency> | |||||
<!-- PDF生成 --> | |||||
<dependency> | |||||
<groupId>com.itextpdf</groupId> | |||||
<artifactId>itextpdf</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.itextpdf</groupId> | |||||
<artifactId>itext-asian</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.itextpdf.tool</groupId> | |||||
<artifactId>xmlworker</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.xhtmlrenderer</groupId> | |||||
<artifactId>flying-saucer-pdf-itext5</artifactId> | |||||
</dependency> | |||||
<!--将html转换成pdf--> | |||||
<dependency> | |||||
<groupId>com.itextpdf</groupId> | |||||
<artifactId>html2pdf</artifactId> | |||||
</dependency> | |||||
<!--导入导出--> | |||||
<dependency> | |||||
<groupId>cn.afterturn</groupId> | |||||
<artifactId>easypoi-base</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.agent</groupId> | |||||
<artifactId>agent-boot</artifactId> | |||||
<version>1.3.22</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/agent-boot-1.3.22.0215.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.agent</groupId> | |||||
<artifactId>agent-boot</artifactId> | |||||
<version>1.3.22</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/agent-boot-1.3.22.0215.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.suwell</groupId> | |||||
<artifactId>suwell-agent-http</artifactId> | |||||
<version>1.7</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/suwell-agent-http-1.7.220630.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.suwell</groupId> | |||||
<artifactId>suwell-agent-wrapper</artifactId> | |||||
<version>1.6</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/suwell-agent-wrapper-1.6.221208.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.slf4j</groupId> | |||||
<artifactId>slf4j-api</artifactId> | |||||
<version>1.7.29</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/slf4j-api-1.7.29.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.httpclient</groupId> | |||||
<artifactId>httpclient</artifactId> | |||||
<version>4.5.13</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/httpclient-4.5.13.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.httpcore</groupId> | |||||
<artifactId>httpcore</artifactId> | |||||
<version>4.4.13</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/httpcore-4.4.13.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.httpmime</groupId> | |||||
<artifactId>httpmime</artifactId> | |||||
<version>4.5.13</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/httpmime-4.5.13.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.jbArchivesTools</groupId> | |||||
<artifactId>jbArchivesTools</artifactId> | |||||
<version>1.0</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/jbArchivesTools-1.0-SNAPSHOT.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.suwell</groupId> | |||||
<artifactId>suwell-convert-base</artifactId> | |||||
<version>1.5.19</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/suwell-convert-base-1.5.19.0408.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.gson</groupId> | |||||
<artifactId>gson</artifactId> | |||||
<version>2.8.0</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/gson-2.8.0.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.suwell</groupId> | |||||
<artifactId>suwell-rpc-manager-client</artifactId> | |||||
<version>2.7</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/suwell-rpc-manager-client-2.7.211125.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.suwell</groupId> | |||||
<artifactId>suwell-packet-wrapper</artifactId> | |||||
<version>1.21</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/suwell-packet-wrapper-1.21.230306.jar</systemPath> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.dom4j</groupId> | |||||
<artifactId>dom4j</artifactId> | |||||
<version>2.0.2</version> | |||||
<scope>system</scope> | |||||
<systemPath>${project.basedir}/lib/dom4j-2.0.2.jar</systemPath> | |||||
</dependency> | |||||
</dependencies> | |||||
<!-- 打包 --> | |||||
<!--配置环境的profile--> | |||||
<profiles> | |||||
<profile> | |||||
<id>dev</id> | |||||
<properties> | |||||
<!--使用${environment}获取值--> | |||||
<environment>dev</environment> | |||||
</properties> | |||||
</profile> | |||||
<profile> | |||||
<id>test</id> | |||||
<properties> | |||||
<environment>test</environment> | |||||
</properties> | |||||
</profile> | |||||
<profile> | |||||
<id>pre</id> | |||||
<properties> | |||||
<environment>pre</environment> | |||||
</properties> | |||||
</profile> | |||||
<profile> | |||||
<id>prod</id> | |||||
<properties> | |||||
<environment>prod</environment> | |||||
</properties> | |||||
</profile> | |||||
</profiles> | |||||
<build> | |||||
<resources> | |||||
<resource> | |||||
<directory>src/main/resources</directory> | |||||
<includes> | |||||
<include>**/*</include> | |||||
</includes> | |||||
</resource> | |||||
<resource> | |||||
<directory>src/main/java</directory> | |||||
<includes> | |||||
<include>**/*.xml</include> | |||||
</includes> | |||||
</resource> | |||||
<resource> | |||||
<directory>src/main/lib</directory> | |||||
<targetPath>BOOT-INF/lib/</targetPath> | |||||
<includes> | |||||
<include>**/*.jar</include> | |||||
</includes> | |||||
</resource> | |||||
<resource> | |||||
<directory>src/main/resources</directory> | |||||
<targetPath>BOOT-INF/classes/</targetPath> | |||||
</resource> | |||||
</resources> | |||||
<finalName>${project.artifactId}</finalName> | |||||
<plugins> | |||||
<plugin> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-maven-plugin</artifactId> | |||||
<version>2.6.8</version> | |||||
<configuration> | |||||
<includeSystemScope>true</includeSystemScope> | |||||
</configuration> | |||||
<executions> | |||||
<execution> | |||||
<goals> | |||||
<goal>repackage</goal> | |||||
</goals> | |||||
</execution> | |||||
</executions> | |||||
</plugin> | |||||
<!-- 跳过单元测试 --> | |||||
<plugin> | |||||
<groupId>org.apache.maven.plugins</groupId> | |||||
<artifactId>maven-surefire-plugin</artifactId> | |||||
<configuration> | |||||
<skipTests>true</skipTests> | |||||
</configuration> | |||||
</plugin> | |||||
</plugins> | |||||
</build> | |||||
</project> |
@@ -0,0 +1,41 @@ | |||||
package com.hz.pm.api; | |||||
import com.ningdatech.basic.util.SpringUtils; | |||||
import com.hz.pm.api.common.util.SpringContextHolder; | |||||
import org.mybatis.spring.annotation.MapperScan; | |||||
import org.springframework.boot.SpringApplication; | |||||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
import org.springframework.context.ApplicationContext; | |||||
import org.springframework.context.annotation.Bean; | |||||
import org.springframework.context.annotation.ComponentScan; | |||||
import org.springframework.context.annotation.EnableAspectJAutoProxy; | |||||
import org.springframework.scheduling.annotation.EnableAsync; | |||||
import org.springframework.scheduling.annotation.EnableScheduling; | |||||
import org.springframework.transaction.annotation.EnableTransactionManagement; | |||||
/** | |||||
* @author liuxinxin | |||||
*/ | |||||
@SpringBootApplication | |||||
@EnableAsync | |||||
@MapperScan(App.MAPPER_PACKAGES) | |||||
@EnableScheduling | |||||
@EnableTransactionManagement | |||||
@EnableAspectJAutoProxy(exposeProxy = true) | |||||
@ComponentScan(basePackages = {"com.hz.pm", "com.ningdatech.irs"}) | |||||
public class App { | |||||
protected static final String MAPPER_PACKAGES = "com.hz.pm.api.**.mapper"; | |||||
public static void main(String[] args) { | |||||
ApplicationContext context = SpringApplication.run(App.class, args); | |||||
// 设置applicationContext | |||||
SpringUtils.setApplicationContext(context); | |||||
} | |||||
@Bean | |||||
public SpringContextHolder springContextHolder() { | |||||
return new SpringContextHolder(); | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
package com.hz.pm.api.common.compare; | |||||
import java.lang.annotation.ElementType; | |||||
import java.lang.annotation.Retention; | |||||
import java.lang.annotation.RetentionPolicy; | |||||
import java.lang.annotation.Target; | |||||
/** | |||||
* 字段标记注解 | |||||
* | |||||
* @author zpf | |||||
* @since 2023/07/21 | |||||
*/ | |||||
@Target(ElementType.FIELD) | |||||
@Retention(RetentionPolicy.RUNTIME) | |||||
public @interface Compare { | |||||
/** | |||||
* 字段名称 | |||||
*/ | |||||
String value(); | |||||
} |
@@ -0,0 +1,47 @@ | |||||
package com.hz.pm.api.common.compare; | |||||
/** | |||||
* @author zpf | |||||
* @since 2023/07/21 | |||||
*/ | |||||
public class CompareNode { | |||||
/** | |||||
* 字段 | |||||
*/ | |||||
private String fieldKey; | |||||
/** | |||||
* 字段值 | |||||
*/ | |||||
private Object fieldValue; | |||||
/** | |||||
* 字段名称 | |||||
*/ | |||||
private String fieldName; | |||||
public String getFieldKey() { | |||||
return fieldKey; | |||||
} | |||||
public void setFieldKey(String fieldKey) { | |||||
this.fieldKey = fieldKey; | |||||
} | |||||
public Object getFieldValue() { | |||||
return fieldValue; | |||||
} | |||||
public void setFieldValue(Object fieldValue) { | |||||
this.fieldValue = fieldValue; | |||||
} | |||||
public String getFieldName() { | |||||
return fieldName; | |||||
} | |||||
public void setFieldName(String fieldName) { | |||||
this.fieldName = fieldName; | |||||
} | |||||
} |
@@ -0,0 +1,182 @@ | |||||
package com.hz.pm.api.common.compare; | |||||
import com.alibaba.fastjson.JSONObject; | |||||
import java.lang.reflect.Field; | |||||
import java.util.*; | |||||
/** | |||||
* 使用须知: <br> | |||||
* (1)该工具类主要用于两个同类对象的属性值比较; <br> | |||||
* (2)使用本工具类前,请将对应的类属性上打上 @Compare("xxx") 注解,其中xxx为字段的表达名称;<br> | |||||
* (3)为了比较灵活,只有打了该注解才会进行比较,不打的字段则不会进行比较 <br> | |||||
* (4)比较后,只会返回有变化的字段,无变化的字符则不返回 <br> | |||||
* | |||||
* @author zpf | |||||
* @since 2023/07/21 | |||||
*/ | |||||
public class CompareUtils<T> { | |||||
private static final String COMMA = ","; | |||||
/** | |||||
* 属性比较 | |||||
* | |||||
* @param source 源数据对象 | |||||
* @param target 目标数据对象 | |||||
* @return 对应属性值的比较变化 | |||||
*/ | |||||
public String compare(T source, T target) { | |||||
return compare(source, target, null); | |||||
} | |||||
/** | |||||
* 属性比较 | |||||
* | |||||
* @param source 源数据对象 | |||||
* @param target 目标数据对象 | |||||
* @param ignoreCompareFields 忽略比较的字段 | |||||
* @return 对应属性值的比较变化 | |||||
*/ | |||||
public String compare(T source, T target, List<String> ignoreCompareFields) { | |||||
if (Objects.isNull(source) && Objects.isNull(target)) { | |||||
return ""; | |||||
} | |||||
Map<String, CompareNode> sourceMap = this.getFiledValueMap(source); | |||||
Map<String, CompareNode> targetMap = this.getFiledValueMap(target); | |||||
if (sourceMap.isEmpty() && targetMap.isEmpty()) { | |||||
return ""; | |||||
} | |||||
// 如果源数据为空,则只显示目标数据,不显示属性变化情况 | |||||
if (sourceMap.isEmpty()) { | |||||
return doEmpty(targetMap, ignoreCompareFields); | |||||
} | |||||
// 如果源数据为空,则显示属性变化情况 | |||||
String s = doCompare(sourceMap, targetMap, ignoreCompareFields); | |||||
if (!s.endsWith(COMMA)) { | |||||
return s; | |||||
} | |||||
return s.substring(0, s.length() - 1); | |||||
} | |||||
public JSONObject compareToJson(T source, T target, List<String> ignoreCompareFields) { | |||||
JSONObject res = new JSONObject(); | |||||
if (Objects.isNull(source) && Objects.isNull(target)) { | |||||
return res; | |||||
} | |||||
Map<String, CompareNode> sourceMap = this.getFiledValueMap(source); | |||||
Map<String, CompareNode> targetMap = this.getFiledValueMap(target); | |||||
if (sourceMap.isEmpty() && targetMap.isEmpty()) { | |||||
return res; | |||||
} | |||||
// 如果源数据为空,则只显示目标数据,不显示属性变化情况 | |||||
if (sourceMap.isEmpty()) { | |||||
return res; | |||||
} | |||||
return doCompareJson(sourceMap, targetMap, ignoreCompareFields); | |||||
} | |||||
private String doEmpty(Map<String, CompareNode> targetMap, List<String> ignoreCompareFields) { | |||||
StringBuilder sb = new StringBuilder(); | |||||
Collection<CompareNode> values = targetMap.values(); | |||||
int size = values.size(); | |||||
int current = 0; | |||||
for (CompareNode node : values) { | |||||
current++; | |||||
Object o = Optional.ofNullable(node.getFieldValue()).orElse(""); | |||||
if (Objects.nonNull(ignoreCompareFields) && ignoreCompareFields.contains(node.getFieldKey())) { | |||||
continue; | |||||
} | |||||
if (o.toString().length() > 0) { | |||||
sb.append("[" + node.getFieldName() + ":" + o + "]"); | |||||
if (current < size) { | |||||
sb.append(COMMA); | |||||
} | |||||
} | |||||
} | |||||
return sb.toString(); | |||||
} | |||||
private String doCompare(Map<String, CompareNode> sourceMap, Map<String, CompareNode> targetMap, List<String> ignoreCompareFields) { | |||||
StringBuilder sb = new StringBuilder(); | |||||
Set<String> keys = sourceMap.keySet(); | |||||
int size = keys.size(); | |||||
int current = 0; | |||||
for (String key : keys) { | |||||
current++; | |||||
CompareNode sn = sourceMap.get(key); | |||||
CompareNode tn = targetMap.get(key); | |||||
if (Objects.nonNull(ignoreCompareFields) && ignoreCompareFields.contains(sn.getFieldKey())) { | |||||
continue; | |||||
} | |||||
String sv = Optional.ofNullable(sn.getFieldValue()).orElse("").toString(); | |||||
String tv = Optional.ofNullable(tn.getFieldValue()).orElse("").toString(); | |||||
// 只有两者属性值不一致时, 才显示变化情况 | |||||
if (!sv.equals(tv)) { | |||||
sb.append(String.format("[%s:%s -> %s]", sn.getFieldName(), sv, tv)); | |||||
if (current < size) { | |||||
sb.append(COMMA); | |||||
} | |||||
} | |||||
} | |||||
return sb.toString(); | |||||
} | |||||
private JSONObject doCompareJson(Map<String, CompareNode> sourceMap, Map<String, CompareNode> targetMap, List<String> ignoreCompareFields) { | |||||
JSONObject res = new JSONObject(); | |||||
Set<String> keys = sourceMap.keySet(); | |||||
int size = keys.size(); | |||||
int current = 0; | |||||
for (String key : keys) { | |||||
current++; | |||||
CompareNode sn = sourceMap.get(key); | |||||
CompareNode tn = targetMap.get(key); | |||||
if (Objects.nonNull(ignoreCompareFields) && ignoreCompareFields.contains(sn.getFieldKey())) { | |||||
continue; | |||||
} | |||||
String sv = Optional.ofNullable(sn.getFieldValue()).orElse("").toString(); | |||||
String tv = Optional.ofNullable(tn.getFieldValue()).orElse("").toString(); | |||||
// 只有两者属性值不一致时, 才显示变化情况 | |||||
if (!sv.equals(tv)) { | |||||
JSONObject valueChange = new JSONObject(); | |||||
valueChange.put("fieldKey",sn.getFieldKey()); | |||||
valueChange.put("old",tv); | |||||
valueChange.put("new",sv); | |||||
res.put(sn.getFieldName(),valueChange); | |||||
} | |||||
} | |||||
return res; | |||||
} | |||||
private Map<String, CompareNode> getFiledValueMap(T t) { | |||||
if (Objects.isNull(t)) { | |||||
return Collections.emptyMap(); | |||||
} | |||||
Field[] fields = t.getClass().getDeclaredFields(); | |||||
if (Objects.isNull(fields) || fields.length == 0) { | |||||
return Collections.emptyMap(); | |||||
} | |||||
Map<String, CompareNode> map = new LinkedHashMap(); | |||||
for (Field field : fields) { | |||||
Compare compareAnnotation = field.getAnnotation(Compare.class); | |||||
if (Objects.isNull(compareAnnotation)) { | |||||
continue; | |||||
} | |||||
field.setAccessible(true); | |||||
try { | |||||
String fieldKey = field.getName(); | |||||
CompareNode node = new CompareNode(); | |||||
node.setFieldKey(fieldKey); | |||||
node.setFieldValue(field.get(t)); | |||||
node.setFieldName(compareAnnotation.value()); | |||||
map.put(field.getName(), node); | |||||
} catch (IllegalArgumentException | IllegalAccessException e) { | |||||
e.printStackTrace(); | |||||
} | |||||
} | |||||
return map; | |||||
} | |||||
} |
@@ -0,0 +1,111 @@ | |||||
package com.hz.pm.api.common.config; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.apache.http.Header; | |||||
import org.apache.http.client.HttpClient; | |||||
import org.apache.http.client.config.RequestConfig; | |||||
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; | |||||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; | |||||
import org.apache.http.impl.client.HttpClientBuilder; | |||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; | |||||
import org.apache.http.message.BasicHeader; | |||||
import org.springframework.context.annotation.Bean; | |||||
import org.springframework.context.annotation.Configuration; | |||||
import org.springframework.http.MediaType; | |||||
import org.springframework.http.client.ClientHttpRequestFactory; | |||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; | |||||
import org.springframework.http.converter.HttpMessageConverter; | |||||
import org.springframework.http.converter.StringHttpMessageConverter; | |||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | |||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |||||
import org.springframework.web.client.RestTemplate; | |||||
import java.nio.charset.StandardCharsets; | |||||
import java.util.ArrayList; | |||||
import java.util.Arrays; | |||||
import java.util.List; | |||||
import java.util.concurrent.ThreadPoolExecutor; | |||||
import java.util.concurrent.TimeUnit; | |||||
/** | |||||
* @Classname BeanConfig | |||||
* @Description | |||||
* @Date 2023/3/2 9:42 | |||||
* @Created by PoffyZhang | |||||
*/ | |||||
@Configuration | |||||
@Slf4j | |||||
public class BeanConfig { | |||||
@Bean | |||||
public RestTemplate restTemplate() { | |||||
// 添加内容转换器,使用默认的内容转换器 | |||||
RestTemplate restTemplate = new RestTemplate(httpRequestFactory()); | |||||
// 设置编码格式为UTF-8,解决中文乱码问题 | |||||
List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters(); | |||||
HttpMessageConverter<?> converterTarget = null; | |||||
for (HttpMessageConverter<?> item : converterList) { | |||||
if (item.getClass() == StringHttpMessageConverter.class) { | |||||
converterTarget = item; | |||||
break; | |||||
} | |||||
} | |||||
if (converterTarget != null) { | |||||
converterList.remove(converterTarget); | |||||
} | |||||
HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8); | |||||
converterList.add(1,converter); | |||||
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); | |||||
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList( | |||||
MediaType.TEXT_HTML, | |||||
MediaType.TEXT_PLAIN)); | |||||
restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter); | |||||
log.info("-----restTemplate-----初始化完成"); | |||||
return restTemplate; | |||||
} | |||||
@Bean | |||||
public ClientHttpRequestFactory httpRequestFactory() { | |||||
return new HttpComponentsClientHttpRequestFactory(httpClient()); | |||||
} | |||||
@Bean | |||||
public HttpClient httpClient() { | |||||
// 长连接保持30秒 | |||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS); | |||||
//设置整个连接池最大连接数 根据自己的场景决定 | |||||
connectionManager.setMaxTotal(500); | |||||
//同路由的并发数,路由是对maxTotal的细分 | |||||
connectionManager.setDefaultMaxPerRoute(500); | |||||
//requestConfig | |||||
RequestConfig requestConfig = RequestConfig.custom() | |||||
//服务器返回数据(response)的时间,超过该时间抛出read timeout | |||||
.setSocketTimeout(10000) | |||||
//连接上服务器(握手成功)的时间,超出该时间抛出connect timeout | |||||
.setConnectTimeout(5000) | |||||
//从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool | |||||
.setConnectionRequestTimeout(500) | |||||
.build(); | |||||
//headers | |||||
List<Header> headers = new ArrayList<>(); | |||||
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36")); | |||||
headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate")); | |||||
headers.add(new BasicHeader("Accept-Language", "zh-CN")); | |||||
headers.add(new BasicHeader("Connection", "Keep-Alive")); | |||||
headers.add(new BasicHeader("Content-type", "application/json;charset=UTF-8")); | |||||
return HttpClientBuilder.create() | |||||
.setDefaultRequestConfig(requestConfig) | |||||
.setConnectionManager(connectionManager) | |||||
.setDefaultHeaders(headers) | |||||
// 保持长连接配置,需要在头添加Keep-Alive | |||||
.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()) | |||||
//重试次数,默认是3次,没有开启 | |||||
.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true)) | |||||
.build(); | |||||
} | |||||
} |
@@ -0,0 +1,45 @@ | |||||
package com.hz.pm.api.common.config; | |||||
import com.alibaba.fastjson.serializer.SerializerFeature; | |||||
import com.alibaba.fastjson.support.config.FastJsonConfig; | |||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; | |||||
import com.hz.pm.api.common.interceptor.LogInterceptor; | |||||
import org.springframework.context.annotation.Configuration; | |||||
import org.springframework.http.MediaType; | |||||
import org.springframework.http.converter.HttpMessageConverter; | |||||
import org.springframework.lang.NonNull; | |||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; | |||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | |||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||||
import java.nio.charset.StandardCharsets; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
/** | |||||
* @author qinxianyun | |||||
*/ | |||||
@EnableWebMvc | |||||
@Configuration | |||||
public class ConfigurerAdapter implements WebMvcConfigurer { | |||||
@Override | |||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { | |||||
// 使用 fastjson 序列化,会导致 @JsonIgnore 失效,可以使用 @JSONField(serialize = false) 替换 | |||||
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); | |||||
List<MediaType> supportMediaTypeList = new ArrayList<>(); | |||||
supportMediaTypeList.add(MediaType.APPLICATION_JSON); | |||||
FastJsonConfig config = new FastJsonConfig(); | |||||
config.setDateFormat("yyyy-MM-dd HH:mm:ss"); | |||||
config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect); | |||||
converter.setFastJsonConfig(config); | |||||
converter.setSupportedMediaTypes(supportMediaTypeList); | |||||
converter.setDefaultCharset(StandardCharsets.UTF_8); | |||||
converters.add(converter); | |||||
} | |||||
@Override | |||||
public void addInterceptors(@NonNull InterceptorRegistry registry) { | |||||
registry.addInterceptor(new LogInterceptor()).addPathPatterns("/**").order(-100); | |||||
} | |||||
} |
@@ -0,0 +1,19 @@ | |||||
package com.hz.pm.api.common.config; | |||||
import lombok.Data; | |||||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
import org.springframework.context.annotation.Configuration; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/9/9 下午5:37 | |||||
*/ | |||||
@Data | |||||
@Configuration | |||||
@ConfigurationProperties(prefix = "organization") | |||||
public class DingOrganizationProperties { | |||||
private List<String> deptVisibleScopes = new ArrayList<>(); | |||||
} |
@@ -0,0 +1,29 @@ | |||||
package com.hz.pm.api.common.config; | |||||
import lombok.Data; | |||||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
import org.springframework.context.annotation.Configuration; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
/** | |||||
* @author zpf | |||||
* @date 2023/3/2 下午5:37 | |||||
*/ | |||||
@Data | |||||
@Configuration | |||||
@ConfigurationProperties(prefix = "provincial") | |||||
public class ProvincialProperties { | |||||
private String host; | |||||
private String pushUrl; | |||||
private String detailUrl; | |||||
private String domainUrl; | |||||
private String key; | |||||
private String secret; | |||||
} |
@@ -0,0 +1,18 @@ | |||||
package com.hz.pm.api.common.constant; | |||||
/** | |||||
* <p> | |||||
* 创建人修改人基础字段 | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 17:17 2023/01/29 | |||||
*/ | |||||
public interface BaseFieldConst { | |||||
String CREATE_BY = "createBy"; | |||||
String UPDATE_BY = "updateBy"; | |||||
String CREATE_ON = "createOn"; | |||||
String UPDATE_ON = "updateOn"; | |||||
} |
@@ -0,0 +1,108 @@ | |||||
package com.hz.pm.api.common.constant; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import java.math.BigDecimal; | |||||
/** | |||||
* <p> | |||||
* 业务常量 | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 13:42 2022/12/1 | |||||
*/ | |||||
public interface BizConst { | |||||
/** | |||||
* SQL查询一条 | |||||
*/ | |||||
String LIMIT_1 = "limit 1"; | |||||
String COOKIE_KEY = "ND_PROJECT_MANAGEMENT_JSESSION"; | |||||
/** | |||||
* 一小时秒数 | |||||
**/ | |||||
BigDecimal SECONDS_BY_HOUR = new BigDecimal(60 * 60); | |||||
/** | |||||
* 十分钟的毫秒数 | |||||
*/ | |||||
long MILLS_10_MIN = 1000L * 60 * 10; | |||||
/** | |||||
* 中国行政区划编码 | |||||
*/ | |||||
long ROOT_REGION_CODE = 100000L; | |||||
/** | |||||
* 一级行政区划数量 | |||||
*/ | |||||
int NUM_PROVINCE = 34; | |||||
/** | |||||
* 默认的父id | |||||
*/ | |||||
long PARENT_ID = 0L; | |||||
/** | |||||
* 默认树层级 | |||||
*/ | |||||
int TREE_GRADE = 0; | |||||
/** | |||||
* 默认的排序 | |||||
*/ | |||||
int SORT_VALUE = 0; | |||||
/** | |||||
* 浙江省的region_id | |||||
*/ | |||||
long ZJ_REGION_CODE = 330000L; | |||||
String NINE_AREA_CODE_LAST = "000"; | |||||
/** | |||||
* 省/直辖市 level | |||||
*/ | |||||
int GOV_L1 = 1; | |||||
/** | |||||
* 市 level | |||||
*/ | |||||
int GOV_L2 = 2; | |||||
/** | |||||
* 区/县 level | |||||
*/ | |||||
int GOV_L3 = 3; | |||||
/** | |||||
* 密码正则:长度8-20位且至少包含大写字母、小写字母、数字或特殊符号中的任意三种 | |||||
*/ | |||||
String REGEX_PASS = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,20}$"; | |||||
ApiResponse<Void> UNAUTHENTICATED = ApiResponse.of(401, "用户未登录", null); | |||||
int MAX_EXPORT_COUNT = 5000; | |||||
String RESPONSE_KEY_DATA = "data"; | |||||
String RESPONSE_KEY_ID = "id"; | |||||
String RESPONSE_KEY_DING_CODE = "dingCode"; | |||||
String RESPONSE_KEY_MATTER_NAME = "matterName"; | |||||
String RESPONSE_KEY_ORG_NAME = "orgName"; | |||||
String RESPONSE_KEY_USER_STATE = "userState"; | |||||
String RESPONSE_KEY_AREA_NAME = "areaName"; | |||||
String ORG_NAME = "organizationName"; | |||||
String ORG_CODE = "organizationCode"; | |||||
String DEV = "dev"; | |||||
String PRE = "pre"; | |||||
String PROD = "prod"; | |||||
String SAVE_SUCCESS = "保存成功"; | |||||
String OP_SUCCESS = "操作成功"; | |||||
String OP_FAIL = "操作失败"; | |||||
String SAVE_FAIL = "保存失败"; | |||||
} |
@@ -0,0 +1,69 @@ | |||||
package com.hz.pm.api.common.constant; | |||||
/** | |||||
* @description: 常量 | |||||
* @author: LiuXinXin | |||||
* @date: 2022/5/5 17:31 | |||||
*/ | |||||
public interface CommonConst { | |||||
String COOKIE_KEY = "ND_JSESSION"; | |||||
Integer EXPORT_PAGE_NUMBER = 1; | |||||
Integer EXPORT_PAGE_SIZE = 100000; | |||||
String CALL_STATUS = "status"; | |||||
String CALL_STATUS_OK_VALUE = "ok"; | |||||
Integer COMMENT_MAX_SIZE = 163; | |||||
Integer SUB_COMMENT_SIZE_MIN = 0; | |||||
Integer SUB_COMMENT_SIZE_MAX = 160; | |||||
String PROJECT_DECLARE = "项目申报"; | |||||
String UNIT_INNER_AUDIT = "单位内部审核"; | |||||
String PRELIMINARY_PREVIEW = "项目预审"; | |||||
String DEPT_UNITED_REVIEW = "部门联审"; | |||||
String PROVINCE_UNITED_REVIEW = "省级部门联审"; | |||||
String ANNUAL_PLAN = "年度计划"; | |||||
String CONSTRUCTION_PLAN_REVIEW = "建设方案评审"; | |||||
String PROJECT_APPROVAL = "立项批复"; | |||||
String TENDER_PURCHASE = "招标采购"; | |||||
String PROJECT_PRELIMINARY_INSPECTION = "项目初验"; | |||||
String PROJECT_FINAL_INSPECTION = "项目终验"; | |||||
String ARCHIVED = "归档"; | |||||
String FILE_NAME = "name"; | |||||
String BASIS_FILE_NAME = "fileName"; | |||||
String NULL = "null"; | |||||
String TITLE = "title"; | |||||
String FILE_NAME_STR = "fileName"; | |||||
String FILE_ID_STR = "fileId"; | |||||
String ID_STR = "id"; | |||||
String FILE_LIST = "fileList"; | |||||
String ITEM_BASED = "依据项:"; | |||||
String ITEM_BASED_FILE_NAME = "依据文件名:"; | |||||
String APPENDIX = "文件:"; | |||||
String NEW_CONSTRUCTION = "新建"; | |||||
String CONTINUED_CONSTRUCTION = "续建"; | |||||
String MONTH = "月"; | |||||
String ZHI = "至"; | |||||
String YEAR = "年"; | |||||
Integer VERSION_ONE = 1; | |||||
Integer VERSION_SIZE = 2; | |||||
Integer VERSION_JUDGE = -1; | |||||
String COPY = "副本"; | |||||
String PROJECT_REPEAT = " 项目已在其他评价计划中,请勿重复添加!"; | |||||
String APP_REPEAT = " 应用已在其他评价计划中,请勿重复添加!"; | |||||
Integer REAPPRAISAL_TYPE = 1; | |||||
Integer VERIFY_TYPE = 2; | |||||
String REPEAT = " 已在其他当前评价计划其他分组中,请勿重复添加!"; | |||||
String NORMAL_TIME_PATTERN = "yyyy-MM-dd"; | |||||
} |
@@ -0,0 +1,34 @@ | |||||
package com.hz.pm.api.common.constant; | |||||
import com.ningdatech.basic.util.StrPool; | |||||
/** | |||||
* 默认值 | |||||
* | |||||
* @author PoffyZhang | |||||
*/ | |||||
public interface DefValConst { | |||||
/** | |||||
* 默认的根节点path | |||||
*/ | |||||
String ROOT_PATH = StrPool.COMMA; | |||||
/** | |||||
* 默认树层级 | |||||
*/ | |||||
Integer TREE_GRADE = 0; | |||||
/** | |||||
* 默认的父id | |||||
*/ | |||||
Long PARENT_ID = 0L; | |||||
/** | |||||
* 默认的排序 | |||||
*/ | |||||
Integer SORT_VALUE = 0; | |||||
/** | |||||
* 字典占位符 | |||||
*/ | |||||
String DICT_PLACEHOLDER = "###"; | |||||
} |
@@ -0,0 +1,14 @@ | |||||
package com.hz.pm.api.common.constant; | |||||
/** | |||||
* 浙政钉常量 | |||||
* | |||||
* @author CMM | |||||
* @since 2023/02/01 14:49 | |||||
*/ | |||||
public interface DingConst { | |||||
/** | |||||
* 工作通知 | |||||
*/ | |||||
String WORKING_NOTICE = "/message/workNotification"; | |||||
} |
@@ -0,0 +1,172 @@ | |||||
package com.hz.pm.api.common.constant; | |||||
import java.math.BigDecimal; | |||||
/** | |||||
* 项目申报表单数据常量key | |||||
* @return | |||||
* @author CMM | |||||
* @since 2023/01/19 10:31 | |||||
*/ | |||||
public interface ProjectDeclareConst { | |||||
/** | |||||
* 基本信息 | |||||
*/ | |||||
class BasicInformation { | |||||
// 项目名称 | |||||
public static final String PROJECT_NAME = "projectName"; | |||||
// 是否一地创新全省共享项目 | |||||
public static final String INNOVATION_SHARING_PROJECT = "innovationSharingProject"; | |||||
// 是否临时增补 | |||||
public static final String TEMPORARY_SUPPLEMENT = "temporarySupplement"; | |||||
// 项目负责人 | |||||
public static final String PROJECT_LEADER = "projectLeader"; | |||||
// 项目负责人手机号 | |||||
public static final String PROJECT_LEADER_PHONE_NUMBER = "projectLeaderPhoneNumber"; | |||||
// 项目联系人 | |||||
public static final String PROJECT_CONTACT = "projectContact"; | |||||
// 项目联系人手机号 | |||||
public static final String PROJECT_CONTACT_PHONE_NUMBER = "projectContactPhoneNumber"; | |||||
// 建设单位 | |||||
public static final String CONSTRUCTION_UNIT = "constructionUnit"; | |||||
// 建设单位统一信用代码 | |||||
public static final String CONSTRUCTION_UNIT_UNIFIED_CREDIT_CODE = "constructionUnitUnifiedCreditCode"; | |||||
// 项目类型 | |||||
public static final String PROJECT_TYPE = "projectType"; | |||||
// 是否首次新建 | |||||
public static final String FIRST_NEW_CONSTRUCTION = "firstNewConstruction"; | |||||
// 预算年度 | |||||
public static final String BUDGET_YEAR = "projectYear"; | |||||
// 建设开始时间 | |||||
public static final String CONSTRUCTION_START_TIME = "constructionStartTime"; | |||||
// 建设结束时间 | |||||
public static final String CONSTRUCTION_END_TIME = "constructionEndTime"; | |||||
// 四大体系 | |||||
public static final String FOUR_SYSTEM = "fourSystem"; | |||||
// 是否数字化改革项目 | |||||
public static final String DIGITAL_REFORM_PROJECT = "digitalReformProject"; | |||||
// 建设层级 | |||||
public static final String CONSTRUCTION_HIERARCHY = "constructionHierarchy"; | |||||
// 立项依据材料 | |||||
public static final String PROJECT_BASIS_MATERIAL = "projectBasisMaterial"; | |||||
// 发改编码 | |||||
public static final String CHANGE_CODE = "changeCode"; | |||||
// 财政编码 | |||||
public static final String FISCAL_CODE = "fiscalCode"; | |||||
// 是否上云 | |||||
public static final String ON_CLOUD = "onCloud"; | |||||
// 项目简介 | |||||
public static final String PROJECT_INTRODUCTION = "projectIntroduction"; | |||||
} | |||||
/** | |||||
* 资金申报情况 | |||||
*/ | |||||
class FundDeclareInfo { | |||||
// 申报金额 | |||||
public static final String DECLARE_AMOUNT = "declareAmount"; | |||||
// 自有资金 | |||||
public static final String OWN_FUND = "ownFund"; | |||||
// 政府投资-本级财政资金 | |||||
public static final String GOVERNMENT_INVESTMENT_SAME_LEVEL_FUND = "governmentInvestmentSameLevelFund"; | |||||
// 政府投资-上级补助资金 | |||||
public static final String GOVERNMENT_INVESTMENT_SUPERIOR_FUND = "governmentInvestmentSuperiorFund"; | |||||
// 银行贷款 | |||||
public static final String BANK_LOAN = "bankLoan"; | |||||
// 其他资金 | |||||
public static final String OTHER_FUND = "otherFund"; | |||||
} | |||||
/** | |||||
* 总投资分配情况 | |||||
*/ | |||||
class TotalInvestmentAllocations { | |||||
// 软件开发 | |||||
public static final String SOFTWARE_DEVELOPMENT = "softwareDevelopment"; | |||||
// 云资源、硬件配置 | |||||
public static final String CLOUD_RESOURCE_HARDWARE_CONFIGURATION = "cloudResourceHardwareConfiguration"; | |||||
// 第三方服务 | |||||
public static final String THIRD_PARTY_SERVICE = "thirdPartyService"; | |||||
} | |||||
/** | |||||
* 年度支付计划 | |||||
*/ | |||||
class AnnualPaymentPlan { | |||||
// 年度支付金额 | |||||
public static final String ANNUAL_PAYMENT_AMOUNT = "annualPaymentAmount"; | |||||
// 自有资金 | |||||
public static final String OWN_FUND = "ownFund"; | |||||
// 政府投资-本级财政资金 | |||||
public static final String GOVERNMENT_INVESTMENT_SAME_LEVEL_FUND = "governmentInvestmentSameLevelFund"; | |||||
// 政府投资-上级补助资金 | |||||
public static final String GOVERNMENT_INVESTMENT_SUPERIOR_FUND = "governmentInvestmentSuperiorFund"; | |||||
// 银行贷款 | |||||
public static final String BANK_LOAN = "bankLoan"; | |||||
// 其他 | |||||
public static final String OTHER = "other"; | |||||
} | |||||
/** | |||||
* 核心业务 | |||||
*/ | |||||
class CoreBusiness { | |||||
} | |||||
/** | |||||
* 安全投入 | |||||
*/ | |||||
class SafetyInput { | |||||
// 投入项 | |||||
public static final String INPUT_ITEM = "inputItem"; | |||||
// 内容描述 | |||||
public static final String CONTENT_DESCRIPTION = "contentDescription"; | |||||
// 金额 | |||||
public static final String AMOUNT = "amount"; | |||||
} | |||||
/** | |||||
* 工程形象进度 | |||||
*/ | |||||
class ProjectImageProgress { | |||||
// 第一季度 | |||||
public static final String FIRST_QUARTER = "firstQuarter"; | |||||
// 第二季度 | |||||
public static final String SECOND_QUARTER = "secondQuarter"; | |||||
// 第三季度 | |||||
public static final String THIRD_QUARTER = "thirdQuarter"; | |||||
// 第四季度 | |||||
public static final String FOURTH_QUARTER = "fourthQuarter"; | |||||
} | |||||
/** | |||||
* 附件 | |||||
*/ | |||||
class Appendix { | |||||
} | |||||
/** | |||||
* 备注 | |||||
*/ | |||||
class Remark { | |||||
} | |||||
/** | |||||
* 应用信息 | |||||
*/ | |||||
class ApplicationInformation { | |||||
} | |||||
class Number { | |||||
public static final BigDecimal DECLARE_AMOUNT_JUDGEMENT = BigDecimal.valueOf(1000); | |||||
//区县是500万 | |||||
public static final BigDecimal DECLARE_COUNTY_AMOUNT_JUDGEMENT = BigDecimal.valueOf(500); | |||||
public static final Integer COUNTRY_BUILD_LEVEL = 1; | |||||
public static final Integer PROVINCE_BUILD_LEVEL = 2; | |||||
public static final Integer PROVINCE_SELF_BUILD_LEVEL = 3; | |||||
public static final Integer CITY_BUILD_LEVEL = 4; | |||||
public static final Integer CITY_SELF_BUILD_LEVEL = 5; | |||||
public static final Integer DISTRICTS_COUNTRIES_BUILD_LEVEL = 6; | |||||
public static final Integer VILLAGES_TOWNS_BUILD_LEVEL = 7; | |||||
} | |||||
} |
@@ -0,0 +1,74 @@ | |||||
package com.hz.pm.api.common.constant; | |||||
import com.google.common.collect.Lists; | |||||
import java.util.List; | |||||
/** | |||||
* <p> | |||||
* RegionConst | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 13:57 2023/3/1 | |||||
*/ | |||||
public interface RegionConst { | |||||
//---------------------------------------地区层级(缩写RL)------------------------------------------------------------- | |||||
int RL_PROVINCE = 1; | |||||
int RL_CITY = 2; | |||||
int RL_COUNTY = 3; | |||||
//---------------------------------------地区编码(缩写RC)------------------------------------------------------------- | |||||
/** | |||||
* 丽水行政区划编码 | |||||
*/ | |||||
String RC_LS = "331100"; | |||||
//丽水开发区 | |||||
String LS_KF = "331118"; | |||||
String LS_KF_IRS = "331151"; | |||||
String RC_LS_SBJ_IRS = "331101"; | |||||
//遂昌县 | |||||
String RC_SC = "331123"; | |||||
String LS_KF_NAME = "开发区"; | |||||
/** | |||||
* 中国行政区划编码 | |||||
*/ | |||||
String RC_CHINA = "100000"; | |||||
/** | |||||
* 浙江行政区划编码 | |||||
*/ | |||||
String RC_ZJ = "330000"; | |||||
String NINE_CODE_LAST = "000"; | |||||
//莲都 | |||||
String LD = "331102"; | |||||
//青田 | |||||
String QT = "331121"; | |||||
//缙云 | |||||
String JY = "331122"; | |||||
//遂昌 | |||||
String SC = "331123"; | |||||
//松阳 | |||||
String SY = "331124"; | |||||
//云和 | |||||
String YH = "331125"; | |||||
//庆元 | |||||
String QY = "331126"; | |||||
String QN = "331127"; | |||||
String LQ = "331181"; | |||||
List<String> LS_ARR = Lists.newArrayList(RC_LS,LS_KF,LD,QT,JY,SC,SY,YH,QY,QN,LQ); | |||||
//----------------------------------------地区父级ID(缩写PID)--------------------------------------------------------- | |||||
long PID_CHINA = 0; | |||||
} |
@@ -0,0 +1,14 @@ | |||||
package com.hz.pm.api.common.constant; | |||||
/** | |||||
* @author CMM | |||||
* @since 2023/02/07 16:24 | |||||
*/ | |||||
public class StateMachineConst { | |||||
public static final String PROJECT_DECLARE = "projectDeclare"; | |||||
public static final String APPLICATION_DECLARE = "applicationDeclare"; | |||||
public static final String LI_SHUI_CITY_AREA_CODE = "331100"; | |||||
} |
@@ -0,0 +1,32 @@ | |||||
package com.hz.pm.api.common.enumeration; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Getter; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/7/26 上午9:21 | |||||
*/ | |||||
@AllArgsConstructor | |||||
@Getter | |||||
public enum BoolDisplayEnum { | |||||
/** | |||||
* true | |||||
*/ | |||||
Y, | |||||
/** | |||||
* false | |||||
*/ | |||||
N; | |||||
public static boolean judgeBoolean(String key) { | |||||
return Y.name().equals(key); | |||||
} | |||||
public static BoolDisplayEnum judgeBoolean(boolean key) { | |||||
return key ? Y : N; | |||||
} | |||||
} |
@@ -0,0 +1,39 @@ | |||||
package com.hz.pm.api.common.enumeration; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Getter; | |||||
/** | |||||
* @author zpf | |||||
* @date 2023/3/12 上午9:21 | |||||
*/ | |||||
@AllArgsConstructor | |||||
@Getter | |||||
public enum CommonEnum { | |||||
/** | |||||
* 公共的一些枚举 | |||||
*/ | |||||
YES(1,"是",1), | |||||
NO(0,"否",1), | |||||
LS_SBJ(331100,"市本级",2), | |||||
LS_LD(331102,"莲都区",2), | |||||
LS_QT(331121,"青田县",2), | |||||
LS_JY(331122,"缙云县",2), | |||||
LS_SC(331123,"遂昌县",2), | |||||
LS_SY(331124,"松阳县",2), | |||||
LS_YH(331125,"云和县",2), | |||||
LS_QY(331126,"庆元县",2), | |||||
LS_JN(331127,"景宁畲族自治县",2), | |||||
LS_LQ(331181,"龙泉市",2), | |||||
LS_KFQ(331199,"开发区",2), | |||||
ZWDD(0,"浙政钉",3), | |||||
MOBILE(1,"短信",3); | |||||
private Integer code; | |||||
private String desc; | |||||
private Integer groupId; | |||||
} |
@@ -0,0 +1,157 @@ | |||||
package com.hz.pm.api.common.enumeration; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Getter; | |||||
import lombok.NoArgsConstructor; | |||||
/** | |||||
* 导出选项枚举 | |||||
* | |||||
* @author CMM | |||||
* @since 2023/02/10 16:38 | |||||
*/ | |||||
@Getter | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public enum ExportOptionEnum { | |||||
/** | |||||
* 导出选项 | |||||
*/ | |||||
id(1, "项目ID"), | |||||
projectName(2, "项目名称"), | |||||
areaCode(3, "行政区划编码"), | |||||
area(4, "行政区划名称"), | |||||
responsibleMan(5, "项目负责人"), | |||||
responsibleManMobile(6, "项目负责人手机号"), | |||||
contactName(7, "项目联系人"), | |||||
contactPhone(8, "项目联系人手机号"), | |||||
higherSuperOrg(9, "上级业务主管单位"), | |||||
higherSuperOrgCode(10, "上级主管单位浙政钉ID"), | |||||
superOrg(11, "本级主管部门"), | |||||
superOrgCode(12, "本级主管部门浙政钉ID"), | |||||
buildOrgName(13, "建设单位名称"), | |||||
buildOrgZheJiangGovDingId(14, "建设单位浙政钉ID"), | |||||
orgCreditCode(15, "建设单位统一信用代码"), | |||||
projectType(16, "项目类型"), | |||||
isFirst(17, "是否首次新建"), | |||||
relatedExistsApplication(18, "关联应用"), | |||||
relatedExistsApplicationCode(19, "关联应用IRS编码"), | |||||
declareAmount(20, "申报金额"), | |||||
approvedTotalInvestmentIncrease(21, "批复金额"), | |||||
/** | |||||
* 表里没有 | |||||
*/ | |||||
budgetSource(22, "预算来源"), | |||||
projectYear(23, "预算年度"), | |||||
projectIntroduction(24, "项目简介"), | |||||
buildBasis(25, "立项依据"), | |||||
buildLevel(26, "建设层级"), | |||||
developCode(27, "发改编码"), | |||||
financialCode(28, "财政编码"), | |||||
/** | |||||
* 表里没有 | |||||
*/ | |||||
informationValidity(29, "信息是否有效"), | |||||
isDigitalReform(30, "是否数字化改革项目"), | |||||
bizDomain(31, "综合应用领域"), | |||||
isCloud(32, "是否上云"), | |||||
cloudType(33, "云类型"), | |||||
fourSystems(34, "四大体系"), | |||||
isTemporaryAugment(35, "是否临时增补"), | |||||
protectionLevel(36, "等保级别"), | |||||
isSecretComments(37, "是否密评"), | |||||
businessNumber(38, "业务编号"), | |||||
businessName(39, "业务名称"), | |||||
orgName(40, "单位名称"), | |||||
softwareDevelopmentAmount(41, "软件开发"), | |||||
cloudHardwarePurchaseAmount(42, "云资源、硬件购置"), | |||||
thirdPartyAmount(43, "第三方服务"), | |||||
safetyInputTitle(44, "投入项"), | |||||
safetyInputDescribe(45, "内容描述"), | |||||
safetyInputAmount(46, "金额"), | |||||
annualPlanAmount(47, "年度支付金额"), | |||||
annualPlanHaveAmount(48, "自有资金"), | |||||
declareGovOwnFinanceAmount(49, "政府投资-本级财政资金"), | |||||
declareGovSuperiorFinanceAmount(50, "政府投资-上级补助资金"), | |||||
declareBankLendingAmount(51, "银行贷款"), | |||||
declareOtherAmount(52, "其它资金"), | |||||
engineeringSpeedOne(53, "第一季度"), | |||||
engineeringSpeedTwo(54, "第二季度"), | |||||
engineeringSpeedThree(55, "第三季度"), | |||||
engineeringSpeedFour(56, "第四季度"), | |||||
preliminaryPlanFile(57, "初步方案"), | |||||
supportingMaterialsFile(58, "附件-佐证材料"), | |||||
projectRemarks(59, "备注"), | |||||
processStatusName(60, "流程状态名称"), | |||||
processLaunchTime(61,"流程发起时间"), | |||||
processHandleTime(62,"流程处理时间"), | |||||
projectStatusName(63,"项目状态名称"), | |||||
createOn(64,"创建时间"), | |||||
updateOn(65,"更新时间"); | |||||
private Integer code; | |||||
private String desc; | |||||
} |
@@ -0,0 +1,39 @@ | |||||
package com.hz.pm.api.common.enumeration; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Getter; | |||||
import lombok.NoArgsConstructor; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import java.util.Objects; | |||||
@Getter | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public enum ProjectProcessStageEnum { | |||||
/** | |||||
* 项目流程配置 阶段枚举 | |||||
*/ | |||||
ORG_INTERNAL_APPROVAL_PROCESS(1,"单位内部审批流程"), | |||||
PROJECT_PREQUALIFICATION_APPROVAL_PROCESS(2,"项目预审审批流程"), | |||||
DEPARTMENT_JOINT_APPROVAL_PROCESS(3,"部门联合审批流程"), | |||||
CONSTRUCTION_PROJECT_APPROVAL_PROCESS(4,"建设方案审批流程"), | |||||
ACCEPTANCE_DECLARATION_APPROVAL_PROCESS(5,"验收申报审批流程"), | |||||
APPLY_DELAY(6,"申请延期审批流程"), | |||||
APPLY_BORROW(7,"申请借阅审批流程"); | |||||
private Integer code; | |||||
private String desc; | |||||
public static String getDesc(Integer code) { | |||||
if (Objects.isNull(code)) { | |||||
return StringUtils.EMPTY; | |||||
} | |||||
for (ProjectProcessStageEnum t : ProjectProcessStageEnum.values()) { | |||||
if (code.equals(t.getCode())) { | |||||
return t.desc; | |||||
} | |||||
} | |||||
return StringUtils.EMPTY; | |||||
} | |||||
} |
@@ -0,0 +1,24 @@ | |||||
package com.hz.pm.api.common.errorcode; | |||||
import lombok.Getter; | |||||
/** | |||||
* @author LiuXinXin | |||||
*/ | |||||
@Getter | |||||
public enum AppErrorCode { | |||||
USER(100), | |||||
AUTH(101); | |||||
private final Integer code; | |||||
AppErrorCode(Integer code) { | |||||
this.code = code; | |||||
} | |||||
public Integer getCode() { | |||||
return code; | |||||
} | |||||
} |
@@ -0,0 +1,48 @@ | |||||
package com.hz.pm.api.common.handler; | |||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; | |||||
import com.hz.pm.api.user.util.LoginUserUtil; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.apache.ibatis.reflection.MetaObject; | |||||
import org.springframework.stereotype.Component; | |||||
import java.time.LocalDateTime; | |||||
import static com.hz.pm.api.common.constant.BaseFieldConst.*; | |||||
/** | |||||
* <p> | |||||
* 字段自动填充处理 | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 17:20 2022/11/24 | |||||
*/ | |||||
@Slf4j | |||||
@Component | |||||
public class BaseFieldFillHandler implements MetaObjectHandler { | |||||
private Long getUserId() { | |||||
if (LoginUserUtil.isLogin()) { | |||||
return LoginUserUtil.getUserId(); | |||||
} | |||||
return 0L; | |||||
} | |||||
@Override | |||||
public void insertFill(MetaObject metaObject) { | |||||
long userId = getUserId(); | |||||
LocalDateTime now = LocalDateTime.now(); | |||||
this.fillStrategy(metaObject, CREATE_BY, userId); | |||||
this.fillStrategy(metaObject, CREATE_ON, now); | |||||
this.fillStrategy(metaObject, UPDATE_BY, userId); | |||||
this.fillStrategy(metaObject, UPDATE_ON, now); | |||||
} | |||||
@Override | |||||
public void updateFill(MetaObject metaObject) { | |||||
this.fillStrategy(metaObject, UPDATE_BY, getUserId()); | |||||
this.fillStrategy(metaObject, UPDATE_ON, LocalDateTime.now()); | |||||
} | |||||
} |
@@ -0,0 +1,62 @@ | |||||
package com.hz.pm.api.common.handler; | |||||
import com.ningdatech.basic.enumeration.Status; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.context.support.DefaultMessageSourceResolvable; | |||||
import org.springframework.http.HttpStatus; | |||||
import org.springframework.validation.BindException; | |||||
import org.springframework.web.bind.MethodArgumentNotValidException; | |||||
import org.springframework.web.bind.annotation.ControllerAdvice; | |||||
import org.springframework.web.bind.annotation.ExceptionHandler; | |||||
import org.springframework.web.bind.annotation.ResponseBody; | |||||
import org.springframework.web.bind.annotation.ResponseStatus; | |||||
import org.springframework.web.servlet.NoHandlerFoundException; | |||||
import javax.validation.ConstraintViolation; | |||||
import javax.validation.ConstraintViolationException; | |||||
import java.util.stream.Collectors; | |||||
/** | |||||
* @description: 统一错误处理 | |||||
* @author: liuxinxin | |||||
* @date: 2023/01/03 11:39 | |||||
*/ | |||||
@Slf4j | |||||
@ControllerAdvice | |||||
@ResponseStatus(HttpStatus.BAD_REQUEST) | |||||
public class GlobalExceptionHandler { | |||||
@ResponseBody | |||||
@ExceptionHandler(value = NoHandlerFoundException.class) | |||||
public ApiResponse<Void> noHandlerFoundException(NoHandlerFoundException e) { | |||||
log.error("【全局异常拦截】NoHandlerFoundException: 请求方法 {}, 请求路径 {}", e.getRequestURL(), e.getHttpMethod()); | |||||
return ApiResponse.ofStatus(Status.REQUEST_NOT_FOUND); | |||||
} | |||||
@ResponseBody | |||||
@ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class}) | |||||
public ApiResponse<Void> bindException(BindException e) { | |||||
String msg = e.getAllErrors().stream() | |||||
.map(DefaultMessageSourceResolvable::getDefaultMessage) | |||||
.collect(Collectors.joining(",")); | |||||
return ApiResponse.of(Status.BAD_REQUEST.getCode(), msg, null); | |||||
} | |||||
@ResponseBody | |||||
@ExceptionHandler(value = ConstraintViolationException.class) | |||||
public ApiResponse<Void> constraintViolationException(ConstraintViolationException e) { | |||||
String msg = e.getConstraintViolations().stream() | |||||
.map(ConstraintViolation::getMessage) | |||||
.collect(Collectors.joining(",")); | |||||
return ApiResponse.of(Status.BAD_REQUEST.getCode(), msg, null); | |||||
} | |||||
@ResponseBody | |||||
@ExceptionHandler(value = Exception.class) | |||||
public ApiResponse<Void> handlerException(Exception e) { | |||||
log.error("【全局异常拦截】: 异常信息 {}: {} ", e.getClass().getSimpleName(), e); | |||||
return ApiResponse.of(Status.BAD_REQUEST.getCode(), e.getMessage(), null); | |||||
} | |||||
} |
@@ -0,0 +1,79 @@ | |||||
package com.hz.pm.api.common.handler; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import org.springframework.core.MethodParameter; | |||||
import org.springframework.http.MediaType; | |||||
import org.springframework.http.converter.HttpMessageConverter; | |||||
import org.springframework.http.server.ServerHttpRequest; | |||||
import org.springframework.http.server.ServerHttpResponse; | |||||
import org.springframework.web.bind.annotation.ExceptionHandler; | |||||
import org.springframework.web.bind.annotation.RestControllerAdvice; | |||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; | |||||
/** | |||||
* @Author liuxinxin | |||||
* @Date 2021/7/21 11:26 | |||||
* @Version 1.0 | |||||
**/ | |||||
@RestControllerAdvice(basePackages = { | |||||
"com.hz.pm.api.fiscal.controller", | |||||
"com.hz.pm.api.organization.controller", | |||||
"com.hz.pm.api.projectdeclared.controller", | |||||
"com.hz.pm.api.projectlib.controller", | |||||
"com.hz.pm.api.sys.controller", | |||||
"com.hz.pm.api.todocenter.controller", | |||||
"com.hz.pm.api.user.controller", | |||||
"com.hz.pm.api.meeting.controller", | |||||
"com.hz.pm.api.expert.controller", | |||||
"com.hz.pm.api.sms.controller", | |||||
"com.hz.pm.api.workbench.controller", | |||||
"com.hz.pm.api.ding.controller", | |||||
"com.hz.pm.api.filemanage.controller", | |||||
"com.hz.pm.api.performance.controller", | |||||
"com.hz.pm.api.irs.controller", | |||||
"com.hz.pm.api.safety.controller", | |||||
"com.hz.pm.api.portrait.controller", | |||||
"com.hz.pm.api.irs.controller", | |||||
"com.hz.pm.api.gov.controller", | |||||
"com.hz.pm.api.dashboard.controller", | |||||
"com.hz.pm.api.wps.controller", | |||||
"com.hz.pm.api.gov.controller" | |||||
}) | |||||
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> { | |||||
private static final String SWAGGER_CLASS_PREFIX = "springfox.documentation"; | |||||
@Override | |||||
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) { | |||||
return filter(methodParameter); | |||||
} | |||||
@Override | |||||
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, | |||||
Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, | |||||
ServerHttpResponse serverHttpResponse) { | |||||
ApiResponse<Object> apiResponse = ApiResponse.ofSuccess(o); | |||||
// 处理字符串时,遇到了类型转换的问题,debug一步一步跟踪,原来是对于字符串的ContentType是“text-plain”, | |||||
// ConverterType是StringHttpMessageConverter这个类型转换, | |||||
// 由于将结果封装成了自定义的ApiResponse类型,所以有ApiResponse转换成String报错 | |||||
// 所以需要对String类型的返回值单独进行处理 | |||||
// if (o instanceof String) { | |||||
// return JSONUtil.toJsonStr(apiResponse); | |||||
// } | |||||
return ApiResponse.ofSuccess(o); | |||||
// return o; | |||||
} | |||||
private Boolean filter(MethodParameter methodParameter) { | |||||
Class<?> declaringClass = methodParameter.getDeclaringClass(); | |||||
// swagger中的所有返回不进行统一封装 | |||||
if (declaringClass.getName().contains(SWAGGER_CLASS_PREFIX)) { | |||||
return false; | |||||
} | |||||
if (methodParameter.hasMethodAnnotation(ExceptionHandler.class)) { | |||||
return false; | |||||
} | |||||
// 如果本身就是使用ApiResponse返回,则不需要进行格式化 | |||||
return !methodParameter.getParameterType().equals(ApiResponse.class); | |||||
} | |||||
} |
@@ -0,0 +1,120 @@ | |||||
package com.hz.pm.api.common.helper; | |||||
import com.hz.pm.api.sys.model.dto.RegionDTO; | |||||
import com.hz.pm.api.sys.model.vo.RegionTreeVO; | |||||
import java.util.Collection; | |||||
import java.util.List; | |||||
/** | |||||
* <p> | |||||
* RegionCacheHelper - | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 13:50 2023/3/1 | |||||
*/ | |||||
public interface RegionCacheHelper { | |||||
/** | |||||
* 获取完整的区域树状结构 | |||||
* | |||||
* @return / | |||||
*/ | |||||
List<RegionDTO> all(); | |||||
/** | |||||
* 根据区域code 区域层级获取 区域类 | |||||
* | |||||
* @param code 区域编码 | |||||
* @param level 区域层级 | |||||
* @return {@link RegionDTO} | |||||
*/ | |||||
RegionDTO getByCodeAndLevel(String code, Integer level); | |||||
/** | |||||
* 获取区域名称 | |||||
* | |||||
* @param code 区域编码 | |||||
* @param level 区域层级 | |||||
* @return 名称 | |||||
*/ | |||||
String getRegionName(String code, int level); | |||||
/** | |||||
* 根据传入的地区code与level获取所有上层地区集合 | |||||
* 按照level升序排列 | |||||
* | |||||
* @param code 地区编码 | |||||
* @param level 地区层级 | |||||
* @return / | |||||
*/ | |||||
List<RegionDTO> listParents(String code, int level); | |||||
/** | |||||
* 根据传入的地区code与level获取所有子区域集合 | |||||
* | |||||
* @param code 地域编码 | |||||
* @param level 地域层级 | |||||
* @return 所有子区域(包含自己) | |||||
* @author WendyYang | |||||
**/ | |||||
List<RegionDTO> listChildren(String code, int level); | |||||
/** | |||||
* 获取当前区域所有的子区域(包括自己) | |||||
* | |||||
* @param code 区域编码 | |||||
* @param level 级别 | |||||
* @return / | |||||
*/ | |||||
Collection<String> listChildRegionCodeList(String code, int level); | |||||
/** | |||||
* 获取当前节点开始的区域树 | |||||
* | |||||
* @param regionCode 区域编码 | |||||
* @param regionLevel 区域层级 | |||||
* @return 区域树 | |||||
*/ | |||||
RegionTreeVO getRegionTree(String regionCode, Integer regionLevel); | |||||
/** | |||||
* 获取展示名称(浙江省/杭州市/滨江区) | |||||
* | |||||
* @param regionCode 区域编码 | |||||
* @param regionLevel 区域层级 | |||||
* @return java.lang.String | |||||
**/ | |||||
String getFullDisplayName(String regionCode, Integer regionLevel); | |||||
/** | |||||
* 获取展示名称(杭州市/滨江区) | |||||
* | |||||
* @param regionCode 区域编码 | |||||
* @param regionLevel 区域层级 | |||||
* @return java.lang.String | |||||
**/ | |||||
String getDisplayName(String regionCode, Integer regionLevel); | |||||
/** | |||||
* 获取用于前端回显示使用的unionList 仅用于返回前端的时候使用 | |||||
* | |||||
* @param code 区域编码 | |||||
* @param level 区域层级 | |||||
* @return \ | |||||
*/ | |||||
String getUnionPath(String code, Integer level); | |||||
/** | |||||
* 根据区域名称获取区域信息(参数格式:浙江省-杭州市-滨江区) | |||||
* | |||||
* @param regionName 地区名称 | |||||
* @return \ | |||||
**/ | |||||
RegionDTO getByRegionName(String regionName); | |||||
} |
@@ -0,0 +1,52 @@ | |||||
package com.hz.pm.api.common.helper; | |||||
import com.hz.pm.api.meta.model.bo.RegionContainsBO; | |||||
import java.util.List; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/12/21 下午5:37 | |||||
* 区域限制帮助类 | |||||
*/ | |||||
public interface RegionLimitHelper { | |||||
/** | |||||
* 校验层级包含关系 | |||||
* | |||||
* @param regionContainsBOList / | |||||
* @param regionCode / | |||||
* @param regionLevel / | |||||
* @return / | |||||
*/ | |||||
Boolean regionContains(List<RegionContainsBO> regionContainsBOList, String regionCode, Integer regionLevel); | |||||
/** | |||||
* 查询操作 包含区域包含列表装配 | |||||
* | |||||
* @param queryRegionContainBo 查询区域范围列表 | |||||
* @param expertAdminContainsRegionList 专家管理员可管理的区域范围列表 | |||||
* @return / | |||||
*/ | |||||
List<RegionContainsBO> queryContainsRegionAssembler(RegionContainsBO queryRegionContainBo, List<RegionContainsBO> expertAdminContainsRegionList); | |||||
/** | |||||
* 根据 区域层级-区域编码 获取区域包含列表 | |||||
* | |||||
* @param regionLevel 区域层级 | |||||
* @param regionCode 区域编码 | |||||
* @return / | |||||
*/ | |||||
RegionContainsBO getContainsRegionBo(Integer regionLevel, String regionCode); | |||||
/** | |||||
* 根据专家管理员用户id 获取专家管理员管辖区域列表 | |||||
* | |||||
* @param expertAdminUserId 专家管理员用户id | |||||
* @return | |||||
*/ | |||||
List<RegionContainsBO> getExpertAdminContainsRegion(Long expertAdminUserId); | |||||
} |
@@ -0,0 +1,52 @@ | |||||
package com.hz.pm.api.common.helper; | |||||
import com.hz.pm.api.user.entity.UserInfo; | |||||
import com.hz.pm.api.user.security.auth.model.UserFullInfoDTO; | |||||
import java.util.Collection; | |||||
import java.util.List; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2023/2/10 下午4:38 | |||||
* @Description: 用户信息管理工具类 helper | |||||
*/ | |||||
public interface UserInfoHelper { | |||||
/** | |||||
* 根据用户id 获取 用户所属组织code organizationCode | |||||
* | |||||
* @param userId | |||||
* @return | |||||
*/ | |||||
String getOrganizationCode(Long userId); | |||||
UserFullInfoDTO getUserFullInfo(Long userId); | |||||
UserFullInfoDTO getUserFullInfo(UserInfo userInfo); | |||||
List<UserFullInfoDTO> getUserFullInfos(List<UserInfo> userInfos); | |||||
String getUserName(Long userId); | |||||
/** | |||||
* 判断该用户是否是区管或者超管 | |||||
* | |||||
* @return | |||||
*/ | |||||
boolean isSuperOrRegionAdmin(Long userId); | |||||
UserFullInfoDTO getUserFullInfoByEmployeeCode(String employeeCode); | |||||
List<UserFullInfoDTO> getUserFullInfoByEmployeeCodes(Collection<String> employeeCodes); | |||||
/** | |||||
* 获取用户任职所在单位code | |||||
* | |||||
* @return | |||||
*/ | |||||
String getUserEmpPosUnitCode(Long userId); | |||||
String getMainOrgCode(String empPosUnitCode); | |||||
} |
@@ -0,0 +1,77 @@ | |||||
package com.hz.pm.api.common.helper.basic; | |||||
import com.github.benmanes.caffeine.cache.Caffeine; | |||||
import com.github.benmanes.caffeine.cache.LoadingCache; | |||||
import com.google.common.collect.Lists; | |||||
import com.hz.pm.api.common.model.RegionMapKey; | |||||
import com.hz.pm.api.sys.convert.RegionConverter; | |||||
import com.hz.pm.api.sys.model.dto.RegionDTO; | |||||
import com.hz.pm.api.sys.model.entity.Region; | |||||
import com.hz.pm.api.sys.service.IRegionService; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.InitializingBean; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import java.util.List; | |||||
import java.util.Objects; | |||||
import java.util.concurrent.TimeUnit; | |||||
/** | |||||
* <p> | |||||
* AbstractRegionCache | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 14:41 2023/3/1 | |||||
*/ | |||||
@Slf4j | |||||
public abstract class AbstractRegionCacheHelper implements InitializingBean { | |||||
private static final String PARENT_CODE_ROOT = "-1"; | |||||
@Autowired | |||||
private IRegionService regionService; | |||||
protected LoadingCache<RegionMapKey, RegionDTO> regionsCache; | |||||
private void initRegionCache() { | |||||
List<RegionDTO> allRegions = regionService.all(); | |||||
if (allRegions.isEmpty()) { | |||||
log.warn("区域元数据未初始化"); | |||||
return; | |||||
} | |||||
allRegions.forEach(w -> { | |||||
RegionMapKey key = RegionMapKey.of(w.getRegionCode(), w.getRegionLevel()); | |||||
regionsCache.put(key, w); | |||||
}); | |||||
} | |||||
protected RegionDTO get(RegionMapKey key) { | |||||
return regionsCache.get(key); | |||||
} | |||||
protected List<RegionDTO> all() { | |||||
return Lists.newArrayList(regionsCache.asMap().values()); | |||||
} | |||||
@Override | |||||
public void afterPropertiesSet() { | |||||
regionsCache = Caffeine.newBuilder() | |||||
.refreshAfterWrite(7, TimeUnit.DAYS) | |||||
.maximumSize(512) | |||||
.build(key -> { | |||||
Region region = regionService.getOne(key.getRegionCode(), key.getRegionLevel()); | |||||
if (Objects.isNull(region)) { | |||||
//查不到直接返回null | |||||
return null; | |||||
} | |||||
return RegionConverter.toRegionDTO(region); | |||||
}); | |||||
// 初始化所有区域数据到缓存 | |||||
initRegionCache(); | |||||
} | |||||
public String getParentCodeRoot() { | |||||
return PARENT_CODE_ROOT; | |||||
} | |||||
} |
@@ -0,0 +1,48 @@ | |||||
package com.hz.pm.api.common.helper.basic; | |||||
import com.hz.pm.api.common.helper.RegionCacheHelper; | |||||
import com.hz.pm.api.common.helper.RegionLimitHelper; | |||||
import com.hz.pm.api.expert.entity.ExpertUserFullInfo; | |||||
import com.hz.pm.api.expert.service.IExpertUserFullInfoService; | |||||
import com.hz.pm.api.meta.model.ExpertRegionInfo; | |||||
import com.hz.pm.api.sys.service.IRegionService; | |||||
import com.hz.pm.api.user.service.IUserInfoService; | |||||
import lombok.AllArgsConstructor; | |||||
import java.util.Objects; | |||||
/** | |||||
* <p> | |||||
* AbstractRegionLimitHelper | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 14:35 2023/3/1 | |||||
*/ | |||||
@AllArgsConstructor | |||||
public abstract class AbstractRegionLimitHelper implements RegionLimitHelper { | |||||
protected final RegionCacheHelper regionCache; | |||||
protected final IExpertUserFullInfoService expertUserFullInfoService; | |||||
protected final IUserInfoService iUserInfoService; | |||||
protected final IRegionService regionService; | |||||
/** | |||||
* 根据 专家用户id 获取专家层级 | |||||
* | |||||
* @param expertUserId / | |||||
* @return / | |||||
*/ | |||||
protected ExpertRegionInfo getExpertRegionInfo(Long expertUserId) { | |||||
ExpertUserFullInfo userFullInfo = expertUserFullInfoService.getByUserId(expertUserId); | |||||
if (Objects.isNull(userFullInfo)) { | |||||
return new ExpertRegionInfo(); | |||||
} | |||||
ExpertRegionInfo regionInfo = new ExpertRegionInfo(); | |||||
regionInfo.setRegionCode(userFullInfo.getRegionCode()); | |||||
regionInfo.setRegionLevel(userFullInfo.getRegionLevel()); | |||||
return regionInfo; | |||||
} | |||||
} |
@@ -0,0 +1,127 @@ | |||||
package com.hz.pm.api.common.helper.impl; | |||||
import cn.hutool.core.collection.CollectionUtil; | |||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||||
import com.hz.pm.api.common.helper.RegionCacheHelper; | |||||
import com.hz.pm.api.common.helper.basic.AbstractRegionLimitHelper; | |||||
import com.hz.pm.api.expert.service.IExpertUserFullInfoService; | |||||
import com.hz.pm.api.meta.model.bo.RegionContainsBO; | |||||
import com.hz.pm.api.sys.model.entity.Region; | |||||
import com.hz.pm.api.sys.service.IRegionService; | |||||
import com.hz.pm.api.user.entity.UserInfo; | |||||
import com.hz.pm.api.user.service.IUserInfoService; | |||||
import org.apache.commons.collections4.CollectionUtils; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import org.springframework.stereotype.Component; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.List; | |||||
import java.util.Objects; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/8/1 下午2:27 | |||||
*/ | |||||
@Component | |||||
public class RegionLimitHelperImpl extends AbstractRegionLimitHelper { | |||||
private static final Logger logger = LoggerFactory.getLogger(RegionLimitHelperImpl.class); | |||||
public RegionLimitHelperImpl(RegionCacheHelper regionCache, IExpertUserFullInfoService expertUserFullInfoService | |||||
, IUserInfoService iUserInfoService, IRegionService regionService) { | |||||
super(regionCache, expertUserFullInfoService, iUserInfoService, regionService); | |||||
} | |||||
public static Boolean contains(Integer adminRegionLevel, List<String> adminAllContainsRegionCodes | |||||
, Integer expertRegionLevel, String expertRegionCode) { | |||||
for (String adminAllContainsRegionCode : adminAllContainsRegionCodes) { | |||||
if (adminAllContainsRegionCode.equals(expertRegionCode) && adminRegionLevel >= expertRegionLevel) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
@Override | |||||
public Boolean regionContains(List<RegionContainsBO> regionContainsBOList, String regionCode, Integer regionLevel) { | |||||
for (RegionContainsBO regionContainsBO : regionContainsBOList) { | |||||
Integer parentRegionTreeLevel = regionContainsBO.getParentRegionTreeLevel(); | |||||
List<String> containsRegionCodeList = regionContainsBO.getContainsRegionCodeList(); | |||||
for (String containsRegionCode : containsRegionCodeList) { | |||||
if (containsRegionCode.equals(regionCode) && parentRegionTreeLevel <= regionLevel) { | |||||
return true; | |||||
} | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
@Override | |||||
public List<RegionContainsBO> queryContainsRegionAssembler(RegionContainsBO queryRegionContainBo, List<RegionContainsBO> expertAdminContainsRegionList) { | |||||
List<RegionContainsBO> resultBoList = new ArrayList<>(); | |||||
if (Objects.nonNull(queryRegionContainBo)) { | |||||
List<String> containsRegionCodeList = queryRegionContainBo.getContainsRegionCodeList(); | |||||
// 查询取并级 | |||||
if (CollectionUtils.isNotEmpty(expertAdminContainsRegionList)) { | |||||
for (RegionContainsBO regionContainsBO : expertAdminContainsRegionList) { | |||||
List<String> regionCodeList = regionContainsBO.getContainsRegionCodeList(); | |||||
regionCodeList.retainAll(containsRegionCodeList); | |||||
if (CollectionUtils.isNotEmpty(regionCodeList)) { | |||||
regionContainsBO.setContainsRegionCodeList(regionCodeList); | |||||
resultBoList.add(regionContainsBO); | |||||
} | |||||
} | |||||
} | |||||
return resultBoList; | |||||
} else { | |||||
return expertAdminContainsRegionList; | |||||
} | |||||
} | |||||
@Override | |||||
public RegionContainsBO getContainsRegionBo(Integer regionLevel, String regionCode) { | |||||
Collection<String> regionCodes = regionCache.listChildRegionCodeList(regionCode, regionLevel); | |||||
RegionContainsBO regionContains = new RegionContainsBO(); | |||||
regionContains.setContainsRegionCodeList(new ArrayList<>(regionCodes)); | |||||
regionContains.setParentRegionTreeLevel(regionLevel); | |||||
return regionContains; | |||||
} | |||||
@Override | |||||
public List<RegionContainsBO> getExpertAdminContainsRegion(Long expertAdminUserId) { | |||||
if (Objects.isNull(expertAdminUserId)) { | |||||
logger.error("getExpertAdminContainsRegion expertAdminUserId is null"); | |||||
return new ArrayList<>(); | |||||
} | |||||
UserInfo userInfo = iUserInfoService.getById(expertAdminUserId); | |||||
if (Objects.isNull(userInfo) || StringUtils.isBlank(userInfo.getRegionCode())) { | |||||
logger.error("getExpertAdminContainsRegion userInfo is null Or regionCode is null"); | |||||
return new ArrayList<>(); | |||||
} | |||||
String regionCode = userInfo.getRegionCode(); | |||||
List<Region> regionList = regionService.list(Wrappers.lambdaQuery(Region.class) | |||||
.eq(Region::getRegionCode, regionCode) | |||||
.orderByDesc(Region::getRegionLevel)); | |||||
Region region = regionList.get(0); | |||||
Collection<String> regionCodes = regionCache | |||||
.listChildRegionCodeList(region.getRegionCode(), region.getRegionLevel()); | |||||
RegionContainsBO regionContainsBO = new RegionContainsBO(); | |||||
regionContainsBO.setContainsRegionCodeList(new ArrayList<>(regionCodes)); | |||||
regionContainsBO.setParentRegionTreeLevel(region.getRegionLevel()); | |||||
ArrayList<RegionContainsBO> regionContainsBOS = CollectionUtil.toList(regionContainsBO); | |||||
return regionContainsBOS; | |||||
} | |||||
} |
@@ -0,0 +1,244 @@ | |||||
package com.hz.pm.api.common.helper.impl; | |||||
import cn.hutool.core.collection.CollUtil; | |||||
import cn.hutool.core.text.StrPool; | |||||
import com.ningdatech.basic.exception.BizException; | |||||
import com.ningdatech.basic.util.CollUtils; | |||||
import com.hz.pm.api.common.constant.RegionConst; | |||||
import com.hz.pm.api.common.helper.RegionCacheHelper; | |||||
import com.hz.pm.api.common.helper.basic.AbstractRegionCacheHelper; | |||||
import com.hz.pm.api.common.model.RegionMapKey; | |||||
import com.hz.pm.api.common.util.StrUtils; | |||||
import com.hz.pm.api.sys.convert.RegionConverter; | |||||
import com.hz.pm.api.sys.model.dto.RegionDTO; | |||||
import com.hz.pm.api.sys.model.dto.RegionTreeDTO; | |||||
import com.hz.pm.api.sys.model.vo.RegionTreeVO; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.apache.commons.collections4.CollectionUtils; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import org.springframework.stereotype.Component; | |||||
import java.util.*; | |||||
import java.util.stream.Collectors; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/7/22 上午8:58 | |||||
* 构建地区码 地区树 | |||||
*/ | |||||
@Slf4j | |||||
@Component | |||||
public class RegionsCacheHelperImpl extends AbstractRegionCacheHelper implements RegionCacheHelper { | |||||
@Override | |||||
public RegionDTO getByCodeAndLevel(String code, Integer level) { | |||||
if (StringUtils.isBlank(code) || Objects.isNull(level)) { | |||||
return null; | |||||
} | |||||
return super.get(RegionMapKey.of(code, level)); | |||||
} | |||||
@Override | |||||
public String getRegionName(String code, int level) { | |||||
RegionDTO dto = getByCodeAndLevel(code, level); | |||||
if (Objects.nonNull(dto)) { | |||||
return dto.getRegionName(); | |||||
} | |||||
return StringUtils.EMPTY; | |||||
} | |||||
@Override | |||||
public List<RegionDTO> all() { | |||||
return super.all(); | |||||
} | |||||
@Override | |||||
public Collection<String> listChildRegionCodeList(String regionCode, int regionLevel) { | |||||
RegionDTO currRegion = getByCodeAndLevel(regionCode, regionLevel); | |||||
if (Objects.isNull(currRegion)) { | |||||
return Collections.emptyList(); | |||||
} | |||||
if (currRegion.getParentCode().equals(regionCode)) { | |||||
return Collections.singletonList(regionCode); | |||||
} | |||||
List<RegionDTO> allRegions = all(); | |||||
return allRegions.stream().filter(w -> StrUtils.split(w.getRegionCodePath()).contains(regionCode)) | |||||
.map(RegionDTO::getRegionCode).collect(Collectors.toSet()); | |||||
} | |||||
@Override | |||||
public RegionTreeVO getRegionTree(String regionCode, Integer regionLevel) { | |||||
Map<Long, List<RegionDTO>> regions; | |||||
Long parentId; | |||||
if (regionCode == null || regionCode.equals(RegionConst.RC_CHINA)) { | |||||
regions = CollUtils.group(all(), RegionDTO::getParentId); | |||||
parentId = RegionConst.PID_CHINA; | |||||
} else { | |||||
RegionDTO currRegion = getByCodeAndLevel(regionCode, regionLevel); | |||||
if (currRegion.getParentCode().equals(regionCode)) { | |||||
return RegionConverter.toRegionTreeVO(currRegion); | |||||
} | |||||
regions = all().stream() | |||||
.filter(w -> StrUtils.split(w.getRegionCodePath()).contains(regionCode)) | |||||
.collect(Collectors.groupingBy(RegionDTO::getParentId)); | |||||
parentId = currRegion.getParentId(); | |||||
} | |||||
regions.values().forEach(w -> w.sort(Comparator.comparing(x -> Long.parseLong(x.getRegionCode())))); | |||||
return RegionConverter.toRegionTree(parentId, regions, false).get(0); | |||||
} | |||||
@Override | |||||
public String getFullDisplayName(String regionCode, Integer regionLevel) { | |||||
RegionDTO regionCurr = getByCodeAndLevel(regionCode, regionLevel); | |||||
return getDisplayName(regionCurr, RegionConst.RL_PROVINCE); | |||||
} | |||||
@Override | |||||
public String getDisplayName(String regionCode, Integer regionLevel) { | |||||
RegionDTO regionCurr = getByCodeAndLevel(regionCode, regionLevel); | |||||
return getDisplayName(regionCurr, RegionConst.RL_CITY); | |||||
} | |||||
//------------------------------------------------------------------------------------------------------------------ | |||||
/** | |||||
* 获取指定层级的展示名称 | |||||
* | |||||
* @param region 当前区域 | |||||
* @param sLevel 开始层级 | |||||
* @return 展示名称 | |||||
*/ | |||||
private String getDisplayName(RegionDTO region, int sLevel) { | |||||
if (Objects.isNull(region)) { | |||||
return StringUtils.EMPTY; | |||||
} | |||||
Integer level = region.getRegionLevel(); | |||||
if (RegionConst.RL_PROVINCE > sLevel || sLevel > level) { | |||||
throw BizException.wrap("区域层级无效"); | |||||
} | |||||
if (sLevel == level) { | |||||
return region.getRegionName(); | |||||
} | |||||
StringBuilder builder = new StringBuilder(); | |||||
List<String> regionCodes = StrUtils.split(region.getRegionCodePath()); | |||||
for (int i = regionCodes.size() - 2; i > 0; i--) { | |||||
if (level <= sLevel) { | |||||
break; | |||||
} | |||||
RegionDTO tmp = getByCodeAndLevel(regionCodes.get(i), --level); | |||||
builder.insert(0, StrPool.SLASH); | |||||
builder.insert(0, tmp.getRegionName()); | |||||
} | |||||
builder.append(region.getRegionName()); | |||||
return builder.toString(); | |||||
} | |||||
protected List<RegionTreeDTO> getCopyListByLevel(int level) { | |||||
List<RegionDTO> regions = all().stream() | |||||
.filter(w -> w.getRegionLevel() <= level) | |||||
.collect(Collectors.toList()); | |||||
return RegionConverter.toRegionTreeDTOList(regions); | |||||
} | |||||
/** | |||||
* 获取某一个地区开始的层级树 | |||||
* | |||||
* @param list 地区集合 | |||||
* @param code 地区编码 | |||||
* @param level 地区层级 | |||||
* @return / | |||||
*/ | |||||
private RegionTreeDTO getTreeByRegionAndCode(List<RegionTreeDTO> list, String code, int level) { | |||||
if (CollectionUtils.isEmpty(list)) { | |||||
list = getCopyListByLevel(3); | |||||
if (CollectionUtils.isEmpty(list)) { | |||||
return null; | |||||
} | |||||
} | |||||
Optional<RegionTreeDTO> first = list.stream() | |||||
.filter(w -> w.getRegionCode().equals(code) && w.getLevel() == level) | |||||
.findFirst(); | |||||
if (first.isPresent()) { | |||||
return first.get(); | |||||
} | |||||
for (RegionTreeDTO dto : list) { | |||||
if (CollectionUtils.isEmpty(dto.getChildren())) { | |||||
continue; | |||||
} | |||||
RegionTreeDTO temp = getTreeByRegionAndCode(dto.getChildren(), code, level); | |||||
if (temp != null) { | |||||
return temp; | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
@Override | |||||
public List<RegionDTO> listParents(String code, int level) { | |||||
List<RegionDTO> result = new ArrayList<>(); | |||||
RegionDTO dto = getByCodeAndLevel(code, level); | |||||
result.add(0, dto); | |||||
if (RegionConst.RC_CHINA.equals(dto.getParentCode())) { | |||||
return result; | |||||
} | |||||
result.addAll(0, listParents(dto.getParentCode(), dto.getRegionLevel() - 1)); | |||||
return result; | |||||
} | |||||
@Override | |||||
public List<RegionDTO> listChildren(String code, int level) { | |||||
RegionDTO curr = getByCodeAndLevel(code, level); | |||||
if (curr.getParentCode().equals(curr.getRegionCode())) { | |||||
return Collections.singletonList(curr); | |||||
} | |||||
return all().stream() | |||||
.filter(w -> StrUtils.split(w.getRegionCodePath()).contains(code)) | |||||
.collect(Collectors.toList()); | |||||
} | |||||
@Override | |||||
public String getUnionPath(String code, Integer level) { | |||||
if (StrUtils.isBlank(code) || Objects.isNull(level)) { | |||||
return StrUtils.EMPTY; | |||||
} | |||||
List<String> unionPathStrList = new ArrayList<>(); | |||||
buildUnionPathStrList(code, level, unionPathStrList); | |||||
Collections.reverse(unionPathStrList); | |||||
if (CollUtil.isEmpty(unionPathStrList)) { | |||||
return StrUtils.EMPTY; | |||||
} | |||||
return String.join("@@", unionPathStrList); | |||||
} | |||||
@Override | |||||
public RegionDTO getByRegionName(String regionName) { | |||||
if (StrUtils.isBlank(regionName)) { | |||||
return null; | |||||
} | |||||
String[] regionArray = regionName.split("-"); | |||||
int length = regionArray.length; | |||||
return all().stream() | |||||
.filter(w -> { | |||||
boolean lastEq = w.getRegionLevel().equals(length) | |||||
&& w.getRegionName().equals(regionArray[length - 1]); | |||||
if (lastEq && length > 1) { | |||||
RegionDTO parent = getByCodeAndLevel(w.getParentCode(), w.getRegionLevel() - 1); | |||||
return parent.getRegionName().equals(regionArray[length - 2]); | |||||
} | |||||
return false; | |||||
}).findFirst().orElse(null); | |||||
} | |||||
protected void buildUnionPathStrList(String code, Integer level, List<String> unionPathStrList) { | |||||
if (level <= 0 || super.getParentCodeRoot().equals(code)) { | |||||
return; | |||||
} | |||||
RegionDTO regionDTO = getByCodeAndLevel(code, level); | |||||
unionPathStrList.add(regionDTO.getRegionCode() + "##" + regionDTO.getRegionName() + "##" + regionDTO.getRegionLevel()); | |||||
if (!super.getParentCodeRoot().equals(regionDTO.getParentCode())) { | |||||
buildUnionPathStrList(regionDTO.getParentCode(), level - 1, unionPathStrList); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,247 @@ | |||||
package com.hz.pm.api.common.helper.impl; | |||||
import cn.hutool.core.collection.CollUtil; | |||||
import cn.hutool.core.collection.CollectionUtil; | |||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||||
import com.hz.pm.api.common.constant.BizConst; | |||||
import com.hz.pm.api.common.helper.UserInfoHelper; | |||||
import com.hz.pm.api.organization.model.entity.DingEmployeeInfo; | |||||
import com.hz.pm.api.organization.model.entity.DingOrganization; | |||||
import com.hz.pm.api.organization.service.IDingEmployeeInfoService; | |||||
import com.hz.pm.api.organization.service.IDingOrganizationService; | |||||
import com.hz.pm.api.sys.mapper.RoleMapper; | |||||
import com.hz.pm.api.sys.model.entity.Role; | |||||
import com.hz.pm.api.sys.model.entity.UserRole; | |||||
import com.hz.pm.api.sys.service.IUserRoleService; | |||||
import com.hz.pm.api.user.constant.UserAvailableEnum; | |||||
import com.hz.pm.api.user.entity.UserInfo; | |||||
import com.hz.pm.api.user.entity.enumeration.RoleEnum; | |||||
import com.hz.pm.api.user.security.auth.model.UserFullInfoDTO; | |||||
import com.hz.pm.api.user.service.IUserInfoService; | |||||
import lombok.RequiredArgsConstructor; | |||||
import org.springframework.stereotype.Component; | |||||
import java.util.*; | |||||
import java.util.stream.Collectors; | |||||
import java.util.stream.Stream; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2023/2/10 下午4:40 | |||||
*/ | |||||
@Component | |||||
@RequiredArgsConstructor | |||||
public class UserInfoHelperImpl implements UserInfoHelper { | |||||
private final IUserInfoService userInfoService; | |||||
private final IDingEmployeeInfoService iDingEmployeeInfoService; | |||||
private final IDingOrganizationService iDingOrganizationService; | |||||
private final IUserRoleService iUserRoleService; | |||||
private final RoleMapper roleMapper; | |||||
@Override | |||||
public String getOrganizationCode(Long userId) { | |||||
UserFullInfoDTO userFullInfo = getUserFullInfo(userId); | |||||
return userFullInfo.getOrganizationCode(); | |||||
} | |||||
@Override | |||||
public UserFullInfoDTO getUserFullInfo(Long userId) { | |||||
UserInfo userInfo = userInfoService.getById(userId); | |||||
if (Objects.isNull(userInfo)) { | |||||
return null; | |||||
} | |||||
// 返回用户全量信息 | |||||
return getUserFullInfo(userInfo); | |||||
} | |||||
@Override | |||||
public UserFullInfoDTO getUserFullInfo(UserInfo userInfo) { | |||||
UserFullInfoDTO userFullInfo = new UserFullInfoDTO(); | |||||
// 获取浙政钉雇员信息 组织信息 | |||||
String employeeCode = userInfo.getEmployeeCode(); | |||||
if (StringUtils.isNotBlank(employeeCode)) { | |||||
List<DingEmployeeInfo> dingEmployeeInfoList = iDingEmployeeInfoService | |||||
.list(Wrappers.lambdaQuery(DingEmployeeInfo.class) | |||||
.eq(DingEmployeeInfo::getEmployeeCode, employeeCode) | |||||
.eq(DingEmployeeInfo::getMainJob, "true")); | |||||
DingEmployeeInfo dingEmployeeInfo = dingEmployeeInfoList.get(0); | |||||
// 装配用户任职所在单位 | |||||
String empPosUnitCode = dingEmployeeInfo.getEmpPosUnitCode(); | |||||
if (StringUtils.isNotBlank(empPosUnitCode)) { | |||||
DingOrganization dingOrganization = iDingOrganizationService.getByOrgCode(empPosUnitCode); | |||||
if (Objects.nonNull(dingOrganization)) { | |||||
userFullInfo.setEmpPosUnitCode(empPosUnitCode); | |||||
userFullInfo.setEmpPosUnitName(dingOrganization.getOrganizationName()); | |||||
userFullInfo.setRegionCode(dingOrganization.getDivisionCode()); | |||||
} | |||||
} | |||||
// 装配用户所在orgCode | |||||
String organizationCode = dingEmployeeInfo.getOrganizationCode(); | |||||
List<DingOrganization> dingOrganizationList = iDingOrganizationService.list(Wrappers | |||||
.lambdaQuery(DingOrganization.class) | |||||
.eq(DingOrganization::getOrganizationCode, organizationCode)); | |||||
if (CollectionUtil.isNotEmpty(dingOrganizationList)) { | |||||
DingOrganization dingOrganization = dingOrganizationList.get(0); | |||||
userFullInfo.setOrganizationCode(dingOrganization.getOrganizationCode()); | |||||
userFullInfo.setOrganizationName(dingOrganization.getOrganizationName()); | |||||
// 测试使用 | |||||
userFullInfo.setRegionLevel(3); | |||||
} | |||||
} | |||||
List<Role> roleList = new ArrayList<>(); | |||||
// 获取用户角色列表信息 | |||||
List<UserRole> userRoleList = iUserRoleService | |||||
.list(Wrappers.lambdaQuery(UserRole.class) | |||||
.eq(UserRole::getUserId, userInfo.getId())); | |||||
if (CollectionUtil.isNotEmpty(userRoleList)) { | |||||
List<Long> roleIdList = userRoleList.stream() | |||||
.map(UserRole::getRoleId).distinct() | |||||
.collect(Collectors.toList()); | |||||
roleList = roleMapper.selectBatchIds(roleIdList); | |||||
} | |||||
userFullInfo.setUserRoleList(roleList); | |||||
// 装配用户任职所在单位 | |||||
// 装配返回 | |||||
userFullInfo.setUserId(userInfo.getId()); | |||||
userFullInfo.setIdentifier(userInfo.getRealName()); | |||||
userFullInfo.setRealName(userInfo.getRealName()); | |||||
userFullInfo.setEmployeeCode(employeeCode); | |||||
userFullInfo.setUsername(userInfo.getRealName()); | |||||
userFullInfo.setMobile(userInfo.getMobile()); | |||||
userFullInfo.setAccountId(userInfo.getAccountId()); | |||||
String available = userInfo.getAvailable(); | |||||
if (StringUtils.isNotBlank(available)) { | |||||
userFullInfo.setAvailable(UserAvailableEnum.valueOf(available)); | |||||
} | |||||
return userFullInfo; | |||||
} | |||||
/** | |||||
* 批量查询 这里 会没有角色 | |||||
* | |||||
* @param userInfos \ | |||||
* @return \ | |||||
*/ | |||||
@Override | |||||
public List<UserFullInfoDTO> getUserFullInfos(List<UserInfo> userInfos) { | |||||
if (CollUtil.isEmpty(userInfos)) { | |||||
return Collections.emptyList(); | |||||
} | |||||
Map<String, UserInfo> userMap = userInfos.stream().collect(Collectors.toMap(UserInfo::getEmployeeCode, e -> e)); | |||||
// 获取浙政钉雇员信息 组织信息 | |||||
List<String> employeeCodes = userInfos.stream().map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
List<DingEmployeeInfo> dingEmployeeInfoList = iDingEmployeeInfoService | |||||
.list(Wrappers.lambdaQuery(DingEmployeeInfo.class) | |||||
.in(DingEmployeeInfo::getEmployeeCode, employeeCodes) | |||||
.eq(DingEmployeeInfo::getMainJob, "true")); | |||||
if (CollUtil.isEmpty(dingEmployeeInfoList)) { | |||||
return Collections.emptyList(); | |||||
} | |||||
// 装配用户任职所在单位 | |||||
List<String> empPosUnitCodes = dingEmployeeInfoList.stream().map(DingEmployeeInfo::getEmpPosUnitCode).collect(Collectors.toList()); | |||||
List<String> orgCodes = dingEmployeeInfoList.stream().map(DingEmployeeInfo::getOrganizationCode).collect(Collectors.toList()); | |||||
List<String> allOrgCodes = Stream.concat(empPosUnitCodes.stream(), orgCodes.stream()).collect(Collectors.toList()); | |||||
if (CollUtil.isEmpty(allOrgCodes)) { | |||||
return Collections.emptyList(); | |||||
} | |||||
List<DingOrganization> dingOrganizations = iDingOrganizationService.listByCodes(allOrgCodes); | |||||
if (CollUtil.isEmpty(dingOrganizations)) { | |||||
return Collections.emptyList(); | |||||
} | |||||
Map<String, DingOrganization> orgMap = dingOrganizations.stream().collect(Collectors.toMap(DingOrganization::getOrganizationCode, d -> d)); | |||||
return dingEmployeeInfoList.stream().map(e -> { | |||||
UserFullInfoDTO userFullInfo = new UserFullInfoDTO(); | |||||
if (orgMap.containsKey(e.getEmpPosUnitCode())) { | |||||
DingOrganization organization = orgMap.get(e.getEmpPosUnitCode()); | |||||
userFullInfo.setEmpPosUnitCode(e.getEmpPosUnitCode()); | |||||
userFullInfo.setEmpPosUnitName(organization.getOrganizationName()); | |||||
userFullInfo.setRegionCode(organization.getDivisionCode()); | |||||
} | |||||
if (orgMap.containsKey(e.getOrganizationCode())) { | |||||
DingOrganization organization = orgMap.get(e.getOrganizationCode()); | |||||
userFullInfo.setOrganizationCode(organization.getOrganizationCode()); | |||||
userFullInfo.setOrganizationName(organization.getOrganizationName()); | |||||
// 测试使用 | |||||
userFullInfo.setRegionLevel(3); | |||||
} | |||||
if (userMap.containsKey(e.getEmployeeCode())) { | |||||
UserInfo userInfo = userMap.get(e.getEmployeeCode()); | |||||
// 装配返回 | |||||
userFullInfo.setUserId(userInfo.getId()); | |||||
userFullInfo.setIdentifier(userInfo.getRealName()); | |||||
userFullInfo.setRealName(userInfo.getRealName()); | |||||
userFullInfo.setEmployeeCode(e.getEmployeeCode()); | |||||
userFullInfo.setUsername(userInfo.getRealName()); | |||||
userFullInfo.setMobile(userInfo.getMobile()); | |||||
userFullInfo.setAccountId(userInfo.getAccountId()); | |||||
String available = userInfo.getAvailable(); | |||||
if (StringUtils.isNotBlank(available)) { | |||||
userFullInfo.setAvailable(UserAvailableEnum.valueOf(available)); | |||||
} | |||||
} | |||||
return userFullInfo; | |||||
}).collect(Collectors.toList()); | |||||
} | |||||
@Override | |||||
public String getUserName(Long userId) { | |||||
UserFullInfoDTO userFullInfo = getUserFullInfo(userId); | |||||
return userFullInfo.getRealName(); | |||||
} | |||||
@Override | |||||
public boolean isSuperOrRegionAdmin(Long userId) { | |||||
UserFullInfoDTO userFullInfo = getUserFullInfo(userId); | |||||
if (CollUtil.isNotEmpty(userFullInfo.getUserRoleList())) { | |||||
for (Role role : userFullInfo.getUserRoleList()) { | |||||
if (RoleEnum.SUPER_ADMIN.name().equals(role.getCode()) || | |||||
RoleEnum.REGION_MANAGER.name().equals(role.getCode())) { | |||||
return Boolean.TRUE; | |||||
} | |||||
} | |||||
} | |||||
return Boolean.FALSE; | |||||
} | |||||
@Override | |||||
public UserFullInfoDTO getUserFullInfoByEmployeeCode(String employeeCode) { | |||||
UserInfo userInfo = userInfoService.getUserInfoByEmployeeCode(employeeCode); | |||||
return getUserFullInfo(userInfo); | |||||
} | |||||
@Override | |||||
public List<UserFullInfoDTO> getUserFullInfoByEmployeeCodes(Collection<String> employeeCodes) { | |||||
List<UserInfo> userInfos = userInfoService.getUserInfoByEmployeeCodes(employeeCodes); | |||||
return getUserFullInfos(userInfos); | |||||
} | |||||
@Override | |||||
public String getUserEmpPosUnitCode(Long userId) { | |||||
UserFullInfoDTO userFullInfo = getUserFullInfo(userId); | |||||
return userFullInfo.getEmpPosUnitCode(); | |||||
} | |||||
@Override | |||||
public String getMainOrgCode(String empPosUnitCode) { | |||||
DingOrganization org = iDingOrganizationService.getOne(Wrappers.lambdaQuery(DingOrganization.class) | |||||
.eq(DingOrganization::getOrganizationCode, empPosUnitCode) | |||||
.last(BizConst.LIMIT_1)); | |||||
if(Objects.isNull(org)){ | |||||
return null; | |||||
} | |||||
return org.getParentCode(); | |||||
} | |||||
} |
@@ -0,0 +1,38 @@ | |||||
package com.hz.pm.api.common.interceptor; | |||||
import cn.hutool.core.lang.UUID; | |||||
import com.hz.pm.api.common.util.MDCUtil; | |||||
import org.springframework.lang.NonNull; | |||||
import org.springframework.web.servlet.HandlerInterceptor; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
/** | |||||
* <p> | |||||
* LogInterceptor | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 2023/10/26 | |||||
**/ | |||||
public class LogInterceptor implements HandlerInterceptor { | |||||
@Override | |||||
public boolean preHandle(@NonNull HttpServletRequest request, | |||||
@NonNull HttpServletResponse response, | |||||
@NonNull Object handler) { | |||||
String traceId = UUID.randomUUID().toString(true); | |||||
response.addHeader(MDCUtil.TRACE_ID_HEADER, traceId); | |||||
MDCUtil.setTraceId(traceId); | |||||
return true; | |||||
} | |||||
@Override | |||||
public void afterCompletion(@NonNull HttpServletRequest request, | |||||
@NonNull HttpServletResponse response, | |||||
@NonNull Object handler, Exception ex) { | |||||
MDCUtil.removeTraceId(); | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
package com.hz.pm.api.common.model; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
import java.io.Serializable; | |||||
import java.util.List; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/8/4 上午11:34 | |||||
*/ | |||||
@Data | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public class CommonPage<T> implements Serializable { | |||||
private static final long serialVersionUID = 1L; | |||||
private int currentPageNumber; | |||||
private Long itemsTotal; | |||||
private List<T> items; | |||||
} |
@@ -0,0 +1,22 @@ | |||||
package com.hz.pm.api.common.model; | |||||
import lombok.Data; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/8/4 上午11:19 | |||||
*/ | |||||
@Data | |||||
public class CommonPageReq { | |||||
private static final long serialVersionUID = 1L; | |||||
private int pageSize; | |||||
private int pageNumber; | |||||
public int getOffset() { | |||||
return (this.getPageNumber() - 1) * this.getPageSize(); | |||||
} | |||||
public int getLimit() { | |||||
return this.getPageSize(); | |||||
} | |||||
} |
@@ -0,0 +1,19 @@ | |||||
package com.hz.pm.api.common.model; | |||||
import com.hz.pm.api.meta.model.ExpertRegionInfo; | |||||
import lombok.Data; | |||||
import java.util.List; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/7/28 下午4:34 | |||||
*/ | |||||
@Data | |||||
public class ExpertRegionModifyDiffBO { | |||||
private List<ExpertRegionInfo> addList; | |||||
private List<ExpertRegionInfo> removeList; | |||||
} |
@@ -0,0 +1,24 @@ | |||||
package com.hz.pm.api.common.model; | |||||
import io.swagger.annotations.ApiModel; | |||||
import io.swagger.annotations.ApiModelProperty; | |||||
import lombok.Data; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/7/25 下午1:55 | |||||
* 用于包装使用 | |||||
*/ | |||||
@Data | |||||
@ApiModel("文件信息基类") | |||||
public class FileBasicInfo { | |||||
@ApiModelProperty("文件id") | |||||
private Long fileId; | |||||
@ApiModelProperty("文件url") | |||||
private String url; | |||||
@ApiModelProperty("文件名") | |||||
private String fileName; | |||||
} |
@@ -0,0 +1,22 @@ | |||||
package com.hz.pm.api.common.model; | |||||
import lombok.Data; | |||||
/** | |||||
* <p> | |||||
* FreemarkerBatchExportDTO | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 2023/8/1 | |||||
**/ | |||||
@Data | |||||
public class FreemarkerBatchExportDTO { | |||||
private String fileName; | |||||
private String template; | |||||
private Object data; | |||||
} |
@@ -0,0 +1,53 @@ | |||||
package com.hz.pm.api.common.model; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Builder; | |||||
import lombok.Data; | |||||
import lombok.experimental.Tolerate; | |||||
import java.util.Objects; | |||||
/** | |||||
* <p> | |||||
* RegionMapKey | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 13:54 2023/3/1 | |||||
*/ | |||||
@Data | |||||
@AllArgsConstructor | |||||
public class RegionMapKey { | |||||
public static RegionMapKey of(String regionCode, int regionLevel) { | |||||
return new RegionMapKey(regionCode, regionLevel); | |||||
} | |||||
/** | |||||
* 区域码 | |||||
*/ | |||||
private String regionCode; | |||||
/** | |||||
* 地区级别 | |||||
*/ | |||||
private Integer regionLevel; | |||||
@Override | |||||
public boolean equals(Object o) { | |||||
if (this == o) { | |||||
return true; | |||||
} | |||||
if (o == null || getClass() != o.getClass()) { | |||||
return false; | |||||
} | |||||
RegionMapKey regionMapKey = (RegionMapKey) o; | |||||
return regionCode.equals(regionMapKey.getRegionCode()) | |||||
&& regionLevel.equals(regionMapKey.getRegionLevel()); | |||||
} | |||||
@Override | |||||
public int hashCode() { | |||||
return Objects.hash(regionCode, regionLevel); | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
package com.hz.pm.api.common.model; | |||||
import lombok.Data; | |||||
/** | |||||
* <p> | |||||
* ReqRegionDTO | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 2023/8/4 | |||||
**/ | |||||
@Data | |||||
public class ReqRegionDTO { | |||||
private String regionCode; | |||||
private Integer regionLevel; | |||||
} |
@@ -0,0 +1,16 @@ | |||||
package com.hz.pm.api.common.model; | |||||
import lombok.Data; | |||||
@Data | |||||
public class ZwddTokenUser { | |||||
private Long accountId; | |||||
private String employeeCode; | |||||
private String employeeName; | |||||
private String mobile; | |||||
private Long tenantId; | |||||
} |
@@ -0,0 +1,20 @@ | |||||
package com.hz.pm.api.common.model.entity; | |||||
import lombok.Data; | |||||
/** | |||||
* <p> | |||||
* CountGroupByDto | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 15:44 2022/8/28 | |||||
*/ | |||||
@Data | |||||
public class CountGroupByDTO<T> { | |||||
private Integer total; | |||||
private T groupKey; | |||||
} |
@@ -0,0 +1,73 @@ | |||||
package com.hz.pm.api.common.model.entity; | |||||
import io.swagger.annotations.ApiModelProperty; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
import java.math.BigDecimal; | |||||
/** | |||||
* <p> | |||||
* DataDTO | |||||
* </p> | |||||
* | |||||
* @author ZPF | |||||
* @since 16:40 2023/12/05 | |||||
*/ | |||||
@Data | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public class DataDTO { | |||||
public static DataDTO of(String name,Integer num){ | |||||
DataDTO dataDTO = new DataDTO(); | |||||
dataDTO.setName(name); | |||||
dataDTO.setNum(num); | |||||
return dataDTO; | |||||
} | |||||
public static DataDTO of(String name,String code,Integer num){ | |||||
DataDTO dataDTO = new DataDTO(); | |||||
dataDTO.setName(name); | |||||
dataDTO.setCode(code); | |||||
dataDTO.setNum(num); | |||||
return dataDTO; | |||||
} | |||||
public static DataDTO of(String name,BigDecimal amount){ | |||||
DataDTO dataDTO = new DataDTO(); | |||||
dataDTO.setName(name); | |||||
dataDTO.setAmount(amount); | |||||
return dataDTO; | |||||
} | |||||
public static DataDTO of(String name,String code,BigDecimal amount){ | |||||
DataDTO dataDTO = new DataDTO(); | |||||
dataDTO.setName(name); | |||||
dataDTO.setCode(code); | |||||
dataDTO.setAmount(amount); | |||||
return dataDTO; | |||||
} | |||||
public static DataDTO ofRate(String name,BigDecimal rate){ | |||||
DataDTO dataDTO = new DataDTO(); | |||||
dataDTO.setName(name); | |||||
dataDTO.setRate(rate); | |||||
return dataDTO; | |||||
} | |||||
@ApiModelProperty("编号") | |||||
private String code; | |||||
@ApiModelProperty("名称") | |||||
private String name; | |||||
@ApiModelProperty("数量") | |||||
private Integer num = 0; | |||||
@ApiModelProperty("金额") | |||||
private BigDecimal amount = BigDecimal.ZERO; | |||||
@ApiModelProperty("比例") | |||||
private BigDecimal rate = BigDecimal.ZERO; | |||||
} |
@@ -0,0 +1,200 @@ | |||||
package com.hz.pm.api.common.model.entity; | |||||
import com.alibaba.excel.annotation.ExcelProperty; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
import java.io.Serializable; | |||||
import java.math.BigDecimal; | |||||
/** | |||||
* 待办中心待我处理项目列表导出实体 | |||||
* | |||||
* @author CMM | |||||
* @since 2023/01/19 16:42 | |||||
*/ | |||||
@Data | |||||
@NoArgsConstructor | |||||
@AllArgsConstructor | |||||
public class ExcelExportDTO implements Serializable { | |||||
private static final long serialVersionUID = 1L; | |||||
@ExcelProperty("项目ID") | |||||
private Long id; | |||||
@ExcelProperty("项目名称") | |||||
private String projectName; | |||||
@ExcelProperty("行政区划编码") | |||||
private String areaCode; | |||||
@ExcelProperty("行政区划名称") | |||||
private String area; | |||||
@ExcelProperty("项目负责人") | |||||
private String responsibleMan; | |||||
@ExcelProperty("项目负责人手机号") | |||||
private String responsibleManMobile; | |||||
@ExcelProperty("项目联系人") | |||||
private String contactName; | |||||
@ExcelProperty("项目联系人手机号") | |||||
private String contactPhone; | |||||
@ExcelProperty("上级业务主管单位") | |||||
private String higherSuperOrg; | |||||
@ExcelProperty("上级主管单位浙政钉ID") | |||||
private String higherSuperOrgCode; | |||||
@ExcelProperty("本级主管部门") | |||||
private String superOrg; | |||||
@ExcelProperty("本级主管部门浙政钉ID") | |||||
private String superOrgCode; | |||||
@ExcelProperty("建设单位名称") | |||||
private String buildOrgName; | |||||
@ExcelProperty("建设单位浙政钉ID") | |||||
private String buildOrgZheJiangGovDingId; | |||||
@ExcelProperty("建设单位统一信用代码") | |||||
private String buildOrgCode; | |||||
@ExcelProperty("项目类型") | |||||
private Integer projectType; | |||||
@ExcelProperty("是否首次新建") | |||||
private Integer isFirst; | |||||
@ExcelProperty("关联应用") | |||||
private String relatedExistsApplication; | |||||
@ExcelProperty("关联应用IRS编码") | |||||
private String relatedExistsApplicationCode; | |||||
@ExcelProperty("申报金额(万元)") | |||||
private BigDecimal declareAmount; | |||||
@ExcelProperty("批复金额") | |||||
private BigDecimal approvedTotalInvestmentIncrease; | |||||
@ExcelProperty("预算来源") | |||||
private String budgetSource; | |||||
@ExcelProperty("预算年度") | |||||
private Integer projectYear; | |||||
@ExcelProperty("项目简介") | |||||
private String projectIntroduction; | |||||
@ExcelProperty("立项依据") | |||||
private String buildBasis; | |||||
@ExcelProperty("建设层级") | |||||
private String buildLevel; | |||||
@ExcelProperty("发改编码") | |||||
private String developCode; | |||||
@ExcelProperty("财政编码") | |||||
private String financialCode; | |||||
@ExcelProperty("信息是否有效") | |||||
private Boolean informationValidity; | |||||
@ExcelProperty("是否数字化改革项目") | |||||
private Integer isDigitalReform; | |||||
@ExcelProperty("综合应用领域") | |||||
private String bizDomain; | |||||
@ExcelProperty("是否上云") | |||||
private Integer isCloud; | |||||
@ExcelProperty("云类型") | |||||
private String cloudType; | |||||
@ExcelProperty("四大体系") | |||||
private Integer fourSystems; | |||||
@ExcelProperty("是否临时增补") | |||||
private Integer isTemporaryAugment; | |||||
@ExcelProperty("等保级别") | |||||
private Integer protectionLevel; | |||||
@ExcelProperty("是否密评 0:否 1:是") | |||||
private Integer isSecretComments; | |||||
@ExcelProperty("业务编号") | |||||
private String businessNumber; | |||||
@ExcelProperty("业务名称") | |||||
private String businessName; | |||||
@ExcelProperty("单位名称") | |||||
private String orgName; | |||||
@ExcelProperty("软件开发(万元)") | |||||
private BigDecimal softwareDevelopmentAmount; | |||||
@ExcelProperty("云资源、硬件购置(万元)") | |||||
private BigDecimal cloudHardwarePurchaseAmount; | |||||
@ExcelProperty("第三方服务(万元)") | |||||
private BigDecimal thirdPartyAmount; | |||||
@ExcelProperty("投入项") | |||||
private String safetyInputTitle; | |||||
@ExcelProperty("内容描述") | |||||
private String safetyInputDescribe; | |||||
@ExcelProperty("金额(万元)") | |||||
private BigDecimal safetyInputAmount; | |||||
@ExcelProperty("年度支付金额(万元)") | |||||
private BigDecimal annualPlanAmount; | |||||
@ExcelProperty("自有资金(万元)") | |||||
private BigDecimal annualPlanHaveAmount; | |||||
@ExcelProperty("政府投资-本级财政资金(万元)") | |||||
private BigDecimal declareGovOwnFinanceAmount; | |||||
@ExcelProperty("政府投资-上级补助资金(万元)") | |||||
private BigDecimal declareGovSuperiorFinanceAmount; | |||||
@ExcelProperty("银行贷款(万元)") | |||||
private BigDecimal declareBankLendingAmount; | |||||
@ExcelProperty("其它资金(万元)") | |||||
private BigDecimal declareOtherAmount; | |||||
@ExcelProperty("第一季度") | |||||
private String engineeringSpeedOne; | |||||
@ExcelProperty("第二季度") | |||||
private String engineeringSpeedTwo; | |||||
@ExcelProperty("第三季度") | |||||
private String engineeringSpeedThree; | |||||
@ExcelProperty("第四季度") | |||||
private String engineeringSpeedFour; | |||||
@ExcelProperty("初步方案") | |||||
private String preliminaryPlanFile; | |||||
@ExcelProperty("附件-佐证材料") | |||||
private String supportingMaterialsFile; | |||||
@ExcelProperty("备注") | |||||
private String projectRemarks; | |||||
} |
@@ -0,0 +1,65 @@ | |||||
package com.hz.pm.api.common.model.entity; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
import java.util.Collection; | |||||
import java.util.List; | |||||
/** | |||||
* 文件模板导出对象 | |||||
* @author CMM | |||||
* @since 2023/02/11 11:26 | |||||
*/ | |||||
@Data | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public class ExcelExportWriter { | |||||
/** | |||||
* 文件名称 | |||||
*/ | |||||
private String fileName; | |||||
/** | |||||
* sheet 名称数组 | |||||
*/ | |||||
private List<String> sheets; | |||||
/** | |||||
* 是否启用 头部Excel属性。 | |||||
* 如果使用,则会读取 class对象注解 ExcelProperty 属性值。 | |||||
* 不启用:则会根据heads 动态对列名称去便利 | |||||
*/ | |||||
private Boolean headPropertyFlag; | |||||
/** | |||||
* 头部属性class | |||||
*/ | |||||
private Class headPropertyClass; | |||||
/** | |||||
* 动态列名称 | |||||
* 描述: | |||||
* 第一个List 代表:sheet 列表集合 | |||||
* 第二个List 代表:表体行数据(集合) | |||||
* 第三个list 代表:表体列数据(集合) | |||||
*/ | |||||
private List<List<List<String>>> heads; | |||||
/** | |||||
* 数据对象 | |||||
* 1、对象写:根据对象固定字段写(分为三层) | |||||
* 第二个List 代表:表体行数据(集合) | |||||
* 第三个对象(class) 对象 | |||||
* List<ActivityUserPrizeVO> | |||||
* | |||||
* 2、无对象写(动态表体数据) 分为三层 | |||||
* 第一个List 代表:表体行数据(集合) | |||||
* 第二个list 代表:表体列数据(集合) | |||||
* List<List<Object>> | |||||
*/ | |||||
private Collection<?> datas; | |||||
} |
@@ -0,0 +1,28 @@ | |||||
package com.hz.pm.api.common.model.entity; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
/** | |||||
* <p> | |||||
* KeyValueDTO | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 16:40 2022/8/31 | |||||
*/ | |||||
@Data | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public class KeyValDTO<K, V> { | |||||
private K key; | |||||
private V value; | |||||
public static <K, V> KeyValDTO<K, V> of(K k, V v) { | |||||
return new KeyValDTO<>(k, v); | |||||
} | |||||
} |
@@ -0,0 +1,125 @@ | |||||
package com.hz.pm.api.common.model.entity; | |||||
import cn.hutool.core.collection.CollUtil; | |||||
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 io.swagger.annotations.ApiModelProperty; | |||||
import lombok.Getter; | |||||
import lombok.Setter; | |||||
import lombok.ToString; | |||||
import lombok.experimental.Accessors; | |||||
import javax.validation.constraints.NotEmpty; | |||||
import javax.validation.constraints.Size; | |||||
import java.io.Serializable; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; | |||||
/** | |||||
* 包括id、create_time、created_by、updated_by、update_time、label、parent_id、sort_value 字段的表继承的树形实体 | |||||
* | |||||
* @author PoffyZhang | |||||
* @since 2022/09/30 | |||||
*/ | |||||
@Getter | |||||
@Setter | |||||
@Accessors(chain = true) | |||||
@ToString(callSuper = true) | |||||
public class MenuTreeEntity<E, T extends Serializable> { | |||||
@TableId(value = "id", type = IdType.AUTO) | |||||
protected Long id; | |||||
/** | |||||
* 名称 | |||||
*/ | |||||
@ApiModelProperty(value = "名称") | |||||
@NotEmpty(message = "名称不能为空") | |||||
@Size(max = 255, message = "名称长度不能超过255") | |||||
@TableField(value = "name", condition = LIKE) | |||||
protected String name; | |||||
/** | |||||
* 菜单标题 | |||||
*/ | |||||
@ApiModelProperty(value = "菜单标题") | |||||
@NotEmpty(message = "菜单标题不能为空") | |||||
@Size(max = 255, message = "菜单标题长度不能超过255") | |||||
@TableField(value = "title", condition = LIKE) | |||||
protected String title; | |||||
/** | |||||
* 父菜单ID | |||||
*/ | |||||
@ApiModelProperty(value = "父ID") | |||||
@TableField(value = "pid") | |||||
protected Long pid; | |||||
/** | |||||
* 排序 | |||||
*/ | |||||
@ApiModelProperty(value = "排序号") | |||||
@TableField(value = "sort") | |||||
protected Integer sort; | |||||
/** | |||||
* 顶层菜单 | |||||
*/ | |||||
@ApiModelProperty(value = "顶层菜单") | |||||
@TableField(exist = false) | |||||
protected String topMenu; | |||||
/** | |||||
* 路径 | |||||
*/ | |||||
@ApiModelProperty(value = "路径") | |||||
@Size(max = 255, message = "路径长度不能超过255") | |||||
@TableField(value = "path", condition = LIKE) | |||||
protected String path; | |||||
@ApiModelProperty(value = "子节点", hidden = true) | |||||
@TableField(exist = false) | |||||
protected List<E> children; | |||||
/** | |||||
* 层级 | |||||
*/ | |||||
@ApiModelProperty(value = "层级") | |||||
@TableField(exist = false) | |||||
protected Integer level = 1; | |||||
/** | |||||
* 初始化子类 | |||||
*/ | |||||
@JsonIgnore | |||||
public void initChildren() { | |||||
if (getChildren() == null) { | |||||
this.setChildren(new ArrayList<>()); | |||||
} | |||||
} | |||||
@JsonIgnore | |||||
public void addChildren(E child) { | |||||
initChildren(); | |||||
children.add(child); | |||||
} | |||||
public Integer getSize() { | |||||
if (CollUtil.isNotEmpty(getChildren())) { | |||||
return getChildren().size(); | |||||
} | |||||
return 0; | |||||
} | |||||
@Override | |||||
public Object clone() throws CloneNotSupportedException { | |||||
return super.clone(); | |||||
} | |||||
} |
@@ -0,0 +1,24 @@ | |||||
package com.hz.pm.api.common.model.entity; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import java.util.Collection; | |||||
/** | |||||
* <p> | |||||
* ViewRegionDTO | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 2023/4/27 | |||||
**/ | |||||
@Data | |||||
@AllArgsConstructor | |||||
public class ViewRegionDTO { | |||||
private Collection<String> regions; | |||||
private Integer regionLevel; | |||||
} |