Browse Source

新增 签名

Administrator 1 year ago
parent
commit
952bfd7a5e

+ 39 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/WordController.java

@@ -0,0 +1,39 @@
+package com.ruoyi.web.controller.common;
+
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.model.LoginBody;
+import com.ruoyi.common.utils.SendSmsUtils;
+import com.ruoyi.common.utils.WordUtil;
+import com.ruoyi.system.domain.vo.WordVo;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.TimeUnit;
+
+import static com.ruoyi.common.constant.CommonConstants.LOGIN_USER_SMS;
+
+/**
+ * @Author: tjf
+ * @Date: 2024/5/15 10:35
+ * @Describe:
+ */
+@RestController
+@RequestMapping("/word")
+public class WordController {
+    /**
+     * word文档签名
+     *
+     * @return
+     */
+    @PostMapping("/wordFilePath")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult wordFilePath(@RequestBody WordVo wordVo) {
+        String wordFilePath = wordVo.getWordFilePath();
+        String image = wordVo.getImage();
+        AjaxResult ajaxResult = WordUtil.wordFilePath(wordFilePath, image);
+        return ajaxResult;
+    }
+}

+ 25 - 0
ruoyi-admin/src/main/resources/docx4j.properties

@@ -0,0 +1,25 @@
+# Page size: use a value from org.docx4j.model.structure.PageSizePaper enum
+# eg A4, LETTER
+docx4j.PageSize=LETTER
+# Page size: use a value from org.docx4j.model.structure.MarginsWellKnown enum
+docx4j.PageMargins=NORMAL
+docx4j.PageOrientationLandscape=false
+# Page size: use a value from org.pptx4j.model.SlideSizesWellKnown enum
+# eg A4, LETTER
+pptx4j.PageSize=LETTER
+pptx4j.PageOrientationLandscape=false
+# These will be injected into docProps/app.xml
+# if App.Write=true
+docx4j.App.write=true
+docx4j.Application=docx4j
+docx4j.AppVersion=6.1.2
+# of the form XX.YYYY where X and Y represent numerical values
+# These will be injected into docProps/core.xml
+docx4j.dc.write=true
+docx4j.dc.creator.value=docx4j
+docx4j.dc.lastModifiedBy.value=docx4j
+#
+#docx4j.McPreprocessor=true
+# If you haven't configured log4j yourself
+# docx4j will autoconfigure it. Set this to true to disable that
+docx4j.Log4j.Configurator.disabled=false

+ 6 - 0
ruoyi-common/pom.xml

@@ -17,6 +17,12 @@
 
 
     <dependencies>
+        <!--word签名-->
+        <dependency>
+            <groupId>org.docx4j</groupId>
+            <artifactId>docx4j</artifactId>
+            <version>6.1.2</version>
+        </dependency>
         <!--阿里云人脸识别-->
         <dependency>
             <groupId>com.aliyun</groupId>

+ 218 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/WordUtil.java

@@ -0,0 +1,218 @@
+package com.ruoyi.common.utils;
+
+import com.ruoyi.common.core.domain.AjaxResult;
+import org.docx4j.TraversalUtil;
+import org.docx4j.XmlUtils;
+import org.docx4j.dml.CTPositiveSize2D;
+import org.docx4j.dml.Graphic;
+import org.docx4j.dml.GraphicData;
+import org.docx4j.dml.picture.Pic;
+import org.docx4j.dml.wordprocessingDrawing.Inline;
+import org.docx4j.finders.RangeFinder;
+import org.docx4j.jaxb.Context;
+import org.docx4j.openpackaging.exceptions.Docx4JException;
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
+import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
+import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
+import org.docx4j.wml.*;
+
+import javax.xml.bind.JAXBElement;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.*;
+
+/**
+ * 给word模板,在需要插入图片(签字)的地方,word中设则书签
+ * wordFilePath word 文档路径
+ * image 签名BASE64
+ * @Author: tjf
+ * @Date: 2024/5/15 10:25
+ * @Describe:
+ */
+public class WordUtil {
+    public static AjaxResult wordFilePath(String wordFilePath,String image) {
+        try {
+            WordprocessingMLPackage wordMLPackage = load(wordFilePath);
+
+            // 提取正文
+            MainDocumentPart main = wordMLPackage.getMainDocumentPart();
+            Document doc = null;
+            doc = main.getContents();
+            Body body = doc.getBody();
+
+            // 获取段落
+            List<Object> paragraphs = body.getContent();
+
+            // 提取书签并获取书签的游标
+            RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
+            new TraversalUtil(paragraphs, rt);
+
+            // 遍历书签
+            for (CTBookmark bm : rt.getStarts()) {
+                System.out.println("name:" + bm.getName());
+                // 替换image sign是书签名字
+                if ("sign".equals(bm.getName())) {
+                    addImage(wordMLPackage, bm, image);
+                    break;
+                }
+            }
+            save(wordMLPackage, wordFilePath);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return AjaxResult.success();
+    }
+
+    /**
+     * @param wPackage 文档
+     * @param bm       书签
+     * @param base64String    签名图片base64
+     * @throws Exception
+     */
+    public static void addImage(WordprocessingMLPackage wPackage, CTBookmark bm, String base64String) throws Exception {
+        P p = (P) (bm.getParent());
+        ObjectFactory factory = Context.getWmlObjectFactory();
+        R run = factory.createR();
+
+        // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
+        // byte[] bytes = IOUtils.toByteArray(new FileInputStream("图片文件路径"));
+        //byte[] bytes = getFileBytes(image);
+        if (base64String.contains("data:")) {
+            int start = base64String.indexOf(",");
+            base64String = base64String.substring(start + 1);
+        }
+        base64String = base64String.replaceAll("\r|\n", "");
+        base64String = base64String.trim();
+        byte[] bytes = Base64.getDecoder().decode(base64String);
+        // 开始创建一个行内图片
+        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
+        // 最后一个是限制图片的宽度,缩放的依据
+        Inline newInline = imagePart.createImageInline(null, null, 0, 1, false, 0);
+        // 构建绘图
+        Drawing drawing = factory.createDrawing();
+        // 加入图片段落
+        drawing.getAnchorOrInline().add(newInline);
+        run.getContent().add(drawing);
+        // 清理书签所在数据
+        // p.getContent().clear();
+        // 加入图片信息
+        p.getContent().add(run);
+    }
+
+
+    /**
+     * 处理图片适应大小
+     * @param cx
+     * @param cy
+     * @param newCx
+     * @param newCy
+     */
+    public static Map<String, Long> dealCxy(Long cx, Long cy, Long newCx, Long newCy){
+        Map<String, Long> map = new HashMap<>();
+        Long setCx;
+        Long setCy;
+
+        if (newCx > cx){
+            if (newCy <= cy){
+                setCx = cx;
+                setCy = newCy/(newCx/cx);
+            } else {
+                if ((newCx/cx) > (newCy/cy)){
+                    setCx = cx;
+                    setCy = newCy/(newCx/cx);
+                } else {
+                    setCy = cy;
+                    setCx = newCx/(newCy/cy);
+                }
+            }
+        } else {   // newCx < cx
+            if (newCy > cy) {
+                setCx = cx;
+                setCy = newCy * (cx/newCx);
+            } else {
+                if ((cx/newCx) > (cy/newCy)) {
+                    setCx = cx;
+                    setCy = newCy *(cx/newCx);
+                } else {
+                    setCy = cy;
+                    setCx = newCy * (cy/newCy);
+                }
+            }
+        }
+        map.put("setCx",setCx);
+        map.put("setCy",setCy);
+        return map;
+    }
+
+    /**
+     * 得到指定类型的元素
+     * @param obj
+     * @param toSearch
+     * @return
+     */
+    public static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
+        List<Object> result = new ArrayList<>();
+        if (obj instanceof JAXBElement)
+            obj = ((JAXBElement<?>) obj).getValue();
+        if (obj.getClass().equals(toSearch))
+            result.add(obj);
+        else if (obj instanceof ContentAccessor) {
+            List<?> children = ((ContentAccessor) obj).getContent();
+            for (Object child : children) {
+                result.addAll(getAllElementFromObject(child, toSearch));
+            }
+        }
+        return result;
+    }
+    /**
+     * 构建文件
+     */
+    public static WordprocessingMLPackage build() throws Exception {
+        return WordprocessingMLPackage.createPackage();
+    }
+
+    /**
+     * 读取存在的word文件
+     *
+     * @param wordFilePath word文件路径
+     */
+    public static WordprocessingMLPackage load(String wordFilePath) throws Exception {
+        return WordprocessingMLPackage.load(new File(wordFilePath));
+    }
+
+    /**
+     * 保存
+     *
+     * @param wordMLPackage word
+     */
+    public static void save(WordprocessingMLPackage wordMLPackage, String wordFilePath) throws Exception {
+        wordMLPackage.save(new File(wordFilePath));
+    }
+
+    /**
+     * 将图片转为Base64数组
+     *
+     * @param filePath
+     * @return
+     * @throws Exception
+     */
+    public static byte[] getFileBytes(String filePath) throws Exception {
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new Exception("文件不存在!");
+        }
+
+        byte[] data = null;
+        try (FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            int len;
+            byte[] buffer = new byte[1024];
+            while ((len = fis.read(buffer)) != -1) {
+                baos.write(buffer, 0, len);
+            }
+            data = baos.toByteArray();
+        }
+        return data;
+    }
+}

+ 33 - 0
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/WordVo.java

@@ -0,0 +1,33 @@
+package com.ruoyi.system.domain.vo;
+
+/**
+ * @Author: tjf
+ * @Date: 2024/5/15 10:36
+ * @Describe:
+ */
+public class WordVo {
+    /**
+     * word 文档路径
+     */
+    private String wordFilePath;
+    /**
+     * 签名base64
+     */
+    private String image;
+
+    public String getWordFilePath() {
+        return wordFilePath;
+    }
+
+    public void setWordFilePath(String wordFilePath) {
+        this.wordFilePath = wordFilePath;
+    }
+
+    public String getImage() {
+        return image;
+    }
+
+    public void setImage(String image) {
+        this.image = image;
+    }
+}

+ 8 - 2
ruoyi-system/src/main/java/com/ruoyi/system/service/idcard/impl/SysUserIdcardServiceImpl.java

@@ -42,11 +42,17 @@ public class SysUserIdcardServiceImpl implements ISysUserIdcardService
     {
         SysUserIdcard sysUserIdcard = sysUserIdcardMapper.selectSysUserIdcardByUserId(userId);
         List<SysUserEnterprise> sysUserEnterpriseList = sysUserEnterpriseMapper.selectSysUserEnterpriseByUserId(userId);
-        sysUserIdcard.setSysUserEnterpriseNum(sysUserEnterpriseList.size());
+        if (sysUserEnterpriseList != null && sysUserEnterpriseList.size() > 0){
+            sysUserIdcard.setSysUserEnterpriseNum(sysUserEnterpriseList.size());
+            sysUserIdcard.setSysUserEnterpriseList(sysUserEnterpriseList);
+        }
         LoanApplication loanApplication =  new LoanApplication();
         loanApplication.setUserId(userId);
         List<LoanApplication> loanApplications = loanApplicationMapper.selectLoanApplicationList(loanApplication);
-        sysUserIdcard.setLoanApplicationNum(loanApplications.size());
+        if (loanApplications != null && loanApplications.size() > 0){
+            sysUserIdcard.setLoanApplicationNum(loanApplications.size());
+            sysUserIdcard.setLoanApplicationList(loanApplications);
+        }
         return sysUserIdcard;
     }
 

+ 3 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/loan/impl/LoanApplicationServiceImpl.java

@@ -108,7 +108,7 @@ public class LoanApplicationServiceImpl implements ILoanApplicationService {
     public List<LoanApplication> selectLoanApplicationList(LoanApplication loanApplication) {
         //判断是否是admin或者管理员manager
         List<SysRole> roles = SecurityUtils.getLoginUser().getUser().getRoles();
-        String roleKey = "admin,manager";
+        String roleKey = "admin,manager,auditing_risk";
         List<LoanApplication> loanApplications = new ArrayList<>();
         for (SysRole role : roles) {
             if (roleKey.contains(role.getRoleKey())) {
@@ -536,6 +536,7 @@ public class LoanApplicationServiceImpl implements ILoanApplicationService {
         }
         loanApplication.setLoanSchedule(TEN);
         loanApplication.setLoanApplicationType(FOR);
+        loanApplication.setFileTime(DateUtils.getNowDate());
         loanApplicationMapper.updateLoanApplication(loanApplication);
         //插入流程记录表
         LoanSchedule loanScheduleNew = new LoanSchedule();
@@ -543,6 +544,7 @@ public class LoanApplicationServiceImpl implements ILoanApplicationService {
         loanScheduleNew.setLoanScheduleValue(loanApplication.getLoanSchedule());
         loanScheduleNew.setLoanScheduleScore(Long.parseLong(loanApplication.getLoanSchedule()));
         loanScheduleNew.setLoanScheduleTime(DateUtils.getNowDate());
+        loanScheduleNew.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
         loanScheduleMapper.insertLoanSchedule(loanScheduleNew);
         //todo 获取所有文件URL 进行打包zip,还有系统内的照片地址 往附件表中插入其他-归档类型的url地址
         Long loanApplicationId = loanApplication.getLoanApplicationId();