package com.ruoyi.stock.word;
|
|
import com.ruoyi.basic.pojo.Product;
|
import com.ruoyi.basic.service.IProductService;
|
import com.ruoyi.stock.dto.StockInRecordDto;
|
import org.apache.poi.xwpf.usermodel.*;
|
import org.apache.poi.xwpf.usermodel.XWPFTable.XWPFBorderType;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Component;
|
|
import java.io.File;
|
import java.io.FileOutputStream;
|
import java.io.IOException;
|
import java.math.BigDecimal;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
|
/**
|
* 磅单Word文档生成器
|
*/
|
@Component
|
public class WeighbridgeDocGenerator {
|
|
@Value("${file.upload-dir}")
|
private String uploadDir;
|
|
@Autowired
|
private IProductService productService;
|
|
/**
|
* 生成磅单Word文档
|
* @param dto 入库记录DTO
|
* @return 文件保存的绝对路径,生成失败返回null
|
*/
|
public String generateWeighbridgeDoc(StockInRecordDto dto) {
|
// 参数校验
|
if (dto == null) {
|
return null;
|
}
|
|
FileOutputStream out = null;
|
XWPFDocument document = null;
|
|
try {
|
// 创建新文档
|
document = new XWPFDocument();
|
|
// 构建文档内容
|
buildDocumentContent(document, dto);
|
|
// 构建文件保存路径(绝对路径)
|
String absolutePath = buildAbsoluteFilePath(dto);
|
File file = new File(absolutePath);
|
|
// 确保目录存在
|
file.getParentFile().mkdirs();
|
|
// 写入文件
|
out = new FileOutputStream(file);
|
document.write(out);
|
out.flush();
|
|
// 返回绝对路径(用于数据库存储)
|
return absolutePath;
|
|
} catch (Exception e) {
|
e.printStackTrace();
|
return null;
|
} finally {
|
// 关闭资源
|
try {
|
if (out != null) {
|
out.close();
|
}
|
if (document != null) {
|
document.close();
|
}
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
|
/**
|
* 构建文档内容
|
*/
|
private void buildDocumentContent(XWPFDocument document, StockInRecordDto dto) {
|
// 1. 添加标题 "磅码单" - 使用黑体
|
XWPFParagraph titlePara = document.createParagraph();
|
titlePara.setAlignment(ParagraphAlignment.CENTER);
|
titlePara.setSpacingAfter(200);
|
|
XWPFRun titleRun = titlePara.createRun();
|
titleRun.setText("磅码单");
|
titleRun.setBold(true);
|
titleRun.setFontSize(28);
|
titleRun.setFontFamily("黑体");
|
|
// 2. 空一行
|
document.createParagraph();
|
|
// 3. 头部信息(年月日和计量单位合并在一行)- 使用宋体
|
XWPFParagraph headerPara = document.createParagraph();
|
headerPara.setSpacingAfter(200);
|
XWPFRun headerRun = headerPara.createRun();
|
|
// 格式化日期为 yyyy-MM-dd
|
String weighDate = "";
|
if (dto.getWeighingDate() != null) {
|
try {
|
// 假设 weighingDate 是 LocalDateTime 类型
|
weighDate = dto.getWeighingDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
} catch (Exception e) {
|
// 如果是字符串类型,尝试转换
|
weighDate = dto.getWeighingDate().toString();
|
if (weighDate.length() > 10) {
|
weighDate = weighDate.substring(0, 10);
|
}
|
}
|
}
|
|
headerRun.setText("年月日:" + weighDate + " 计量单位:(吨)");
|
headerRun.setFontSize(12);
|
headerRun.setFontFamily("宋体");
|
|
// 4. 创建主表格 - 4行6列(表头1行+数据1行+合计1行+空行1行)
|
XWPFTable table = document.createTable(4, 6);
|
|
// 设置表格宽度
|
table.setWidth("100%");
|
|
// 设置表格边框加粗(边框宽度设为2)
|
table.setInsideHBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
|
table.setInsideVBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
|
table.setTopBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
|
table.setBottomBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
|
table.setLeftBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
|
table.setRightBorder(XWPFBorderType.SINGLE, 2, 0, "000000");
|
|
// 设置行高
|
table.getRow(0).setHeight(400);
|
table.getRow(1).setHeight(400);
|
table.getRow(2).setHeight(400);
|
table.getRow(3).setHeight(400);
|
|
// 设置表头 - 使用黑体加粗
|
String[] headers = {"车号", "品名", "毛重", "皮重", "净重", "备注"};
|
XWPFTableRow headerRow = table.getRow(0);
|
for (int i = 0; i < headers.length; i++) {
|
XWPFTableCell cell = headerRow.getCell(i);
|
cell.setText(headers[i]);
|
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
|
|
XWPFParagraph cellPara = cell.getParagraphs().get(0);
|
cellPara.setAlignment(ParagraphAlignment.CENTER);
|
XWPFRun cellRun = cellPara.getRuns().get(0);
|
cellRun.setBold(true);
|
cellRun.setFontSize(12);
|
cellRun.setFontFamily("黑体");
|
}
|
|
// 设置数据行 - 使用宋体
|
XWPFTableRow dataRow = table.getRow(1);
|
String netWeight = dto.getNetWeight() != null ? dto.getNetWeight().toString() : "";
|
String grossWeight = dto.getGrossWeight() != null ? dto.getGrossWeight().toString() : "";
|
String tareWeight = dto.getTareWeight() != null ? dto.getTareWeight().toString() : "";
|
|
String[] data = {
|
dto.getLicensePlateNo() != null ? dto.getLicensePlateNo() : "",
|
getProductModelName(dto.getProductId()),
|
grossWeight + "t",
|
tareWeight + "t",
|
netWeight + "t",
|
dto.getRemark() != null ? dto.getRemark() : ""
|
};
|
|
for (int i = 0; i < data.length; i++) {
|
XWPFTableCell cell = dataRow.getCell(i);
|
cell.setText(data[i]);
|
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
|
|
XWPFParagraph cellPara = cell.getParagraphs().get(0);
|
cellPara.setAlignment(ParagraphAlignment.CENTER);
|
XWPFRun cellRun = cellPara.getRuns().get(0);
|
cellRun.setFontSize(12);
|
cellRun.setFontFamily("宋体");
|
}
|
|
// 合计行 - 第3行
|
XWPFTableRow totalRow = table.getRow(2);
|
|
// 第1列显示"合计(大写)"
|
XWPFTableCell totalLabelCell = totalRow.getCell(0);
|
totalLabelCell.setText("合计(大写)");
|
totalLabelCell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
|
XWPFParagraph totalLabelPara = totalLabelCell.getParagraphs().get(0);
|
totalLabelPara.setAlignment(ParagraphAlignment.CENTER);
|
XWPFRun totalLabelRun = totalLabelPara.getRuns().get(0);
|
totalLabelRun.setBold(true);
|
totalLabelRun.setFontSize(12);
|
totalLabelRun.setFontFamily("宋体");
|
|
|
XWPFTableCell contentCell = totalRow.getCell(1);
|
String netWeightChinese = ChineseNumberUtil.numberToChinese(
|
dto.getNetWeight() != null ? dto.getNetWeight() : BigDecimal.ZERO
|
);
|
contentCell.setText(netWeightChinese + "吨");
|
contentCell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
|
XWPFParagraph contentPara = contentCell.getParagraphs().get(0);
|
contentPara.setAlignment(ParagraphAlignment.LEFT);
|
XWPFRun contentRun = contentPara.getRuns().get(0);
|
contentRun.setFontSize(12);
|
contentRun.setFontFamily("宋体");
|
|
// 合并第3-6列到第2列
|
for (int i = 2; i < 6; i++) {
|
XWPFTableCell cell = totalRow.getCell(i);
|
// 设置这些单元格为合并状态(继承自第2列)
|
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge.CONTINUE);
|
}
|
|
// 6. 创建过磅员行(单独一行,左对齐)
|
XWPFParagraph operatorPara = document.createParagraph();
|
operatorPara.setSpacingAfter(100);
|
operatorPara.setAlignment(ParagraphAlignment.LEFT);
|
XWPFRun operatorRun = operatorPara.createRun();
|
String operator = dto.getWeighingOperator() != null ? dto.getWeighingOperator() : "";
|
operatorRun.setText("过磅员:" + operator);
|
operatorRun.setFontSize(8);
|
operatorRun.setFontFamily("宋体");
|
|
}
|
|
/**
|
* 构建文件保存的绝对路径
|
*/
|
private String buildAbsoluteFilePath(StockInRecordDto dto) {
|
LocalDateTime now = LocalDateTime.now();
|
String year = String.valueOf(now.getYear());
|
String month = String.format("%02d", now.getMonthValue());
|
String day = String.format("%02d", now.getDayOfMonth());
|
|
// 文件名格式:磅单_车牌号_年月日时分秒.docx
|
String fileName = String.format("磅单_%s_%s.docx",
|
dto.getLicensePlateNo() != null ? dto.getLicensePlateNo() : "未知车牌",
|
now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
|
|
return uploadDir + File.separator + year + File.separator + month + File.separator + day + File.separator + fileName;
|
}
|
|
/**
|
* 获取产品型号名称
|
*/
|
private String getProductModelName(Long productModelId) {
|
if (productModelId == null) {
|
return "未知产品";
|
}
|
try {
|
Product product = productService.getById(productModelId);
|
return product != null ? product.getProductName() : "未知产品";
|
} catch (Exception e) {
|
e.printStackTrace();
|
return "未知产品";
|
}
|
}
|
}
|