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 { ...@@ -200,6 +200,9 @@ public class JgInstallationNoticeDto extends BaseDto {
@ApiModelProperty(value = "告知设备列表") @ApiModelProperty(value = "告知设备列表")
private List<Map<String, Object>> deviceList; private List<Map<String, Object>> deviceList;
@ApiModelProperty(value = "告知单PDF URL")
private String noticeReportUrl;
public String getFullAddress() { public String getFullAddress() {
return (StringUtils.isEmpty(this.provinceName) ? "" : this.provinceName) return (StringUtils.isEmpty(this.provinceName) ? "" : this.provinceName)
+ (StringUtils.isEmpty(this.cityName) ? "" : this.cityName) + (StringUtils.isEmpty(this.cityName) ? "" : this.cityName)
......
...@@ -335,4 +335,10 @@ public class JgInstallationNotice extends BaseEntity { ...@@ -335,4 +335,10 @@ public class JgInstallationNotice extends BaseEntity {
@TableField("instance_id") @TableField("instance_id")
private String instanceId; 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; ...@@ -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.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.dto.JgInstallationNoticeDto;
import com.yeejoin.amos.boot.module.jg.api.entity.JgInstallationNotice; import com.yeejoin.amos.boot.module.jg.api.entity.JgInstallationNotice;
...@@ -13,7 +14,7 @@ import java.util.Map; ...@@ -13,7 +14,7 @@ import java.util.Map;
* @author system_generator * @author system_generator
* @date 2023-12-12 * @date 2023-12-12
*/ */
public interface IJgInstallationNoticeService { public interface IJgInstallationNoticeService extends IService<JgInstallationNotice> {
/** /**
* 根据sequenceNbr查询 * 根据sequenceNbr查询
...@@ -56,4 +57,12 @@ public interface IJgInstallationNoticeService { ...@@ -56,4 +57,12 @@ public interface IJgInstallationNoticeService {
* @param submitType 保存类型 * @param submitType 保存类型
*/ */
void saveNotice(String submitType, Map<String, JgInstallationNoticeDto> model); void saveNotice(String submitType, Map<String, JgInstallationNoticeDto> model);
/**
* 打印告知单
*
* @param sequenceNbr 主键
* @return pdf文件路径
*/
String generateInstallationNoticeReport(Long sequenceNbr);
} }
...@@ -49,6 +49,19 @@ ...@@ -49,6 +49,19 @@
<select id="queryEquipInformation" resultType="java.util.Map"> <select id="queryEquipInformation" resultType="java.util.Map">
select select
isn.sequence_nbr AS sequenceNbr, 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_list AS equList,
ri.equ_category AS equCategory, ri.equ_category AS equCategory,
ri.EQU_DEFINE AS equDefine, ri.EQU_DEFINE AS equDefine,
......
...@@ -31,6 +31,12 @@ ...@@ -31,6 +31,12 @@
<version>1.10.1</version> <version>1.10.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>19.5jdk</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
......
package com.yeejoin.amos.boot.module.jg.biz.controller; package com.yeejoin.amos.boot.module.jg.biz.controller;
import cn.hutool.core.bean.BeanUtil; 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.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.controller.BaseController; 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.common.biz.utils.CommonResponseUtil;
import com.yeejoin.amos.boot.module.jg.api.dto.JgInstallationNoticeDto; 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.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.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
...@@ -24,8 +18,6 @@ import org.typroject.tyboot.core.restful.utils.ResponseHelper; ...@@ -24,8 +18,6 @@ import org.typroject.tyboot.core.restful.utils.ResponseHelper;
import org.typroject.tyboot.core.restful.utils.ResponseModel; import org.typroject.tyboot.core.restful.utils.ResponseModel;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
...@@ -41,7 +33,7 @@ import java.util.Objects; ...@@ -41,7 +33,7 @@ import java.util.Objects;
public class JgInstallationNoticeController extends BaseController { public class JgInstallationNoticeController extends BaseController {
@Autowired @Autowired
JgInstallationNoticeServiceImpl jgInstallationNoticeServiceImpl; private IJgInstallationNoticeService iJgInstallationNoticeService;
/** /**
* 新增 * 新增
...@@ -49,12 +41,12 @@ public class JgInstallationNoticeController extends BaseController { ...@@ -49,12 +41,12 @@ public class JgInstallationNoticeController extends BaseController {
* @return * @return
*/ */
@TycloudOperation(ApiLevel = UserType.AGENCY) @TycloudOperation(ApiLevel = UserType.AGENCY)
@PostMapping(value = "/save") @PostMapping(value = "/save")
@ApiOperation(httpMethod = "POST", value = "新增安装告知", notes = "新增安装告知") @ApiOperation(httpMethod = "POST", value = "新增安装告知", notes = "新增安装告知")
public ResponseModel<String> save(@RequestParam String submitType,@RequestBody Map<String, JgInstallationNoticeDto> model) { public ResponseModel<String> save(@RequestParam String submitType, @RequestBody Map<String, JgInstallationNoticeDto> model) {
jgInstallationNoticeServiceImpl.saveNotice(submitType, model); iJgInstallationNoticeService.saveNotice(submitType, model);
return ResponseHelper.buildResponse(""); return ResponseHelper.buildResponse("");
} }
/** /**
* 根据sequenceNbr更新 * 根据sequenceNbr更新
...@@ -69,7 +61,7 @@ public class JgInstallationNoticeController extends BaseController { ...@@ -69,7 +61,7 @@ public class JgInstallationNoticeController extends BaseController {
if (Objects.isNull(installationInfo)) { if (Objects.isNull(installationInfo)) {
throw new IllegalArgumentException("参数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 { ...@@ -81,7 +73,7 @@ public class JgInstallationNoticeController extends BaseController {
@DeleteMapping(value = "/delete") @DeleteMapping(value = "/delete")
@ApiOperation(httpMethod = "DELETE", value = "根据sequenceNbr删除安装告知", notes = "根据sequenceNbr删除安装告知") @ApiOperation(httpMethod = "DELETE", value = "根据sequenceNbr删除安装告知", notes = "根据sequenceNbr删除安装告知")
public ResponseModel<Boolean> deleteBySequenceNbr(@RequestParam(value = "sequenceNbr") Long[] 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 { ...@@ -94,7 +86,7 @@ public class JgInstallationNoticeController extends BaseController {
@ApiOperation(value = "根据sequenceNbr删除维保合同备案", notes = "根据sequenceNbr删除维保合同备案") @ApiOperation(value = "根据sequenceNbr删除维保合同备案", notes = "根据sequenceNbr删除维保合同备案")
public ResponseModel<Boolean> deleteForBatch(@RequestParam("sequenceNbrs") Long[] sequenceNbrs) { public ResponseModel<Boolean> deleteForBatch(@RequestParam("sequenceNbrs") Long[] sequenceNbrs) {
try { try {
return ResponseHelper.buildResponse(jgInstallationNoticeServiceImpl.deleteForBatch(sequenceNbrs)); return ResponseHelper.buildResponse(iJgInstallationNoticeService.deleteForBatch(sequenceNbrs));
} catch (Exception e) { } catch (Exception e) {
return CommonResponseUtil.failure(e.getMessage()); return CommonResponseUtil.failure(e.getMessage());
} }
...@@ -110,7 +102,7 @@ public class JgInstallationNoticeController extends BaseController { ...@@ -110,7 +102,7 @@ public class JgInstallationNoticeController extends BaseController {
@ApiOperation(httpMethod = "GET", value = "根据sequenceNbr查询单个安装告知", notes = "根据sequenceNbr查询单个安装告知") @ApiOperation(httpMethod = "GET", value = "根据sequenceNbr查询单个安装告知", notes = "根据sequenceNbr查询单个安装告知")
public ResponseModel<Map<String, public ResponseModel<Map<String,
Map<String, Object>>> selectOne(@RequestParam("sequenceNbr") Long sequenceNbr) { 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 { ...@@ -131,18 +123,16 @@ public class JgInstallationNoticeController extends BaseController {
@RequestBody(required = false) JgInstallationNoticeDto model @RequestBody(required = false) JgInstallationNoticeDto model
) { ) {
Page<JgInstallationNotice> page = new Page<>(current, size); 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) @TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(httpMethod = "GET", value = "安装告知列表全部数据查询", notes = "安装告知列表全部数据查询") @ApiOperation(httpMethod = "GET", value = "安装告知列表全部数据查询", notes = "安装告知列表全部数据查询")
@GetMapping(value = "/list") @GetMapping(value = "/generate-report")
public ResponseModel<List<JgInstallationNoticeDto>> selectForList() { public ResponseModel<String> generateReport(@RequestParam("sequenceNbr") Long sequenceNbr) {
return ResponseHelper.buildResponse(jgInstallationNoticeServiceImpl.queryForJgInstallationNoticeList()); return ResponseHelper.buildResponse(iJgInstallationNoticeService.generateInstallationNoticeReport(sequenceNbr));
} }
} }
...@@ -12,6 +12,7 @@ import java.awt.*; ...@@ -12,6 +12,7 @@ import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.*; import java.io.*;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -302,4 +303,35 @@ public class ImageUtils { ...@@ -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