@@ -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; | |||
} |