فهرست منبع

Merge remote-tracking branch 'origin/dev' into dev

LHB 13 ساعت پیش
والد
کامیت
457ae80936

+ 333 - 22
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java

@@ -15,7 +15,7 @@ import lombok.SneakyThrows;
 import org.apache.commons.lang.StringUtils;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xssf.usermodel.*;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
@@ -52,6 +52,7 @@ import org.springframework.dao.DataAccessException;
 import org.springframework.http.ResponseEntity;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SingleColumnRowMapper;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -455,7 +456,7 @@ public class WbsTreeContractController extends BladeController {
         Map<String, List<WbsTreeContract>> mainCopyGroupMap = new LinkedHashMap<>(); // 保持主表原始顺序
         List<WbsTreeContract> copyTableList = new ArrayList<>(); // 临时存储所有复制表
 
-            // 2.1 第一次遍历:分离主表和复制表
+        // 2.1 第一次遍历:分离主表和复制表
         for (WbsTreeContract contract : formList) {
             String nodeName = contract.getNodeName();
             boolean isCopy = nodeName.contains("__");
@@ -477,7 +478,7 @@ public class WbsTreeContractController extends BladeController {
             }
         }
 
-            // 3. 第二步:批量处理所有复制表,匹配主表分组
+        // 3. 第二步:批量处理所有复制表,匹配主表分组
         List<WbsTreeContract> orphanCopyList = new ArrayList<>();
         for (WbsTreeContract copyContract : copyTableList) {
             String nodeName = copyContract.getNodeName();
@@ -506,7 +507,7 @@ public class WbsTreeContractController extends BladeController {
             }
         }
 
-            // 4. 第三步:处理每个主表分组,对复制表排序(保持主表原始顺序)
+        // 4. 第三步:处理每个主表分组,对复制表排序(保持主表原始顺序)
         List<WbsTreeContract> sortedList = new ArrayList<>();
         for (Map.Entry<String, List<WbsTreeContract>> entry : mainCopyGroupMap.entrySet()) {
             List<WbsTreeContract> groupList = entry.getValue();
@@ -545,15 +546,30 @@ public class WbsTreeContractController extends BladeController {
         // 获取节点及祖先节点信息用于构建文件名
         WbsTreeContract node = wbsTreeContractServiceImpl.getById(nodeId);
         List<WbsTreeContract> ancestorsList = wbsTreeContractServiceImpl.getAncestorsList(node.getAncestorsPId());
+        // 按照指定的nodeType顺序排序: 1, 18, 2, 3, 4, 5, 6
+        ancestorsList.sort((a, b) -> {
+            List<Integer> order = Arrays.asList(1, 18, 2, 3, 4, 5, 6);
+            Integer typeA = a.getNodeType();
+            Integer typeB = b.getNodeType();
+            return Integer.compare(
+                    order.indexOf(typeA != null ? typeA : -1),
+                    order.indexOf(typeB != null ? typeB : -1)
+            );
+        });
         for (WbsTreeContract ancestor : ancestorsList) {
-            if (2 == ancestor.getNodeType()) {
+            if (18 == ancestor.getNodeType()) {
                 excelName.append(ancestor.getNodeName());
-            } else if (4 == ancestor.getNodeType()) {
-                excelName.append("-" + ancestor.getNodeName());
+            } else if (2 == ancestor.getNodeType()) {
+                excelName.append("》" + ancestor.getNodeName());
+            } else if (3 == ancestor.getNodeType()) {
+                excelName.append("》" + ancestor.getNodeName());
+            }else if (4 == ancestor.getNodeType()) {
+                excelName.append("》" + ancestor.getNodeName());
+            } else if (5 == ancestor.getNodeType()) {
+                excelName.append("》" + ancestor.getNodeName());
             }
         }
-        excelName.append("-" + node.getNodeName());
-
+        excelName.append("》" + node.getNodeName());
         // 创建主工作簿(用于合并多sheet)
         XSSFWorkbook mainWorkbook = new XSSFWorkbook();
 
@@ -594,6 +610,8 @@ public class WbsTreeContractController extends BladeController {
                 InputStream htmlStream = FileUtils.getInputStreamByUrl(htmlUrl);
                 String htmlContent = IoUtil.readToString(htmlStream);
                 org.apache.poi.ss.usermodel.Workbook singleSheetWorkbook = HtmlTableToExcelConverter.convertHtmlTableToExcel(htmlContent);
+                //给excel添加默认值
+                addDefaultValue(singleSheetWorkbook,form.getInitTableName(),htmlContent,form.getPId());
 
                 // 3. 将单个sheet复制到主工作簿
                 if (singleSheetWorkbook.getNumberOfSheets() > 0) {
@@ -610,10 +628,19 @@ public class WbsTreeContractController extends BladeController {
             if (mainWorkbook.getNumberOfSheets() == 0) {
                 throw new ServiceException("所有表单均无法生成有效Excel内容");
             }
-
             String originalFileName = excelName + ".xlsx";
-
+            if(originalFileName.startsWith("》")){
+                originalFileName=originalFileName.substring(1);
+            }
+            XSSFSheet sheetAt = mainWorkbook.getSheetAt(0);
+            if (sheetAt != null) {
+                XSSFRow row = sheetAt.createRow(0);
+                XSSFCell cell = row.createCell(0);
+                // 设置批注
+                setCommentToFirstCell(mainWorkbook, sheetAt, cell, originalFileName);
+            }
             try {
+                originalFileName = originalFileName.replaceAll("#", "号");
                 // 1. 先编码所有字符
                 String fullyEncoded = URLEncoder.encode(originalFileName, StandardCharsets.UTF_8.name());
 
@@ -623,25 +650,19 @@ public class WbsTreeContractController extends BladeController {
                         .replaceAll("%2B", "+")       // 解码+号
                         .replaceAll("%2F", "/")       // 解码/号
                         .replaceAll("%23", "#")       // 解码#号
-                        .replaceAll("%7E", "~")       // 解码~号
-                        // - 号不需要处理,URL编码不会编码-
-                        ;
+                        .replaceAll("%7E", "~");      // 解码~号
 
                 // 3. 设置响应头
                 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                 response.setHeader("Content-Disposition",
-                        "attachment; filename=\"" + partiallyDecoded + "\"; ");
+                        "attachment; filename=\"" + partiallyDecoded + "\"; filename*=UTF-8''" + fullyEncoded);
 
             } catch (Exception e) {
-                // 备用方案:简单清理
-                String safeFileName = originalFileName
-                        .replaceAll("[\\\\:*?\"<>|]", "_")
-                        .trim();
+                // 备用方案
+                String safeFileName = originalFileName.replaceAll("[\\\\:*?\"<>|]", "_").trim();
                 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
-                response.setHeader("Content-Disposition",
-                        "attachment; filename=\"" + safeFileName + "\"");
+                response.setHeader("Content-Disposition", "attachment; filename=\"" + safeFileName + "\"");
             }
-
             // 写入输出流
             try (ServletOutputStream outputStream = response.getOutputStream()) {
                 mainWorkbook.write(outputStream);
@@ -657,6 +678,292 @@ public class WbsTreeContractController extends BladeController {
             }
         }
     }
+    public static void setCommentToFirstCell(XSSFWorkbook workbook, XSSFSheet sheet,
+                                             XSSFCell cell, String commentText) {
+        // 创建绘图对象
+        XSSFDrawing drawing = sheet.createDrawingPatriarch();
+
+        // 创建锚点,定位批注框
+        ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
+        anchor.setCol1(cell.getColumnIndex());      // 起始列
+        anchor.setCol2(cell.getColumnIndex() + 3);  // 结束列(控制宽度)
+        anchor.setRow1(cell.getRowIndex());         // 起始行
+        anchor.setRow2(cell.getRowIndex() + 2);     // 结束行(控制高度)
+
+        // 创建批注
+        Comment comment = drawing.createCellComment(anchor);
+
+        // 设置批注内容
+        comment.setString(new XSSFRichTextString(commentText));
+
+        // 将批注关联到单元格
+        cell.setCellComment(comment);
+    }
+    private void addDefaultValue(org.apache.poi.ss.usermodel.Workbook singleSheetWorkbook, String initTableName,String htmlContent,Long pId) {
+        if (singleSheetWorkbook == null || initTableName == null) {
+            return;
+        }
+        Document doc = Jsoup.parse(htmlContent);
+        Sheet sourceSheet = singleSheetWorkbook.getSheetAt(0);
+        //字段查询、获取公式字段
+        String colKeys = "SELECT e_key from m_table_info a ,m_wbs_form_element b WHERE a.tab_en_name = '" + initTableName + "' and a.id=b.f_id and b.id  in(SELECT element_id from m_element_formula_mapping c where c.is_deleted=0) ";
+        List<Map<String, Object>> maps = jdbcTemplate.queryForList(colKeys);
+        String sql="select formula_config from m_wbs_tree_contract_extend where p_key_id="+pId;
+        List<String> query = jdbcTemplate.query(sql, new SingleColumnRowMapper<>(String.class));
+        Map<String,Object>list=new HashMap<>();
+        if (!query.isEmpty()) {
+            String formulaConfig = query.get(0);
+            String[] strings = formulaConfig.split(",");
+            for (String string : strings) {
+                String[] strings1 = string.split(":");
+                if (strings1.length >= 2) {
+                    if(strings1[0].equals(initTableName)){
+                        list.put(strings1[1],strings1[0]);
+                    }
+                }
+            }
+        }
+        if (maps.size() > 0) {
+            //1.对公式字段添加默认值
+            for (Map<String, Object> keys : maps) {
+                if(!list.isEmpty()){
+                    if(list.containsKey(keys.get("e_key"))){
+                        continue;
+                    }
+                }
+                String key = keys.get("e_key") + "__";
+                Elements elements = doc.select("[keyname~=^" + key + "]");
+                for (Element element : elements) {
+                    Elements x = element.getElementsByAttribute("x1");
+                    Elements y = element.getElementsByAttribute("y1");
+                    Cell cell = getCellAt(sourceSheet, x.attr("x1"), y.attr("y1"));
+                    // 给单元格添加默认值并设置背景色为灰色
+                    if (cell != null) {
+                        // 设置默认值
+                        cell.setCellValue("公式配置");
+                        // 创建灰色背景样式
+                        CellStyle grayStyle = singleSheetWorkbook.createCellStyle();
+                        grayStyle.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
+                        grayStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+                        grayStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+                        // 设置字体居中
+                        grayStyle.setAlignment(HorizontalAlignment.CENTER);
+                        grayStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+                        // 应用样式到单元格
+                        cell.setCellStyle(grayStyle);
+                    }
+                }
+
+            }
+        }
+        //2.对日期字段添加默认值
+        Elements dateElements = doc.select("el-date-picker");
+        if(!dateElements.isEmpty()){
+            for (Element element : dateElements) {
+                Elements elements1 = element.select("[type=date]");
+                if(!elements1.isEmpty()){
+                    for (Element element1 : elements1) {
+                        Elements x1 = element1.getElementsByAttribute("x1");
+                        Elements y1 = element1.getElementsByAttribute("y1");
+                        Cell cell = getCellAt(sourceSheet, x1.attr("x1"), y1.attr("y1"));
+                        if (cell != null) {
+                            if(cell.getCellTypeEnum()==CellType.STRING){
+                                if(StringUtils.isNotEmpty(cell.getStringCellValue())){
+                                    if(cell.getStringCellValue().equals("公式配置")){
+                                        // 设置单元格值为"日期框"
+                                        cell.setCellValue("公式配置,日期框");
+                                        continue;
+                                    }
+                                }
+                            }
+                            // 设置单元格值为"日期框"
+                            cell.setCellValue("日期框");
+                            // 创建或获取单元格样式并设置居中
+                            CellStyle centerStyle = singleSheetWorkbook.createCellStyle();
+                            centerStyle.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
+                            centerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
+                            centerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
+                            // 应用样式到单元格
+                            cell.setCellStyle(centerStyle);
+                        }
+
+                    }
+                }
+                Elements elements2 = element.select("[type=datetimerange]");
+                if(!elements2.isEmpty()){
+                    for (Element element2 : elements2) {
+                        Elements x1 = element2.getElementsByAttribute("x1");
+                        Elements y1 = element2.getElementsByAttribute("y1");
+                        Cell cell = getCellAt(sourceSheet, x1.attr("x1"), y1.attr("y1"));
+                        if (cell != null) {
+                            if(cell.getCellTypeEnum()==CellType.STRING){
+                                if(StringUtils.isNotEmpty(cell.getStringCellValue())){
+                                    if(cell.getStringCellValue().equals("公式配置")){
+                                        cell.setCellValue("公式配置,日期范围框,两日期用-分割");
+                                        continue;
+                                    }
+                                }
+                            }
+                            // 设置单元格值为"日期框"
+                            cell.setCellValue("日期范围框,两日期用-分割");
+                            // 创建或获取单元格样式并设置居中
+                            CellStyle centerStyle = singleSheetWorkbook.createCellStyle();
+                            centerStyle.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
+                            centerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
+                            centerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
+                            // 应用样式到单元格
+                            cell.setCellStyle(centerStyle);
+                        }
+
+                    }
+                }
+            }
+        }
+        //3.对下拉框字段添加默认值
+        Elements selectElements = doc.select("el-select");
+        if(!selectElements.isEmpty()){
+            for (Element selectElement : selectElements) {
+                Elements elements = selectElement.select("[class=is-multiple]");
+                if(!elements.isEmpty()){
+                    for (Element element : elements) {
+                        Elements x1 = element.getElementsByAttribute("x1");
+                        Elements y1 = element.getElementsByAttribute("y1");
+                        Cell cell = getCellAt(sourceSheet, x1.attr("x1"), y1.attr("y1"));
+                        if (cell != null) {
+                            if(cell.getCellTypeEnum()==CellType.STRING){
+                                if(StringUtils.isNotEmpty(cell.getStringCellValue())){
+                                    if(cell.getStringCellValue().equals("公式配置")){
+                                        continue;
+                                    }
+                                }
+                            }
+                            // 设置单元格值为"多选下拉框"
+                            cell.setCellValue("多选下拉框,如需填写选项内容,并用、分割");
+                            // 创建或获取单元格样式并设置居中
+                            CellStyle centerStyle = singleSheetWorkbook.createCellStyle();
+                            centerStyle.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
+                            centerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
+                            centerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
+                            // 应用样式到单元格
+                            cell.setCellStyle(centerStyle);
+                        }
+                    }
+                }else {
+                    Elements x1 = selectElement.getElementsByAttribute("x1");
+                    Elements y1 = selectElement.getElementsByAttribute("y1");
+                    Cell cell = getCellAt(sourceSheet, x1.attr("x1"), y1.attr("y1"));
+                    if (cell != null) {
+                        if(cell.getCellTypeEnum()==CellType.STRING){
+                            if(StringUtils.isNotEmpty(cell.getStringCellValue())){
+                                if(cell.getStringCellValue().equals("公式配置")){
+                                    continue;
+                                }
+                            }
+                        }
+                        // 设置单元格值为"单选下拉框"
+                        cell.setCellValue("单选下拉框,如需填写选项内容,否则无法导入");
+                        // 创建或获取单元格样式并设置居中
+                        CellStyle centerStyle = singleSheetWorkbook.createCellStyle();
+                        centerStyle.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
+                        centerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
+                        centerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
+                        // 应用样式到单元格
+                        cell.setCellStyle(centerStyle);
+                    }
+
+                }
+            }
+        }
+        //4.对电签字段添加默认值
+        Elements dqlist = doc.getElementsByAttribute("dqid");
+        if(!dqlist.isEmpty()){
+            for (Element element : dqlist) {
+                Elements x1 = element.getElementsByAttribute("x1");
+                Elements y1 = element.getElementsByAttribute("y1");
+                Cell cell = getCellAt(sourceSheet, x1.attr("x1"), y1.attr("y1"));
+                if (cell != null) {
+                    if(cell.getCellTypeEnum()==CellType.STRING){
+                        if(StringUtils.isNotEmpty(cell.getStringCellValue())){
+                            if(cell.getStringCellValue().equals("公式配置")){
+                                continue;
+                            }
+                        }
+                    }
+                    // 设置单元格值为"电签配置,请勿填写数据"
+                    cell.setCellValue("电签配置,请勿填写数据");
+                    // 创建或获取单元格样式并设置居中
+                    CellStyle centerStyle = singleSheetWorkbook.createCellStyle();
+                    centerStyle.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
+                    centerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
+                    centerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
+                    // 应用样式到单元格
+                    cell.setCellStyle(centerStyle);
+                }
+            }
+        }
+        //5.对图片上传框添加默认值
+        // 跳过包含hc-table-form-upload子元素的td
+        Elements uploadElements = doc.select("hc-table-form-upload");
+        if (!uploadElements.isEmpty()) {
+            for (Element element : uploadElements) {
+                Elements x1 = element.getElementsByAttribute("x1");
+                Elements y1 = element.getElementsByAttribute("y1");
+                Cell cell = getCellAt(sourceSheet, x1.attr("x1"), y1.attr("y1"));
+                if (cell != null) {
+                    if(cell.getCellTypeEnum()==CellType.STRING){
+                        if(StringUtils.isNotEmpty(cell.getStringCellValue())){
+                            if(cell.getStringCellValue().equals("公式配置")){
+                                continue;
+                            }
+                        }
+                    }
+                    // 设置单元格值为"电签配置,请勿填写数据"
+                    cell.setCellValue("图片框,请到客户端上传");
+                    // 创建或获取单元格样式并设置居中
+                    CellStyle centerStyle = singleSheetWorkbook.createCellStyle();
+                    centerStyle.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
+                    centerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
+                    centerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
+                    // 应用样式到单元格
+                    cell.setCellStyle(centerStyle);
+                }
+            }
+        }
+        //6.对默认值字段添加默认值
+        Elements deflist = doc.getElementsByAttribute("defText");
+        if(!deflist.isEmpty()){
+            for (Element element : deflist) {
+                Elements x1 = element.getElementsByAttribute("x1");
+                Elements y1 = element.getElementsByAttribute("y1");
+                Cell cell = getCellAt(sourceSheet, x1.attr("x1"), y1.attr("y1"));
+                if (cell != null) {
+                    if(cell.getCellTypeEnum()==CellType.STRING){
+                        if(StringUtils.isNotEmpty(cell.getStringCellValue())){
+                            if(cell.getStringCellValue().equals("公式配置")){
+                                continue;
+                            }
+                        }
+                    }
+                    // 设置单元格值为"电签配置,请勿填写数据"
+                    cell.setCellValue("默认值配置");
+                    // 创建或获取单元格样式并设置居中
+                    CellStyle centerStyle = singleSheetWorkbook.createCellStyle();
+                    centerStyle.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
+                    centerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
+                    centerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
+                    // 应用样式到单元格
+                    cell.setCellStyle(centerStyle);
+                }
+            }
+        }
+    }
+    Cell getCellAt(Sheet sheet, String x, String y) {
+        Row row = sheet.getRow(Integer.parseInt(y)-1);
+        if (row != null) {
+            return row.getCell(Integer.parseInt(x)-1);
+        }
+        return null;
+    }
 
     /**
      * 复制sheet内容(包括样式、合并区域、行高列宽)
@@ -1045,6 +1352,10 @@ public class WbsTreeContractController extends BladeController {
         for (Map.Entry<String, Object> entry : originalMap.entrySet()) {
             String key = entry.getKey();
             String value = entry.getValue()+"";
+            value = value.replaceAll("\\s+", "");
+            if(StringUtils.isNotEmpty(value)&&(value.equals("公式配置")||value.equals("日期框")||value.equals("日期范围框,两日期用-分割")||value.equals("多选下拉框,如需填写选项内容,并用、分割")||value.equals("单选下拉框,如需填写选项内容,否则无法导入")||value.equals("电签配置,请勿填写数据")||value.equals("图片框,请到客户端上传")||value.equals("默认值配置")||value.equals("公式配置,日期框")||value.equals("公式配置,日期范围框,两日期用-分割"))){
+                continue;
+            }
             Matcher matcher = pattern.matcher(key);
 
             if (matcher.matches()) {