Compare commits
3 Commits
0fdb14af2a
...
0ebf6d4258
Author | SHA1 | Date |
---|---|---|
|
0ebf6d4258 | |
|
9f3596abd6 | |
|
52abbf6a8f |
|
@ -0,0 +1,37 @@
|
|||
package com.dpkj.common.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
|
||||
/**
|
||||
* mvcConfig配置类
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @since 2023-05-23 15:24:43
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Configuration
|
||||
public class MvcConfig extends WebMvcConfigurationSupport {
|
||||
|
||||
/**
|
||||
* 添加资源过滤处理器
|
||||
* @param registry 资源处理器
|
||||
*/
|
||||
@Override
|
||||
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/**")
|
||||
.addResourceLocations("classpath:/static/");
|
||||
registry.addResourceHandler("/swagger-ui.html/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/");
|
||||
registry.addResourceHandler("/webjars/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
registry.addResourceHandler("/swagger-ui/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
|
||||
.resourceChain(false);
|
||||
|
||||
super.addResourceHandlers(registry);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
package com.dpkj.common.exception;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* controller控制器异常处理接口实现类
|
||||
* <p>其它module可以集成此类进行controller层的异常处理</p>
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RestControllerAdvice(annotations = {RestController.class, Controller.class})
|
||||
public class ControllerAdvice {
|
||||
|
||||
/**
|
||||
* controller方法中的参数校验失败,但是前提是要使用
|
||||
* #@Validated注解开启参数校验
|
||||
*
|
||||
* @param e 异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = MethodArgumentNotValidException.class)
|
||||
public Result<String> bindingException(MethodArgumentNotValidException e) {
|
||||
// 获得所有校验出错的返回集
|
||||
BindingResult bindingResult = e.getBindingResult();
|
||||
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
|
||||
// 循环获得所有校验异常的字段
|
||||
Map<String, String> fieldMap = new HashMap<>();
|
||||
for (FieldError fieldError : fieldErrors) {
|
||||
fieldMap.put(fieldError.getField(), fieldError.getDefaultMessage());
|
||||
}
|
||||
|
||||
String errMsg = fieldMap.values().toString().replaceAll("]", "").replaceAll("\\[", "");
|
||||
log.warn(errMsg);
|
||||
// 返回给前端
|
||||
return Result.error(errMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理空指针异常
|
||||
* @param nullPointerException 空指针异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = NullPointerException.class)
|
||||
public Result<String> nullPointException(NullPointerException nullPointerException) {
|
||||
log.error("空指针异常类型: {},信息: {}", nullPointerException.getClass(),nullPointerException.getMessage());
|
||||
return Result.error(ErrorEnum.NULL_POINTER_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 所有的运行时异常,抛出异常
|
||||
* @param throwable 异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = Throwable.class)
|
||||
public Result<String> handleException(Throwable throwable) {
|
||||
log.error("异常类型: {}, {}, 信息为: {}", throwable.getCause(), throwable.getClass(), throwable.getMessage());
|
||||
if (throwable instanceof RRException){
|
||||
RRException rrException = (RRException) throwable;
|
||||
return Result.error(rrException.getCode(), rrException.getMsg());
|
||||
}
|
||||
return Result.error(ErrorEnum.RUNTIME_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* http信息无可读
|
||||
* @param e 异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = HttpMessageNotReadableException.class)
|
||||
public Result<String> httpMessageNotReadAbleException(HttpMessageNotReadableException e){
|
||||
log.warn("异常类型: {} 无可读信息: {}", e.getClass(), e.getMessage());
|
||||
return Result.error(ErrorEnum.HTTP_MESSAGE_NOT_READABLE_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行时异常
|
||||
* @param e 运行异常对象
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = RuntimeException.class)
|
||||
public Result<String> runtimeException(RuntimeException e){
|
||||
log.error("运行时异常:{}", e.getMessage());
|
||||
if (e instanceof RRException){
|
||||
RRException rrException = (RRException) e;
|
||||
return Result.error(rrException.getCode(), rrException.getMsg());
|
||||
}
|
||||
return Result.error(ErrorEnum.RUNTIME_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求不支持
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
|
||||
public Result<String> httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){
|
||||
log.warn("暂不支持该请求: {}", e.getMessage());
|
||||
return Result.error("暂不支持此请求方式");
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数类型错误
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
public Result<String> methodArgument(MethodArgumentTypeMismatchException e){
|
||||
log.warn("参数发生错误: {}", e.getMessage());
|
||||
return Result.error("参数发生错误");
|
||||
}
|
||||
|
||||
/**
|
||||
* 缺少请求参数
|
||||
* @param e 缺少请求参数异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||||
public Result<String> exception(MissingServletRequestParameterException e){
|
||||
log.warn("缺少请求参数: {}", e.getMessage());
|
||||
return Result.error("缺少请求参数");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.dpkj.common.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
|
||||
/**
|
||||
* 错误返回枚举类
|
||||
*/
|
||||
@Getter
|
||||
public enum ErrorEnum implements ErrorInterface{
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
* 成功范围
|
||||
* @code 200
|
||||
* @apiNote 访问成功
|
||||
*/
|
||||
SUCCESS(200, "访问成功"),
|
||||
|
||||
/**
|
||||
* 系统异常
|
||||
* @code 500
|
||||
* @apiNote 系统异常
|
||||
*/
|
||||
FAIL(500, "系统异常"),
|
||||
|
||||
/**
|
||||
* 调用对象位空(null)
|
||||
* @code 10002
|
||||
* @apiNote 调用对象位空(null)
|
||||
*/
|
||||
NULL_POINTER_EXCEPTION(501, "调用对象位空(null)"),
|
||||
|
||||
/**
|
||||
* 运行时异常,
|
||||
* @code 10003
|
||||
* @apiNote 系统发生错误,请联系管理员
|
||||
*/
|
||||
RUNTIME_EXCEPTION(502, "系统发生错误,请联系管理员"),
|
||||
|
||||
/**
|
||||
* Http传入的参数没有可以读的数据
|
||||
* @code 10004
|
||||
* @apiNote 传入的数据不可读
|
||||
*/
|
||||
HTTP_MESSAGE_NOT_READABLE_EXCEPTION(503, "传入的数据不可读"),
|
||||
|
||||
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
;
|
||||
private final Integer code;
|
||||
private final String message;
|
||||
ErrorEnum(Integer code, String message){
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCode(){
|
||||
return this.code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage(){
|
||||
return this.message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.dpkj.common.exception;
|
||||
|
||||
/**
|
||||
* 错误枚举接口,所有的错误枚举都需要实现该接口,如果需要自定义
|
||||
* 错误信息,可通过实现该接口与RespBean进行使用
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @see com.dpkj.common.vo.Result
|
||||
* @since 2023-07-27 13:05:00
|
||||
*/
|
||||
public interface ErrorInterface {
|
||||
|
||||
/**
|
||||
* 获取响应码
|
||||
*/
|
||||
int getCode();
|
||||
|
||||
/**
|
||||
* 获取响应信息
|
||||
*/
|
||||
String getMessage();
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.dpkj.common.exception;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 总的异常,所有的自定义异常都需要继承类
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @since 2023-07-24 09:42:00
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class RRException extends RuntimeException{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String msg;
|
||||
private int code = 500;
|
||||
|
||||
public RRException(){
|
||||
super("系统错误");
|
||||
this.msg = "系统错误";
|
||||
}
|
||||
|
||||
public RRException(Throwable throwable){
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
public RRException(String msg) {
|
||||
super(msg);
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public RRException(String msg, Throwable e) {
|
||||
super(msg, e);
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public RRException(int code, String msg) {
|
||||
super(msg);
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
}
|
||||
public RRException(ErrorInterface error){
|
||||
super(error.getMessage());
|
||||
this.code = error.getCode();
|
||||
this.msg = error.getMessage();
|
||||
}
|
||||
|
||||
public RRException(int code,String msg, Throwable e) {
|
||||
super(msg, e);
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
package com.dpkj.common.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.context.Context;
|
||||
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
|
||||
import org.thymeleaf.templatemode.TemplateMode;
|
||||
import org.thymeleaf.templateresolver.StringTemplateResolver;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xhtmlrenderer.layout.SharedContext;
|
||||
import org.xhtmlrenderer.simple.Graphics2DRenderer;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 模板服务类
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-01-18 15:33:51
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class TemplateUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 生成小票图片
|
||||
*
|
||||
* @param data json数据,用来填充模板
|
||||
* @param template 模板(html字符串或者模板名称)
|
||||
* @param width 图片宽度
|
||||
* @param height 图片高度
|
||||
* @param saveDir 图片的保存路径,如果为空,那么不进行图片的保存
|
||||
* @return 图片字节数组
|
||||
*/
|
||||
public byte[] generateReceiptImage(JSONObject data, String template, int width, int height, String saveDir) {
|
||||
try {
|
||||
// 获取模板上下文
|
||||
Context context = this.getContext(data);
|
||||
|
||||
TemplateEngine templateEngine = new TemplateEngine();
|
||||
if (checkIsHtml(template)) {
|
||||
StringTemplateResolver resolver = new StringTemplateResolver();
|
||||
resolver.setTemplateMode("HTML");
|
||||
// 设置模板引擎使用这个自定义的模板解析器
|
||||
templateEngine.setTemplateResolver(resolver);
|
||||
}else {
|
||||
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
|
||||
resolver.setPrefix("classpath:/templates/");
|
||||
resolver.setSuffix(".html");
|
||||
resolver.setTemplateMode(TemplateMode.HTML);
|
||||
resolver.setCacheable(true);
|
||||
resolver.setApplicationContext(new AnnotationConfigReactiveWebApplicationContext());
|
||||
templateEngine.setTemplateResolver(resolver);
|
||||
}
|
||||
|
||||
// 渲染模板
|
||||
String html = templateEngine.process(template, context);
|
||||
|
||||
BufferedImage image = this.generate(html, width, height);
|
||||
|
||||
// 保存图片
|
||||
if (saveDir != null && !"".equals(saveDir)) {
|
||||
String outputPath = saveDir + "\\genera_image_" + System.currentTimeMillis() + ".png";
|
||||
ImageIO.write(image, "PNG", new File(outputPath));
|
||||
}
|
||||
|
||||
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "PNG", byteOutputStream);
|
||||
return byteOutputStream.toByteArray();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RRException("图片打印失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成图片
|
||||
* @param html html内容
|
||||
*/
|
||||
private BufferedImage generate(String html, int width, int height){
|
||||
try {
|
||||
// 转换为xhtml
|
||||
String xhtml = this.htmlToXhtml(html);
|
||||
|
||||
// 转换为document
|
||||
Document document = this.xhtmlToDocument(xhtml);
|
||||
|
||||
// 生成图片
|
||||
return createImageToDocument(document, width, height);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RRException("图片打印失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过JsonObject进行context内容填充
|
||||
* @param data jsonObject
|
||||
* @return context
|
||||
*/
|
||||
private Context getContext(JSONObject data) {
|
||||
// 创建Thymeleaf上下文
|
||||
Context context = new Context();
|
||||
Set<String> keys = data.keySet();
|
||||
for (String key : keys) {
|
||||
// 判单是否有图片生成,统一后面采用的是_2base64Type
|
||||
String[] split = key.split("_");
|
||||
if (split.length > 1 && split[1].equals("2base64Type")) {
|
||||
int width = split.length > 2 ? Integer.parseInt(split[2]) : 100;
|
||||
int height = split.length > 3 ? Integer.parseInt(split[3]) : 100;
|
||||
// 如果是图片类型,需要进行base64转换
|
||||
String base64 = this.generateQRCode(String.valueOf(data.get(key)), width, height);
|
||||
context.setVariable(split[0], "data:image/jpeg;base64," + base64);
|
||||
} else {
|
||||
// 普通字段直接设置
|
||||
context.setVariable(key, data.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据内容生成二维码
|
||||
* @param content 转换内容
|
||||
*/
|
||||
private String generateQRCode(String content, int width, int height) {
|
||||
try {
|
||||
Map<EncodeHintType, Object> hints = new HashMap<>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 设置字符编码为 UTF-8
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); // 设置纠错级别
|
||||
|
||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
||||
BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
|
||||
BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
qrImage.createGraphics();
|
||||
|
||||
Graphics2D graphics = (Graphics2D) qrImage.getGraphics();
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.fillRect(0, 0, width, height);
|
||||
graphics.setColor(Color.BLACK);
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
if (bitMatrix.get(i, j)) {
|
||||
graphics.fillRect(i, j, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(qrImage, "png", baos);
|
||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
||||
}catch (Exception e){
|
||||
log.error("二维码生成失败");
|
||||
throw new RRException("二维码生成失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xhtml 转换为 Document
|
||||
* @param xhtml xhtml
|
||||
* @return document
|
||||
* @throws Exception e
|
||||
*/
|
||||
private Document xhtmlToDocument(String xhtml) throws Exception {
|
||||
// 创建DocumentBuilder
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setValidating(false);
|
||||
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
|
||||
// 解析XHTML字符串为Document
|
||||
return builder.parse(new ByteArrayInputStream(xhtml.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换,将html转换为xhtml
|
||||
* @param html html内容
|
||||
* @return xhtml
|
||||
*/
|
||||
private String htmlToXhtml(String html) {
|
||||
org.jsoup.nodes.Document doc = Jsoup.parse(html);
|
||||
doc.outputSettings()
|
||||
.syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml)
|
||||
.charset(StandardCharsets.UTF_8);
|
||||
|
||||
// 不使用外部DTD
|
||||
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
|
||||
"<head>\n" +
|
||||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n" +
|
||||
"<style type=\"text/css\">\n" +
|
||||
"body { font-family: SimSun, serif; }\n" +
|
||||
"</style>\n" +
|
||||
"</head>\n" +
|
||||
"<body>\n" +
|
||||
doc.body().html() +
|
||||
"\n</body>\n" +
|
||||
"</html>";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过document转换为图片
|
||||
* @param document doc
|
||||
* @param width 图片的宽度
|
||||
* @param height 图片的高度
|
||||
* @return bufferedImage
|
||||
*/
|
||||
private BufferedImage createImageToDocument(Document document, int width, int height) {
|
||||
try {
|
||||
// 创建Dimension对象
|
||||
Dimension dimension = new Dimension(width, height);
|
||||
|
||||
// 创建图片
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D graphics = (Graphics2D) image.getGraphics();
|
||||
|
||||
// 设置白色背景
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.fillRect(0, 0, width, height);
|
||||
|
||||
// 设置渲染提示
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
|
||||
// 创建渲染器
|
||||
Graphics2DRenderer renderer = new Graphics2DRenderer();
|
||||
renderer.setDocument(document, null);
|
||||
|
||||
// 设置渲染参数
|
||||
SharedContext sharedContext = renderer.getSharedContext();
|
||||
sharedContext.setInteractive(false);
|
||||
sharedContext.setDPI(256f);
|
||||
|
||||
// 使用系统默认字体,假设系统默认字体支持UTF - 8
|
||||
Font font = new Font(Font.DIALOG, Font.PLAIN, 20);
|
||||
graphics.setFont(font);
|
||||
|
||||
// 使用Dimension对象进行布局
|
||||
renderer.layout(graphics, dimension);
|
||||
renderer.render(graphics);
|
||||
|
||||
graphics.dispose();
|
||||
return image;
|
||||
} catch (Exception e) {
|
||||
throw new RRException("渲染图片失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验这个模板内容是不是html字符串,而非模板名称
|
||||
* @param template template
|
||||
* @return 是否是html字符串
|
||||
*/
|
||||
private boolean checkIsHtml(String template){
|
||||
try {
|
||||
String pattern = "<(\"[^\"]*\"|'[^']*'|[^'\">])*>";
|
||||
Pattern r = Pattern.compile(pattern);
|
||||
return r.matcher(template).find();
|
||||
}catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将document对象转换为字符串
|
||||
* @param doc document
|
||||
* @return document转换为的字符串
|
||||
*/
|
||||
private String documentToString(Document doc) {
|
||||
try {
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Transformer transformer = tf.newTransformer();
|
||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
|
||||
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
transformer.transform(new DOMSource(doc), new StreamResult(writer));
|
||||
return writer.getBuffer().toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.dpkj.common.vo;
|
||||
|
||||
import com.dpkj.common.constant.CommonConst;
|
||||
import com.dpkj.common.exception.ErrorEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -69,6 +70,14 @@ public class Result<T> implements Serializable {
|
|||
return error(CommonConst.SC_500, msg, null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(ErrorEnum errorEnum) {
|
||||
return error(errorEnum.getCode(), errorEnum.getMessage(), null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(int code, String message) {
|
||||
return error(code, message, null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(int code, String msg, T data) {
|
||||
Result<T> r = new Result<T>();
|
||||
r.setCode(code);
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>挂号单</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="font-size: 24px;">
|
||||
<div style="">
|
||||
<div style="text-align: center; font-size: 36px; font-weight: 700;"><span th:text="${hospitalName}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; font-size: 26px;">****<span th:text="${registeTerminalName}"></span></span>****</div>
|
||||
<div style="text-align: center; font-weight: 700; margin-bottom: -5px;">-----------------------------------------------------------------------------</div>
|
||||
<div style="text-align: center; font-size: 36px; font-weight: 700;"><span th:text="${registeType}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; margin-top: -7px;">-----------------------------------------------------------------------------</div>
|
||||
</div>
|
||||
<div style="font-weight: 700;">
|
||||
<div style="margin-left: 59px;">姓  名:<span th:text="${name}"></span></div>
|
||||
<div style="margin-left: 59px;">性  别:<span th:text="${gender}"></span></div>
|
||||
<div style="margin-left: 59px;">年  龄:<span th:text="${age}"></span></div>
|
||||
<div style="margin-left: 59px;">出生日期:<span th:text="${birthDate}"></span></div>
|
||||
<div style="margin-left: 59px;">卡  号:<span th:text="${cardNumber}"></span></div>
|
||||
<div style="margin-left: 59px;">门 诊 号:<span th:text="${outpatientNumber}"></span></div>
|
||||
<div style="margin-left: 59px;">就诊科室:<span th:text="${department}"></span></div>
|
||||
<div style="margin-left: 59px;">出诊级别:<span th:text="${visitLevel}"></span></div>
|
||||
<div style="margin-left: 59px;">就诊医生:<span th:text="${doctor}"></span></div>
|
||||
<div style="margin-left: 59px;">号  序:<span th:text="${sequence}"></span></div>
|
||||
<div style="margin-left: 59px;">挂号日期:<span th:text="${registerDate}"></span></div>
|
||||
<div style="margin-left: 59px; font-size: 31px; ">总费用:<span th:text="${totalFee}"></span> 元</div>
|
||||
<div style="margin-left: 59px;">支付方式:<span th:text="${paymentMethod}"></span></div>
|
||||
<div style="margin-left: 59px;">订 单 号:<span th:text="${orderNumber}"></span></div>
|
||||
<div style="margin-left: 59px;">交易流水:<span th:text="${transactionNumber}"></span></div>
|
||||
<img style="margin-left: 35px; margin-top: -8px; margin-bottom: -8px;" th:src="${qrCodeBase64}" alt="QR Code"/>
|
||||
</div>
|
||||
<div>
|
||||
<div style="margin-top: -20px; text-align: center; font-weight: 700;">-----------------------------------------------------------------------------</div>
|
||||
<div style="margin-left: 59px; font-weight: 700;">备注(REFERENCE):凭此条退费,请妥善保管!</div>
|
||||
<div style="margin-left: 59px;">终 端 号:<span th:text="${terminalNumber}"></span></div>
|
||||
<div style="margin-left: 59px;">打印时间:<span th:text="${printTime}"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue