Commit b67f49896fee23e920482db8f0a5b8bd4c63dc02

Authored by 杨鸣坤
1 parent 8579e249

楚江ERP:打印,增加规格导出

... ... @@ -40,6 +40,13 @@
40 40 <version>2.11.0</version>
41 41 </dependency>
42 42
  43 + <!-- JLaTeXMath 用于将LaTeX渲染为图片 -->
  44 + <dependency>
  45 + <groupId>org.scilab.forge</groupId>
  46 + <artifactId>jlatexmath</artifactId>
  47 + <version>1.0.7</version>
  48 + </dependency>
  49 +
43 50 <!-- Lombok(可选) -->
44 51 <dependency>
45 52 <groupId>org.projectlombok</groupId>
... ...
... ... @@ -165,7 +165,7 @@ public class QueryContractDistributorStandardBo extends BaseBo<ContractDistribut
165 165 * 发货状态
166 166 */
167 167 @ApiModelProperty(value = "发货状态")
168   - private String shippingStatus;
  168 + private String shippingStatusName;
169 169
170 170 public QueryContractDistributorStandardBo() {
171 171
... ...
... ... @@ -38,6 +38,7 @@ import com.lframework.xingyun.sc.entity.ContractFramework;
38 38 import com.lframework.xingyun.sc.service.contract.ContractDistributorLineService;
39 39 import com.lframework.xingyun.sc.service.contract.ContractDistributorStandardService;
40 40 import com.lframework.xingyun.sc.service.contract.ContractFrameworkService;
  41 +import com.lframework.xingyun.sc.utils.LatexFormulaExcelExporterUtil;
41 42 import com.lframework.xingyun.sc.vo.contract.createVo.CreateContractDistributorStandardVo;
42 43 import com.lframework.xingyun.sc.vo.contract.queryVo.QueryContractDistributorStandardVo;
43 44 import com.lframework.xingyun.sc.vo.contract.updateVo.UpdateContractDistributorStandardVo;
... ... @@ -66,6 +67,7 @@ import java.net.URLEncoder;
66 67 import java.time.LocalDate;
67 68 import java.time.format.DateTimeFormatter;
68 69 import java.util.*;
  70 +import java.util.List;
69 71 import java.util.function.Function;
70 72 import java.util.stream.Collectors;
71 73
... ... @@ -139,6 +141,7 @@ public class ContractDistributorStandardController extends DefaultBaseController
139 141 }
140 142
141 143 vo.setDeptIdList(sysDeptList.stream().map(SysDept::getId).collect(Collectors.toList()));
  144 + vo.setCreateById(SecurityUtil.getCurrentUser().getId());
142 145 }
143 146
144 147 PageResult<ContractDistributorStandard> pageResult = contractDistributorStandardService.query(getPageIndex(vo), getPageSize(vo), vo);
... ... @@ -443,6 +446,7 @@ public class ContractDistributorStandardController extends DefaultBaseController
443 446 Wrapper<ContractFramework> contractFrameworkWrapper = Wrappers.lambdaQuery(ContractFramework.class)
444 447 .eq(ContractFramework::getCustomerId, data.getBuyer())
445 448 .ge(ContractFramework::getValidityTime, LocalDate.now())
  449 + .ge(ContractFramework::getCompany, data.getSupplier())
446 450 .eq(ContractFramework::getHasFrameworkAgreement, true);
447 451 List<ContractFramework> contractFrameworkList = contractFrameworkService.list(contractFrameworkWrapper);
448 452 List<String> productNameList = new ArrayList<>();
... ... @@ -483,7 +487,38 @@ public class ContractDistributorStandardController extends DefaultBaseController
483 487
484 488 setCellValue(sheet, startRow, 1, contractDistributorLineBo.getProductName()); // B列
485 489 setCellValue(sheet, startRow, 4, contractDistributorLineBo.getBrand()); // D列
486   -// setCellValue(sheet, startRow, 5, contractDistributorLineBo.getSpecification()); // E列
  490 +// setCellValue(sheet, startRow, 5, convertToSimpleLatex(components)); // E列
  491 +
  492 + List<LatexFormulaExcelExporterUtil.FormulaComponent> formulaComponentList = new ArrayList<>(3);
  493 + if (contractDistributorLineBo.getThickness() != null) {
  494 + LatexFormulaExcelExporterUtil.FormulaComponent formulaComponent = new LatexFormulaExcelExporterUtil.FormulaComponent();
  495 + formulaComponent.setBase(contractDistributorLineBo.getThickness());
  496 + formulaComponent.setSup(contractDistributorLineBo.getThicknessTolPos());
  497 + formulaComponent.setSub(contractDistributorLineBo.getThicknessTolNeg());
  498 + formulaComponentList.add(formulaComponent);
  499 + }
  500 +
  501 + if (contractDistributorLineBo.getWidth() != null) {
  502 + LatexFormulaExcelExporterUtil.FormulaComponent formulaComponent = new LatexFormulaExcelExporterUtil.FormulaComponent();
  503 + formulaComponent.setBase(contractDistributorLineBo.getWidth());
  504 + formulaComponent.setSup(contractDistributorLineBo.getWidthTolPos());
  505 + formulaComponent.setSub(contractDistributorLineBo.getWidthTolNeg());
  506 + formulaComponentList.add(formulaComponent);
  507 + }
  508 +
  509 + if (contractDistributorLineBo.getLength() != null) {
  510 + LatexFormulaExcelExporterUtil.FormulaComponent formulaComponent = new LatexFormulaExcelExporterUtil.FormulaComponent();
  511 + formulaComponent.setBase(contractDistributorLineBo.getLength());
  512 + formulaComponent.setSup(contractDistributorLineBo.getLengthTolPos());
  513 + formulaComponent.setSub(contractDistributorLineBo.getLengthTolNeg());
  514 + formulaComponentList.add(formulaComponent);
  515 + }
  516 +
  517 + String latex = LatexFormulaExcelExporterUtil.convertToLatex(formulaComponentList);
  518 + if (StringUtils.isNotBlank(latex)) {
  519 + LatexFormulaExcelExporterUtil.insertLatexImageToCell(workbook, sheet, latex, startRow, 5);// E列
  520 + }
  521 +
487 522 setCellValue(sheet, startRow, 6, contractDistributorLineBo.getStatus()); // F列
488 523 setCellValue(sheet, startRow, 7, contractDistributorLineBo.getQuantity()); // G列
489 524 setCellValue(sheet, startRow, 9, contractDistributorLineBo.getUnitPrice()); // I列
... ...
  1 +package com.lframework.xingyun.sc.utils;
  2 +
  3 +import lombok.Data;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.apache.commons.collections4.CollectionUtils;
  6 +import org.apache.poi.ss.usermodel.*;
  7 +import org.scilab.forge.jlatexmath.TeXConstants;
  8 +import org.scilab.forge.jlatexmath.TeXFormula;
  9 +import org.scilab.forge.jlatexmath.TeXIcon;
  10 +
  11 +import javax.imageio.ImageIO;
  12 +import javax.swing.*;
  13 +import java.awt.*;
  14 +import java.awt.Color;
  15 +import java.awt.image.BufferedImage;
  16 +import java.io.ByteArrayOutputStream;
  17 +import java.io.IOException;
  18 +import java.math.BigDecimal;
  19 +import java.util.List;
  20 +
  21 +@Slf4j
  22 +public class LatexFormulaExcelExporterUtil {
  23 +
  24 + public static String convertToLatex(List<FormulaComponent> componentList) {
  25 + if (CollectionUtils.isEmpty(componentList)) {
  26 + return "";
  27 + }
  28 +
  29 +
  30 + StringBuilder latex = new StringBuilder();
  31 + latex.append("\\mathbf{");
  32 + for (int i = 0; i < componentList.size(); i++) {
  33 + FormulaComponent comp = componentList.get(i);
  34 + if (comp.getBase() == null) {
  35 + continue;
  36 + }
  37 +
  38 + latex.append(comp.getBase().stripTrailingZeros());
  39 + if (comp.getSup() != null) {
  40 + latex.append("^{+").append(comp.getSup().stripTrailingZeros()).append("}");
  41 + }
  42 +
  43 + if (comp.getSub() != null) {
  44 + latex.append("_{-").append(comp.getSub().stripTrailingZeros()).append("}");
  45 + }
  46 +
  47 + if (i < componentList.size() - 1) {
  48 + latex.append(" \\times ");
  49 + }
  50 + }
  51 +
  52 + latex.append("}");
  53 + return latex.toString();
  54 + }
  55 +
  56 + /**
  57 + * 将LaTeX公式字符串渲染为图片字节数组
  58 + *
  59 + * @param latex LaTeX公式字符串,如 "\\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}"
  60 + * @param fontSize 渲染的字体大小
  61 + * @return 图片的字节数组 (PNG格式)
  62 + * @throws IOException 如果渲染或转换失败
  63 + */
  64 + public static byte[] latexToImageBytes(String latex, int fontSize) throws IOException {
  65 + try {
  66 + // 1. 创建TeXFormula对象,解析LaTeX字符串
  67 + TeXFormula formula = new TeXFormula(latex);
  68 +
  69 + // 2. 创建TeXIcon,指定样式和大小
  70 + TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, fontSize);
  71 +
  72 + // 3. 创建一个BufferedImage,用于绘制公式
  73 + BufferedImage image = new BufferedImage(
  74 + icon.getIconWidth(),
  75 + icon.getIconHeight(),
  76 + BufferedImage.TYPE_INT_ARGB
  77 + );
  78 +
  79 + // 4. 获取Graphics2D进行绘制
  80 + Graphics2D g2 = image.createGraphics();
  81 +
  82 + // 设置最高质量的渲染提示
  83 + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  84 + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
  85 + g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
  86 + g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
  87 + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
  88 + g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
  89 + g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
  90 + g2.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
  91 +
  92 + // 设置背景为白色
  93 + g2.setColor(Color.WHITE);
  94 + g2.fillRect(0, 0, icon.getIconWidth(), icon.getIconHeight());
  95 +
  96 + // 设置公式颜色为黑色
  97 + JLabel label = new JLabel();
  98 + label.setForeground(Color.BLACK);
  99 +
  100 + // 5. 将公式绘制到BufferedImage上
  101 + icon.paintIcon(label, g2, 0, 0);
  102 + g2.dispose();
  103 +
  104 + // 6. 将BufferedImage转换为字节数组
  105 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
  106 + ImageIO.write(image, "png", baos);
  107 +
  108 + return baos.toByteArray();
  109 +
  110 + } catch (Exception e) {
  111 + throw new IOException("LaTeX渲染失败: " + e.getMessage(), e);
  112 + }
  113 + }
  114 +
  115 + /**
  116 + * 将LaTeX公式作为图片插入到指定单元格
  117 + */
  118 + public static void insertLatexImageToCell(Workbook workbook, Sheet sheet, String latex, int rowIndex, int colIndex) throws IOException {
  119 + // 1. 将LaTeX渲染为图片字节
  120 + byte[] imageBytes = latexToImageBytes(latex, 48);
  121 +
  122 + // 2. 将图片添加到工作簿
  123 + int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);
  124 +
  125 + // 3. 创建绘图对象
  126 + Drawing<?> drawing = sheet.createDrawingPatriarch();
  127 +
  128 + // 4. 创建锚点,确定图片位置
  129 + ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
  130 + anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
  131 + anchor.setCol1(colIndex); // C列 (从0开始计数)
  132 + anchor.setRow1(rowIndex); // 当前数据行 (表头在第0行)
  133 + anchor.setCol2(colIndex + 1); // 结束于D列
  134 + anchor.setRow2(rowIndex + 1); // 结束于下一行
  135 +
  136 + // 设置较小的起始偏移
  137 + anchor.setDx1(50); // 水平偏移(建议值:10-100)
  138 + anchor.setDy1(25); // 垂直偏移(建议值:10-50)
  139 +
  140 +
  141 + // 5. 创建图片并插入
  142 + Picture pict = drawing.createPicture(anchor, pictureIdx);
  143 +
  144 + // 6. 自动调整图片大小以适应单元格 (可选)
  145 + // 取消注释此行使图片自动适应锚点区域
  146 +// pict.resize(0.95); // 缩小到90%,自然产生边距
  147 + }
  148 +
  149 + @Data
  150 + public static class FormulaComponent {
  151 + BigDecimal base;
  152 + BigDecimal sup;
  153 + BigDecimal sub;
  154 + }
  155 +}
... ...
... ... @@ -79,5 +79,8 @@ public class QueryContractDistributorStandardVo extends PageVo implements BaseVo
79 79 */
80 80 @ApiModelProperty(value = "标准合同是否审核完成(AUDIT:审核中,PASS:审核通过,REFUSE:已驳回,CANCEL:已取消)")
81 81 private String standardApproved;
  82 +
  83 + @ApiModelProperty("创建人ID")
  84 + private String createById;
82 85 }
83 86
... ...
... ... @@ -143,15 +143,18 @@
143 143 </if>
144 144 <if test="vo.status != null">
145 145 AND tb.status LIKE CONCAT(#{vo.status}, '%')
  146 + <if test="vo.status == 'DRAFT' and vo.createById != null">
  147 + AND tb.create_by_id = #{vo.createById}
  148 + </if>
146 149 </if>
147 150 <if test="vo.type != null">
148 151 AND tb.type = #{vo.type}
149 152 </if>
150 153 <if test="vo.formalApproved != null">
151   - AND tb.formalApproved = #{vo.formalApproved}
  154 + AND tb.formal_approved = #{vo.formalApproved}
152 155 </if>
153 156 <if test="vo.standardApproved != null">
154   - AND tb.standardApproved = #{vo.standardApproved}
  157 + AND tb.standard_approved = #{vo.standardApproved}
155 158 </if>
156 159 </where>
157 160 order by tb.create_time desc
... ...