word转pdf;个人模板细化;配置文件添加学校名和发布限制;

This commit is contained in:
cjw 2024-05-21 09:36:15 +08:00
parent ecddd11751
commit 8be7e5d21a
17 changed files with 195 additions and 51 deletions

View File

@ -66,16 +66,16 @@
</dependency>
<!-- skywalking 整合 logback -->
<!-- <dependency>-->
<!-- <groupId>org.apache.skywalking</groupId>-->
<!-- <artifactId>apm-toolkit-logback-1.x</artifactId>-->
<!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.skywalking</groupId>-->
<!-- <artifactId>apm-toolkit-trace</artifactId>-->
<!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.skywalking</groupId>-->
<!-- <artifactId>apm-toolkit-logback-1.x</artifactId>-->
<!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.skywalking</groupId>-->
<!-- <artifactId>apm-toolkit-trace</artifactId>-->
<!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
</dependencies>
@ -86,6 +86,9 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>

View File

@ -89,6 +89,14 @@
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
</dependency>
<dependency>
<groupId>com.aspose.words</groupId>
<artifactId>aspose-words</artifactId>
<version>15.12.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/aspose-words-15.8.0-jdk16.jar</systemPath>
</dependency>
</dependencies>
</project>

View File

@ -1,12 +1,13 @@
package org.dromara.scale.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.util.PoitlIOUtils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
@ -17,12 +18,15 @@ import org.dromara.scale.domain.bo.BaseQueryBo;
import org.dromara.scale.domain.bo.SysEvaluationRecordBo;
import org.dromara.scale.domain.vo.SysEvaluationRecordVo;
import org.dromara.scale.service.ISysEvaluationRecordService;
import org.dromara.scale.utils.AsposeUtil;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
/**
* 量测记录
@ -54,16 +58,23 @@ public class EvaluationRecordController extends BaseController {
@Log(title = "个人量测记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(BaseQueryBo bo, HttpServletResponse response) throws IOException {
XWPFTemplate template = sysEvaluationRecordService.getWordTemplate(bo);
//ExcelUtil.exportExcel(list, "量测记录", SysEvaluationRecordVo.class, response);
String filePath = sysEvaluationRecordService.getWordTemplate(bo);
File pdf = FileUtil.createTempFile(".pdf", true);
String pdfPath = pdf.getPath();
File pdfFile = new File(pdfPath);
AsposeUtil.wordToPdf(filePath, pdfFile);
FileUtils.setAttachmentResponseHeader(response, bo.getNickName() + "的报告" + "-" + bo.getScaleName());
response.setContentType("application/octet-stream");
OutputStream out = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out);
template.write(bos);
bos.flush();
out.flush();
PoitlIOUtils.closeQuietlyMulti(template, bos, out);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
try (InputStream inputStream = new FileInputStream(pdfFile)) {
int available = inputStream.available();
IoUtil.copy(inputStream, response.getOutputStream(), available);
response.setContentLength(available);
} catch (Exception e) {
throw new ServiceException(e.getMessage());
} finally {
FileUtil.del(filePath);
FileUtil.del(pdfPath);
}
}
/**

View File

@ -1,12 +1,13 @@
package org.dromara.scale.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.util.PoitlIOUtils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
@ -22,12 +23,15 @@ import org.dromara.scale.domain.bo.SysScalePublishBo;
import org.dromara.scale.domain.vo.EvaluationVo;
import org.dromara.scale.domain.vo.SysScalePublishVo;
import org.dromara.scale.service.ISysScalePublishService;
import org.dromara.scale.utils.AsposeUtil;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.util.List;
/**
@ -129,7 +133,6 @@ public class ScalePublishController extends BaseController {
public R<Void> delete(@NotNull(message = "主键不能为空") @PathVariable Long batchNo) {
return toAjax(sysScalePublishService.deleteById(batchNo));
}
/**
* 导出量测记录列表
*/
@ -137,15 +140,22 @@ public class ScalePublishController extends BaseController {
@Log(title = "场次量测记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(BaseQueryBo bo, HttpServletResponse response) throws IOException {
XWPFTemplate template = sysScalePublishService.getWordTemplate(bo);
//ExcelUtil.exportExcel(list, "量测记录", SysEvaluationRecordVo.class, response);
FileUtils.setAttachmentResponseHeader(response, bo.getSessionName() + "的报告");
response.setContentType("application/octet-stream");
OutputStream out = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out);
template.write(bos);
bos.flush();
out.flush();
PoitlIOUtils.closeQuietlyMulti(template, bos, out);
String filePath = sysScalePublishService.getWordTemplate(bo);
File pdf = FileUtil.createTempFile(".pdf", true);
String pdfPath = pdf.getPath();
File pdfFile = new File(pdfPath);
AsposeUtil.wordToPdf(filePath, pdfFile);
FileUtils.setAttachmentResponseHeader(response, bo.getSessionName() + "的报告");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
try (InputStream inputStream = new FileInputStream(pdfFile)) {
int available = inputStream.available();
IoUtil.copy(inputStream, response.getOutputStream(), available);
response.setContentLength(available);
} catch (Exception e) {
throw new ServiceException(e.getMessage());
} finally {
FileUtil.del(filePath);
FileUtil.del(pdfPath);
}
}
}

View File

@ -17,6 +17,7 @@ import java.util.List;
public class EvaluationRecordWordData {
private String createTime;
private String schoolName;
private String useTime;
private String nickName;
private String deptName;

View File

@ -19,6 +19,9 @@ public class WordEvaluationFactor {
private BigDecimal totalScore;
private BigDecimal score;
private Integer status;
private String rangeName;
private BigDecimal minValue;
private BigDecimal maxValue;
private String evalDesc;
private String evalPropose;

View File

@ -35,4 +35,6 @@ public interface SysScalePublishMapper extends BaseMapperPlus<SysScalePublish, S
StatisticNumVo selectSexNumByBatchNo(Long batchNo);
int selectCountScalePublish();
}

View File

@ -1,6 +1,5 @@
package org.dromara.scale.service;
import com.deepoove.poi.XWPFTemplate;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.scale.domain.bo.BaseQueryBo;
@ -34,7 +33,7 @@ public interface ISysEvaluationRecordService {
List<SysEvaluationRecordVo> queryList(SysEvaluationRecordBo bo);
XWPFTemplate getWordTemplate(BaseQueryBo bo) throws IOException;
String getWordTemplate(BaseQueryBo bo) throws IOException;

View File

@ -1,6 +1,5 @@
package org.dromara.scale.service;
import com.deepoove.poi.XWPFTemplate;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.scale.domain.bo.BaseQueryBo;
@ -56,7 +55,7 @@ public interface ISysScalePublishService {
List<EvaluationVo> queryUndoneExportList(BaseQueryBo query);
XWPFTemplate getWordTemplate(BaseQueryBo bo) throws IOException;
String getWordTemplate(BaseQueryBo bo) throws IOException;
}

View File

@ -1,5 +1,6 @@
package org.dromara.scale.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@ -27,10 +28,13 @@ import org.dromara.scale.mapper.SysScaleMapper;
import org.dromara.scale.service.ISysEvaluationRecordService;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.service.ISysConfigService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.rmi.ServerException;
import java.util.Date;
import java.util.LinkedList;
@ -52,6 +56,8 @@ public class SysEvaluationRecordServiceImpl implements ISysEvaluationRecordServi
private final SysScaleMapper scaleMapper;
private final ISysConfigService configService;
/**
* 查询量测记录
*/
@ -90,7 +96,7 @@ public class SysEvaluationRecordServiceImpl implements ISysEvaluationRecordServi
}
@Override
public XWPFTemplate getWordTemplate(BaseQueryBo bo) throws IOException {
public String getWordTemplate(BaseQueryBo bo) throws IOException {
Long userId = bo.getUserId();
if (userId == null) {
throw new ServerException("用户ID不能为空");
@ -105,11 +111,14 @@ public class SysEvaluationRecordServiceImpl implements ISysEvaluationRecordServi
}
EvaluationRecordWordData wordData = new EvaluationRecordWordData();
String name = configService.selectConfigByKey("sys.school.name");
wordData.setScaleName(name);
SysEvaluationRecord sysEvaluationRecord = baseMapper.selectById(recordId);
Date createTime = sysEvaluationRecord.getCreateTime();
Date updateTime = sysEvaluationRecord.getUpdateTime();
wordData.setCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, createTime));
wordData.setUseTime(DateUtils.getDatePoor(createTime,updateTime));
wordData.setUseTime(DateUtils.getDatePoor(createTime, updateTime));
SysUserVo user = userMapper.selectUserById(userId);
wordData.setNickName(user.getNickName());
@ -125,10 +134,10 @@ public class SysEvaluationRecordServiceImpl implements ISysEvaluationRecordServi
borderStyle.setColor("A6A6A6");
borderStyle.setSize(4);
borderStyle.setType(XWPFTable.XWPFBorderType.SINGLE);
RowRenderData factorHeader = Rows.of("名称", "包含题目", "原始分", "得分").bgColor("F2F2F2").center()
RowRenderData factorHeader = Rows.of("名称", "包含题目", "原始分", "得分", "命中区间", "区间描述").bgColor("F2F2F2").center()
.textColor("7F7f7F").textFontFamily("Hei").textFontSize(9).create();
TableRenderData factorTable = Tables.ofA4MediumWidth().addRow(factorHeader).border(borderStyle)
.width(14.63d,null).center().create();
.width(14.63d, null).center().create();
//一并处理数据
int size = answerVos.size();
LinkedList<WordFactor> factors = new LinkedList<>();
@ -138,9 +147,19 @@ public class SysEvaluationRecordServiceImpl implements ISysEvaluationRecordServi
for (int i = 0; i < size; i++) {
WordEvaluationFactor answerVo = answerVos.get(i);
double score = answerVo.getScore().doubleValue();
StringBuilder range = new StringBuilder();
BigDecimal minValue = answerVo.getMinValue();
BigDecimal maxValue = answerVo.getMaxValue();
if (minValue != null) {
range.append(minValue.doubleValue());
}
range.append("~");
if (maxValue != null) {
range.append(maxValue.doubleValue());
}
//处理因子得分表格
RowRenderData one = Rows.of(answerVo.getFactorName(), answerVo.getQuestionNum().toString(),
answerVo.getTotalScore().toString(), answerVo.getScore().toString()).center().create();
answerVo.getTotalScore().toString(), answerVo.getScore().toString(), range.toString(), answerVo.getRangeName()).center().create();
factorTable.addRow(one);
//处理测评结果
WordFactor wordFactor = new WordFactor();
@ -171,6 +190,11 @@ public class SysEvaluationRecordServiceImpl implements ISysEvaluationRecordServi
ClassPathResource classPathResource = new ClassPathResource("word/personalTemplate.docx");
Configure config = Configure.builder()
.bind("factors", new LoopRowTableRenderPolicy()).useSpringEL().build();
return XWPFTemplate.compile(classPathResource.getInputStream(),config).render(wordData);
XWPFTemplate template = XWPFTemplate.compile(classPathResource.getInputStream(), config).render(wordData);
File docx = FileUtil.createTempFile(".docx", true);
String wordPath = docx.getPath();
template.writeToFile(wordPath);
return wordPath;
}
}

View File

@ -1,5 +1,6 @@
package org.dromara.scale.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -37,9 +38,11 @@ import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.mapper.SysDeptMapper;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.service.ISysConfigService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
@ -72,6 +75,8 @@ public class SysScalePublishServiceImpl implements ISysScalePublishService {
private final SysWarnRecordMapper warnMapper;
private final ISysConfigService configService;
/**
* 查询量发布
*/
@ -115,6 +120,12 @@ public class SysScalePublishServiceImpl implements ISysScalePublishService {
*/
@Override
public Boolean insertByBo(SysScalePublishBo bo) {
int i = baseMapper.selectCountScalePublish();
String s = configService.selectConfigByKey("sys.publish.limit");
int limit = Integer.parseInt(s);
if(limit != -1 && i>=limit){
throw new ServiceException("发布数量超出系统限制");
}
LoginUser loginUser = getLoginUser();
SysScalePublish add = MapstructUtils.convert(bo, SysScalePublish.class);
add.setStatus(StatusEnum.IN_USE.getValue());
@ -273,7 +284,7 @@ public class SysScalePublishServiceImpl implements ISysScalePublishService {
}
@Override
public XWPFTemplate getWordTemplate(BaseQueryBo bo) throws IOException {
public String getWordTemplate(BaseQueryBo bo) throws IOException {
Long batchNo = bo.getBatchNo();
if (batchNo == null) {
throw new ServerException("场次Id不能为空");
@ -314,7 +325,6 @@ public class SysScalePublishServiceImpl implements ISysScalePublishService {
.series("", new Integer[]{maleNum, femaleNum}).create();
wordData.setSexChart(sexChart);
int undoneNum = recordMapper.selectUndoneNumByBatchNo(batchNo);
int recordNum = completeNum + undoneNum;
int completePercent = processHalfUpPercent(completeNum, recordNum);
@ -402,7 +412,12 @@ public class SysScalePublishServiceImpl implements ISysScalePublishService {
ClassPathResource classPathResource = new ClassPathResource("word/groupTemplate.docx");
Configure config = Configure.builder()
.bind("warnCharts", new LoopRowTableRenderPolicy()).useSpringEL().build();
return XWPFTemplate.compile(classPathResource.getInputStream(), config).render(wordData);
XWPFTemplate template = XWPFTemplate.compile(classPathResource.getInputStream(), config).render(wordData);
File docx = FileUtil.createTempFile(".docx", true);
String wordPath = docx.getPath();
template.writeToFile(wordPath);
return wordPath;
}
private int processHalfUpPercent(int num, int total) {

View File

@ -0,0 +1,46 @@
package org.dromara.scale.utils;
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import lombok.SneakyThrows;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
/**
* <p>TODO<p>
*
* @author cjw
* @version V1.0.0
* @date 2024/5/20 15:03
*/
public class AsposeUtil {
/**
* 加载license 用于破解 不生成水印
*/
@SneakyThrows
private static void getLicense() {
try (InputStream is = AsposeUtil.class.getClassLoader().getResourceAsStream("License.xml")) {
License license = new License();
license.setLicense(is);
}
}
/**
* word转pdf
*
* @param wordPath word文件保存的路径
* @param pdfFile 转换后pdf文件保存的路径
*/
@SneakyThrows
public static void wordToPdf(String wordPath, File pdfFile) {
getLicense();
try (FileOutputStream os = new FileOutputStream(pdfFile)) {
Document doc = new Document(wordPath);
doc.save(os, SaveFormat.PDF);
}
}
}

View File

@ -0,0 +1,15 @@
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>
sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=
</Signature>
</License>

View File

@ -39,6 +39,9 @@
sf.question_score as `totalScore`,
ec.score as `score`,
ec.status as `status`,
sfr.range_name as `rangeName`,
sfr.min_value as `minValue`,
sfr.max_value as `maxValue`,
sfr.eval_desc as `evalDesc`,
sfr.eval_propose as `evalPropose`
from sys_evaluation_conclusion ec

View File

@ -84,4 +84,9 @@
where er.batch_no = #{batchNo}
order by u.user_id
</select>
<select id="selectCountScalePublish" resultType="int">
select count(*)
from sys_scale_publish
</select>
</mapper>