Преглед изворни кода

项目字段修改&合同上传

wucl пре 2 година
родитељ
комит
99f021ac22

+ 71 - 0
biz-base/src/main/java/com/dayou/controller/FileController.java

@@ -0,0 +1,71 @@
+package com.dayou.controller;
+
+import com.dayou.annotation.IgnoreAuth;
+import com.dayou.common.RestResponse;
+import com.dayou.configuration.DfsConfig;
+import com.dayou.exception.ErrorCode;
+import com.dayou.exception.file.InvalidExtensionException;
+import com.dayou.service.IGlobalConfigService;
+import com.dayou.utils.FileUploadUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import static com.dayou.exception.ErrorCode.DEFAULTERROR;
+import static com.dayou.exception.ErrorCode.FILE_EXT_ERROR;
+
+
+/**
+ * 文件上传
+ *
+ * @author wucl
+ * @since 2023-2-7
+ */
+@Slf4j
+@RestController
+@IgnoreAuth
+public class FileController {
+
+    private static final Pattern PORTPATTERN = Pattern.compile(":\\d+");
+
+    @Autowired
+    private DfsConfig dfsConfig;
+
+
+    @Value("${server.port:80}")
+    private Integer port;
+
+    /**
+     * 通用上传请求
+     */
+    @PostMapping("upload")
+    public RestResponse upload(MultipartFile file) {
+        try {
+            // 上传文件路径
+            String filePath = dfsConfig.getPath();
+            // 上传并返回新文件名称
+            String fileName = null;
+            fileName = FileUploadUtils.upload(filePath, file);
+            String url = dfsConfig.getDomain() + fileName;
+            Map map = new HashMap();
+            map.put("fileName", fileName);
+            map.put("url", url);
+            return RestResponse.data(map);
+        } catch (InvalidExtensionException e) {
+            ErrorCode.throwBusinessException(FILE_EXT_ERROR);
+        } catch (Exception e) {
+            log.error("upload error", e);
+            ErrorCode.throwBusinessException(DEFAULTERROR);
+        }
+
+        return RestResponse.error();
+    }
+
+}

+ 0 - 4
biz-base/src/main/resources/application-local.yml

@@ -26,10 +26,6 @@ advice:
   file:
     tmp: tmp
 
-#百度编辑器
-ueditor:
-  uploadPath: ${dfs.path}
-  urlPrefix: replaceurl  #动态替换url
 
 #系统配置
 system:

+ 0 - 11
biz-base/src/main/resources/application-prod.yml

@@ -22,17 +22,6 @@ dfs:
   path: /opt/dfs
   domain: /dfs
 
-baidu:
-  ai:
-    tokenexpire: 20
-    ak: o73GBsDk7MUlarPG3mMmnsNQ
-    sk: fjIV0S5NeaUiGdMFZuFLYSRQnhCjZAM0
-
-advice:
-  file:
-    tmp: tmp
-
-
 #系统配置
 system:
   login:

+ 1 - 5
biz-base/src/main/resources/application-test.yml

@@ -3,7 +3,7 @@ server:
 
 spring:
   datasource:
-    url: jdbc:mysql://localhost:3306/item-management?autoReconnect=true&useUnicode=true&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true
+    url: jdbc:mysql://localhost:1230/item-management?autoReconnect=true&useUnicode=true&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true
     username: root
     password: Dypg@1996
     initialSize: 10 #初始化连接数
@@ -22,10 +22,6 @@ dfs:
   path: /opt/dfs
   domain: /dfs
 
-advice:
-  file:
-    tmp: tmp
-
 
 #系统配置
 system:

+ 2 - 0
common/src/main/java/com/dayou/exception/ErrorCode.java

@@ -35,6 +35,8 @@ public class ErrorCode {
 
     public static final ErrorCode PASSWORD_ERROR= ErrorCode("10015", "原密码错误,请检查.");
 
+    public static final ErrorCode FILE_EXT_ERROR = ErrorCode("10016", "不支持此文件扩展名");
+
 
 
 

+ 374 - 0
common/src/main/java/com/dayou/utils/FileUploadUtils.java

@@ -0,0 +1,374 @@
+package com.dayou.utils;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.RandomUtil;
+import com.dayou.exception.file.FileNameLengthLimitExceededException;
+import com.dayou.exception.file.FileSizeLimitExceededException;
+import com.dayou.exception.file.InvalidExtensionException;
+import lombok.extern.slf4j.Slf4j;
+import net.coobird.thumbnailator.Thumbnails;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.MediaType;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.commons.CommonsMultipartFile;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * 文件上传工具类
+ *
+ * @author xysy
+ */
+@Slf4j
+public class FileUploadUtils {
+    // 图片默认缩放比率
+    private static final double DEFAULT_SCALE = 0.7d;
+    /**
+     * 默认大小 50M
+     */
+    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
+
+    /**
+     * 默认的文件名最大长度 100
+     */
+    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+
+    private static int counter = 0;
+
+    /**
+     * 根据文件路径上传
+     *
+     * @param baseDir 相对应用的基目录
+     * @param file    上传的文件
+     * @return 文件名称
+     * @throws IOException
+     */
+    public static final String upload(String baseDir, MultipartFile file) throws FileSizeLimitExceededException,
+            FileNameLengthLimitExceededException,
+            InvalidExtensionException, IOException {
+        return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, null);
+    }
+
+    /**
+     * @param baseDir
+     * @param file
+     * @param assginName 自定义文件名 包含扩展名
+     * @return
+     * @throws FileSizeLimitExceededException
+     * @throws FileNameLengthLimitExceededException
+     * @throws InvalidExtensionException
+     * @throws IOException
+     */
+    public static final String upload(String baseDir, MultipartFile file, String assginName) throws FileSizeLimitExceededException,
+            FileNameLengthLimitExceededException,
+            InvalidExtensionException, IOException {
+        return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, assginName);
+    }
+
+    /**
+     * 文件上传
+     *
+     * @param baseDir 相对应用的基目录
+     * @param file    上传的文件
+     * @return 返回上传成功的文件名
+     * @throws FileSizeLimitExceededException       如果超出最大大小
+     * @throws FileNameLengthLimitExceededException 文件名太长
+     * @throws IOException                          比如读写文件出错时
+     * @throws InvalidExtensionException            文件校验异常
+     */
+    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension, String assignName)
+            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+            InvalidExtensionException {
+        int fileNamelength = file.getOriginalFilename().length();
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
+            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+        }
+        assertAllowed(file, allowedExtension);
+        String fileName = extractFilename(file, assignName);
+        fileName = createDateIndexFileName(fileName);
+        File desc = getAbsoluteFile(baseDir, fileName);
+        try {
+            BufferedImage bufferedImage = ImageIO.read(file.getInputStream()); // 通过MultipartFile得到InputStream
+            // ,从而得到BufferedImage
+            if (bufferedImage == null) {
+                // 证明上传的文件不是图片,获取图片流失败,不进行下面的操作
+                file.transferTo(desc);
+            } else {
+                //不能使用bufferedImage 否则会出现翻转
+                Thumbnails.of(file.getInputStream())
+                        .scale(FileUploadUtils.DEFAULT_SCALE)
+                        .toFile(desc.getAbsolutePath());
+            }
+            // 省略逻辑判断
+        } catch (Exception e) {
+            // 省略异常操作
+            log.error("图片压缩失败", e);
+            file.transferTo(desc);
+        }
+        String pathFileName = fileName;
+        return pathFileName;
+
+    }
+
+
+    private static String createDateIndexFileName(String fileName) {
+        Date now = new Date();
+        String year = DateUtil.format(now, "yyyy");
+        String month = DateUtil.format(now, "MM");
+        String day = DateUtil.format(new Date(), "dd");
+//        String index =
+//                File.separator + year + File.separator + month + File.separator + day + File.separator + fileName;
+        //能够兼容win 和linux
+        String spliter = "/";
+        String index = spliter + year + spliter + month + spliter + day + spliter + fileName;
+        return index;
+    }
+
+    /**
+     * MultipartFile 转 File
+     *
+     * @param file
+     * @throws Exception
+     */
+    public static File multipartFileToFile(MultipartFile file) throws Exception {
+
+        File toFile = null;
+        if ("".equals(file) || file.getSize() <= 0) {
+            file = null;
+        } else {
+            InputStream ins = null;
+            ins = file.getInputStream();
+            toFile = new File(RandomUtil.randomString(32) + file.getOriginalFilename());
+            inputStreamToFile(ins, toFile);
+            ins.close();
+        }
+        return toFile;
+    }
+
+    //获取流文件
+    private static void inputStreamToFile(InputStream ins, File file) {
+        try {
+            OutputStream os = new FileOutputStream(file);
+            int bytesRead = 0;
+            byte[] buffer = new byte[8192];
+            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
+                os.write(buffer, 0, bytesRead);
+            }
+            os.close();
+            ins.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 删除本地临时文件
+     *
+     * @param file
+     */
+    public static void delteTempFile(File file) {
+        if (file != null) {
+            File del = new File(file.toURI());
+            del.delete();
+        }
+    }
+
+    /**
+     * 编码文件名
+     */
+    public static final String extractFilename(MultipartFile file, String assignName) {
+        String fileName = file.getOriginalFilename();
+        String extension = getExtension(file);
+        fileName = Objects.nonNull(assignName) ? assignName : encodingFilename(fileName) + "-" + DateUtil.format(new Date(), "yyyyMMddHHmmssSSS") + "." + extension;
+        return fileName;
+    }
+
+    /**
+     * 编码文件名
+     */
+    public static final String extractFilename(File file) {
+        String fileName = file.getName();
+        String extension = getExtension(file);
+        fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + "-" + encodingFilename(fileName) + "." + extension;
+        return fileName;
+    }
+
+    private static final String getPathFileName(String uploadDir, String fileName) throws IOException {
+        int dirLastIndex = uploadDir.lastIndexOf("/") + 1;
+        String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
+//        String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
+        String pathFileName = currentDir + "/" + fileName;
+        return pathFileName;
+    }
+
+    private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
+        File desc = new File(uploadDir + File.separator + fileName);
+        // 高版本spring中CommonsMultipartFile会自动创建desc,如果创建会报错
+        if (!desc.getParentFile().exists()) {
+            desc.getParentFile().mkdirs();
+        }
+//         if (!desc.exists())
+//         {
+//         desc.createNewFile();
+//         }
+        return desc;
+    }
+
+    public static boolean isImage(String extension) {
+        String[] imageExtension = new String[]{"jpeg", "jpg", "gif", "bmp", "png"};
+
+        for (String e : imageExtension) if (extension.toLowerCase().equals(e)) return true;
+
+        return false;
+    }
+
+    /**
+     * 编码文件名
+     */
+    private static final String encodingFilename(String fileName) {
+        fileName = fileName.replace("_", " ");
+        fileName = Md5Utils.hash(fileName + System.nanoTime() + counter++);
+        return fileName;
+    }
+
+    /**
+     * 文件大小校验
+     *
+     * @param file 上传的文件
+     * @return
+     * @throws FileSizeLimitExceededException 如果超出最大大小
+     * @throws InvalidExtensionException
+     */
+    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
+            throws FileSizeLimitExceededException, InvalidExtensionException {
+        long size = file.getSize();
+        if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE) {
+            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
+        }
+        String fileName = file.getOriginalFilename();
+        String extension = getExtension(file);
+        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
+            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
+                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
+                        fileName);
+            } else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
+                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
+                        fileName);
+            } else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
+                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
+                        fileName);
+            } else {
+                throw new InvalidExtensionException(allowedExtension, extension, fileName);
+            }
+        }
+    }
+
+    /**
+     * 判断MIME类型是否是允许的MIME类型
+     *
+     * @param extension
+     * @param allowedExtension
+     * @return
+     */
+    public static final boolean isAllowedExtension(String extension, String[] allowedExtension) {
+        for (String str : allowedExtension) {
+            if (str.equalsIgnoreCase(extension)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 获取文件名的后缀
+     *
+     * @param file 表单文件
+     * @return 后缀名
+     */
+    public static final String getExtension(MultipartFile file) {
+        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
+        if (StringUtils.isEmpty(extension)) {
+            extension = MimeTypeUtils.getExtension(file.getContentType());
+        }
+        return extension;
+    }
+
+    /**
+     * 获取文件名的后缀
+     *
+     * @param file 表单文件
+     * @return 后缀名
+     */
+    public static final String getExtension(File file) {
+        String extension = FilenameUtils.getExtension(file.getName());
+        return extension;
+    }
+
+    /**
+     * 获取封装得MultipartFile
+     *
+     * @param inputStream inputStream
+     * @param fileName    fileName
+     * @return MultipartFile
+     */
+    public static MultipartFile getMultipartFile(InputStream inputStream, String fileName) {
+        FileItem fileItem = createFileItem(inputStream, fileName);
+        //CommonsMultipartFile是feign对multipartFile的封装,但是要FileItem类对象
+        return new CommonsMultipartFile(fileItem);
+    }
+
+
+    /**
+     * FileItem类对象创建
+     *
+     * @param inputStream inputStream
+     * @param fileName    fileName
+     * @return FileItem
+     */
+    public static FileItem createFileItem(InputStream inputStream, String fileName) {
+        FileItemFactory factory = new DiskFileItemFactory(16, null);
+        String textFieldName = "file";
+        FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
+        int bytesRead = 0;
+        byte[] buffer = new byte[10 * 1024 * 1024];
+        OutputStream os = null;
+        //使用输出流输出输入流的字节
+        try {
+            os = item.getOutputStream();
+            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
+                os.write(buffer, 0, bytesRead);
+            }
+            inputStream.close();
+        } catch (IOException e) {
+            log.error("Stream copy exception", e);
+            throw new IllegalArgumentException("文件上传失败");
+        } finally {
+            if (os != null) {
+                try {
+                    os.close();
+                } catch (IOException e) {
+                    log.error("Stream close exception", e);
+
+                }
+            }
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    log.error("Stream close exception", e);
+                }
+            }
+        }
+
+        return item;
+    }
+
+}

+ 67 - 0
common/src/main/java/com/dayou/utils/Md5Utils.java

@@ -0,0 +1,67 @@
+package com.dayou.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.security.MessageDigest;
+
+/**
+ * Md5加密方法
+ * 
+ * @author ruoyi
+ */
+public class Md5Utils
+{
+    private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
+
+    private static byte[] md5(String s)
+    {
+        MessageDigest algorithm;
+        try
+        {
+            algorithm = MessageDigest.getInstance("MD5");
+            algorithm.reset();
+            algorithm.update(s.getBytes("UTF-8"));
+            byte[] messageDigest = algorithm.digest();
+            return messageDigest;
+        }
+        catch (Exception e)
+        {
+            log.error("MD5 Error...", e);
+        }
+        return null;
+    }
+
+    private static final String toHex(byte hash[])
+    {
+        if (hash == null)
+        {
+            return null;
+        }
+        StringBuffer buf = new StringBuffer(hash.length * 2);
+        int i;
+
+        for (i = 0; i < hash.length; i++)
+        {
+            if ((hash[i] & 0xff) < 0x10)
+            {
+                buf.append("0");
+            }
+            buf.append(Long.toString(hash[i] & 0xff, 16));
+        }
+        return buf.toString();
+    }
+
+    public static String hash(String s)
+    {
+        try
+        {
+            return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8");
+        }
+        catch (Exception e)
+        {
+            log.error("not supported charset...{}", e);
+            return s;
+        }
+    }
+}

+ 59 - 0
common/src/main/java/com/dayou/utils/MimeTypeUtils.java

@@ -0,0 +1,59 @@
+package com.dayou.utils;
+
+/**
+ * 媒体类型工具类
+ *
+ * @author ruoyi
+ */
+public class MimeTypeUtils {
+    public static final String IMAGE_PNG = "image/png";
+
+    public static final String IMAGE_JPG = "image/jpg";
+
+    public static final String IMAGE_JPEG = "image/jpeg";
+
+    public static final String IMAGE_BMP = "image/bmp";
+
+    public static final String IMAGE_GIF = "image/gif";
+
+    public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
+
+    public static final String[] FLASH_EXTENSION = {"swf", "flv"};
+
+    public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+            "asf", "rm", "rmvb"};
+
+    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
+            // 图片
+            "bmp", "gif", "jpg", "jpeg", "png", "blob", "webp", "svg", "pcx", "ico",
+            // word excel powerpoint
+            "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
+            // 压缩文件
+            "rar", "zip", "gz", "bz2", "7z", "tar.gz",
+            "xml",
+            // pdf
+            "pdf",
+            //视频
+            "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+            "asf", "rm", "rmvb", "mp4", "mov",
+            //应用
+            "apk"
+    };
+
+    public static String getExtension(String prefix) {
+        switch (prefix) {
+            case IMAGE_PNG:
+                return "png";
+            case IMAGE_JPG:
+                return "jpg";
+            case IMAGE_JPEG:
+                return "jpeg";
+            case IMAGE_BMP:
+                return "bmp";
+            case IMAGE_GIF:
+                return "gif";
+            default:
+                return "";
+        }
+    }
+}

+ 5 - 1
dao/src/main/resources/mapper/ItemMapper.xml

@@ -11,7 +11,9 @@
         <result column="business_no" property="businessNo" />
         <result column="oa_no" property="oaNo" />
         <result column="name" property="name" />
+        <result column="cate" property="cate" />
         <result column="business_source" property="businessSource" />
+        <result column="belong_to" property="belongTo" />
         <result column="client_unit" property="clientUnit" />
         <result column="client_name" property="clientName" />
         <result column="mobile" property="mobile" />
@@ -22,6 +24,7 @@
         <result column="amount" property="amount" />
         <result column="state" property="state" />
         <result column="department_id" property="departmentId" />
+        <result column="contract_url" property="contractUrl" />
         <collection property="userIds" ofType="java.lang.Long" select="selectItemUserId" column="id"/>
     </resultMap>
 
@@ -31,7 +34,8 @@
         i.deleted,
         i.created,
         i.modified,
-        i.business_no, i.oa_no, i.name, i.business_source, i.client_unit, i.client_name, i.mobile, i.client_manager, i.skiller, i.sign_date, i.payment_method, i.amount, i.state,i.department_id
+        i.business_no, i.oa_no, i.name,i.cate, i.business_source,i.belong_to,i.client_unit,
+        i.client_name, i.mobile, i.client_manager, i.skiller, i.sign_date, i.payment_method, i.amount, i.state,i.department_id,i.contract_url
     </sql>
 
     <select id="stat" resultType="com.dayou.vo.ItemStatVO">

+ 20 - 1
domain/src/main/java/com/dayou/entity/Item.java

@@ -30,7 +30,7 @@ public class Item extends BaseEntity {
     private String businessNo;
 
     /**
-     * 公司OA流水号
+     * 公司OA流水号(项目编号)
      */
     @ImportCell
     @ExportCell(columnName = "公司OA流水号")
@@ -44,6 +44,13 @@ public class Item extends BaseEntity {
     private String name;
 
     /**
+     * 项目类型
+     */
+    @ImportCell
+    @ExportCell(columnName = "项目类型")
+    private String cate;
+
+    /**
      * 业务来源
      */
     @ImportCell
@@ -51,6 +58,13 @@ public class Item extends BaseEntity {
     private String businessSource;
 
     /**
+     * 归属单位
+     */
+    @ImportCell
+    @ExportCell(columnName = "归属单位")
+    private String belongTo;
+
+    /**
      * 委托单位
      */
     @ImportCell
@@ -116,5 +130,10 @@ public class Item extends BaseEntity {
      */
     private Long departmentId;
 
+    /**
+     * 合同url
+     */
+    private String contractUrl;
+
 
 }

+ 2 - 0
service/src/main/java/com/dayou/service/impl/ItemServiceImpl.java

@@ -11,6 +11,7 @@ import com.dayou.service.IItemService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.dayou.service.IItemStageService;
 import com.dayou.service.IItemUserService;
+import com.dayou.utils.DateUtils;
 import com.dayou.utils.LoginContext;
 import com.dayou.vo.ItemStageVO;
 import com.dayou.vo.ItemStatVO;
@@ -93,6 +94,7 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
     @Transactional
     @Override
     public Boolean add(ItemDTO itemDTO){
+        itemDTO.setBusinessNo(DateUtils.dateTimeNow());
         this.save(itemDTO);
         List<Long> userIds = itemDTO.getUserIds();
         Set<ItemUser> itemUsers = userIds.stream().map(x -> {

+ 23 - 20
sql/init.sql

@@ -153,26 +153,29 @@ CREATE TABLE `global_config`  (
 -- ----------------------------
 DROP TABLE IF EXISTS `item`;
 CREATE TABLE `item`  (
-  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
-  `business_no` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '事业部流水号',
-  `oa_no` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '公司OA流水号',
-  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '项目名称',
-  `business_source` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '业务来源',
-  `client_unit` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '委托单位',
-  `client_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '委托人',
-  `mobile` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '联系方式',
-  `client_manager` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '客户经理',
-  `skiller` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '技术负责人',
-  `sign_date` date NULL DEFAULT NULL COMMENT '合同签订时间',
-  `payment_method` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '合同支付方式',
-  `amount` decimal(16, 0) NULL DEFAULT NULL COMMENT '合同金额',
-  `state` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '状态',
-  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '逻辑删除标识:1:删除 0:未删除',
-  `created` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
-  `modified` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '修改时间',
-  `department_id` bigint(20) NULL DEFAULT NULL COMMENT '所属部门',
-  PRIMARY KEY (`id`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '项目信息表' ROW_FORMAT = Dynamic;
+    `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
+    `business_no` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '事业部流水号',
+    `oa_no` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '公司OA流水号',
+    `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '项目名称',
+    `cate` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '项目类型',
+    `business_source` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '业务来源',
+    `belong_to` varchar(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '归属单位',
+    `client_unit` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '委托单位',
+    `client_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '委托人',
+    `mobile` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '联系方式',
+    `client_manager` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '客户经理',
+    `skiller` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '技术负责人',
+    `sign_date` date NULL DEFAULT NULL COMMENT '合同签订时间',
+    `payment_method` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '合同支付方式',
+    `amount` decimal(16, 0) NULL DEFAULT NULL COMMENT '合同金额',
+    `state` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '状态',
+    `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '逻辑删除标识:1:删除 0:未删除',
+    `created` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
+    `modified` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '修改时间',
+    `department_id` bigint(20) NULL DEFAULT NULL COMMENT '所属部门',
+    `contract_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '合同URI地址',
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '项目信息表' ROW_FORMAT = Dynamic;
 
 -- ----------------------------
 -- Table structure for item_stage