map = new HashMap<>();
+ if (list != null) {
+ try {
+ Method methodGetKey = c.getMethod(fieldName);
+ for (int i = 0; i < list.size(); i++) {
+ V value = list.get(i);
+ @SuppressWarnings("unchecked")
+ K key = (K) methodGetKey.invoke(list.get(i));
+ map.put(key, value);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return map;
+ }
+
+}
diff --git a/src/main/java/com/ai/da/common/utils/DateUtil.java b/src/main/java/com/ai/da/common/utils/DateUtil.java
new file mode 100644
index 00000000..c491d2c9
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/DateUtil.java
@@ -0,0 +1,65 @@
+package com.ai.da.common.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+@Slf4j
+public class DateUtil {
+ public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+ public static final String YYYYMM = "yyyyMM";
+ public static final String YYYY_MM_DD = "yyyyMMdd";
+ /**
+ * LocalDate -> Date
+ */
+ public static Date asDate(LocalDate localDate) {
+ return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
+ }
+
+ /**
+ * LocalDateTime -> Date
+ */
+ public static Date asDate(LocalDateTime localDateTime) {
+ return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+ }
+ /**
+ * date 装 String
+ * @param date
+ * @param formatter
+ * @return
+ */
+ public static String dateToStr(Date date, String formatter) {
+ DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatter);
+ Instant instant = date.toInstant();
+ ZoneId zoneId = ZoneId.systemDefault();
+ LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
+ return dateTimeFormatter.format(localDateTime);
+ }
+ /**
+ * 根据时区获取时间
+ * @param timeZone "Asia/Tokyo"
+ * @return
+ */
+ public static Date getByTimeZone(String timeZone) {
+ String dateStr = dateToStr(new Date(),YYYY_MM_DD_HH_MM_SS);
+ SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
+ // 设置时区
+ sdf.setTimeZone(TimeZone.getTimeZone(timeZone));
+ Date date = null;
+ try{
+ date = sdf.parse(dateStr);
+ }catch (ParseException parseException){
+ log.error("时间转换异常!",parseException);
+ }
+ return date;
+ }
+
+}
diff --git a/src/main/java/com/ai/da/common/utils/FileUtil.java b/src/main/java/com/ai/da/common/utils/FileUtil.java
new file mode 100644
index 00000000..3b4b3a09
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/FileUtil.java
@@ -0,0 +1,272 @@
+package com.ai.da.common.utils;
+
+import cn.hutool.core.exceptions.ExceptionUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import com.ai.da.common.config.exception.BusinessException;
+import com.ai.da.model.vo.FileVO;
+import org.apache.tomcat.util.http.fileupload.FileUtils;
+import org.apache.tomcat.util.http.fileupload.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.FileSystemUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.imageio.ImageIO;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+//import org.apache.poi.util.IOUtils;
+//import org.apache.poi.xssf.streaming.SXSSFSheet;
+
+public class FileUtil extends cn.hutool.core.io.FileUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(com.ai.da.common.utils.FileUtil.class);
+
+ /**
+ * 系统临时目录
+ *
+ * windows 包含路径分割符,但Linux 不包含,
+ * 在windows \\==\ 前提下,
+ * 为安全起见 同意拼装 路径分割符,
+ *
+ * java.io.tmpdir
+ * windows : C:\Users/xxx\AppData\Local\Temp\
+ * linux: /temp
+ *
+ */
+ public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
+ /**
+ * 定义GB的计算常量
+ */
+ private static final int GB = 1024 * 1024 * 1024;
+ /**
+ * 定义MB的计算常量
+ */
+ private static final int MB = 1024 * 1024;
+ /**
+ * 定义KB的计算常量
+ */
+ private static final int KB = 1024;
+
+ /**
+ * 格式化小数
+ */
+ private static final DecimalFormat DF = new DecimalFormat("0.00");
+
+ public static final String IMAGE = "图片";
+ public static final String TXT = "文档";
+ public static final String MUSIC = "音乐";
+ public static final String VIDEO = "视频";
+ public static final String OTHER = "其他";
+
+
+ /**
+ * MultipartFile转File
+ */
+ public static File toFile(MultipartFile multipartFile) {
+ // 获取文件名
+ String fileName = multipartFile.getOriginalFilename();
+ // 获取文件后缀
+ String prefix = "." + getExtensionName(fileName);
+ File file = null;
+ try {
+ // 用uuid作为文件名,防止生成的临时文件重复
+ file = new File(SYS_TEM_DIR + IdUtil.simpleUUID() + prefix);
+ // MultipartFile to File
+ multipartFile.transferTo(file);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ return file;
+ }
+
+// public static void main(String[] args) {
+// File file = new File(
+// "http://18.162.111.141:5568/download/202211/userFile/collection/Printboard/1/a3c9838c-2171-44d7-af54-c94ee6affcd9print_2.jpg.png");
+// FileUtil.getFileSize()
+// }
+
+ /**
+ * 获取文件扩展名,不带 .
+ */
+ public static String getExtensionName(String filename) {
+ if ((filename != null) && (filename.length() > 0)) {
+ int dot = filename.lastIndexOf('.');
+ if ((dot > -1) && (dot < (filename.length() - 1))) {
+ return filename.substring(dot + 1);
+ }
+ }
+ return filename;
+ }
+
+
+ /**
+ * inputStream 转 File
+ */
+ static File inputStreamToFile(InputStream ins, String name) {
+ File file = new File(SYS_TEM_DIR + name);
+ if (file.exists()) {
+ return file;
+ }
+ OutputStream os = null;
+ try {
+ os = new FileOutputStream(file);
+ int bytesRead;
+ int len = 8192;
+ byte[] buffer = new byte[len];
+ while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
+ os.write(buffer, 0, bytesRead);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ CloseUtil.close(os);
+ CloseUtil.close(ins);
+ }
+ return file;
+ }
+
+ /**
+ * 获取文件尺寸
+ */
+ public static FileVO getFileSize(MultipartFile file) {
+ int width = 0;
+ int height = 0;
+ try{
+ // 图片对象
+ BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
+ // 宽度
+ width = bufferedImage.getWidth();
+ // 高度
+ height = bufferedImage.getHeight();
+ }catch (IOException ioException){
+ log.error("获取文件尺寸异常###{}", ExceptionUtil.stacktraceToString(ioException));
+ }
+ return new FileVO(height,width);
+ }
+ /**
+ * 获取文件尺寸
+ */
+ public static FileVO getFileSize(InputStream inputStream) {
+ int width = 0;
+ int height = 0;
+ try{
+ // 图片对象
+ BufferedImage bufferedImage = ImageIO.read(inputStream);
+ // 宽度
+ width = bufferedImage.getWidth();
+ // 高度
+ height = bufferedImage.getHeight();
+ }catch (IOException ioException){
+ log.error("获取文件尺寸异常###{}", ExceptionUtil.stacktraceToString(ioException));
+ }
+ return new FileVO(height,width);
+ }
+ /**
+ * 获取远程文件流
+ */
+ public static InputStream getOriginFile(String path) {
+
+ try{
+ //远程
+ URL url = new URL(path);
+ return url.openStream();
+ }catch (IOException ioException){
+ log.error("获取文件尺寸异常###{}###path##{}", ExceptionUtil.stacktraceToString(ioException),path);
+ throw new BusinessException("get file is failed!");
+ }
+ }
+ /**
+ * 将文件名解析成文件的上传路径
+ */
+ public static File upload(MultipartFile file, String filePath) {
+ Date date = new Date();
+ SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
+ String suffix = getExtensionName(file.getOriginalFilename());
+ String nowStr = format.format(date)+"-" ;
+ try {
+ String fileName = file.getOriginalFilename();
+ String path = filePath + fileName;
+ // getCanonicalFile 可解析正确各种路径
+ File dest = new File(path).getCanonicalFile();
+ // 检测是否存在目录
+ if (!dest.getParentFile().exists()) {
+ if (!dest.getParentFile().mkdirs()) {
+ System.out.println("was not successful.");
+ }
+ }
+ // 文件写入
+ file.transferTo(dest);
+ return dest;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ return null;
+ }
+ /**
+ * 删除文件
+ */
+ public static boolean delete(String path) {
+ File file = new File(path);
+ if (file.exists()) {
+ return file.delete();
+ }
+ return false;
+ }
+ /**
+ * 获取指定文件夹下所有文件,不含文件夹里的文件
+ *
+ * @param dirFilePath 文件夹路径
+ * @return
+ */
+ public static List getAllFile(String dirFilePath) {
+ if (StrUtil.isBlank(dirFilePath)){
+ return null;
+ }
+ return getAllFile(new File(dirFilePath));
+ }
+
+ /**
+ * 获取指定文件夹下所有文件,不含文件夹里的文件
+ *
+ * @param dirFile 文件夹
+ * @return
+ */
+ public static List getAllFile(File dirFile) {
+ // 如果文件夹不存在或着不是文件夹,则返回 null
+ if (Objects.isNull(dirFile) || !dirFile.exists() || dirFile.isFile()){
+ return null;
+ }
+ File[] childrenFiles = dirFile.listFiles();
+ if (Objects.isNull(childrenFiles) || childrenFiles.length == 0){
+ return null;
+ }
+ List files = new ArrayList<>();
+ for (File childFile : childrenFiles) {
+ // 如果是文件,直接添加到结果集合
+ if (childFile.isFile()) {
+ files.add(childFile);
+ }
+ //以下几行代码取消注释后可以将所有子文件夹里的文件也获取到列表里
+ else {
+ // 如果是文件夹,则将其内部文件添加进结果集合
+ List cFiles = getAllFile(childFile);
+ if (Objects.isNull(cFiles) || cFiles.isEmpty()){
+ continue;
+ }
+ files.addAll(cFiles);
+ }
+ }
+ return files;
+ }
+
+
+}
diff --git a/src/main/java/com/ai/da/common/utils/ImageUtil.java b/src/main/java/com/ai/da/common/utils/ImageUtil.java
new file mode 100644
index 00000000..5cc737c4
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/ImageUtil.java
@@ -0,0 +1,47 @@
+package com.ai.da.common.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * 图片工具类
+ */
+@Slf4j
+public class ImageUtil {
+ static BufferedImage bufferedImage;
+ static int r,g,b; // 分别用来存放获取的RGB值
+ static int heigth,width;
+ static int id = 0;
+ public static void find(){
+ // 读取要操作的图片,这里的图片路径请改成自己要处理的图片
+ try {
+ bufferedImage = ImageIO.read(new File("D:\\programManager\\private\\curtain\\curtain\\WechatIMG170.png"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ // 获取图片的宽和高;
+ heigth = bufferedImage.getHeight();
+ width = bufferedImage.getHeight();
+ System.out.println("heigth = "+heigth +", width ="+width);
+ // 采用行优先遍历,先遍历宽
+ for (int y = 0; y < heigth; y++) {
+ for (int x = 0; x < width; x++) {
+ id++;
+ Color color = new Color(bufferedImage.getRGB(x,y));
+ r = color.getRed();
+ g = color.getGreen();
+ b = color.getBlue();
+ System.out.println("此时的id为: "+ id+ " R = "+ r + ", G = "+g+", B ="+b);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ find();
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/JSONResponseUtils.java b/src/main/java/com/ai/da/common/utils/JSONResponseUtils.java
new file mode 100644
index 00000000..8caa3e5d
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/JSONResponseUtils.java
@@ -0,0 +1,42 @@
+package com.ai.da.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.ai.da.common.response.Response;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.servlet.ServletResponse;
+import java.io.PrintWriter;
+
+
+/**
+ * @author: dangweijian
+ * @description: 构造JSON响应工具类
+ * @Author dwjian
+ * @Date 2020/7/10 15:51
+ **/
+@Slf4j
+public class JSONResponseUtils {
+
+ /**
+ * 使用response输出JSON
+ *
+ * @param servletResponse
+ * @param response
+ */
+ public static void build(ServletResponse servletResponse, Response> response) {
+ PrintWriter out = null;
+ try {
+ servletResponse.setCharacterEncoding("UTF-8");
+ servletResponse.setContentType("application/json");
+ out = servletResponse.getWriter();
+ out.println(JSON.toJSONString(response));
+ } catch (Exception e) {
+ log.error(e + "输出JSON出错");
+ } finally {
+ if (out != null) {
+ out.flush();
+ out.close();
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/LocalCacheUtils.java b/src/main/java/com/ai/da/common/utils/LocalCacheUtils.java
new file mode 100644
index 00000000..08b88158
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/LocalCacheUtils.java
@@ -0,0 +1,406 @@
+package com.ai.da.common.utils;
+
+import com.ai.da.mapper.entity.Collection;
+import com.ai.da.mapper.entity.SysFile;
+import com.ai.da.model.vo.SysFileVO;
+import com.google.common.cache.*;
+import com.google.common.collect.Lists;
+import io.swagger.models.auth.In;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author: yanglei
+ * @description: 本地缓存工具
+ * @create: 2022-08-11 9:23
+ **/
+@Slf4j
+public final class LocalCacheUtils {
+ /**
+ * token
+ */
+ private static LoadingCache tokenCache = loadTokenCache();
+ /**
+ *
+ *缓存接口这里是LoadingCache,LoadingCache在缓存项不存在时可以自动加载缓存
+ */
+ private static LoadingCache loadTokenCache(){
+ LoadingCache tokenCache = CacheBuilder.newBuilder()
+ .concurrencyLevel(10)
+ .expireAfterWrite(24*100, TimeUnit.HOURS)
+ .initialCapacity(100)
+ .maximumSize(10000)
+ .recordStats()
+ .build(new CacheLoader() {
+ @Override
+ public String load(String key) throws Exception {
+ return "null";
+ }
+ });
+ return tokenCache;
+ }
+ /**
+ * 邮箱,短信验证码
+ */
+ private static LoadingCache emailCache = CacheBuilder.newBuilder()
+ //设置并发级别为5,并发级别是指可以同时写缓存的线程数
+ .concurrencyLevel(10)
+ //设置写缓存后3分钟过期
+ .expireAfterWrite(60*3, TimeUnit.SECONDS)
+ //刷新机制 每隔一定时间刷新缓存loader 只有调用get具体的操作才生效(懒加载) 不设置则不刷新
+// .refreshAfterWrite(60, TimeUnit.SECONDS)
+ //设置缓存容器的初始容量为100
+ .initialCapacity(100)
+ //设置缓存最大容量10000,超过100之后就会按照LRU最近虽少使用算法来移除缓存项
+ .maximumSize(10000)
+ //设置要统计缓存的命中率
+ .recordStats()
+ //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
+ .build(new CacheLoader() {
+ @Override
+ public String load(String key) throws Exception {
+ return "null";
+ }
+ });
+
+ /**
+ * 系统文件 最大最小值
+ */
+ private static LoadingCache sysFileMaxAndMinCache = CacheBuilder.newBuilder()
+ //设置并发级别为5,并发级别是指可以同时写缓存的线程数
+ .concurrencyLevel(10)
+ //设置写缓存后一天过期
+ .expireAfterWrite(60*60*24, TimeUnit.SECONDS)
+ //设置缓存容器的初始容量为100
+ .initialCapacity(100)
+ //设置缓存最大容量50000,超过50000之后就会按照LRU最近虽少使用算法来移除缓存项
+ .maximumSize(500)
+ //设置要统计缓存的命中率
+ .recordStats()
+ //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
+ .build(new CacheLoader() {
+ @Override
+ public Long load(String key) throws Exception {
+ return 0L;
+ }
+ });
+ /**
+ * 系统文件本地缓存 id -> path
+ */
+ private static LoadingCache sysFileCache = CacheBuilder.newBuilder()
+ //设置并发级别为5,并发级别是指可以同时写缓存的线程数
+ .concurrencyLevel(10)
+ //设置写缓存后一天过期
+ .expireAfterWrite(60*60*24, TimeUnit.SECONDS)
+ //设置缓存容器的初始容量为100
+ .initialCapacity(100)
+ //设置缓存最大容量50000,超过50000之后就会按照LRU最近虽少使用算法来移除缓存项
+ .maximumSize(50000)
+ //设置要统计缓存的命中率
+ .recordStats()
+ //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
+ .build(new CacheLoader() {
+ @Override
+ public SysFileVO load(Long key) throws Exception {
+ return new SysFileVO();
+ }
+ });
+
+ /**
+ * 系统文件本地缓存 level1-> sysFile 数组
+ */
+ private static LoadingCache> sysFileLevelType1Cache = CacheBuilder.newBuilder()
+ //设置并发级别为5,并发级别是指可以同时写缓存的线程数
+ .concurrencyLevel(10)
+ //设置写缓存后一天过期
+ .expireAfterWrite(60*60*24, TimeUnit.SECONDS)
+ //设置缓存容器的初始容量为15000
+ .initialCapacity(15000)
+ //设置缓存最大容量50000,超过50000之后就会按照LRU最近虽少使用算法来移除缓存项
+ .maximumSize(50000)
+ //设置要统计缓存的命中率
+ .recordStats()
+ //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
+ .build(new CacheLoader>() {
+ @Override
+ public List load(String key) throws Exception {
+ return new ArrayList();
+ }
+ });
+
+ /**
+ * design文件进度统计
+ */
+ private static LoadingCache> designProcessCache = CacheBuilder.newBuilder()
+ //设置并发级别为10,并发级别是指可以同时写缓存的线程数
+ .concurrencyLevel(10)
+ //设置写缓存后5分钟过期
+ .expireAfterWrite(60*5, TimeUnit.SECONDS)
+ //设置缓存容器的初始容量为100
+ .initialCapacity(5)
+ //设置缓存最大容量50000,超过50000之后就会按照LRU最近虽少使用算法来移除缓存项
+ .maximumSize(100)
+ //设置要统计缓存的命中率
+ .recordStats()
+ //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
+ .build(new CacheLoader>() {
+ @Override
+ public List load(Long key) throws Exception {
+ return Collections.EMPTY_LIST;
+ }
+ });
+
+ /**
+ * aida 接口限流(先粗暴做)
+ */
+ private static LoadingCache aidaInterfaceCurrentLimiting = CacheBuilder.newBuilder()
+ //设置并发级别为5,并发级别是指可以同时写缓存的线程数
+ .concurrencyLevel(20)
+ //设置写缓存后30天过期
+ .expireAfterWrite(60*60*24*30, TimeUnit.SECONDS)
+ //设置缓存容器的初始容量为100
+ .initialCapacity(5)
+ //设置缓存最大容量50000,超过50000之后就会按照LRU最近虽少使用算法来移除缓存项
+ .maximumSize(20)
+ //设置要统计缓存的命中率
+ .recordStats()
+ //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
+ .build(new CacheLoader() {
+ @Override
+ public Integer load(String key) throws Exception {
+ return 0;
+ }
+ });
+ /**
+ * 添加token本地缓存
+ * @param key
+ * @param value
+ */
+ public static void setTokenCache(String key, String value) {
+ tokenCache.put(key, value);
+ }
+
+ /**
+ * 获取token本地缓存
+ * @param key
+ * @return
+ */
+ public static String getTokenCache(String key) {
+ try {
+ String value = tokenCache.get(key);
+ if ("null".equals(value)) {
+ return null;
+ }
+ return value;
+ } catch (ExecutionException e) {
+ log.error("getTokenCache方法错误", e);
+ }
+ return null;
+ }
+ /**
+ * 删除token本地缓存(登出)
+ * @param key
+ * @return
+ */
+ public static void delTokenCache(String key) {
+ try {
+ tokenCache.invalidate(key);
+ } catch (Exception e) {
+ log.error("delTokenCache方法错误", e);
+ }
+ }
+ /**
+ * 添加验证码本地缓存
+ * @param key
+ * @param value
+ */
+ public static void setVerifyCodeCache(String key, String value) {
+ emailCache.put(key, value);
+ }
+
+ /**
+ * 获取验证码本地缓存
+ * @param key
+ * @return
+ */
+ public static String getVerifyCodeCache(String key) {
+ try {
+ String value = emailCache.get(key);
+ if ("null".equals(value)) {
+ return null;
+ }
+ return value;
+ } catch (ExecutionException e) {
+ log.error("getVerifyCodeCache方法错误", e);
+ }
+ return null;
+ }
+ /**
+ * 添加系统文本地缓存
+ * @param key
+ * @param sysFile
+ */
+ public static void setSysFileCache(Long key, SysFileVO sysFile) {
+ sysFileCache.put(key, sysFile);
+ }
+
+ /**
+ * 获取系统文件本地缓存
+ * @param key
+ * @return
+ */
+ public static SysFileVO getSysFileCache(Long key) {
+ try {
+ SysFileVO value = sysFileCache.get(key);
+ return value;
+ } catch (ExecutionException e) {
+ log.error("getSysFileCache方法错误", e);
+ }
+ return null;
+ }
+ /**
+ * 清除所有系统文件本地缓存
+ * @return
+ */
+ public static void clearAllSysFileCache() {
+ try {
+ sysFileCache.invalidateAll();
+ } catch (Exception e) {
+ log.error("clearAllSysFileCache方法错误", e);
+ }
+ }
+ /**
+ * 添加系统文本地缓存,通过类型
+ * @param level1Type
+ * @param sysFileList
+ */
+ public static void setSysFileCacheByLevel2Type(String level1Type, List sysFileList) {
+ sysFileLevelType1Cache.put(level1Type, sysFileList);
+ }
+
+ /**
+ * 获取系统文件本地缓存
+ * @param level2Type
+ * @return
+ */
+ public static List getSysFileCacheByLevel2Type(String level2Type) {
+ try {
+ return sysFileLevelType1Cache.get(level2Type);
+ } catch (ExecutionException e) {
+ log.error("getSysFileCacheByLevel1Type方法错误", e);
+ }
+ return null;
+ }
+ /**
+ * 清除所有系统文件本地缓存
+ * @return
+ */
+ public static void clearAllSysFileCacheByLevel2Type() {
+ try {
+ sysFileLevelType1Cache.invalidateAll();
+ } catch (Exception e) {
+ log.error("clearAllSysFileCacheByLevel2Type方法错误", e);
+ }
+ }
+ /**
+ * 添加系统文件范围最大最小值本地缓存
+ * @param key
+ * @param value
+ */
+ public static void setFileMaxMinValueCache(String key, Long value) {
+ sysFileMaxAndMinCache.put(key, value);
+ }
+
+ /**
+ * 获取系统文件范围最大最小值本地缓存
+ * @param key
+ * @return
+ */
+ public static Long getFileMaxMinValueCache(String key) {
+ try {
+ Long value = sysFileMaxAndMinCache.get(key);
+ if (0L == value) {
+ return null;
+ }
+ return value;
+ } catch (ExecutionException e) {
+ log.error("getFileMaxMinValueCache方法错误", e);
+ }
+ return null;
+ }
+ /**
+ * 清除所有系统文件范围最大最小值本地缓存
+ * @return
+ */
+ public static void clearAllMaxMinValueCache() {
+ try {
+ sysFileMaxAndMinCache.invalidateAll();
+ } catch (Exception e) {
+ log.error("clearAllMaxMinValueCache方法错误", e);
+ }
+ }
+ /**
+ * 添加系design文件进度统计
+ * @param key
+ * @param value
+ */
+ public static void setDesignProcessCache(Long key, List value) {
+ designProcessCache.put(key, value);
+ }
+
+ /**
+ * 获取design文件进度统计
+ * @param key
+ * @return
+ */
+ public static List getDesignProcessCache(Long key) {
+ try {
+ List value = designProcessCache.get(key);
+ return value;
+ } catch (ExecutionException e) {
+ log.error("getDesignProcessCache方法错误", e);
+ }
+ return null;
+ }
+ /**
+ * 进度统计完后 删除进度
+ * @param key
+ * @return
+ */
+ public static void delDesignProcessCache(Long key) {
+ try {
+ designProcessCache.invalidate(key);
+ } catch (Exception e) {
+ log.error("delDesignProcessCache方法错误", e);
+ }
+ }
+
+ /**
+ * 设置本次接口流量数
+ * @param key
+ * @param value
+ */
+ public static void setAidaInterfaceCurrentLimitingCache(String key, Integer value) {
+ aidaInterfaceCurrentLimiting.put(key, value);
+ }
+
+ /**
+ * 获取本次接口流量数
+ * @param key
+ * @return
+ */
+ public static Integer getAidaInterfaceCurrentLimitingCache(String key) {
+ try {
+ return aidaInterfaceCurrentLimiting.get(key);
+ } catch (ExecutionException e) {
+ log.error("getAidaInterfaceCurrentLimitingCache方法错误", e);
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/ai/da/common/utils/MD5Utils.java b/src/main/java/com/ai/da/common/utils/MD5Utils.java
new file mode 100644
index 00000000..896dc3ca
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/MD5Utils.java
@@ -0,0 +1,117 @@
+package com.ai.da.common.utils;
+
+import cn.hutool.core.exceptions.ExceptionUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.DigestUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.math.BigInteger;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * MD5加密工具
+ */
+@Slf4j
+public class MD5Utils {
+
+ /**
+ * MD5加密
+ *
+ * @param str
+ * @return
+ */
+ public static String encrypt(String str) {
+ byte[] mdBytes = null;
+ try {
+ mdBytes = MessageDigest.getInstance("MD5").digest(
+ str.getBytes());
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("MD5算法不存在!");
+ }
+ String mdCode = new BigInteger(1, mdBytes).toString(16);
+
+ if (mdCode.length() < 32) {
+ int a = 32 - mdCode.length();
+ for (int i = 0; i < a; i++) {
+ mdCode = "0" + mdCode;
+ }
+ }
+ // 默认返回32位小写
+ return mdCode;
+ }
+
+ /**
+ * MD5加密文件
+ *
+ * @param file
+ * @return
+ */
+ public static String encryptFile(MultipartFile file) {
+ String md5 = null;
+ try {
+ md5 = DigestUtils.md5DigestAsHex(file.getInputStream());
+ } catch (IOException ioException) {
+ log.error("文件MultipartFile md5加密异常ioException##{}", ExceptionUtil.getThrowableList(ioException));
+ }
+ return md5;
+ }
+ /**
+ * MD5加密文件
+ *
+ * @param inputStream
+ * @return
+ */
+ public static String encryptFile(FileInputStream inputStream) {
+ String md5 = null;
+ try {
+ md5 = DigestUtils.md5DigestAsHex(inputStream);
+ } catch (IOException ioException) {
+ log.error("文件MultipartFile md5加密异常ioException##{}", ExceptionUtil.getThrowableList(ioException));
+ }
+ return md5;
+ }
+
+ public static void main(String[] args) throws FileNotFoundException, IOException {
+ File file1 = new File("/Users/yanglei/Documents/阳磊日报2019-04-23.numbers");
+ File file2 = new File("/Users/yanglei/Documents/7777.numbers");
+ FileInputStream fileInputStream1 = new FileInputStream(file1);
+ FileInputStream fileInputStream2 = new FileInputStream(file2);
+ String md51 = DigestUtils.md5DigestAsHex(fileInputStream1);
+ String md52 = DigestUtils.md5DigestAsHex(fileInputStream2);
+ if (md51.equals(md52)) {
+ System.out.println(md51);
+ }
+ System.out.println("md51==" + md51);
+ System.out.println("md52==" + md52);
+
+ }
+
+
+ /**
+ * MD5加密文件
+ *
+ * @param path
+ * @return
+ */
+ public static String encryptFile(String path, Boolean isLocal) {
+ String md5 = null;
+ try {
+ InputStream inputStream = null;
+ if (isLocal) {
+ File file = new File(path);
+ inputStream = new FileInputStream(file);
+ } else {
+ //远程
+ inputStream = FileUtil.getOriginFile(path);
+ }
+ md5 = DigestUtils.md5DigestAsHex(inputStream);
+ } catch (IOException ioException) {
+ log.error("文件File md5加密异常ioException##{}", ExceptionUtil.getThrowableList(ioException));
+ }
+ return md5;
+ }
+
+}
diff --git a/src/main/java/com/ai/da/common/utils/MultiReadHttpServletRequest.java b/src/main/java/com/ai/da/common/utils/MultiReadHttpServletRequest.java
new file mode 100644
index 00000000..7935ae27
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/MultiReadHttpServletRequest.java
@@ -0,0 +1,170 @@
+package com.ai.da.common.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 多次读写BODY用HTTP REQUEST - 解决流只能读一次问题
+ */
+@Slf4j
+public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
+
+ private final byte[] body;
+
+ public MultiReadHttpServletRequest(HttpServletRequest request) {
+ super(request);
+ String sessionStream = getBodyString(request);
+ body = sessionStream.getBytes(StandardCharsets.UTF_8);
+ }
+
+ /**
+ * 获取请求Body
+ *
+ * @param request 请求
+ * @return Body字符串
+ */
+ private String getBodyString(final ServletRequest request) {
+ StringBuilder sb = new StringBuilder();
+ InputStream inputStream = null;
+ BufferedReader reader = null;
+ try {
+ inputStream = cloneInputStream(request.getInputStream());
+ reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
+ String line = "";
+ while ((line = reader.readLine()) != null) {
+ sb.append(line);
+ }
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (reader != null) {
+ try {
+ reader.close();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 复制输入流
+ * @param inputStream 请求输入流
+ * @return 复制出来的输入流
+ */
+ private InputStream cloneInputStream(ServletInputStream inputStream) {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int len;
+ try {
+ while ((len = inputStream.read(buffer)) > -1) {
+ byteArrayOutputStream.write(buffer, 0, len);
+ }
+ byteArrayOutputStream.flush();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
+ }
+
+ @Override
+ public BufferedReader getReader() {
+ return new BufferedReader(new InputStreamReader(getInputStream()));
+ }
+
+ @Override
+ public ServletInputStream getInputStream() {
+
+ final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+
+ return new ServletInputStream() {
+
+ @Override
+ public int read() {
+ return bais.read();
+ }
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ }
+ };
+ }
+
+ /**
+ * 将前端请求的表单数据转换成json字符串 - 前后端一体的情况下使用
+ *
+ * @param request:
+ * @return: java.lang.String
+ */
+ public static String getBodyJsonStrByForm(ServletRequest request) {
+ Map bodyMap = new HashMap<>(16);
+ try {
+ // 参数定义
+ String paraName = null;
+ // 获取请求参数并转换
+ Enumeration e = request.getParameterNames();
+ while (e.hasMoreElements()) {
+ paraName = e.nextElement();
+ bodyMap.put(paraName, request.getParameter(paraName));
+ }
+ } catch (Exception e) {
+ log.error("请求参数转换错误!", e);
+ }
+ return JSONObject.toJSONString(bodyMap);
+ }
+
+ /**
+ * 将前端传递的json数据转换成json字符串 - 前后端分离的情况下使用
+ *
+ * @param request:
+ * @return: java.lang.String
+ */
+ public static String getBodyJsonStrByJson(ServletRequest request) {
+ StringBuffer json = new StringBuffer();
+ String line;
+ try {
+ BufferedReader reader = request.getReader();
+ while ((line = reader.readLine()) != null) {
+ json.append(line);
+ }
+ } catch (Exception e) {
+ log.error("请求参数转换错误!", e);
+ }
+ return json.toString();
+ }
+
+}
diff --git a/src/main/java/com/ai/da/common/utils/MultiReadHttpServletResponse.java b/src/main/java/com/ai/da/common/utils/MultiReadHttpServletResponse.java
new file mode 100644
index 00000000..8b39a9bd
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/MultiReadHttpServletResponse.java
@@ -0,0 +1,77 @@
+package com.ai.da.common.utils;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+
+/**
+ * 多次读写BODY用HTTP RESPONSE - 解决流只能读一次问题
+ */
+public class MultiReadHttpServletResponse extends HttpServletResponseWrapper {
+
+ private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ private HttpServletResponse response;
+
+ public MultiReadHttpServletResponse(HttpServletResponse response) {
+ super(response);
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application/json");
+ this.response = response;
+ }
+
+ public byte[] getBody() {
+ return byteArrayOutputStream.toByteArray();
+ }
+
+ @Override
+ public ServletOutputStream getOutputStream() {
+ return new ServletOutputStreamWrapper(this.byteArrayOutputStream, this.response);
+ }
+
+ @Override
+ public PrintWriter getWriter() throws IOException {
+ return new PrintWriter(new OutputStreamWriter(getOutputStream(), this.response.getCharacterEncoding()));
+ }
+
+
+ @Data
+ @AllArgsConstructor
+ private static class ServletOutputStreamWrapper extends ServletOutputStream {
+
+ private ByteArrayOutputStream outputStream;
+ private HttpServletResponse response;
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener listener) {
+
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ this.outputStream.write(b);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (!this.response.isCommitted()) {
+ byte[] body = this.outputStream.toByteArray();
+ ServletOutputStream outputStream = this.response.getOutputStream();
+ outputStream.write(body);
+ outputStream.flush();
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/ObjectUtils.java b/src/main/java/com/ai/da/common/utils/ObjectUtils.java
new file mode 100644
index 00000000..b70bc4c0
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/ObjectUtils.java
@@ -0,0 +1,35 @@
+package com.ai.da.common.utils;
+import java.util.*;
+import java.lang.reflect.Field;
+
+public class ObjectUtils {
+
+ /**
+ * 判断该对象是否所有属性为空
+ * 返回ture表示所有属性为null,返回false表示不是所有属性都是null
+ */
+ public static boolean isAllFieldNull(Object object) {
+ boolean flag = true;
+
+ Class clazz = object.getClass();
+ Field[] fields = clazz.getDeclaredFields();
+
+ for (Field field : fields) {
+ //设置属性是可以访问的(私有的也可以)
+ field.setAccessible(true);
+ Object value = null;
+ try {
+ value = field.get(object);
+ // 只要有1个属性不为空,那么就不是所有的属性值都为空
+ if (value != null) {
+ flag = false;
+ break;
+ }
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return flag;
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/RandomsUtil.java b/src/main/java/com/ai/da/common/utils/RandomsUtil.java
new file mode 100644
index 00000000..19af8494
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/RandomsUtil.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ai.da.common.utils;
+
+import cn.hutool.core.util.RandomUtil;
+
+import java.text.DecimalFormat;
+
+/**
+ * @author yanglei
+ * @description 随机数工具类
+ * @date 2022-07
+ **/
+public class RandomsUtil {
+
+ private static String PREFIX = "ver";
+
+ /**
+ * 生成验证码
+ *
+ * @param randomStart
+ * @param randomEnd
+ */
+ public static String generateVerifyCode(Long randomStart, Long randomEnd) {
+ return String.valueOf(RandomUtil.randomLong(randomStart,randomEnd));
+ }
+ /**
+ * 生成随机系统图片
+ *
+ * @param randomStart 可以等于
+ * @param randomEnd 小于最大值
+ */
+ public static Long randomSysFile(Long randomStart, Long randomEnd) {
+ return RandomUtil.randomLong(randomStart,randomEnd);
+ }
+
+
+}
diff --git a/src/main/java/com/ai/da/common/utils/RedisCacheUtils.java b/src/main/java/com/ai/da/common/utils/RedisCacheUtils.java
new file mode 100644
index 00000000..ea96a4eb
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/RedisCacheUtils.java
@@ -0,0 +1,50 @@
+package com.ai.da.common.utils;
+
+import cn.hutool.core.util.StrUtil;
+import org.springframework.data.redis.core.RedisTemplate;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author: dangweijian
+ * @description: redis缓存工具
+ * @create: 2021-01-08 9:23
+ **/
+public final class RedisCacheUtils {
+
+ private static RedisTemplate getRedisTemplate(){
+ return SpringUtils.getBean("redisTemplate");
+ }
+
+ private static RedisTemplate getRedisTemplate(Class clazz){
+ return SpringUtils.getBean("redisTemplate");
+ }
+
+ private static RedisTemplate> getListRedisTemplate(Class clazz){
+ return SpringUtils.getBean("redisTemplate");
+ }
+
+ public static T get(String key, Class clazz){
+ return getRedisTemplate(clazz).opsForValue().get(key);
+ }
+
+ public static List getList(String key, Class clazz){
+ return getListRedisTemplate(clazz).opsForValue().get(key);
+ }
+
+ public static void set(String key, Object value){
+ getRedisTemplate().opsForValue().set(key, value);
+ }
+
+ public static void set(String key, Object value, long time, TimeUnit unit){
+ getRedisTemplate().opsForValue().set(key, value, time, unit);
+ }
+
+ public static boolean delete(String key){
+ if(StrUtil.isNotEmpty(key)){
+ return Boolean.TRUE.equals(getRedisTemplate().delete(key));
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/RequestInfoUtil.java b/src/main/java/com/ai/da/common/utils/RequestInfoUtil.java
new file mode 100644
index 00000000..1e3d12dd
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/RequestInfoUtil.java
@@ -0,0 +1,49 @@
+package com.ai.da.common.utils;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class RequestInfoUtil {
+
+ /**
+ * description 获取客户端IP
+ *
+ * @param request
+ * @return java.lang.String
+ * @version 1.0
+ *
+ *
+ * 使用了ng等代理服务器要在ng加以下配置
+ * location / {
+ * proxy_pass http://127.0.0.1:10678;
+ * proxy_set_header Host $host;
+ * proxy_set_header X-Real-IP $remote_addr;
+ * proxy_set_header REMOTE-HOST $remote_addr;
+ * proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ * }
+
+ */
+ public static String getIpAddress(HttpServletRequest request) {
+ String ip = request.getHeader("x-forwarded-for");
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_CLIENT_IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ // 如果是多级代理,那么取第一个IP为客户端IP
+ if (ip != null && ip.indexOf(",") != -1) {
+ ip = ip.substring(0, ip.indexOf(",")).trim();
+ }
+ return ip;
+ }
+
+}
diff --git a/src/main/java/com/ai/da/common/utils/RsaDecryptUtils.java b/src/main/java/com/ai/da/common/utils/RsaDecryptUtils.java
new file mode 100644
index 00000000..83962f69
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/RsaDecryptUtils.java
@@ -0,0 +1,70 @@
+package com.ai.da.common.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.codec.binary.Base64;
+
+import javax.crypto.Cipher;
+import java.io.ByteArrayOutputStream;
+import java.security.*;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+/**
+ * Rsa解密工具
+ */
+@Slf4j
+public class RsaDecryptUtils {
+
+ public static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJA0JB/XhdVz/rxlt/XI8LmB7WvPhT1ZpoLXaMfg7zNN+jRWOpuYc+NDr17uA07yl9h2FHOZ6aG5eoobyUP13gAopQuS7BJYwrrA0HLJjZuROWPw/djA8uxQQ97q22k7evlnZ4a1mVJRONbzQxUKQEgLM0S7+l699/NIZGyI4+XPAgMBAAECgYBlyjh5tZPGIbP93rtlJqst91XVVU4TCVZtY4qWFOQkTfXAveFu9cVP9fYzx0TUlI+0/1zeYRW20At8s7J1Y3eJhurZTLns+GpbFD2qExZVL9w5hqmn9fvOE4jCP7uTlTzVgT9zDxAvCid8mSVHz4z7MWG3/zrJloWQzE2riqeeyQJBAOiqfE4M5dQPopFKGhJBBWdKYLAK+trfi4iqstMfdndCiExGd0Nlw9/RS21LXZFk7RwCood6Q/XyKyXTZMwbTHUCQQCeqnTXhEhYlnRIHOuGKYGVHEFMrIGhPH0LZ7ZQUBp+q0wzUsCY79D9ppIwJPHggDsyJOZatm5eMtHb0dDEqbCzAkEAmHF72LfirjtATOm8g1FO9Qpqp23KRzZI+la9rE7lE+bn3vIcmnBHEpLTVN0YhXcXVE71psaZWMA/PR1w4brRMQJADJvPHTFN7nxGUVS7ArZZrdfI+KbcxktgRH/BZTB4aoiCTbHNzFmCaiXKiDjnX8fQ7HMyOxM0QhgXxTgvNvGlMQJATbRaCq7Ytw1SpHRuRbThjwkKVuinSX9y8rRhof7vEKTYomhoDoH7ZITWq421kXT81mj66ahtkPBccw1NeOqYCg==";
+
+ public static String decrypt(String content, String privateKey) {
+ byte[] result;
+ try {
+ PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PrivateKey privateKeyText = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.DECRYPT_MODE, privateKeyText);
+ result = doLongerCipherFinal(cipher, Base64.decodeBase64(content));
+ } catch (Exception e) {
+ log.error("RSA解密失败", e);
+ return null;
+ }
+ return new String(result);
+ }
+
+ private static byte[] doLongerCipherFinal(Cipher cipher, byte[] source) throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(cipher.doFinal(source));
+ out.close();
+ return out.toByteArray();
+ }
+
+ /**
+ * 构建RSA密钥对
+ * @param args
+ */
+// public static void main(String[] args) throws NoSuchAlgorithmException {
+// KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+// keyPairGenerator.initialize(1024);
+// KeyPair keyPair = keyPairGenerator.generateKeyPair();
+// RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
+// RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
+// String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
+// String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
+// System.out.println("公钥:" + publicKeyString);
+// System.out.println("私钥:" + privateKeyString);
+// }
+
+ /**
+ * 解密
+ * @param args
+ * @throws NoSuchAlgorithmException
+ */
+ public static void main(String[] args) throws Exception {
+ String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJA0JB/XhdVz/rxlt/XI8LmB7WvPhT1ZpoLXaMfg7zNN+jRWOpuYc+NDr17uA07yl9h2FHOZ6aG5eoobyUP13gAopQuS7BJYwrrA0HLJjZuROWPw/djA8uxQQ97q22k7evlnZ4a1mVJRONbzQxUKQEgLM0S7+l699/NIZGyI4+XPAgMBAAECgYBlyjh5tZPGIbP93rtlJqst91XVVU4TCVZtY4qWFOQkTfXAveFu9cVP9fYzx0TUlI+0/1zeYRW20At8s7J1Y3eJhurZTLns+GpbFD2qExZVL9w5hqmn9fvOE4jCP7uTlTzVgT9zDxAvCid8mSVHz4z7MWG3/zrJloWQzE2riqeeyQJBAOiqfE4M5dQPopFKGhJBBWdKYLAK+trfi4iqstMfdndCiExGd0Nlw9/RS21LXZFk7RwCood6Q/XyKyXTZMwbTHUCQQCeqnTXhEhYlnRIHOuGKYGVHEFMrIGhPH0LZ7ZQUBp+q0wzUsCY79D9ppIwJPHggDsyJOZatm5eMtHb0dDEqbCzAkEAmHF72LfirjtATOm8g1FO9Qpqp23KRzZI+la9rE7lE+bn3vIcmnBHEpLTVN0YhXcXVE71psaZWMA/PR1w4brRMQJADJvPHTFN7nxGUVS7ArZZrdfI+KbcxktgRH/BZTB4aoiCTbHNzFmCaiXKiDjnX8fQ7HMyOxM0QhgXxTgvNvGlMQJATbRaCq7Ytw1SpHRuRbThjwkKVuinSX9y8rRhof7vEKTYomhoDoH7ZITWq421kXT81mj66ahtkPBccw1NeOqYCg==";
+ String decrypt = decrypt("EzAxC/373prww88TXDayIZTvxS3uFAvGhhzLNs+5cOfJU6zm3x/1RA5KcouuWwcYs0bbvNV7zSitLeEGeo23aPUxzr+rsNvCqKHrPNKbcl/oyOFBtOfguVbuHVEy8Q4cpVxfWCd/aEXx9OJXkLEAvlDdDF6SHyKhf+RUmSGEQOg=", privateKey);
+ System.out.println(decrypt);
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/RsaEncryptUtils.java b/src/main/java/com/ai/da/common/utils/RsaEncryptUtils.java
new file mode 100644
index 00000000..9e4b8b46
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/RsaEncryptUtils.java
@@ -0,0 +1,46 @@
+package com.ai.da.common.utils;
+
+import org.apache.tomcat.util.codec.binary.Base64;
+
+import javax.crypto.Cipher;
+import java.io.ByteArrayOutputStream;
+import java.security.KeyFactory;
+import java.security.PublicKey;
+import java.security.spec.X509EncodedKeySpec;
+
+/**
+ * Rsa加密工具
+ */
+public class RsaEncryptUtils {
+
+ /**
+ * 加密方法
+ *
+ * @param content 需要加密的内容
+ * @param publicKey 公钥
+ * @return 加密后得到的字符串
+ * @throws Exception
+ */
+ public static String encrypt(String content, String publicKey) throws Exception {
+ X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PublicKey publicKeyText = keyFactory.generatePublic(x509EncodedKeySpec2);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.ENCRYPT_MODE, publicKeyText);
+ byte[] result = doLongerCipherFinal(cipher, content.getBytes());
+ return Base64.encodeBase64String(result);
+ }
+
+ private static byte[] doLongerCipherFinal(Cipher cipher, byte[] source) throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int offset = 0;
+ int totalSize = source.length;
+ while (totalSize - offset > 0) {
+ int size = Math.min(cipher.getOutputSize(0) - 11, totalSize - offset);
+ out.write(cipher.doFinal(source, offset, size));
+ offset += size;
+ }
+ out.close();
+ return out.toByteArray();
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/SecurityContextUtils.java b/src/main/java/com/ai/da/common/utils/SecurityContextUtils.java
new file mode 100644
index 00000000..34a82627
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/SecurityContextUtils.java
@@ -0,0 +1,32 @@
+package com.ai.da.common.utils;
+
+import com.ai.da.model.vo.AuthPrincipalVo;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+public class SecurityContextUtils {
+
+ public static AuthPrincipalVo getCurrentUser() {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if(authentication != null && authentication.getPrincipal() != null){
+ return (AuthPrincipalVo) authentication.getPrincipal();
+ }
+ return null;
+ }
+
+ public static Long getCurrentUserId() {
+ AuthPrincipalVo currentUser = getCurrentUser();
+ if(currentUser != null){
+ return currentUser.getId();
+ }
+ return null;
+ }
+
+ public static String getCurrentUsername() {
+ AuthPrincipalVo currentUser = getCurrentUser();
+ if(currentUser != null){
+ return currentUser.getUsername();
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/SendEmailUtil.java b/src/main/java/com/ai/da/common/utils/SendEmailUtil.java
new file mode 100644
index 00000000..eaa3873f
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/SendEmailUtil.java
@@ -0,0 +1,116 @@
+package com.ai.da.common.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ai.da.common.config.exception.BusinessException;
+import com.tencentcloudapi.common.Credential;
+import com.tencentcloudapi.common.exception.TencentCloudSDKException;
+import com.tencentcloudapi.common.profile.ClientProfile;
+import com.tencentcloudapi.common.profile.HttpProfile;
+import com.tencentcloudapi.ses.v20201002.SesClient;
+import com.tencentcloudapi.ses.v20201002.models.SendEmailRequest;
+import com.tencentcloudapi.ses.v20201002.models.SendEmailResponse;
+import com.tencentcloudapi.ses.v20201002.models.Template;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Date;
+
+/**
+ * 邮件发送类
+ */
+@Slf4j
+public class SendEmailUtil {
+ /**
+ * 秘钥id
+ */
+ private static String SECRET_ID = "AKID52lRwDIBsLaZLtDI9m9LJMAj36wYw50i";
+ /**
+ * 秘钥key
+ */
+ private static String SECRET_KEy = "XqujLlywhHfrqcCYfYVHtNgmeIiwxkKf";
+ /**
+ * 发信地址
+ */
+ private static String SEND_ADDRESS = "info@aida.com.hk";
+ /**
+ * 登入主题
+ */
+ public static String LOGIN_SUBJECT = "Log on";
+ /**
+ * 忘记密码主题
+ */
+ public static String FORGET_PWD_SUBJECT = "Reset password";
+ /**
+ * 异常ip
+ */
+ public static String EXCEPTION_ID_SUBJECT = "Exception ip";
+ /**
+ * 绑定邮箱
+ */
+ public static String BIND_MAILBOX_SUBJECT = "绑定邮箱";
+ /**
+ * 登入模板id
+ */
+ public static Long LOGIN_TEMPLATE_ID = 58020L;
+ /**
+ * 修改密码模板id
+ */
+ public static Long UPDATE_PWD_TEMPLATE_ID = 58022L;
+ /**
+ * 异常ip模板id
+ */
+ public static Long EXCEPTION_ID_TEMPLATE_ID = 58021L;
+ /**
+ * 绑定邮箱模板id
+ */
+ public static Long BIND_MAILBOX_TEMPLATE_ID = 45619L;
+
+
+ public static Boolean send(String receiverAddress,String ip,Long templateId,String verifyCode) {
+ try{
+ // 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密
+ // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
+ Credential cred = new Credential(SECRET_ID, SECRET_KEy);
+ // 实例化一个http选项,可选的,没有特殊需求可以跳过
+ HttpProfile httpProfile = new HttpProfile();
+ httpProfile.setEndpoint("ses.tencentcloudapi.com");
+ // 实例化一个client选项,可选的,没有特殊需求可以跳过
+ ClientProfile clientProfile = new ClientProfile();
+ clientProfile.setHttpProfile(httpProfile);
+ // 实例化要请求产品的client对象,clientProfile是可选的
+ SesClient client = new SesClient(cred, "ap-hongkong", clientProfile);
+ // 实例化一个请求对象,每个接口都会对应一个request对象
+ SendEmailRequest req = new SendEmailRequest();
+
+ req.setFromEmailAddress(SEND_ADDRESS);
+ req.setDestination(new String[]{receiverAddress});
+ String subject = templateId == LOGIN_TEMPLATE_ID ? LOGIN_SUBJECT :
+ templateId == UPDATE_PWD_TEMPLATE_ID ? FORGET_PWD_SUBJECT :
+ templateId == EXCEPTION_ID_TEMPLATE_ID ? EXCEPTION_ID_SUBJECT :BIND_MAILBOX_SUBJECT;
+ req.setSubject(subject);
+ req.setTemplate(contractTemplate(templateId, verifyCode,ip));
+
+ // 返回的resp是一个SendEmailResponse的实例,与请求对象对应
+ SendEmailResponse resp = client.SendEmail(req);
+ // 输出json格式的字符串回包
+ log.info("短信发送结果res###{}",SendEmailResponse.toJsonString(resp));
+ return Boolean.TRUE;
+ } catch (TencentCloudSDKException e) {
+ log.info("邮件发送失败###{}",e.toString());
+ throw new BusinessException(e.getMessage());
+ }
+ }
+ private static Template contractTemplate(Long templateId,String verifyCode,String ip){
+ Template template = new Template();
+ template.setTemplateID(templateId);
+
+ JSONObject jsonObject = new JSONObject();
+ if(templateId == EXCEPTION_ID_TEMPLATE_ID ){
+ jsonObject.put("exceptionIp",ip);
+ jsonObject.put("loginTime",DateUtil.dateToStr(new Date(),DateUtil.YYYY_MM_DD_HH_MM_SS));
+ }else{
+ jsonObject.put("code",verifyCode);
+ }
+ template.setTemplateData(jsonObject.toJSONString());
+ return template;
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/SendSmsUtil.java b/src/main/java/com/ai/da/common/utils/SendSmsUtil.java
new file mode 100644
index 00000000..c0da38a4
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/SendSmsUtil.java
@@ -0,0 +1,106 @@
+//package com.ai.da.common.utils;
+//
+//import com.ai.da.common.config.exception.BusinessException;
+//import com.tencentcloudapi.common.Credential;
+//import com.tencentcloudapi.common.exception.TencentCloudSDKException;
+//import com.tencentcloudapi.common.profile.ClientProfile;
+//import com.tencentcloudapi.common.profile.HttpProfile;
+//import com.tencentcloudapi.sms.v20210111.SmsClient;
+//import com.tencentcloudapi.sms.v20210111.models.*;
+//import lombok.extern.slf4j.Slf4j;
+//import org.bouncycastle.util.Arrays;
+//
+//import java.util.Objects;
+//
+///**
+// * 短信发送类
+// */
+//@Slf4j
+//public class SendSmsUtil {
+// /**
+// * 秘钥id
+// */
+// private static String SECRET_ID = "AKIDylJaZIkunPkZ7OPAermRovlKccLnysVr";
+// /**
+// * 秘钥key
+// */
+// private static String SECRET_KEy = "5tQgeLlumPmshFVUCdngIcfXeU4NPAdq";
+// /**
+// * sdkAppId
+// */
+// private static String SDK_APP_ID = "1400722195";
+// /**
+// * 签名
+// */
+// public static String SIGN_NAME = "深呼吸智能窗帘";
+// /**
+// * 忘记密码模板
+// */
+// public static String FORGET_TEMPLATE_ID = "1514353";
+// /**
+// * 登入模板
+// */
+// public static String LOGIN_TEMPLATE_ID = "1514349";
+// /**
+// * 登入操作
+// */
+// public static String LOGIN_OPERATION = "登入";
+// /**
+// * 忘记密码操作
+// */
+// public static String FORGET_PWD_OPERATION = "忘记密码操作";
+//
+//
+// public static Boolean send(String phone, String templateId, String verifyCode) {
+// try{
+// // 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密
+// // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
+// Credential cred = new Credential(SECRET_ID, SECRET_KEy);
+// // 实例化一个http选项,可选的,没有特殊需求可以跳过
+// HttpProfile httpProfile = new HttpProfile();
+// httpProfile.setReqMethod("POST");
+// /* SDK有默认的超时时间,非必要请不要进行调整
+// * 如有需要请在代码中查阅以获取最新的默认值 */
+// httpProfile.setConnTimeout(60);
+// /* 指定接入地域域名,默认就近地域接入域名为 sms.tencentcloudapi.com ,也支持指定地域域名访问,例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com */
+// httpProfile.setEndpoint("sms.tencentcloudapi.com");
+//
+// /* 非必要步骤:
+// * 实例化一个客户端配置对象,可以指定超时时间等配置 */
+// ClientProfile clientProfile = new ClientProfile();
+// /* SDK默认用TC3-HMAC-SHA256进行签名
+// * 非必要请不要修改这个字段 */
+// clientProfile.setSignMethod("HmacSHA256");
+// clientProfile.setHttpProfile(httpProfile);
+// /* 实例化要请求产品(以sms为例)的client对象
+// * 第二个参数是地域信息,可以直接填写字符串ap-guangzhou,支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */
+// SmsClient client = new SmsClient(cred, "ap-guangzhou",clientProfile);
+//
+// SendSmsRequest req = new SendSmsRequest();
+// req.setSmsSdkAppId(SDK_APP_ID);
+// req.setSignName(SIGN_NAME);
+// req.setTemplateId(templateId);
+// //模板参数
+// String[] templateParamSet = {verifyCode};
+// req.setTemplateParamSet(templateParamSet);
+// /* 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号]
+// * 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号 */
+// String[] phoneNumberSet = {phone};
+// req.setPhoneNumberSet(phoneNumberSet);
+// //发送短信
+// SendSmsResponse res = client.SendSms(req);
+// log.info("短信发送结果res###{}",SendSmsResponse.toJsonString(res));
+// if(Objects.isNull(res)|| Arrays.isNullOrContainsNull(res.getSendStatusSet())
+// || res.getSendStatusSet()[0].getCode() != "Ok"){
+// SendStatus message = res.getSendStatusSet()[0];
+// throw new BusinessException(message.getMessage());
+// }
+// // 输出json格式的字符串回包
+// } catch (TencentCloudSDKException e) {
+// log.error(e.toString());
+// return Boolean.FALSE;
+// }
+// return Boolean.TRUE;
+// }
+//
+//}
diff --git a/src/main/java/com/ai/da/common/utils/SpringUtils.java b/src/main/java/com/ai/da/common/utils/SpringUtils.java
new file mode 100644
index 00000000..99f15050
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/SpringUtils.java
@@ -0,0 +1,44 @@
+package com.ai.da.common.utils;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName SpringUtils
+ * @Description springBean工具
+ * @Author dwjian
+ * @Date 2020/1/15 17:10
+ */
+@Component
+public class SpringUtils implements ApplicationContextAware {
+
+ private static ApplicationContext applicationContext;
+
+ public static T getBean(Class clazz) {
+ return applicationContext.getBean(clazz);
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ SpringUtils.applicationContext = applicationContext;
+ }
+
+ public static T getBean(String beanName) {
+ if(applicationContext.containsBean(beanName)){
+ return (T) applicationContext.getBean(beanName);
+ }else{
+ return null;
+ }
+ }
+
+ public static Map getBeansOfType(Class baseType){
+ return applicationContext.getBeansOfType(baseType);
+ }
+
+ public static ApplicationContext getApplicationContext(){
+ return applicationContext;
+ }
+}
diff --git a/src/main/java/com/ai/da/controller/AccountController.java b/src/main/java/com/ai/da/controller/AccountController.java
new file mode 100644
index 00000000..8b2376cb
--- /dev/null
+++ b/src/main/java/com/ai/da/controller/AccountController.java
@@ -0,0 +1,69 @@
+package com.ai.da.controller;
+
+import com.ai.da.common.response.Response;
+import com.ai.da.common.security.jwt.JWTTokenHelper;
+import com.ai.da.model.dto.*;
+import com.ai.da.model.vo.AccountLoginVO;
+import com.ai.da.model.vo.AccountPreLoginVO;
+import com.ai.da.service.AccountService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+
+
+@Api(tags = "Account模块")
+@Slf4j
+@RestController
+@RequestMapping("/api/account")
+public class AccountController {
+
+ @Resource
+ private AccountService accountService;
+
+ @ApiOperation(value = "预先登入")
+ @PostMapping("/preLogin")
+ public Response preLogin(@Valid @RequestBody AccountPreLoginDTO accountDTO) {
+ return Response.success(accountService.preLogin(accountDTO));
+ }
+ @ApiOperation(value = "登入")
+ @PostMapping("/login")
+ public Response login(@Valid @RequestBody AccountLoginDTO accountDTO, HttpServletRequest request) {
+ return Response.success(accountService.login(accountDTO,request));
+ }
+
+ @ApiOperation(value = "绑定邮箱")
+ @PostMapping("/bindEmail")
+ public Response bindEmail(@Valid @RequestBody AccountBindEmailDTO accountBindEmailDTO) {
+ return Response.success(accountService.bindEmail(accountBindEmailDTO));
+ }
+
+ @ApiOperation(value = "忘记密码")
+ @PostMapping("/resetPwd")
+ public Response resetPwd(@Valid @RequestBody AccountRegisterDTO accountRegisterDTO) {
+ return Response.success(accountService.forgetPwd(accountRegisterDTO));
+ }
+
+ @ApiOperation(value = "发送邮件")
+ @PostMapping("/sendEmail")
+ public Response sendEmail(@Valid @RequestBody EmailSendDTO emailSendDTO) {
+ return Response.success(accountService.sendEmail(emailSendDTO));
+ }
+
+ @ApiOperation(value = "登出")
+ @PostMapping("/logout")
+ public Response logout(@Valid @RequestBody AccountLogoutDTO accountLogoutDTO) {
+ return Response.success( accountService.logout(accountLogoutDTO));
+ }
+
+ @ApiOperation(value = "是否登入")
+ @PostMapping("/isLogin")
+ public Response isLogin(@Valid @RequestBody AccountLogoutDTO accountLogoutDTO) {
+ return Response.success( accountService.isLogin(accountLogoutDTO));
+ }
+
+}
diff --git a/src/main/java/com/ai/da/controller/DesignController.java b/src/main/java/com/ai/da/controller/DesignController.java
new file mode 100644
index 00000000..94e8985a
--- /dev/null
+++ b/src/main/java/com/ai/da/controller/DesignController.java
@@ -0,0 +1,63 @@
+package com.ai.da.controller;
+
+import com.ai.da.common.response.Response;
+import com.ai.da.model.dto.*;
+import com.ai.da.model.vo.DesignCollectionVO;
+import com.ai.da.model.vo.DesignItemDetailVO;
+import com.ai.da.model.vo.DesignLikeVO;
+import com.ai.da.service.DesignService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.math.BigDecimal;
+
+
+@Api(tags = "design模块")
+@Slf4j
+@RestController
+@RequestMapping("/api/design")
+public class DesignController {
+ @Resource
+ private DesignService designService;
+
+ @ApiOperation(value = "设计 Conllection")
+ @PostMapping("/designCollection")
+ public Response designCollection(@Valid @RequestBody DesignCollectionDTO designDTO) {
+ return Response.success(designService.designCollection(designDTO));
+ }
+
+ @ApiOperation(value = "重新设计 Collection")
+ @PostMapping("/reDesignCollection")
+ public Response reDesignCollection(@Valid @RequestBody ReDesignCollectionDTO reDesignDTO) {
+ return Response.success(designService.reDesignCollection(reDesignDTO));
+ }
+ @ApiOperation(value = "designItem list,刷新用")
+ @GetMapping("/designItemList")
+ public Response designItemList(@ApiParam("designId") @RequestParam("designId") Long designId) {
+ return Response.success(designService.designItemList(designId));
+ }
+
+ @ApiOperation(value = "统计design进度")
+ @PostMapping("/countDesignProcess")
+ public Response countDesignProcess() {
+ return Response.success(designService.countDesignProcess());
+ }
+
+ @ApiOperation(value = "Design Like")
+ @PostMapping("/like")
+ public Response like(@Valid @RequestBody DesignLikeDTO designLikeDTO) {
+ return Response.success(designService.like(designLikeDTO));
+ }
+
+ @ApiOperation(value = "Design Dislike")
+ @PostMapping("/dislike")
+ public Response dislike(@Valid @RequestBody DisDesignLikeDTO disDesignLikeDTO) {
+ return Response.success(designService.dislike(disDesignLikeDTO));
+ }
+
+}
diff --git a/src/main/java/com/ai/da/controller/DesignDetailController.java b/src/main/java/com/ai/da/controller/DesignDetailController.java
new file mode 100644
index 00000000..1b4ca8c7
--- /dev/null
+++ b/src/main/java/com/ai/da/controller/DesignDetailController.java
@@ -0,0 +1,74 @@
+package com.ai.da.controller;
+
+import com.ai.da.common.response.Response;
+import com.ai.da.mapper.entity.CollectionElement;
+import com.ai.da.mapper.entity.DesignItem;
+import com.ai.da.model.dto.*;
+import com.ai.da.model.vo.*;
+import com.ai.da.service.DesignItemService;
+import com.ai.da.service.DesignService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.math.BigDecimal;
+
+
+@Api(tags = "design Detail模块")
+@Slf4j
+@RestController
+@RequestMapping("/api/design/detail")
+public class DesignDetailController {
+ @Resource
+ private DesignService designService;
+ @Resource
+ private DesignItemService designItemService;
+
+ @ApiOperation(value = "生成高级design图片")
+ @PostMapping("/generateHighDesign")
+ public Response generateHighDesign(@Valid @RequestBody GenerateHighDesignDTO generateHighDesignDTO) {
+ Response response = new Response();
+ response.setData(designService. generateHighDesign(generateHighDesignDTO));
+ return response;
+ }
+ @ApiOperation(value = "删除高级design图片")
+ @PostMapping("/deleteHighDesign")
+ public Response deleteHighDesign(@Valid @RequestBody GenerateHighDesignDTO generateHighDesignDTO) {
+ Response response = new Response();
+ response.setData(designService.deleteHighDesign(generateHighDesignDTO));
+ return response;
+ }
+ @ApiOperation(value = "查询design详情")
+ @GetMapping("/getDetail")
+ public Response getDetail(@ApiParam("designItemId") @RequestParam("designItemId") Long designItemId) {
+ return Response.success(designService.detail(designItemId));
+ }
+
+ @ApiOperation(value = "切换系统的element")
+ @GetMapping("/getNextSysElement")
+ public Response getNextSysElement(@ApiParam("要切换的系统element 类型") @RequestParam("type") String type,
+ @ApiParam("要切换的系统element id") @RequestParam("id") Long id,
+ @ApiParam("操作类型 PREV 上一步 NEXT 下一步") @RequestParam("operateType") String operateType) {
+ return Response.success(designItemService.getNextSysElement(id,type,operateType));
+ }
+ @ApiOperation(value = "单个design")
+ @PostMapping("/designSingle")
+ public Response designSingle(@Valid @RequestBody DesignSingleDTO designSingleDTO ) {
+ return Response.success(designItemService.designSingle(designSingleDTO));
+ }
+
+ @ApiOperation(value = "print打点")
+ @PostMapping("/printDot")
+ public Response printDot(@Valid @RequestBody DesignSingleDTO designSingleDTO ) {
+ Response response =new Response();
+ String url = designItemService.printDot(designSingleDTO);
+ response.setData(url);
+ return response;
+ }
+
+
+}
diff --git a/src/main/java/com/ai/da/controller/ElementController.java b/src/main/java/com/ai/da/controller/ElementController.java
new file mode 100644
index 00000000..1d28fae7
--- /dev/null
+++ b/src/main/java/com/ai/da/controller/ElementController.java
@@ -0,0 +1,99 @@
+package com.ai.da.controller;
+
+import com.ai.da.common.response.Response;
+import com.ai.da.common.utils.FileUtil;
+import com.ai.da.common.utils.MD5Utils;
+import com.ai.da.model.dto.*;
+import com.ai.da.model.vo.*;
+import com.ai.da.service.CollectionElementService;
+import com.ai.da.service.PanToneService;
+import com.ai.da.service.SysFileService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.List;
+
+
+@Api(tags = "collection模块")
+@Slf4j
+@RestController
+@RequestMapping("/api/element")
+public class ElementController {
+
+ @Resource
+ private CollectionElementService collectionElementService;
+ @Resource
+ private PanToneService panToneService;
+ @Resource
+ private SysFileService sysFileService;
+
+ @ApiOperation(value = "初始化系统文件")
+ @PostMapping("/initDefaultSysFile")
+ public Response initDefaultSysFile(@RequestParam("validate") String validateUse) {
+ if (validateUse.equals("da_fl_mm_dad88888")) {
+ //防止被调用
+ sysFileService.initDefaultSysFile();
+ }
+ return Response.success();
+ }
+
+ @ApiOperation(value = "element文件上传")
+ @PostMapping("/upload")
+ public Response upload(@RequestParam("file") MultipartFile file,
+ @ApiParam("一级类型 Moodboard Printboard Sketchboard MarketingSketch Colorboard")
+ @RequestParam(value = "level1Type") String level1Type,
+ @ApiParam("本地时区,比如 'Asia/Tokyo' 东京时间 , 'Asia/Shanghai' 北京时间 由js本地获取")
+ @RequestParam(value = "timeZone") String timeZone) {
+ Assert.isTrue(!StringUtils.isEmpty(file.getOriginalFilename()),"Please select a file!");
+ return Response.success(collectionElementService.upload(
+ new CollectionElementUploadDTO(file, level1Type, timeZone, MD5Utils.encryptFile(file))));
+ }
+
+ @ApiOperation(value = "element文件删除")
+ @PostMapping("/delete")
+ public Response delete(@Valid @RequestBody CollectionDeleteFileDTO deleteFileDTO) {
+ collectionElementService.delete(deleteFileDTO.getId());
+ return Response.success();
+ }
+
+ @ApiOperation(value = "生成印花")
+ @PostMapping("/generatePrint")
+ public Response generatePrint(@Valid @RequestBody CollectionGeneratePrintDTO generatePrintDTO) {
+ return Response.success(collectionElementService.generatePrint(generatePrintDTO));
+ }
+
+ @ApiOperation(value = "保存印花")
+ @PostMapping("/savePrint")
+ public Response savePrint(@Valid @RequestBody CollectionSavePrintDTO savePrintDTO) {
+ return Response.success(collectionElementService.savePrint(savePrintDTO));
+ }
+
+ @ApiOperation(value = "通过tcx值获取潘通信息")
+ @GetMapping("/getRgbByTcx")
+ public Response getRgbByHsv(@ApiParam("tcx") @RequestParam("tcx") String tcx) {
+ return Response.success(panToneService.getByTCX(tcx));
+ }
+
+ @ApiOperation(value = "通过hsv值获取潘通信息")
+ @GetMapping("/getRgbByHsv")
+ public Response getRgbByHsv(@RequestParam("h") Integer h,
+ @RequestParam("s") Integer s, @RequestParam("v") Integer v) {
+ return Response.success(panToneService.getByHSV(h, s, v));
+ }
+
+ @ApiOperation(value = "通过hsv值数组批量获取潘通信息")
+ @PostMapping("/getRgbByHsvBatch")
+ public Response> getRgbByHsvBatch(@RequestBody @Valid List rgbByHsvBatch) {
+ return Response.success(panToneService.getRgbByHsvBatch(rgbByHsvBatch));
+ }
+
+}
diff --git a/src/main/java/com/ai/da/controller/LibraryController.java b/src/main/java/com/ai/da/controller/LibraryController.java
new file mode 100644
index 00000000..335bc9db
--- /dev/null
+++ b/src/main/java/com/ai/da/controller/LibraryController.java
@@ -0,0 +1,158 @@
+package com.ai.da.controller;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.system.UserInfo;
+import com.ai.da.common.config.FileProperties;
+import com.ai.da.common.context.UserContext;
+import com.ai.da.common.enums.LibraryLevel1TypeEnum;
+import com.ai.da.common.response.PageBaseResponse;
+import com.ai.da.common.response.Response;
+import com.ai.da.common.utils.CopyUtil;
+import com.ai.da.common.utils.DateUtil;
+import com.ai.da.common.utils.FileUtil;
+import com.ai.da.common.utils.MD5Utils;
+import com.ai.da.mapper.entity.Library;
+import com.ai.da.mapper.entity.LibraryModelPoint;
+import com.ai.da.model.dto.*;
+import com.ai.da.model.vo.*;
+import com.ai.da.service.LibraryModelPointService;
+import com.ai.da.service.LibraryService;
+import com.alibaba.fastjson.JSON;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.io.File;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+
+
+@Api(tags = "library模块")
+@Slf4j
+@RestController
+@RequestMapping("/api/library")
+public class LibraryController {
+
+ @Resource
+ private LibraryService libraryService;
+ @Resource
+ private LibraryModelPointService libraryModelPointService;
+ @Resource
+ private FileProperties fileProperties;
+
+ @ApiOperation(value = "Library分页列表")
+ @PostMapping("/queryLibraryPage")
+ public Response> queryLibraryPage(@Valid @RequestBody QueryLibraryPageDTO query) {
+ return Response.success(libraryService.queryLibraryPage(CopyUtil.copyObject(query,QueryLibraryPageServiceDTO.class)));
+ }
+
+ @ApiOperation(value = "Library分页列表(查询top和bottom)")
+ @PostMapping("/queryLibraryTopAndBottomPage")
+ public Response> queryLibraryTopAndBottomPage(@Valid @RequestBody QueryLibraryTopPageDTO query) {
+ return Response.success(libraryService.queryLibraryPage(CopyUtil.copyObject(query,QueryLibraryPageServiceDTO.class)));
+ }
+
+ @ApiOperation(value = "Library文件上传")
+ @PostMapping("/upload")
+ public Response upload(@RequestParam("file") MultipartFile file,
+ @ApiParam("一级类型 Moodboard Printboard Sketchboard MarketingSketch Models")
+ @RequestParam(value = "level1Type") String level1Type,
+ @ApiParam("二级类型 争对 Sketchboard; 有 Outwear Dress Blouse Skirt Trousers")
+ @RequestParam(value = "level2Type",required = false) String level2Type,
+ @ApiParam("本地时区,比如 'Asia/Tokyo' 东京时间 , 'Asia/Shanghai' 北京时间 由js本地获取")
+ @RequestParam(value = "timeZone") String timeZone) {
+ Assert.isTrue(!StringUtils.isEmpty(file.getOriginalFilename()),"Please select a file!");
+ Integer high =null;
+ Integer width =null;
+ if(level1Type.equals(LibraryLevel1TypeEnum.MODELS.getRealName())){
+ FileVO fileVO = FileUtil.getFileSize(file);
+ high = fileVO.getHigh();
+ width = fileVO.getWidth();
+ }
+ return Response.success(libraryService.upload(new LibraryUploadDTO(file, level1Type,level2Type,
+ timeZone, MD5Utils.encryptFile(file),high,width)));
+ }
+ @ApiOperation(value = "保存或者编辑template打点")
+ @PostMapping("/saveOrEditTemplatePoint")
+ public Response saveOrEditTemplatePoint(@Valid @RequestBody LibraryModelPointDTO libraryModelPoint) {
+ return Response.success(libraryModelPointService.saveOrEditTemplatePoint(libraryModelPoint));
+ }
+ @ApiOperation(value = "批量Library修改用户文件名")
+ @PostMapping("/batchUpdateLibraryName")
+ public Response batchUpdateLibraryName(@Valid @RequestBody LibraryUpdateDTO libraryUpdateDTO) {
+ libraryService.updateLibraryName(libraryUpdateDTO);
+ return Response.success(Boolean.TRUE);
+ }
+
+ @ApiOperation(value = "批量删除library")
+ @PostMapping("/batchDeleteLibrary")
+ public Response batchDeleteLibrary(@Valid @RequestBody LibraryDeleteDTO deleteDTO) {
+ List librarys = libraryService.getByIds(deleteDTO.getLibraryIds());
+ Assert.notEmpty(librarys,"librarys does not exist!");
+ libraryService.removeBatchByIds(deleteDTO.getLibraryIds());
+ librarys.forEach(library -> {
+ FileUtil.delete(library.getUrl());
+ });
+ return Response.success(Boolean.TRUE);
+ }
+
+
+ @ApiOperation(value = "Models打点预览")
+ @PostMapping("/modelsDot")
+ public Response modelsDot(@ApiParam("file") @RequestPart(value = "file",required = false) MultipartFile file,
+ @ApiParam("models对象")@RequestPart("models") ModelsDotDTO modelsDotDTO) {
+ if(Objects.nonNull(file)){
+ Assert.isTrue(!StringUtils.isEmpty(file.getOriginalFilename()),"Please select a file!");
+ AuthPrincipalVo userInfo = UserContext.getUserHolder();
+ //需要宽高和地址参数design
+ FileVO fileVO = FileUtil.getFileSize(file);
+ modelsDotDTO.setHigh(fileVO.getHigh());
+ modelsDotDTO.setWidth(fileVO.getWidth());
+ //存储template临时地址
+ String path = calculateTempFileUrl(userInfo.getId());
+ File uploadFile = FileUtil.upload(file, path);
+ modelsDotDTO.setTemplateUrl(calculateTemplateUrl(uploadFile));
+ }else{
+ Assert.notNull(modelsDotDTO.getLibraryId(),"libraryId cannot be empty!");
+ Assert.notNull(modelsDotDTO.getTemplateId(),"templateId cannot be empty!");
+ LibraryModelPoint modelPoint = libraryModelPointService.getById(modelsDotDTO.getTemplateId());
+ Assert.notNull(modelPoint,"template does not exist!");
+ Library library = libraryService.getById(modelsDotDTO.getLibraryId());
+ Assert.notNull(library,"library does not exist!");
+ modelsDotDTO.setHigh(library.getHigh());
+ modelsDotDTO.setWidth(library.getWidth());
+ modelsDotDTO.setTemplateUrl(library.getUrl());
+ }
+ Response response =new Response();
+ log.info("Models打点预览入参####{}", JSON.toJSONString(modelsDotDTO));
+ String url = libraryModelPointService.modelsDot(modelsDotDTO);
+ response.setData(url);
+ return response;
+ }
+
+ private String calculateTempFileUrl(Long userId) {
+ String rootPath = fileProperties.getSys().getPath();
+ String day = DateUtil.dateToStr(new Date(), DateUtil.YYYYMM);
+ return rootPath + day + File.separator + "tmp" + File.separator + userId + File.separator+ UUID.randomUUID().toString();
+ }
+ private String calculateTemplateUrl(File uploadFile){
+ String linuxDomain = fileProperties.getLinuxDomain();
+ if (!StringUtils.isEmpty(linuxDomain)) {
+ //linux 系统
+ String oldPath = fileProperties.getSys().getPath();
+ return uploadFile.getAbsolutePath().replace(oldPath, linuxDomain);
+ }
+ //本地用
+// return "/home/pangkaicheng/python_code/Multi-layer-Virtual-Try-on/dataset_for_test/Img_model.png";
+ return "/workspace/python_code/Multi-layer-Virtual-Try-on/dataset_for_test/Img_model.png";
+ }
+
+}
diff --git a/src/main/java/com/ai/da/controller/PythonController.java b/src/main/java/com/ai/da/controller/PythonController.java
new file mode 100644
index 00000000..f9dbd0f4
--- /dev/null
+++ b/src/main/java/com/ai/da/controller/PythonController.java
@@ -0,0 +1,67 @@
+package com.ai.da.controller;
+
+import com.ai.da.common.enums.CollectionLevel1TypeEnum;
+import com.ai.da.common.response.Response;
+import com.ai.da.common.utils.CopyUtil;
+import com.ai.da.common.utils.MD5Utils;
+import com.ai.da.model.dto.CollectionDeleteFileDTO;
+import com.ai.da.model.dto.CollectionElementUploadDTO;
+import com.ai.da.model.dto.CollectionGeneratePrintDTO;
+import com.ai.da.model.dto.CollectionSavePrintDTO;
+import com.ai.da.model.vo.*;
+import com.ai.da.python.PythonService;
+import com.ai.da.service.*;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+@Api(tags = "python对接模块")
+@Slf4j
+@RestController
+@RequestMapping("/api/python")
+public class PythonController {
+
+ @Resource
+ private PythonService pythonService;
+ @Resource
+ private SysFileService sysFileService;
+ @Resource
+ private LibraryService libraryService;
+
+ @ApiOperation(value = "python服务保存图片到java服务")
+ @PostMapping("/saveGeneratePicture")
+ public Response upload(@RequestParam("file") MultipartFile file,
+ @ApiParam("操作类型 generatePrint ->生成印花 " +
+ "designCollection ->设计collection generateAdvancedDesign ->生成高级design")
+ @RequestParam(value = "operateType") String operateType) {
+ return Response.success(pythonService.upload(file,operateType));
+ }
+
+ @ApiOperation(value = "通过文件类型获取系统文件")
+ @GetMapping("/getSysFileByLevel2Type")
+ public Response> getSysFileByLevel2Type(/*@RequestParam(value = "level2Type",required = false) String level2Type*/) {
+ return Response.success(sysFileService.getByLevel2Type("All"));
+ }
+
+ @ApiOperation(value = "通过用户id获取library")
+ @GetMapping("/getLibraryByUserId")
+ public Response