Commit d78f5813 authored by 李秀明's avatar 李秀明

feat(jg): 安装告知单生成

parent 7cf88d55
package com.yeejoin.amos.boot.module.jg.api.dto;
import lombok.Getter;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.file.Files;
@Getter
public class ByteArrayMultipartFile implements MultipartFile {
private byte[] bytes;
private String name;
private String originalFilename;
private String contentType;
public ByteArrayMultipartFile() {
}
public ByteArrayMultipartFile(String name, String originalFilename, String contentType, byte[] bytes) {
super();
this.name = name;
this.originalFilename = originalFilename;
this.contentType = contentType;
this.bytes = bytes;
}
@Override
public boolean isEmpty() {
return bytes.length == 0;
}
@Override
public long getSize() {
return bytes.length;
}
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(bytes);
}
@Override
public void transferTo(File destination) throws IOException {
try (OutputStream outputStream = Files.newOutputStream(destination.toPath())) {
outputStream.write(bytes);
}
}
}
......@@ -200,6 +200,9 @@ public class JgInstallationNoticeDto extends BaseDto {
@ApiModelProperty(value = "告知设备列表")
private List<Map<String, Object>> deviceList;
@ApiModelProperty(value = "告知单PDF URL")
private String noticeReportUrl;
public String getFullAddress() {
return (StringUtils.isEmpty(this.provinceName) ? "" : this.provinceName)
+ (StringUtils.isEmpty(this.cityName) ? "" : this.cityName)
......
......@@ -335,4 +335,10 @@ public class JgInstallationNotice extends BaseEntity {
@TableField("instance_id")
private String instanceId;
/**
* 告知单PDF URL
*/
@TableField("notice_report_url")
private String noticeReportUrl;
}
......@@ -2,6 +2,7 @@ package com.yeejoin.amos.boot.module.jg.api.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yeejoin.amos.boot.module.jg.api.dto.JgInstallationNoticeDto;
import com.yeejoin.amos.boot.module.jg.api.entity.JgInstallationNotice;
......@@ -13,7 +14,7 @@ import java.util.Map;
* @author system_generator
* @date 2023-12-12
*/
public interface IJgInstallationNoticeService {
public interface IJgInstallationNoticeService extends IService<JgInstallationNotice> {
/**
* 根据sequenceNbr查询
......@@ -56,4 +57,12 @@ public interface IJgInstallationNoticeService {
* @param submitType 保存类型
*/
void saveNotice(String submitType, Map<String, JgInstallationNoticeDto> model);
/**
* 打印告知单
*
* @param sequenceNbr 主键
* @return pdf文件路径
*/
String generateInstallationNoticeReport(Long sequenceNbr);
}
......@@ -49,6 +49,19 @@
<select id="queryEquipInformation" resultType="java.util.Map">
select
isn.sequence_nbr AS sequenceNbr,
isn.install_unit_name AS installUnitName,
isn.apply_no AS applyNo,
isn.province AS province,
isn.city AS city,
isn.county AS county,
isn.street AS street,
isn.address AS address,
isn.install_start_date AS installStartDate,
isn.install_license_no AS installLicenseNo,
isn.install_license_expiration_date AS installLicenseExpirationDate,
isn.install_leader_name AS installLeaderName,
isn.install_leader_phone AS installLeaderPhone,
isn.use_unit_name AS useUnitName,
ri.equ_list AS equList,
ri.equ_category AS equCategory,
ri.EQU_DEFINE AS equDefine,
......
......@@ -31,6 +31,12 @@
<version>1.10.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>19.5jdk</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
......
package com.yeejoin.amos.boot.module.jg.biz.controller;
import cn.hutool.core.bean.BeanUtil;
import com.yeejoin.amos.boot.module.jg.api.entity.JgInstallationNotice;
import org.omg.PortableInterceptor.SUCCESSFUL;
import org.springframework.web.bind.annotation.RequestMapping;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.controller.BaseController;
import com.yeejoin.amos.boot.module.common.biz.utils.CommonResponseUtil;
import com.yeejoin.amos.boot.module.jg.api.dto.JgInstallationNoticeDto;
import com.yeejoin.amos.boot.module.jg.api.entity.JgInstallationNotice;
import com.yeejoin.amos.boot.module.jg.biz.service.impl.JgInstallationNoticeServiceImpl;
import com.yeejoin.amos.boot.module.jg.api.service.IJgInstallationNoticeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
......@@ -24,8 +18,6 @@ import org.typroject.tyboot.core.restful.utils.ResponseHelper;
import org.typroject.tyboot.core.restful.utils.ResponseModel;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Objects;
......@@ -41,7 +33,7 @@ import java.util.Objects;
public class JgInstallationNoticeController extends BaseController {
@Autowired
JgInstallationNoticeServiceImpl jgInstallationNoticeServiceImpl;
private IJgInstallationNoticeService iJgInstallationNoticeService;
/**
* 新增
......@@ -49,12 +41,12 @@ public class JgInstallationNoticeController extends BaseController {
* @return
*/
@TycloudOperation(ApiLevel = UserType.AGENCY)
@PostMapping(value = "/save")
@ApiOperation(httpMethod = "POST", value = "新增安装告知", notes = "新增安装告知")
public ResponseModel<String> save(@RequestParam String submitType,@RequestBody Map<String, JgInstallationNoticeDto> model) {
jgInstallationNoticeServiceImpl.saveNotice(submitType, model);
return ResponseHelper.buildResponse("");
}
@PostMapping(value = "/save")
@ApiOperation(httpMethod = "POST", value = "新增安装告知", notes = "新增安装告知")
public ResponseModel<String> save(@RequestParam String submitType, @RequestBody Map<String, JgInstallationNoticeDto> model) {
iJgInstallationNoticeService.saveNotice(submitType, model);
return ResponseHelper.buildResponse("");
}
/**
* 根据sequenceNbr更新
......@@ -69,7 +61,7 @@ public class JgInstallationNoticeController extends BaseController {
if (Objects.isNull(installationInfo)) {
throw new IllegalArgumentException("参数installationInfo不能为空");
}
return ResponseHelper.buildResponse(jgInstallationNoticeServiceImpl.updateInstallationNotice(installationInfo, op));
return ResponseHelper.buildResponse(iJgInstallationNoticeService.updateInstallationNotice(installationInfo, op));
}
/**
......@@ -81,7 +73,7 @@ public class JgInstallationNoticeController extends BaseController {
@DeleteMapping(value = "/delete")
@ApiOperation(httpMethod = "DELETE", value = "根据sequenceNbr删除安装告知", notes = "根据sequenceNbr删除安装告知")
public ResponseModel<Boolean> deleteBySequenceNbr(@RequestParam(value = "sequenceNbr") Long[] sequenceNbr) {
return ResponseHelper.buildResponse(jgInstallationNoticeServiceImpl.removeById(sequenceNbr));
return ResponseHelper.buildResponse(iJgInstallationNoticeService.removeById(sequenceNbr));
}
/**
......@@ -94,7 +86,7 @@ public class JgInstallationNoticeController extends BaseController {
@ApiOperation(value = "根据sequenceNbr删除维保合同备案", notes = "根据sequenceNbr删除维保合同备案")
public ResponseModel<Boolean> deleteForBatch(@RequestParam("sequenceNbrs") Long[] sequenceNbrs) {
try {
return ResponseHelper.buildResponse(jgInstallationNoticeServiceImpl.deleteForBatch(sequenceNbrs));
return ResponseHelper.buildResponse(iJgInstallationNoticeService.deleteForBatch(sequenceNbrs));
} catch (Exception e) {
return CommonResponseUtil.failure(e.getMessage());
}
......@@ -110,7 +102,7 @@ public class JgInstallationNoticeController extends BaseController {
@ApiOperation(httpMethod = "GET", value = "根据sequenceNbr查询单个安装告知", notes = "根据sequenceNbr查询单个安装告知")
public ResponseModel<Map<String,
Map<String, Object>>> selectOne(@RequestParam("sequenceNbr") Long sequenceNbr) {
return ResponseHelper.buildResponse(jgInstallationNoticeServiceImpl.queryBySequenceNbr(sequenceNbr));
return ResponseHelper.buildResponse(iJgInstallationNoticeService.queryBySequenceNbr(sequenceNbr));
}
......@@ -131,18 +123,16 @@ public class JgInstallationNoticeController extends BaseController {
@RequestBody(required = false) JgInstallationNoticeDto model
) {
Page<JgInstallationNotice> page = new Page<>(current, size);
return ResponseHelper.buildResponse(jgInstallationNoticeServiceImpl.queryForJgInstallationNoticePage(page, model, type));
return ResponseHelper.buildResponse(iJgInstallationNoticeService.queryForJgInstallationNoticePage(page, model, type));
}
/**
* 列表全部数据查询
*
* @return
* 生成告知单
*/
@TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(httpMethod = "GET", value = "安装告知列表全部数据查询", notes = "安装告知列表全部数据查询")
@GetMapping(value = "/list")
public ResponseModel<List<JgInstallationNoticeDto>> selectForList() {
return ResponseHelper.buildResponse(jgInstallationNoticeServiceImpl.queryForJgInstallationNoticeList());
@GetMapping(value = "/generate-report")
public ResponseModel<String> generateReport(@RequestParam("sequenceNbr") Long sequenceNbr) {
return ResponseHelper.buildResponse(iJgInstallationNoticeService.generateInstallationNoticeReport(sequenceNbr));
}
}
......@@ -12,6 +12,7 @@ import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -302,4 +303,35 @@ public class ImageUtils {
}
}
/**
* 生成二维码(白色背景),并将其转换成base64
*
* @param text 二维码内容
* @param width 二维码宽度
* @param height 二维码高度
* @return base64
*/
public static String generateQRCode(String text, int width, int height) {
try {
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
BitMatrix bm = multiFormatWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 二维码颜色:黑色
int QRCOLOR = 0x201f1f;
//二维码背景颜色:白色
int BGWHITE = 0xFFFFFF;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
}
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "png", outputStream);
return Base64.getEncoder().encodeToString(outputStream.toByteArray());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.yeejoin.amos.boot.module.jg.biz.utils;
import com.aspose.words.Document;
import com.aspose.words.License;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@Slf4j
public class WordTemplateUtils {
public static final String BASE_PACKAGE_PATH = "/templates";
private static WordTemplateUtils wordTemplateUtils;
private final Configuration configuration;
private WordTemplateUtils() {
configuration = new Configuration(Configuration.VERSION_2_3_23);
}
public static synchronized WordTemplateUtils getInstance() {
if (wordTemplateUtils == null) {
wordTemplateUtils = new WordTemplateUtils();
}
return wordTemplateUtils;
}
/**
* 创建doc并写入内容
*
* @param templatePath doc模板文件路径
* @param dataMap 内容
* @param template 模板
* @return doc文件
*/
private File createDoc(String templatePath, Map<String, ?> dataMap, Template template) throws TemplateException, IOException {
// templatePath在后缀之前加上UUID是为了防止并发时多个线程使用同一个模板文件而导致生成的Word文档内容不一致
int i = templatePath.lastIndexOf(".");
templatePath = UUID.randomUUID() + templatePath.substring(i);
if (templatePath.endsWith(".ftl")) {
templatePath = templatePath.replace(".ftl", ".doc");
}
File docFile = new File(templatePath);
try (
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer writer = new OutputStreamWriter(Files.newOutputStream(docFile.toPath()), StandardCharsets.UTF_8)
) {
template.process(dataMap, writer);
}
return docFile;
}
public File fillAndConvertDocFile(String templatePath, String targetFileName, Map<String, ?> map, int saveFormat) throws Exception {
// 指定模板所在包路径
configuration.setClassForTemplateLoading(this.getClass(), BASE_PACKAGE_PATH);
// 获取模板, 生成Word文档
Template freemarkerTemplate = configuration.getTemplate(templatePath, "UTF-8");
map = new HashMap<>(map);
File docFile = createDoc(templatePath, map, freemarkerTemplate);
// 转换Word文档
File converedFile = converDocFile(docFile.getAbsolutePath(), targetFileName, saveFormat);
// 删除临时文件
Files.deleteIfExists(docFile.toPath());
return converedFile;
}
/**
* word转换
*
* @param docPath word文件路径
* @param targetPath 转换后文件路径
* @param saveFormat 目标文件类型 取自 com.aspose.words.SaveFormat
*/
private File converDocFile(String docPath, String targetPath, int saveFormat) throws Exception {
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getLicense()) {
throw new RuntimeException("验证License失败");
}
if (StringUtils.isEmpty(docPath)) {
throw new FileNotFoundException("文档文件不存在");
}
try (
InputStream inputStream = Files.newInputStream(Paths.get(docPath));
OutputStream outputStream = Files.newOutputStream(Paths.get(targetPath));
) {
File targetFile = new File(targetPath);
Document doc = new Document(inputStream);
doc.save(outputStream, saveFormat);
return targetFile;
}
}
/**
* 获取License
*
* @return boolean
*/
private boolean getLicense() {
boolean result = false;
try {
String s = "<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>";
ByteArrayInputStream is = new ByteArrayInputStream(s.getBytes());
License license = new License();
license.setLicense(is);
result = true;
} catch (Exception e) {
log.error("获取License失败", e);
}
return result;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment