Browse Source

分析模板

qzy 10 months ago
parent
commit
3755e66810
20 changed files with 984 additions and 32 deletions
  1. 8 0
      pom.xml
  2. 11 0
      zhbsq-admin/src/main/java/com/hjy/modlue/report/ReportRecordController.java
  3. 95 0
      zhbsq-admin/src/main/java/com/hjy/modlue/report/ReportWordController.java
  4. 2 2
      zhbsq-admin/src/main/java/com/hjy/modlue/template/controller/GenerateTemplateController.java
  5. 2 1
      zhbsq-admin/src/main/resources/application.yml
  6. 4 1
      zhbsq-common/pom.xml
  7. 12 0
      zhbsq-common/src/main/java/com/hjy/common/config/ZhbsqConfig.java
  8. 269 0
      zhbsq-common/src/main/java/com/hjy/common/utils/WordUtil.java
  9. 122 0
      zhbsq-modlue/src/main/java/com/hjy/module/domain/report/ReportDTO.java
  10. 45 0
      zhbsq-modlue/src/main/java/com/hjy/module/domain/report/ReportWord.java
  11. 26 0
      zhbsq-modlue/src/main/java/com/hjy/module/mapper/report/ReportWordMapper.java
  12. 3 0
      zhbsq-modlue/src/main/java/com/hjy/module/service/report/IReportRecordService.java
  13. 44 0
      zhbsq-modlue/src/main/java/com/hjy/module/service/report/IReportWordService.java
  14. 21 0
      zhbsq-modlue/src/main/java/com/hjy/module/service/report/impl/ReportRecordServiceImpl.java
  15. 48 0
      zhbsq-modlue/src/main/java/com/hjy/module/service/report/impl/ReportWordServiceImpl.java
  16. 1 1
      zhbsq-modlue/src/main/java/com/hjy/module/service/template/IExcelOutInTotalService.java
  17. 201 26
      zhbsq-modlue/src/main/java/com/hjy/module/service/template/impl/ExcelOutInTotalServiceImpl.java
  18. 22 0
      zhbsq-modlue/src/main/java/com/hjy/module/vo/report/ReportWordVo.java
  19. 1 1
      zhbsq-modlue/src/main/resources/mapper/report/ReportRecordMapper.xml
  20. 47 0
      zhbsq-modlue/src/main/resources/mapper/report/ReportWordMapper.xml

+ 8 - 0
pom.xml

@@ -31,6 +31,7 @@
         <commons.fileupload.version>1.4</commons.fileupload.version>
         <commons.collections.version>3.2.2</commons.collections.version>
         <poi.version>4.1.2</poi.version>
+        <scratchpad.version>5.2.1</scratchpad.version>
         <velocity.version>2.3</velocity.version>
         <jwt.version>0.9.1</jwt.version>
         <weixin-java-mp.version>4.4.0</weixin-java-mp.version>
@@ -117,6 +118,13 @@
                 <artifactId>poi-ooxml</artifactId>
                 <version>${poi.version}</version>
             </dependency>
+            <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad -->
+            <dependency>
+                <groupId>org.apache.poi</groupId>
+                <artifactId>poi-scratchpad</artifactId>
+                <version>5.2.1</version>
+            </dependency>
+
 
             <!-- velocity代码生成使用模板 -->
             <dependency>

+ 11 - 0
zhbsq-admin/src/main/java/com/hjy/modlue/report/ReportRecordController.java

@@ -7,6 +7,7 @@ import com.hjy.common.enums.BusinessType;
 import com.hjy.common.utils.poi.ExcelUtil;
 
 import com.hjy.module.service.report.IReportRecordService;
+import com.hjy.module.service.report.IReportWordService;
 import com.hjy.module.service.template.IExcelOutInTotalService;
 import com.hjy.module.vo.report.ReportRecordVo;
 import io.swagger.annotations.Api;
@@ -17,6 +18,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 import com.hjy.common.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import java.util.Arrays;
@@ -36,6 +38,7 @@ public class ReportRecordController extends BaseController {
 
     private final IReportRecordService reportRecordService;
     private final IExcelOutInTotalService iExcelOutInTotalService;
+    private final IReportWordService reportWordService;
 
     @ApiOperation("查询辅助决策列表")
     @PreAuthorize("@ss.hasPermi('report:RECORD:list')")
@@ -82,6 +85,13 @@ public class ReportRecordController extends BaseController {
     public AjaxResult edit(@RequestBody ReportRecordVo entity) {
         return toAjax(reportRecordService.updateById(entity));
     }
+    @ApiOperation("上传辅助决策")
+    @PreAuthorize("@ss.hasPermi('report:RECORD:edit')")
+    @Log(title = "辅助决策", businessType = BusinessType.UPDATE)
+    @PostMapping("upload")
+    public AjaxResult upload(@RequestPart MultipartFile file,String id) throws Exception{
+        return toAjax(reportRecordService.upload(file,id));
+    }
 
     @ApiOperation("删除辅助决策")
     @PreAuthorize("@ss.hasPermi('report:RECORD:remove')")
@@ -91,6 +101,7 @@ public class ReportRecordController extends BaseController {
     public AjaxResult remove(@PathVariable String[] ids) {
         for (String id : ids) {
             iExcelOutInTotalService.removeByReportId(id);
+            reportWordService.removeByReportId(id);
         }
         return toAjax(reportRecordService.removeByIds(Arrays.asList(ids)) ? 1 : 0);
     }

+ 95 - 0
zhbsq-admin/src/main/java/com/hjy/modlue/report/ReportWordController.java

@@ -0,0 +1,95 @@
+package com.hjy.modlue.report;
+
+import com.hjy.common.annotation.Log;
+import com.hjy.common.core.controller.BaseController;
+import com.hjy.common.core.domain.AjaxResult;
+import com.hjy.common.enums.BusinessType;
+import com.hjy.common.utils.poi.ExcelUtil;
+
+import com.hjy.framework.config.ServerConfig;
+import com.hjy.module.service.report.IReportWordService;
+import com.hjy.module.vo.report.ReportWordVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import com.hjy.common.core.page.TableDataInfo;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 模板报告Controller
+ *
+ * @author Tellsea
+ * @date 2024-05-06
+ */
+@Api(tags = "模板报告Controller")
+@RestController
+@RequestMapping("/report/WORD")
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+public class ReportWordController extends BaseController {
+
+    private final IReportWordService reportWordService;
+    private final ServerConfig serverConfig;
+
+    @ApiOperation("查询模板报告列表")
+    @PreAuthorize("@ss.hasPermi('report:WORD:list')")
+    @GetMapping("/list")
+    public TableDataInfo<ReportWordVo> list(ReportWordVo entity) {
+        return reportWordService.queryList(entity);
+    }
+
+    @ApiOperation("查询模板报告所有列表")
+    @GetMapping("/listAll")
+    public AjaxResult listAll(ReportWordVo entity) {
+        List<ReportWordVo>list= reportWordService.queryAll(entity);
+        String url=serverConfig.getUrl();
+        list.forEach(word->word.setWordPath(url+word.getWordPath()));
+        return AjaxResult.success("查询成功",list);
+    }
+
+    @ApiOperation("导出模板报告列表")
+    @PreAuthorize("@ss.hasPermi('report:WORD:export')")
+    @Log(title = "模板报告", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, ReportWordVo entity) {
+        List<ReportWordVo> list = reportWordService.queryAll(entity);
+        ExcelUtil<ReportWordVo> util = new ExcelUtil<>(ReportWordVo.class);
+        util.exportExcel(response, list, "模板报告数据");
+    }
+
+    @ApiOperation("获取模板报告详细信息")
+    @PreAuthorize("@ss.hasPermi('report:WORD:query')")
+    @GetMapping(value = "/getInfo/{id}")
+    public AjaxResult getInfo(@PathVariable("id") String id) {
+        return AjaxResult.success("查询成功", reportWordService.queryById(id));
+    }
+
+    @ApiOperation("新增模板报告")
+    @PreAuthorize("@ss.hasPermi('report:WORD:add')")
+    @Log(title = "模板报告", businessType = BusinessType.INSERT)
+    @PostMapping("add")
+    public AjaxResult add(@RequestBody ReportWordVo entity) {
+        return toAjax(reportWordService.save(entity));
+    }
+
+    @ApiOperation("修改模板报告")
+    @PreAuthorize("@ss.hasPermi('report:WORD:edit')")
+    @Log(title = "模板报告", businessType = BusinessType.UPDATE)
+    @PostMapping("edit")
+    public AjaxResult edit(@RequestBody ReportWordVo entity) {
+        return toAjax(reportWordService.updateById(entity));
+    }
+
+    @ApiOperation("删除模板报告")
+    @PreAuthorize("@ss.hasPermi('report:WORD:remove')")
+    @Log(title = "模板报告", businessType = BusinessType.DELETE)
+	@GetMapping("/remove/{ids}")
+    public AjaxResult remove(@PathVariable String[] ids) {
+        return toAjax(reportWordService.removeByIds(Arrays.asList(ids)) ? 1 : 0);
+    }
+}

+ 2 - 2
zhbsq-admin/src/main/java/com/hjy/modlue/template/controller/GenerateTemplateController.java

@@ -53,8 +53,8 @@ public class GenerateTemplateController extends BaseController {
     @ApiOperation("导入excel")
     @PreAuthorize("@ss.hasPermi('business:template:import')")
     @PostMapping("/importExcel")
-    public AjaxResult importExcel(MultipartFile file) {
-        excelOutInTotalService.analyze(file);
+    public AjaxResult importExcel(MultipartFile file,String gxTradeTotalMoney) {
+        excelOutInTotalService.analyze(file,gxTradeTotalMoney);
         return AjaxResult.success("导入成功");
     }
 

+ 2 - 1
zhbsq-admin/src/main/resources/application.yml

@@ -9,11 +9,12 @@ zhbsq:
   # 实例演示开关
   demoEnabled: true
   # 文件路径 示例( Windows配置D:/zhbsq/uploadPath,Linux配置 /home/zhbsq/uploadPath)
-  profile: /home/zhbsq/uploadPath
+  profile: E://home//zhbsq
   # 获取ip地址开关
   addressEnabled: false
   # 验证码类型 math 数组计算 char 字符验证
   captchaType: math
+  report-path: G://report.docx
 
 # 开发环境配置
 server:

+ 4 - 1
zhbsq-common/pom.xml

@@ -147,7 +147,10 @@
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-scratchpad</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-boot-starter</artifactId>

+ 12 - 0
zhbsq-common/src/main/java/com/hjy/common/config/ZhbsqConfig.java

@@ -39,6 +39,15 @@ public class ZhbsqConfig {
      * 实例演示开关
      */
     private boolean demoEnabled;
+    private String reportPath;
+
+    public String getReportPath() {
+        return reportPath;
+    }
+
+    public void setReportPath(String reportPath) {
+        this.reportPath = reportPath;
+    }
 
     public static String getProfile() {
         return profile;
@@ -91,6 +100,9 @@ public class ZhbsqConfig {
     public static String getUploadPath() {
         return getProfile() + "/upload";
     }
+    public static String getWordPath() {
+        return getProfile() + "/word";
+    }
 
     public String getName() {
         return name;

+ 269 - 0
zhbsq-common/src/main/java/com/hjy/common/utils/WordUtil.java

@@ -0,0 +1,269 @@
+package com.hjy.common.utils;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.poi.ooxml.POIXMLDocument;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.xwpf.usermodel.*;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlToken;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
+import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class WordUtil {
+
+    private static Log log = LogFactory.getLog(WordUtil.class);
+    /**
+     * 装载模板所对应的对象
+     * @param object
+     * @return map
+     */
+    public static Map<String,Object> setMapObject(Object object){
+        Map<String,Object> mapObject = new HashMap<String,Object>();
+        if(object != null){
+            Field[] fields = object.getClass().getDeclaredFields();
+            log.info("fields" + fields.length);
+            for(Field field : fields){
+                try {
+                    field.setAccessible(true);
+                    String str = "${" + field.getName() + "}";
+                    Object objValue = field.get(object);
+                    if(objValue != null){
+                        log.info(str + "----" + objValue.toString());
+                        mapObject.put(str, objValue);
+                    }else{
+                        mapObject.put(str, "");
+                    }
+                } catch(Exception e) {
+                    log.error("模板对象出现错误", e);
+                }
+            }
+        } else {
+            log.error("模板对象不是对应的一个类对象");
+        }
+        return mapObject;
+    }
+
+    /**
+     * 根据指定的参数值、模板,生成 word 文档
+     * @param param 需要替换的变量
+     * @param template 模板
+     * @return XWPFDocument
+     * @throws IOException
+     * @throws InvalidFormatException
+     */
+    public static XWPFDocument generateWord(Map<String, Object> param, String template) throws IOException, InvalidFormatException {
+        if(param == null || template == null){
+            return null ;
+        }
+        XWPFDocument xwpfDocument = null;
+        log.info("解析的模版为:" + template);
+        try {
+            OPCPackage pack = POIXMLDocument.openPackage(template);
+            xwpfDocument = new XWPFDocument(pack);
+            if (param.size() > 0) {
+                //处理段落
+                List<XWPFParagraph> paragraphList = xwpfDocument.getParagraphs();
+                processParagraphs(paragraphList, param, xwpfDocument);
+                //处理表格
+                Iterator<XWPFTable> it = xwpfDocument.getTablesIterator();
+                while (it.hasNext()) {
+                    XWPFTable table = it.next();
+                    List<XWPFTableRow> rows = table.getRows();
+                    for (XWPFTableRow row : rows) {
+                        List<XWPFTableCell> cells = row.getTableCells();
+                        for (XWPFTableCell cell : cells) {
+                            List<XWPFParagraph> paragraphListTable = cell.getParagraphs();
+                            processParagraphs(paragraphListTable, param, xwpfDocument);
+                        }
+                    }
+                }
+            }
+        } catch (IOException e) {
+            log.error("文件处理异常", e);
+            throw(e);
+        }catch (InvalidFormatException e) {
+            log.error("文档中内容处理异常", e);
+            throw(e);
+        }
+        return xwpfDocument;
+    }
+
+    /**
+     * 处理段落
+     * @param paragraphList
+     * @param param
+     * @param doc
+     * @throws InvalidFormatException
+     * @throws FileNotFoundException
+     */
+    public static void processParagraphs(List<XWPFParagraph> paragraphList, Map<String, Object> param, XWPFDocument doc) throws InvalidFormatException, FileNotFoundException{
+        if(paragraphList != null && paragraphList.size() > 0){
+            for(XWPFParagraph paragraph : paragraphList){
+                List<XWPFRun> runs = paragraph.getRuns();
+                for (XWPFRun run : runs) {
+                    String text = run.getText(0);
+                    if(text != null){
+                        boolean isSetText = false;
+                        for (Map.Entry<String, Object> entry : param.entrySet()) {
+                            String key = entry.getKey();
+                            if(text.indexOf(key) != -1){
+                                isSetText = true;
+                                Object value = entry.getValue();
+                                if (value instanceof String) {//文本替换
+                                    log.info(key + "模板中模要转化属性对应的值:" + value);
+                                    text = text.replace(key, value.toString());
+                                } else if (value instanceof Map) {//图片替换
+                                    text = text.replace(key, "");
+                                    Map pic = (Map)value;
+                                    int width = Integer.parseInt(pic.get("width").toString());
+                                    int height = Integer.parseInt(pic.get("height").toString());
+                                    int picType = getPictureType(pic.get("type").toString());
+                                    String byteArray = (String) pic.get("imgPath");
+                                    log.info("模板中模要转化的图片" + byteArray);
+                                    CTInline inline = run.getCTR().addNewDrawing().addNewInline();
+                                    insertPicture(doc,byteArray,inline, width, height);
+                                }
+                            }
+                        }
+                        if(isSetText){
+                            run.setText(text,0);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 根据图片类型,取得对应的图片类型代码
+     * @param picType
+     * @return int
+     */
+    private static int getPictureType(String picType){
+        int res = XWPFDocument.PICTURE_TYPE_PICT;
+        if(picType != null){
+            if(picType.equalsIgnoreCase("png")){
+                res = XWPFDocument.PICTURE_TYPE_PNG;
+            }else if(picType.equalsIgnoreCase("dib")){
+                res = XWPFDocument.PICTURE_TYPE_DIB;
+            }else if(picType.equalsIgnoreCase("emf")){
+                res = XWPFDocument.PICTURE_TYPE_EMF;
+            }else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){
+                res = XWPFDocument.PICTURE_TYPE_JPEG;
+            }else if(picType.equalsIgnoreCase("wmf")){
+                res = XWPFDocument.PICTURE_TYPE_WMF;
+            }
+        }
+        return res;
+    }
+
+    /**
+     * 将输入流中的数据写入字节数组
+     * @param inputStream
+     * @param isClose
+     * @return
+     */
+    public static byte[] inputStream2ByteArray(InputStream inputStream, boolean isClose){
+        byte[] byteArray = null;
+        try {
+            int total = inputStream.available();
+            byteArray = new byte[total];
+            inputStream.read(byteArray);
+        } catch (IOException e) {
+            log.error("IO异常",e);
+        } finally {
+            if(isClose){
+                try {
+                    inputStream.close();
+                } catch (Exception e2) {
+                    log.debug("关闭流失败");
+                }
+            }
+        }
+        return byteArray;
+    }
+
+    /**
+     *
+     * @param document
+     * @param filePath
+     * @param inline
+     * @param width
+     * @param height
+     * @throws InvalidFormatException
+     * @throws FileNotFoundException
+     */
+    private static void insertPicture(XWPFDocument document, String filePath, CTInline inline, int width, int height) throws InvalidFormatException, FileNotFoundException {
+        document.addPictureData(new FileInputStream(filePath), XWPFDocument.PICTURE_TYPE_PNG);
+        int id = document.getAllPictures().size() - 1;
+        final int EMU = 9525;
+        width *= EMU;
+        height *= EMU;
+//        String blipId = document.getAllPictures().get(id).getPackageRelationship().getId();
+        Integer blipIdString = document.getAllPictures().get(id).getPictureType();
+        String blipId = blipIdString.toString();
+        String picXml = getPicXml(blipId, width, height);
+        XmlToken xmlToken = null;
+        try {
+            xmlToken = XmlToken.Factory.parse(picXml);
+        } catch (XmlException xe) {
+            log.error("XmlException",xe);
+        }
+        inline.set(xmlToken);
+        inline.setDistT(0);
+        inline.setDistB(0);
+        inline.setDistL(0);
+        inline.setDistR(0);
+        CTPositiveSize2D extent = inline.addNewExtent();
+        extent.setCx(width);
+        extent.setCy(height);
+        CTNonVisualDrawingProps docPr = inline.addNewDocPr();
+        docPr.setId(id);
+        docPr.setName("IMG_" + id);
+        docPr.setDescr("IMG_" + id);
+    }
+
+    /**
+     * get the xml of the picture
+     * @param blipId
+     * @param width
+     * @param height
+     * @return
+     */
+    private static String getPicXml(String blipId, int width, int height) {
+        String picXml =
+                "" + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
+                        "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
+                        "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
+                        "         <pic:nvPicPr>" + "            <pic:cNvPr id=\"" + 0 +
+                        "\" name=\"Generated\"/>" + "            <pic:cNvPicPr/>" +
+                        "         </pic:nvPicPr>" + "         <pic:blipFill>" +
+                        "            <a:blip r:embed=\"" + blipId +
+                        "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
+                        "            <a:stretch>" + "               <a:fillRect/>" +
+                        "            </a:stretch>" + "         </pic:blipFill>" +
+                        "         <pic:spPr>" + "            <a:xfrm>" +
+                        "               <a:off x=\"0\" y=\"0\"/>" +
+                        "               <a:ext cx=\"" + width + "\" cy=\"" + height +
+                        "\"/>" + "            </a:xfrm>" +
+                        "            <a:prstGeom prst=\"rect\">" +
+                        "               <a:avLst/>" + "            </a:prstGeom>" +
+                        "         </pic:spPr>" + "      </pic:pic>" +
+                        "   </a:graphicData>" + "</a:graphic>";
+        return picXml;
+    }
+
+}

+ 122 - 0
zhbsq-modlue/src/main/java/com/hjy/module/domain/report/ReportDTO.java

@@ -0,0 +1,122 @@
+package com.hjy.module.domain.report;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+@Data
+@Accessors(chain = true)
+public class ReportDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 年
+     */
+    private String year;
+    /**
+     * 月
+     */
+    private String month;
+    /**
+     * 总结描述
+     */
+    private String preface;
+    /**
+     * 全区外贸总值>tradeTotalMoney
+     */
+    private String gxTradeTotalMoney;
+    /**
+     * 全区综保区亿元
+     */
+    private String tradeTotalMoney;
+    /**
+     *占全区进出口总值百分比
+     */
+    private String tradeTotalMoneyPercent;
+    /**
+     * 占全区进出口总值百分比增长或者下降(tradeTotalMoneyInc>0——>增长;<0下降)
+     */
+    private String tradeTotalMoneyIncDirection;
+    /**
+     * 进出口总值同比
+     */
+    private String tradeTotalMoneyInc;
+    /**
+     *
+     * 整体状况
+     */
+    private String tradeSituation;
+
+    /**
+     * 凭祥同比增长
+     */
+    private String pxInc;
+    /**
+     * 南宁同比增长
+     */
+    private String nnInc;
+    /**
+     * 梧州同比增长
+     */
+    private String wzInc;
+    /**
+     * 钦州同比增长
+     */
+    private String qzInc;
+    /**
+     * 北海同比增长
+     */
+    private String bhInc;
+
+
+    /**
+     * 凭祥进出口总值
+     */
+    private String pxTotalMoney;
+    /**
+     * 南宁同比增长
+     */
+    private String nnTotalMoney;
+    /**
+     * 梧州同比增长
+     */
+    private String wzTotalMoney;
+    /**
+     * 钦州同比增长
+     */
+    private String qzTotalMoney;
+    /**
+     * 北海同比增长
+     */
+    private String bhTotalMoney;
+
+
+    /**
+     * 凭祥进出口总值全国排名
+     */
+    private Integer pxIndex;
+    /**
+     * 南宁进出口总值增长
+     */
+    private Integer nnIndex;
+    /**
+     * 梧州进出口总值增长
+     */
+    private Integer wzIndex;
+    /**
+     * 钦州进出口总值增长
+     */
+    private Integer qzIndex;
+    /**
+     * 北海进出口总值增长
+     */
+    private Integer bhIndex;
+    /**
+     * 所有综保区同比分析描述:如:xxx、xxx同比增长了xx
+     */
+    private String bondedIncAnalyse;
+    /**
+     * 排名描述
+     */
+    private String tradeTotalMoneyIndexDesc;
+
+}

+ 45 - 0
zhbsq-modlue/src/main/java/com/hjy/module/domain/report/ReportWord.java

@@ -0,0 +1,45 @@
+package com.hjy.module.domain.report;
+
+import com.hjy.common.annotation.Excel;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.hjy.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+/**
+ * 模板报告对象 REPORT_WORD
+ *
+ * @author Tellsea
+ * @date 2024-05-06
+ */
+@Data
+@Accessors(chain = true)
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+public class ReportWord extends BaseEntity {
+
+    /**
+     * 主键
+     */
+    @Excel(name = "主键")
+    private String id;
+
+    /**
+     * 报告ID
+     */
+    @Excel(name = "报告ID")
+    private String recordId;
+
+    @Excel(name = "wordName")
+    private String wordName;
+
+    /**
+     * 路径
+     */
+    @Excel(name = "路径")
+    private String wordPath;
+
+}

+ 26 - 0
zhbsq-modlue/src/main/java/com/hjy/module/mapper/report/ReportWordMapper.java

@@ -0,0 +1,26 @@
+package com.hjy.module.mapper.report;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import com.hjy.module.domain.report.ReportWord;
+import com.hjy.module.vo.report.ReportWordVo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 模板报告Mapper接口
+ *
+ * @author Tellsea
+ * @date 2024-05-06
+ */
+public interface ReportWordMapper extends BaseMapper<ReportWord> {
+
+    Page<ReportWordVo> queryList(Page<?> page, @Param("entity") ReportWordVo entity);
+
+    List<ReportWordVo> queryList(@Param("entity") ReportWordVo entity);
+
+    ReportWordVo queryById(@Param("id") String id);
+
+}

+ 3 - 0
zhbsq-modlue/src/main/java/com/hjy/module/service/report/IReportRecordService.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.hjy.common.core.page.TableDataInfo;
 import com.hjy.module.domain.report.ReportRecord;
 import com.hjy.module.vo.report.ReportRecordVo;
+import org.springframework.web.multipart.MultipartFile;
 
 
 import java.util.List;
@@ -41,4 +42,6 @@ public interface IReportRecordService extends IService<ReportRecord> {
     ReportRecordVo queryById(String id);
 
     ReportRecord findReport(String year, String month);
+
+    boolean upload(MultipartFile file, String id)throws Exception;
 }

+ 44 - 0
zhbsq-modlue/src/main/java/com/hjy/module/service/report/IReportWordService.java

@@ -0,0 +1,44 @@
+package com.hjy.module.service.report;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.hjy.common.core.page.TableDataInfo;
+import com.hjy.module.domain.report.ReportWord;
+import com.hjy.module.vo.report.ReportWordVo;
+
+
+import java.util.List;
+
+/**
+ * 模板报告Service接口
+ *
+ * @author Tellsea
+ * @date 2024-05-06
+ */
+public interface IReportWordService extends IService<ReportWord> {
+
+    /**
+     * 分页查询
+     *
+     * @param entity
+     * @return
+     */
+    TableDataInfo<ReportWordVo> queryList(ReportWordVo entity);
+
+    /**
+     * 查询全部
+     *
+     * @param entity
+     * @return
+     */
+    List<ReportWordVo> queryAll(ReportWordVo entity);
+
+    /**
+     * 根据ID查询
+     *
+     * @param id
+     * @return
+     */
+    ReportWordVo queryById(String id);
+
+    void removeByReportId(String reportId);
+}

+ 21 - 0
zhbsq-modlue/src/main/java/com/hjy/module/service/report/impl/ReportRecordServiceImpl.java

@@ -2,15 +2,22 @@ package com.hjy.module.service.report.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.hjy.common.config.ZhbsqConfig;
 import com.hjy.common.core.page.TableDataInfo;
 import com.hjy.common.utils.PageUtils;
 
+import com.hjy.common.utils.file.FileUploadUtils;
 import com.hjy.module.domain.report.ReportRecord;
+import com.hjy.module.domain.report.ReportWord;
 import com.hjy.module.mapper.report.ReportRecordMapper;
 import com.hjy.module.service.report.IReportRecordService;
+import com.hjy.module.service.report.IReportWordService;
 import com.hjy.module.vo.report.ReportRecordVo;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.Resource;
 import java.util.List;
 
 /**
@@ -22,6 +29,9 @@ import java.util.List;
 @Service
 public class ReportRecordServiceImpl extends ServiceImpl<ReportRecordMapper, ReportRecord> implements IReportRecordService {
 
+
+    @Resource
+    private IReportWordService reportWordService;
     @Override
     public TableDataInfo<ReportRecordVo> queryList(ReportRecordVo entity) {
         return PageUtils.buildDataInfo(this.baseMapper.queryList(PageUtils.buildPage(), entity));
@@ -47,4 +57,15 @@ public class ReportRecordServiceImpl extends ServiceImpl<ReportRecordMapper, Rep
         List<ReportRecord>list= list(ew);
         return list.isEmpty()?null:list.get(0);
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean upload(MultipartFile file, String id) throws Exception{
+        String filePath = ZhbsqConfig.getWordPath();
+        String fileName ="/profile"+ FileUploadUtils.upload(filePath, file);
+        ReportWord reportWord=new ReportWord();
+        reportWord.setWordName(file.getOriginalFilename()).setWordPath(fileName).setRecordId(id);
+        reportWordService.save(reportWord);
+        return true;
+    }
 }

+ 48 - 0
zhbsq-modlue/src/main/java/com/hjy/module/service/report/impl/ReportWordServiceImpl.java

@@ -0,0 +1,48 @@
+package com.hjy.module.service.report.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.hjy.common.core.page.TableDataInfo;
+import com.hjy.common.utils.PageUtils;
+
+import com.hjy.module.domain.report.ReportWord;
+import com.hjy.module.mapper.report.ReportWordMapper;
+import com.hjy.module.service.report.IReportWordService;
+import com.hjy.module.vo.report.ReportWordVo;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 模板报告Service业务层处理
+ *
+ * @author Tellsea
+ * @date 2024-05-06
+ */
+@Service
+public class ReportWordServiceImpl extends ServiceImpl<ReportWordMapper, ReportWord> implements IReportWordService {
+
+    @Override
+    public TableDataInfo<ReportWordVo> queryList(ReportWordVo entity) {
+        return PageUtils.buildDataInfo(this.baseMapper.queryList(PageUtils.buildPage(), entity));
+    }
+
+    @Override
+    public List<ReportWordVo> queryAll(ReportWordVo entity) {
+        return this.baseMapper.queryList(entity);
+    }
+
+    @Override
+    public ReportWordVo queryById(String id) {
+        return this.baseMapper.queryById(id);
+    }
+
+    @Override
+    public void removeByReportId(String reportId) {
+        QueryWrapper<ReportWord>ew=new QueryWrapper<>();
+        ew.lambda().eq(ReportWord::getRecordId,reportId);
+        this.baseMapper.delete(ew);
+    }
+
+
+}

+ 1 - 1
zhbsq-modlue/src/main/java/com/hjy/module/service/template/IExcelOutInTotalService.java

@@ -42,7 +42,7 @@ public interface IExcelOutInTotalService extends IService<ExcelOutInTotal> {
      */
     ExcelOutInTotalVo queryById(Long id);
 
-    boolean analyze(MultipartFile file);
+    boolean analyze(MultipartFile file,String gxTradeTotalMoney);
 
     void removeByReportId(String reportId);
 }

+ 201 - 26
zhbsq-modlue/src/main/java/com/hjy/module/service/template/impl/ExcelOutInTotalServiceImpl.java

@@ -1,28 +1,38 @@
 package com.hjy.module.service.template.impl;
 
 import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.ReflectUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
 import cn.hutool.poi.excel.ExcelReader;
 import cn.hutool.poi.excel.ExcelUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.hjy.common.config.ZhbsqConfig;
 import com.hjy.common.core.page.TableDataInfo;
 import com.hjy.common.utils.PageUtils;
+import com.hjy.common.utils.file.FileUploadUtils;
+import com.hjy.common.utils.file.FileUtils;
+import com.hjy.module.domain.report.ReportDTO;
 import com.hjy.module.domain.report.ReportRecord;
+import com.hjy.module.domain.report.ReportWord;
 import com.hjy.module.domain.reportsetting.ReportSetting;
 import com.hjy.module.domain.template.ExcelOutInTotal;
 import com.hjy.module.mapper.template.ExcelOutInTotalMapper;
 import com.hjy.module.service.report.IReportRecordService;
+import com.hjy.module.service.report.IReportWordService;
 import com.hjy.module.service.reportsetting.IReportSettingService;
 import com.hjy.module.service.template.IExcelOutInTotalService;
 import com.hjy.module.vo.report.ReportRecordVo;
 import com.hjy.module.vo.template.ExcelOutInTotalVo;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.xwpf.usermodel.*;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
+import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDate;
@@ -45,6 +55,12 @@ public class ExcelOutInTotalServiceImpl extends ServiceImpl<ExcelOutInTotalMappe
     @Resource
     private IReportSettingService reportSettingService;
 
+    @Resource
+    private ZhbsqConfig zhbsqConfig;
+    @Resource
+    private IReportWordService reportWordService;
+
+
 
     @Override
     public TableDataInfo<ExcelOutInTotalVo> queryList(ExcelOutInTotalVo entity) {
@@ -62,12 +78,15 @@ public class ExcelOutInTotalServiceImpl extends ServiceImpl<ExcelOutInTotalMappe
     }
 
     @Override
-    public boolean analyze(MultipartFile file) {
+    public boolean analyze(MultipartFile file,String gxTradeTotalMoney) {
         final String nn = "南宁综";
         final String wz = "梧州综";
         final String qz = "钦州综";
         final String bh = "北海综";
         final String px = "凭祥综";
+        BigDecimal tenThousand = BigDecimal.valueOf(10000);
+        ReportDTO reportDTO = new ReportDTO();
+        reportDTO.setGxTradeTotalMoney(gxTradeTotalMoney+"");
         try (InputStream inputStream = file.getInputStream()) {
             ExcelReader reader = ExcelUtil.getReader(inputStream);
             String text = reader.readAsText(false);
@@ -80,6 +99,7 @@ public class ExcelOutInTotalServiceImpl extends ServiceImpl<ExcelOutInTotalMappe
             String time = StrUtil.subBefore(StrUtil.subAfter(title, "20", true), "特定地区进出口总值", true);
             String year = "20" + StrUtil.subBefore(time, "年", true);
             String month = StrUtil.subBetween(time, "年", "月");
+            reportDTO.setYear(year).setMonth(month);
             ReportRecord reportRecord = reportRecordService.findReport(year, month);
             if (reportRecord == null) {
                 reportRecord = new ReportRecord();
@@ -101,9 +121,29 @@ public class ExcelOutInTotalServiceImpl extends ServiceImpl<ExcelOutInTotalMappe
                 String name = str.getName();
                 return name.contains(nn) || name.contains(wz) || name.contains(qz) || name.contains(bh) || name.contains(px);
             }).collect(Collectors.toList());
-            gxList.forEach(excelOutInTotal -> excelOutInTotal.setReportId(reportId));
+            gxList.forEach(excelOutInTotal -> {
+                excelOutInTotal.setReportId(reportId);
+                String name = excelOutInTotal.getName();
+                int index = excelOutInTotal.getIndex();
+                String totalInc = excelOutInTotal.getTotalInc()+"%";
+                totalInc=Double.parseDouble(excelOutInTotal.getTotalInc())==0?"-":totalInc;
+                String totalMoney = new BigDecimal(excelOutInTotal.getTotalCumulativeMonth()).divide(tenThousand, 1, RoundingMode.HALF_UP).toString();
+                if (name.contains(nn)) {
+                    reportDTO.setNnIndex(index)
+                            .setNnInc(totalInc)
+                            .setNnTotalMoney(totalMoney);
+                } else if (name.contains(px)) {
+                    reportDTO.setPxIndex(index).setPxInc(totalInc).setPxTotalMoney(totalMoney);
+                } else if (name.contains(wz)) {
+                    reportDTO.setWzIndex(index).setWzInc(totalInc).setWzTotalMoney(totalMoney);
+                } else if (name.contains(bh)) {
+                    reportDTO.setBhIndex(index).setBhInc(totalInc).setBhTotalMoney(totalMoney);
+                } else if (name.contains(qz)) {
+                    reportDTO.setQzIndex(index).setQzInc(totalInc).setQzTotalMoney(totalMoney);
+                }
+            });
             this.saveBatch(gxList);
-            generateReport(reportRecord, gxList, excelDTOList.size());
+            generateReport(reportRecord, gxList, excelDTOList.size(), reportDTO);
             reportRecordService.updateById(reportRecord);
         } catch (IOException e) {
             e.printStackTrace();
@@ -111,38 +151,166 @@ public class ExcelOutInTotalServiceImpl extends ServiceImpl<ExcelOutInTotalMappe
         return false;
     }
 
-    @Override
-    public void removeByReportId(String reportId) {
-        this.baseMapper.removeByReportId(reportId);
-    }
 
-    private void generateReport(ReportRecord reportRecord, List<ExcelOutInTotal> gxList, int total) {
+    private void generateReport(ReportRecord reportRecord, List<ExcelOutInTotal> gxList, int total, ReportDTO reportDTO) {
         Double beforeTotalCumulativeMonth = 0D;
         BigDecimal hundred = BigDecimal.valueOf(100);
+        BigDecimal tenThousand = BigDecimal.valueOf(10000);
+        gxList.sort(Comparator.comparing(excelOutInTotal -> Double.parseDouble(excelOutInTotal.getTotalInc())));
+        List<ExcelOutInTotal> incList = new ArrayList<>();
+        List<ExcelOutInTotal> descList = new ArrayList<>();
+        StringBuilder tradeTotalMoneyIndexDesc = new StringBuilder();
         for (ExcelOutInTotal excelOutInTotal : gxList) {
             Double totalCumulativeMonth = Double.parseDouble(excelOutInTotal.getTotalCumulativeMonth());
-            Double totalInc = (new BigDecimal(excelOutInTotal.getTotalInc()).add(hundred))
+            BigDecimal totalIncD = new BigDecimal(excelOutInTotal.getTotalInc());
+            Double totalInc = totalIncD.add(hundred)
                     .divide(hundred, 5, RoundingMode.HALF_UP).doubleValue();
+            if (totalIncD.doubleValue() > 0) {
+                incList.add(excelOutInTotal);
+            } else if (totalIncD.doubleValue() < 0) {
+                descList.add(excelOutInTotal);
+            }
             Double t = NumberUtil.div(totalCumulativeMonth, totalInc, 1, RoundingMode.HALF_UP);
-            log.info("t==============:{},{},{}", totalCumulativeMonth, totalInc, t);
+            //log.info("t==============:{},{},{}", totalCumulativeMonth, totalInc, t);
             beforeTotalCumulativeMonth = NumberUtil.add(t, beforeTotalCumulativeMonth);
+            tradeTotalMoneyIndexDesc.append(excelOutInTotal.getName()).append("排名").append(excelOutInTotal.getIndex()).append("、");
         }
-
-        long gxTotal = gxList.stream().collect(Collectors.summarizingLong(e -> Long.parseLong(e.getTotalCumulativeMonth()))).getSum();
-        double foreignTradeInc = (BigDecimal.valueOf(gxTotal).subtract(BigDecimal.valueOf(beforeTotalCumulativeMonth)))
-                .divide(BigDecimal.valueOf(gxTotal), 4, RoundingMode.HALF_UP)
+        reportDTO.setTradeTotalMoneyIndexDesc(tradeTotalMoneyIndexDesc.toString());
+        String gxTradeTotalMoney=reportDTO.getGxTradeTotalMoney();
+        long tradeTotalMoney = gxList.stream().collect(Collectors.summarizingLong(e -> Long.parseLong(e.getTotalCumulativeMonth()))).getSum();
+        if (StrUtil.isNotEmpty(gxTradeTotalMoney)&&!StrUtil.equals(gxTradeTotalMoney,"undefined")){
+           BigDecimal tradeTotalMoneyPercent= new BigDecimal(tradeTotalMoney)
+                   .divide(tenThousand,1,RoundingMode.UP).divide(new BigDecimal(gxTradeTotalMoney),3,RoundingMode.UP);
+           reportDTO.setTradeTotalMoneyPercent(tradeTotalMoneyPercent.multiply(hundred).toString());
+        }
+        //同比增长
+        double tradeTotalMoneyInc = (BigDecimal.valueOf(tradeTotalMoney).subtract(BigDecimal.valueOf(beforeTotalCumulativeMonth)))
+                .divide(BigDecimal.valueOf(beforeTotalCumulativeMonth), 3, RoundingMode.UP)
                 .multiply(hundred).doubleValue();
-        reportRecord.setForeignTrade(gxTotal + "").setForeignTradeInc(foreignTradeInc + "");
-        log.info("total:{},{},{}", beforeTotalCumulativeMonth, gxTotal, foreignTradeInc);
+        String tradeTotalMoneyIncDirection = tradeTotalMoneyInc > 0 ? "增长" : "下降";
+        reportDTO.setTradeTotalMoney(new BigDecimal(tradeTotalMoney).divide(tenThousand, 1, RoundingMode.HALF_UP).toString())
+                .setTradeTotalMoneyInc(Math.abs(tradeTotalMoneyInc) + "%")
+                .setTradeTotalMoneyIncDirection(tradeTotalMoneyIncDirection);
+        reportRecord.setForeignTrade(tradeTotalMoney + "").setForeignTradeInc(tradeTotalMoneyInc + "%");
+        //log.info("total:{},{},{}", beforeTotalCumulativeMonth, tradeTotalMoney, tradeTotalMoneyInc);
         List<ReportSetting> reportSettings = reportSettingService.list();
-        String content = "<h3>(一)外贸进出口";
-        Optional<ReportSetting> optionalReportSetting = reportSettings.stream()
-                .filter(reportSetting -> Double.parseDouble(reportSetting.getMinNum()) <= foreignTradeInc
-                        && Double.parseDouble(reportSetting.getMaxNum()) > foreignTradeInc)
-                .findFirst();
-        String titleSuff = optionalReportSetting.isPresent() ? optionalReportSetting.get().getDescription() : "{"+foreignTradeInc+"%}";
-        content=content+titleSuff+":</h3>";
-        reportRecord.setResult(content);
+        reportSettings.stream()
+                .filter(reportSetting -> Double.parseDouble(reportSetting.getMinNum()) <= tradeTotalMoneyInc
+                        && Double.parseDouble(reportSetting.getMaxNum()) > tradeTotalMoneyInc)
+                .findFirst().ifPresent(reportSetting -> reportDTO.setTradeSituation(reportSetting.getDescription()));
+        String incName = incList.stream().map(ExcelOutInTotal::getName).collect(Collectors.joining("、"));
+        String incPercent = incList.stream().map(excelOutInTotal -> excelOutInTotal.getTotalInc() + "%").collect(Collectors.joining("、"));
+        String descName = descList.stream().map(ExcelOutInTotal::getName).collect(Collectors.joining("、"));
+        String descPercent = descList.stream().map(excelOutInTotal -> Math.abs(Double.parseDouble(excelOutInTotal.getTotalInc())) + "%").collect(Collectors.joining("、"));
+        StringBuilder bondedIncAnalyse = new StringBuilder("其中,");
+        if (incList.size() > 0) {
+            bondedIncAnalyse.append(incName).append("同比增长了").append(incPercent).append(";");
+        }
+        if (descList.size() > 0) {
+            bondedIncAnalyse.append(descName).append("同比下降了").append(descPercent);
+        }
+
+        reportDTO.setBondedIncAnalyse(bondedIncAnalyse.toString());
+        log.info("report:{}", JSONUtil.toJsonStr(reportDTO));
+        createWord(reportDTO,reportRecord);
+    }
+
+    /**
+     * 生成word文档
+     * @param reportDTO
+     */
+    private void createWord(ReportDTO reportDTO,ReportRecord reportRecord) {
+        // 上传文件路径
+        String filePath = ZhbsqConfig.getWordPath();
+        File file=new File(filePath);
+        if (!file.exists()) {
+            file.mkdirs();
+        }
+        Field[] fields = ReflectUtil.getFields(reportDTO.getClass());
+        String reportPath= zhbsqConfig.getReportPath();
+        try (FileInputStream fileInputStream = new FileInputStream(reportPath)) {
+            XWPFDocument document = new XWPFDocument(fileInputStream);
+            List<XWPFParagraph> paragraphs = document.getParagraphs();
+            paragraphs.forEach(paragraph -> {
+                List<XWPFRun> runs = paragraph.getRuns();
+                StringBuilder sb = new StringBuilder();
+                for (XWPFRun r : runs) {
+                    sb.append(r.getText(0));
+                }
+
+                String text = sb.toString();
+                for (Field field : fields) {
+                    String fieldName = field.getName();
+                    if (text.contains("${" + fieldName + "}")) {
+                        Object fieldValue = ReflectUtil.getFieldValue(reportDTO, fieldName);
+                        if (fieldValue != null) {
+                            text = StrUtil.replace(text, "${" + fieldName + "}", fieldValue.toString());
+                        }
+                    }
+                }
+                if (StrUtil.isNotEmpty(text)) {
+                    // 清除所有的runs
+                    for (int i = runs.size() - 1; i >= 0; i--) {
+                        paragraph.removeRun(i);
+                    }
+
+                    // 添加新的run
+                    XWPFRun newRun = paragraph.createRun();
+                    newRun.setText(text);
+                    if (text.contains("广西综合保税区经济运行分析") || text.contains("月经济运行指标情况")) {
+                        newRun.setFontSize(22);
+                        newRun.setFontFamily("方正小标宋_GBK");
+                    } else if (text.contains("(一)")){
+                        newRun.setFontSize(16);
+                        newRun.setFontFamily("方正仿宋_GBK");
+                    }else {
+                        newRun.setFontSize(16);
+                        newRun.setFontFamily("方正仿宋_GBK");
+                    }
+                }
+
+            });
+            List<XWPFTable> tables = document.getTables();
+            for (XWPFTable table : tables) {
+                List<XWPFTableRow> rows = table.getRows();
+                for (XWPFTableRow row : rows) {
+                    for (XWPFTableCell cell : row.getTableCells()) {
+                        String text = cell.getText();
+                        for (Field field : fields) {
+                            String fieldName = field.getName();
+                            if (text.contains("${"+fieldName+ "}")) {
+                                Object fieldValue = ReflectUtil.getFieldValue(reportDTO, fieldName);
+                                if (fieldValue != null) {
+                                    // 清空单元格
+                                    cell.removeParagraph(0);
+                                    XWPFParagraph newPara = cell.addParagraph();
+                                    //居中
+                                    newPara.setAlignment(ParagraphAlignment.CENTER);
+                                    XWPFRun run= newPara.createRun();
+                                    if (text.contains("tradeTotalMoney")) {
+                                        run.setBold(true);
+                                    }
+                                    text = StrUtil.replace(text, "${" + fieldName + "}", fieldValue.toString());
+                                    run.setText(text);
+                                }
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            fileInputStream.close();
+            String filename = reportDTO.getYear() + "年-" + reportDTO.getMonth() + "月分析报告-" + System.currentTimeMillis() + ".docx";
+            FileOutputStream out = new FileOutputStream(filePath +File.separator+ filename);
+            document.write(out);
+            out.close();
+            document.close();
+            ReportWord reportWord=new ReportWord();
+            reportWord.setWordName(filename).setWordPath("/profile/word/"+filename).setRecordId(reportRecord.getId());
+            reportWordService.save(reportWord);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     private List<ExcelOutInTotal> buildDTO(List<String> list, String currentMonth, String cumulativeMonth) {
@@ -169,9 +337,16 @@ public class ExcelOutInTotalServiceImpl extends ServiceImpl<ExcelOutInTotalMappe
         Collections.reverse(excelDTOList);
         int index = 0;
         for (ExcelOutInTotal e : excelDTOList) {
+            e.setIndex(index);
 
             index++;
         }
         return excelDTOList;
     }
+
+    @Override
+    public void removeByReportId(String reportId) {
+        this.baseMapper.removeByReportId(reportId);
+    }
+
 }

+ 22 - 0
zhbsq-modlue/src/main/java/com/hjy/module/vo/report/ReportWordVo.java

@@ -0,0 +1,22 @@
+package com.hjy.module.vo.report;
+
+
+import com.hjy.module.domain.report.ReportWord;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+/**
+ * 模板报告Vo对象 REPORT_WORD
+ *
+ * @author Tellsea
+ * @date 2024-05-06
+ */
+@Data
+@Accessors(chain = true)
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+public class ReportWordVo extends ReportWord {
+
+}

+ 1 - 1
zhbsq-modlue/src/main/resources/mapper/report/ReportRecordMapper.xml

@@ -36,7 +36,7 @@
         <if test="entity.result != null and entity.result != ''">
             and A.RESULT like concat('%', #{entity.result}, '%')
         </if>
-        order by A.create_time desc
+        order by A.REPORT_YEAR desc,REPORT_MONTH desc
     </select>
 
     <select id="queryById" resultType="com.hjy.module.vo.report.ReportRecordVo">

+ 47 - 0
zhbsq-modlue/src/main/resources/mapper/report/ReportWordMapper.xml

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.hjy.module.mapper.report.ReportWordMapper">
+
+    <sql id="querySql">
+        select <include refid="allField"/>
+        from REPORT_WORD A
+        <include refid="search"/>
+    </sql>
+
+    <select id="queryList" resultType="com.hjy.module.vo.report.ReportWordVo">
+        <include refid="querySql"/>
+        <if test="entity.id != null and entity.id != ''">
+            and A.ID like concat('%', #{entity.id}, '%')
+        </if>
+        <if test="entity.recordId != null and entity.recordId != ''">
+            and A.RECORD_ID = #{entity.recordId}
+        </if>
+        <if test="entity.wordPath != null and entity.wordPath != ''">
+            and A.WORD_PATH like concat('%', #{entity.wordPath}, '%')
+        </if>
+
+        order by A.create_time desc
+    </select>
+
+    <select id="queryById" resultType="com.hjy.module.vo.report.ReportWordVo">
+        <include refid="querySql"/>
+        and A.id = #{id}
+    </select>
+
+    <sql id="allField">
+        A.ID,
+        A.RECORD_ID,
+        A.WORD_NAME,
+        A.WORD_PATH,
+        A.CREATE_TIME,
+        A.CREATE_BY,
+        A.UPDATE_TIME,
+        A.UPDATE_BY
+    </sql>
+
+    <sql id="search">
+        where 1 = 1
+    </sql>
+</mapper>