zhangxiaomeng 7 months ago
parent
commit
ab81927960
  1. 298
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TitleFormatterController.java
  2. 64
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TitleTemplateController.java
  3. 48
      ruoyi-api/src/main/java/com/ruoyi/api/domain/TitleTemplate.java
  4. 25
      ruoyi-api/src/main/java/com/ruoyi/api/mapper/TitleTemplateMapper.java
  5. 24
      ruoyi-api/src/main/java/com/ruoyi/api/service/ITitleTemplateService.java
  6. 50
      ruoyi-api/src/main/java/com/ruoyi/api/service/impl/TitleTemplateServiceImpl.java
  7. 76
      ruoyi-api/src/main/resources/mapper/api/TitleTemplateMapper.xml

298
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TitleFormatterController.java

@ -0,0 +1,298 @@
package com.ruoyi.web.controller.system;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.api.domain.TitleTemplate;
import com.ruoyi.api.service.impl.TitleTemplateServiceImpl;
import com.ruoyi.common.core.domain.AjaxResult;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.*;
@RestController
@RequestMapping("/system/formatter")
public class TitleFormatterController {
@Autowired
private TitleTemplateServiceImpl titleTemplateService;
@PostMapping
public AjaxResult formatDocument(@RequestParam("file") MultipartFile file,
@RequestParam("template") String templateJson) {
try {
// 解析模板参数
JSONObject templateObj = JSON.parseObject(templateJson);
Long templateType = Long.parseLong(templateObj.getString("id"));
TitleTemplate titleTemplate = titleTemplateService.selectTitleTemplateById(templateType);
if (titleTemplate == null) {
return AjaxResult.error("未找到对应的标题模板");
}
// 检查文件类型
if (!file.getOriginalFilename().endsWith(".docx")) {
return AjaxResult.error("仅支持.docx格式的文档");
}
// 处理文档
Map<String, Object> result = processDocumentWithNumbering(file, titleTemplate);
return AjaxResult.success("文档处理成功", result);
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error("文档处理失败: " + e.getMessage());
}
}
/**
* 处理文档并添加多级标题编号
*/
private Map<String, Object> processDocumentWithNumbering(MultipartFile file, TitleTemplate titleTemplate)
throws IOException {
Map<String, Object> result = new HashMap<>();
List<Map<String, Object>> paragraphsInfo = new ArrayList<>();
// 初始化各级标题计数器
int[] levelCounters = new int[5]; // 0不使用,1-4对应各级标题
Arrays.fill(levelCounters, 0);
try (InputStream inputStream = file.getInputStream();
XWPFDocument document = new XWPFDocument(inputStream)) {
// 获取模板中的标题配置
String firstTitle = titleTemplate.getFirstTitle();
String secondTitle = titleTemplate.getSecondTitle();
String thirdTitle = titleTemplate.getThirdTitle();
String fourthTitle = titleTemplate.getFourthTitle();
System.out.println("=== 开始处理文档 ===");
System.out.println("模板配置: 一级标题='" + firstTitle + "', 二级标题='" + secondTitle +
"', 三级标题='" + thirdTitle + "', 四级标题='" + fourthTitle + "'");
// 遍历文档中的所有段落
List<XWPFParagraph> paragraphs = document.getParagraphs();
for (int i = 0; i < paragraphs.size(); i++) {
XWPFParagraph paragraph = paragraphs.get(i);
// 获取段落文本
String fullText = getParagraphText(paragraph);
if (fullText.isEmpty()) {
continue;
}
System.out.println("\n--- 处理段落 " + (i + 1) + " ---");
System.out.println("完整文本: '" + fullText + "'");
Map<String, Object> paraInfo = new HashMap<>();
paraInfo.put("originalText", fullText);
String numberedText = fullText;
int levelNumber = 0;
String levelName = "正文";
// 检查段落是否包含模板字符串并确定标题级别(精确匹配)
if (isExactTemplateMatch(fullText, firstTitle)) {
levelCounters[1]++;
resetLowerLevels(levelCounters, 1);
numberedText = generateLevelNumber(levelCounters, 1) + " " + extractPureContent(fullText, firstTitle);
levelNumber = 1;
levelName = "一级标题";
setParagraphStyle(paragraph, "Heading1");
System.out.println("识别为一级标题,新编号: " + numberedText);
} else if (isExactTemplateMatch(fullText, secondTitle)) {
levelCounters[2]++;
resetLowerLevels(levelCounters, 2);
numberedText = generateLevelNumber(levelCounters, 2) + " " + extractPureContent(fullText, secondTitle);
levelNumber = 2;
levelName = "二级标题";
setParagraphStyle(paragraph, "Heading2");
System.out.println("识别为二级标题,新编号: " + numberedText);
} else if (isExactTemplateMatch(fullText, thirdTitle)) {
levelCounters[3]++;
resetLowerLevels(levelCounters, 3);
numberedText = generateLevelNumber(levelCounters, 3) + " " + extractPureContent(fullText, thirdTitle);
levelNumber = 3;
levelName = "三级标题";
setParagraphStyle(paragraph, "Heading3");
System.out.println("识别为三级标题,新编号: " + numberedText);
} else if (isExactTemplateMatch(fullText, fourthTitle)) {
levelCounters[4]++;
resetLowerLevels(levelCounters, 4);
numberedText = generateLevelNumber(levelCounters, 4) + " " + extractPureContent(fullText, fourthTitle);
levelNumber = 4;
levelName = "四级标题";
setParagraphStyle(paragraph, "Heading4");
System.out.println("识别为四级标题,新编号: " + numberedText);
} else {
System.out.println("识别为正文");
}
// 设置段落信息
paraInfo.put("level", levelName);
paraInfo.put("levelNumber", levelNumber);
paraInfo.put("numberedText", numberedText);
paragraphsInfo.add(paraInfo);
// 更新段落文本
updateParagraphText(paragraph, numberedText);
}
}
result.put("paragraphs", paragraphsInfo);
result.put("summary", String.format(
"文档处理完成:一级标题%d个,二级标题%d个,三级标题%d个,四级标题%d个",
levelCounters[1], levelCounters[2], levelCounters[3], levelCounters[4]
));
return result;
}
/**
* 精确模板匹配
*/
private boolean isExactTemplateMatch(String text, String template) {
if (text == null || template == null || template.isEmpty()) {
return false;
}
return text.trim().startsWith(template.trim());
}
/**
* 提取纯文本内容
*/
private String extractPureContent(String fullText, String template) {
if (fullText.startsWith(template)) {
return fullText.substring(template.length()).trim();
}
return fullText;
}
/**
* 获取段落文本
*/
private String getParagraphText(XWPFParagraph paragraph) {
StringBuilder textBuilder = new StringBuilder();
for (XWPFRun run : paragraph.getRuns()) {
if (run.getText(0) != null) {
textBuilder.append(run.getText(0));
}
}
return textBuilder.toString().trim();
}
/**
* 生成级别编号
*/
private String generateLevelNumber(int[] levelCounters, int level) {
for (int i = 1; i < levelCounters.length; i++) {
if (levelCounters[i] == 0) {
levelCounters[i] = 1;
}
}
switch (level) {
case 1:
return generateChineseNumber(levelCounters[1]) + "、";
case 2:
return "(" + generateChineseNumber(levelCounters[2]) + ")";
case 3:
return levelCounters[3] + ".";
case 4:
return "(" + levelCounters[4] + ")";
default:
return "";
}
}
/**
* 生成中文数字
*/
private String generateChineseNumber(int number) {
String[] chineseNumbers = {"", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"};
if (number <= 10) {
return chineseNumbers[number];
} else if (number < 20) {
return "十" + (number > 10 ? chineseNumbers[number - 10] : "");
} else if (number < 100) {
int tens = number / 10;
int units = number % 10;
return chineseNumbers[tens] + "十" + (units > 0 ? chineseNumbers[units] : "");
} else {
return String.valueOf(number);
}
}
/**
* 重置下级标题计数器
*/
private void resetLowerLevels(int[] levelCounters, int currentLevel) {
for (int i = currentLevel + 1; i < levelCounters.length; i++) {
levelCounters[i] = 0;
}
}
/**
* 更新段落文本
*/
private void updateParagraphText(XWPFParagraph paragraph, String newText) {
// 清除原有的runs
for (int i = paragraph.getRuns().size() - 1; i >= 0; i--) {
paragraph.removeRun(i);
}
// 创建新的run并设置文本
XWPFRun run = paragraph.createRun();
run.setText(newText);
// 设置字体样式
run.setFontSize(12);
if (paragraph.getStyle() != null && paragraph.getStyle().startsWith("Heading")) {
run.setBold(true);
// 根据标题级别设置不同的字体大小
switch (paragraph.getStyle()) {
case "Heading1":
run.setFontSize(16);
break;
case "Heading2":
run.setFontSize(14);
break;
case "Heading3":
run.setFontSize(13);
break;
case "Heading4":
run.setFontSize(12);
break;
}
}
}
/**
* 设置段落样式
*/
private void setParagraphStyle(XWPFParagraph paragraph, String style) {
paragraph.setStyle(style);
if (style.startsWith("Heading")) {
// 设置不同的缩进
switch (style) {
case "Heading1":
paragraph.setIndentationLeft(0);
break;
case "Heading2":
paragraph.setIndentationLeft(200);
break;
case "Heading3":
paragraph.setIndentationLeft(400);
break;
case "Heading4":
paragraph.setIndentationLeft(600);
break;
}
}
}
}

64
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TitleTemplateController.java

@ -0,0 +1,64 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.api.domain.TitleTemplate;
import com.ruoyi.api.service.ITitleTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
@RestController
@RequestMapping("/system/template")
public class TitleTemplateController extends BaseController
{
@Autowired
private ITitleTemplateService titleTemplateService;
@GetMapping("/list")
public TableDataInfo list(TitleTemplate titleTemplate)
{
startPage();
List<TitleTemplate> list = titleTemplateService.selectTitleTemplateList(titleTemplate);
return getDataTable(list);
}
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(titleTemplateService.selectTitleTemplateById(id));
}
@PostMapping
public AjaxResult add(@RequestBody TitleTemplate titleTemplate)
{
return toAjax(titleTemplateService.insertTitleTemplate(titleTemplate));
}
@PutMapping
public AjaxResult edit(@RequestBody TitleTemplate titleTemplate)
{
return toAjax(titleTemplateService.updateTitleTemplate(titleTemplate));
}
@DeleteMapping("/{id}")
public AjaxResult remove(@PathVariable Long id)
{
return toAjax(titleTemplateService.deleteTitleTemplateById(id));
}
}

48
ruoyi-api/src/main/java/com/ruoyi/api/domain/TitleTemplate.java

@ -0,0 +1,48 @@
package com.ruoyi.api.domain;
public class TitleTemplate {
private String name;
private Long id;
private String firstTitle;
private String secondTitle;
private String thirdTitle;
private String fourthTitle;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFirstTitle() {
return firstTitle;
}
public void setFirstTitle(String firstTitle) {
this.firstTitle = firstTitle;
}
public String getSecondTitle() {
return secondTitle;
}
public void setSecondTitle(String secondTitle) {
this.secondTitle = secondTitle;
}
public String getThirdTitle() {
return thirdTitle;
}
public void setThirdTitle(String thirdTitle) {
this.thirdTitle = thirdTitle;
}
public String getFourthTitle() {
return fourthTitle;
}
public void setFourthTitle(String fourthTitle) {
this.fourthTitle = fourthTitle;
}
}

25
ruoyi-api/src/main/java/com/ruoyi/api/mapper/TitleTemplateMapper.java

@ -0,0 +1,25 @@
package com.ruoyi.api.mapper;
import com.ruoyi.api.domain.TitleTemplate;
import java.util.List;
public interface TitleTemplateMapper
{
public TitleTemplate selectTitleTemplateById(Long id);
public List<TitleTemplate> selectTitleTemplateList(TitleTemplate titleTemplate);
public int insertTitleTemplate(TitleTemplate titleTemplate);
public int updateTitleTemplate(TitleTemplate titleTemplate);
public int deleteTitleTemplateById(Long id);
}

24
ruoyi-api/src/main/java/com/ruoyi/api/service/ITitleTemplateService.java

@ -0,0 +1,24 @@
package com.ruoyi.api.service;
import com.ruoyi.api.domain.TitleTemplate;
import java.util.List;
public interface ITitleTemplateService
{
public TitleTemplate selectTitleTemplateById(Long id);
public List<TitleTemplate> selectTitleTemplateList(TitleTemplate titleTemplate);
public int insertTitleTemplate(TitleTemplate titleTemplate);
public int updateTitleTemplate(TitleTemplate titleTemplate);
public int deleteTitleTemplateById(Long id);
}

50
ruoyi-api/src/main/java/com/ruoyi/api/service/impl/TitleTemplateServiceImpl.java

@ -0,0 +1,50 @@
package com.ruoyi.api.service.impl;
import java.util.List;
import com.ruoyi.api.domain.TitleTemplate;
import com.ruoyi.api.mapper.TitleTemplateMapper;
import com.ruoyi.api.service.ITitleTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TitleTemplateServiceImpl implements ITitleTemplateService
{
@Autowired
private TitleTemplateMapper titleTemplateMapper;
@Override
public TitleTemplate selectTitleTemplateById(Long id)
{
return titleTemplateMapper.selectTitleTemplateById(id);
}
@Override
public List<TitleTemplate> selectTitleTemplateList(TitleTemplate titleTemplate)
{
return titleTemplateMapper.selectTitleTemplateList(titleTemplate);
}
@Override
public int insertTitleTemplate(TitleTemplate titleTemplate)
{
return titleTemplateMapper.insertTitleTemplate(titleTemplate);
}
@Override
public int updateTitleTemplate(TitleTemplate titleTemplate)
{
return titleTemplateMapper.updateTitleTemplate(titleTemplate);
}
@Override
public int deleteTitleTemplateById(Long id)
{
return titleTemplateMapper.deleteTitleTemplateById(id);
}
}

76
ruoyi-api/src/main/resources/mapper/api/TitleTemplateMapper.xml

@ -0,0 +1,76 @@
<?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.ruoyi.api.mapper.TitleTemplateMapper">
<resultMap type="TitleTemplate" id="TitleTemplateResult">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="firstTitle" column="first_title" />
<result property="secondTitle" column="second_title" />
<result property="thirdTitle" column="third_title" />
<result property="fourthTitle" column="fourth_title" />
</resultMap>
<sql id="selectTitleTemplateVo">
select id, name, first_title, second_title, third_title, fourth_title from title_template
</sql>
<select id="selectTitleTemplateList" parameterType="TitleTemplate" resultMap="TitleTemplateResult">
<include refid="selectTitleTemplateVo"/>
<where>
<if test="name != null and name != ''"> and name like concat('%', #{name}, '%')</if>
<if test="firstTitle != null and firstTitle != ''"> and first_title = #{firstTitle}</if>
<if test="secondTitle != null and secondTitle != ''"> and second_title = #{secondTitle}</if>
<if test="thirdTitle != null and thirdTitle != ''"> and third_title = #{thirdTitle}</if>
<if test="fourthTitle != null and fourthTitle != ''"> and fourth_title = #{fourthTitle}</if>
</where>
</select>
<select id="selectTitleTemplateById" parameterType="Long" resultMap="TitleTemplateResult">
<include refid="selectTitleTemplateVo"/>
where id = #{id}
</select>
<insert id="insertTitleTemplate" parameterType="TitleTemplate">
insert into title_template
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name != null">name,</if>
<if test="firstTitle != null">first_title,</if>
<if test="secondTitle != null">second_title,</if>
<if test="thirdTitle != null">third_title,</if>
<if test="fourthTitle != null">fourth_title,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="name != null">#{name},</if>
<if test="firstTitle != null">#{firstTitle},</if>
<if test="secondTitle != null">#{secondTitle},</if>
<if test="thirdTitle != null">#{thirdTitle},</if>
<if test="fourthTitle != null">#{fourthTitle},</if>
</trim>
</insert>
<update id="updateTitleTemplate" parameterType="TitleTemplate">
update title_template
<trim prefix="SET" suffixOverrides=",">
<if test="name != null">name = #{name},</if>
<if test="firstTitle != null">first_title = #{firstTitle},</if>
<if test="secondTitle != null">second_title = #{secondTitle},</if>
<if test="thirdTitle != null">third_title = #{thirdTitle},</if>
<if test="fourthTitle != null">fourth_title = #{fourthTitle},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteTitleTemplateById" parameterType="Long">
delete from title_template where id = #{id}
</delete>
<delete id="deleteTitleTemplateByIds" parameterType="String">
delete from title_template where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
Loading…
Cancel
Save