2024-10-11 16:26:38 +08:00
|
|
|
|
import fs, { writeFileSync } from "fs";
|
2024-09-23 16:23:39 +08:00
|
|
|
|
import path from "path";
|
2024-10-09 17:11:41 +08:00
|
|
|
|
import ExcelJS from "exceljs";
|
2024-10-11 16:26:38 +08:00
|
|
|
|
import { PDFDocument, StandardFonts, rgb } from "pdf-lib";
|
2024-09-23 16:23:39 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 读取指定路径下的所有.stl文件
|
|
|
|
|
* @param dirPath 要搜索的目录路径
|
|
|
|
|
* @returns 返回包含所有.stl文件名的数组
|
|
|
|
|
*/
|
|
|
|
|
export const findSTLFiles = (dirPath: string): Promise<string[]> => {
|
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
|
// 检查路径是否存在
|
|
|
|
|
if (!fs.existsSync(dirPath)) {
|
|
|
|
|
resolve([]); // 路径不存在时返回空数组
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 异步读取目录内容
|
|
|
|
|
fs.readdir(dirPath, (err, files) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
resolve([]); // 读取错误时返回空数组
|
|
|
|
|
} else {
|
|
|
|
|
// 过滤出.stl文件
|
|
|
|
|
const stlFiles = files.filter(
|
|
|
|
|
(file) => path.extname(file).toLowerCase() === ".stl"
|
|
|
|
|
);
|
|
|
|
|
resolve(stlFiles);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
2024-10-09 17:11:41 +08:00
|
|
|
|
|
2024-10-11 16:26:38 +08:00
|
|
|
|
export const createPDF = async (savePath: string) => {
|
|
|
|
|
// 创建一个新的 PDF 文档
|
|
|
|
|
const pdfDoc = await PDFDocument.create();
|
|
|
|
|
|
|
|
|
|
// 自定义纸张大小,例如:宽 600,高 800
|
|
|
|
|
const page = pdfDoc.addPage([600, 800]);
|
|
|
|
|
|
|
|
|
|
// 自定义边距,例如左右上下都是 50
|
|
|
|
|
const margin = 50;
|
|
|
|
|
const pageWidth = page.getWidth();
|
|
|
|
|
const pageHeight = page.getHeight();
|
|
|
|
|
|
|
|
|
|
// 设置字体
|
|
|
|
|
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
|
|
|
|
|
|
|
|
// 绘制透明色块
|
|
|
|
|
// 设置颜色为半透明蓝色,透明度为 0.5
|
|
|
|
|
const color = rgb(0.11, 0.62, 0.92, 0.5); // 最后一个值是透明度
|
|
|
|
|
page.drawRectangle({
|
|
|
|
|
x: margin,
|
|
|
|
|
y: margin,
|
|
|
|
|
width: pageWidth - 2 * margin,
|
|
|
|
|
height: pageHeight - 2 * margin,
|
|
|
|
|
color: color,
|
|
|
|
|
opacity: 0.5,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 添加文本
|
|
|
|
|
page.drawText("这里是自定义边距内的文本。", {
|
|
|
|
|
x: margin,
|
|
|
|
|
y: pageHeight - margin - 30, // 文本的位置考虑了顶部边距
|
|
|
|
|
size: 12,
|
|
|
|
|
font: font,
|
|
|
|
|
color: rgb(0, 0, 0),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 保存 PDF
|
|
|
|
|
const pdfBytes = await pdfDoc.save();
|
|
|
|
|
writeFileSync(path.join(savePath, "报告.pdf"), pdfBytes);
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-09 17:11:41 +08:00
|
|
|
|
/**
|
|
|
|
|
* json存excel
|
|
|
|
|
*/
|
|
|
|
|
export const createExcelFile = async (savePath: string, measurement) => {
|
|
|
|
|
// 创建一个新的工作簿
|
|
|
|
|
const workbook = new ExcelJS.Workbook();
|
|
|
|
|
// 添加一个工作表
|
|
|
|
|
const worksheet = workbook.addWorksheet("My Sheet");
|
|
|
|
|
|
|
|
|
|
// 添加列标题
|
|
|
|
|
worksheet.columns = [
|
|
|
|
|
{ key: "1", header: "瓣环平面周长", width: 10 },
|
|
|
|
|
{ key: "2", header: "瓣环平面周长导出径", width: 10 },
|
|
|
|
|
{ key: "3", header: "瓣环平面面积", width: 10 },
|
|
|
|
|
{ key: "4", header: "瓣环平面面积导出径", width: 10 },
|
|
|
|
|
{ key: "5", header: "瓣环平面长径", width: 10 },
|
|
|
|
|
{ key: "6", header: "瓣环平面短径", width: 10 },
|
|
|
|
|
{ key: "7", header: "瓣环平面平均径", width: 10 },
|
|
|
|
|
//
|
|
|
|
|
{ key: "8", header: "窦管交界周长", width: 10 },
|
|
|
|
|
{ key: "9", header: "窦管交界周长导出径", width: 10 },
|
|
|
|
|
{ key: "10", header: "窦管交界面积", width: 10 },
|
|
|
|
|
{ key: "11", header: "窦管交界面积导出径", width: 10 },
|
|
|
|
|
{ key: "12", header: "窦管交界长径", width: 10 },
|
|
|
|
|
{ key: "13", header: "窦管交界短径", width: 10 },
|
|
|
|
|
{ key: "14", header: "窦管交界平均径", width: 10 },
|
|
|
|
|
//
|
|
|
|
|
{ key: "15", header: "左室流出道周长", width: 10 },
|
|
|
|
|
{ key: "16", header: "左室流出道周长导出径", width: 10 },
|
|
|
|
|
{ key: "17", header: "左室流出道面积", width: 10 },
|
|
|
|
|
{ key: "18", header: "左室流出道面积导出径", width: 10 },
|
|
|
|
|
{ key: "19", header: "左室流出道长径", width: 10 },
|
|
|
|
|
{ key: "20", header: "左室流出道短径", width: 10 },
|
|
|
|
|
{ key: "21", header: "左室流出道平均径", width: 10 },
|
|
|
|
|
//
|
|
|
|
|
{ key: "22", header: "升主动脉(瓣环上4cm)周长", width: 10 },
|
|
|
|
|
{ key: "23", header: "升主动脉(瓣环上4cm)周长导出径", width: 10 },
|
|
|
|
|
{ key: "24", header: "升主动脉(瓣环上4cm)面积", width: 10 },
|
|
|
|
|
{ key: "25", header: "升主动脉(瓣环上4cm)面积导出径", width: 10 },
|
|
|
|
|
{ key: "26", header: "升主动脉(瓣环上4cm)长径", width: 10 },
|
|
|
|
|
{ key: "27", header: "升主动脉(瓣环上4cm)短径", width: 10 },
|
|
|
|
|
{ key: "28", header: "升主动脉(瓣环上4cm)平均径", width: 10 },
|
|
|
|
|
//
|
2024-10-11 16:26:38 +08:00
|
|
|
|
{ key: "29", header: "瓦氏窦周长", width: 10 },
|
|
|
|
|
{ key: "30", header: "瓦氏窦周长导出径", width: 10 },
|
|
|
|
|
{ key: "31", header: "瓦氏窦面积", width: 10 },
|
|
|
|
|
{ key: "32", header: "瓦氏窦面积导出径", width: 10 },
|
|
|
|
|
{ key: "33", header: "瓦氏窦长径", width: 10 },
|
|
|
|
|
{ key: "34", header: "瓦氏窦短径", width: 10 },
|
|
|
|
|
{ key: "35", header: "瓦氏窦平均径", width: 10 },
|
2024-10-09 17:11:41 +08:00
|
|
|
|
//
|
|
|
|
|
{ key: "36", header: "左侧冠脉开口高度", width: 10 },
|
|
|
|
|
{ key: "37", header: "右侧冠脉开口高度", width: 10 },
|
|
|
|
|
{ key: "38", header: "钙化信息", width: 10 },
|
|
|
|
|
{ key: "39", header: "主动脉夹角", width: 10 },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const annulus_plane = measurement["annulus_plane"];
|
|
|
|
|
const STJ_plane = measurement["STJ_plane"];
|
|
|
|
|
const LVOT_plane = measurement["LVOT_plane"];
|
|
|
|
|
const nominal_aorta_plane = measurement["nominal_aorta_plane"];
|
|
|
|
|
const SOV_plane = measurement["SOV_plane"];
|
|
|
|
|
const calcification_analysis =
|
|
|
|
|
measurement["calcification_analysis"]["HU_statistic"];
|
|
|
|
|
|
|
|
|
|
worksheet.addRow({
|
|
|
|
|
1: annulus_plane["perimeter"],
|
|
|
|
|
2: annulus_plane["PED"],
|
|
|
|
|
3: annulus_plane["area"],
|
|
|
|
|
4: annulus_plane["AED"],
|
|
|
|
|
5: annulus_plane["max_dist"],
|
|
|
|
|
6: annulus_plane["min_dist"],
|
|
|
|
|
7: annulus_plane["average_dist"],
|
|
|
|
|
//
|
|
|
|
|
8: STJ_plane["perimeter"],
|
|
|
|
|
9: STJ_plane["PED"],
|
|
|
|
|
10: STJ_plane["area"],
|
|
|
|
|
11: STJ_plane["AED"],
|
|
|
|
|
12: STJ_plane["max_dist"],
|
|
|
|
|
13: STJ_plane["min_dist"],
|
|
|
|
|
14: STJ_plane["average_dist"],
|
|
|
|
|
//
|
|
|
|
|
15: LVOT_plane["perimeter"],
|
|
|
|
|
16: LVOT_plane["PED"],
|
|
|
|
|
17: LVOT_plane["area"],
|
|
|
|
|
18: LVOT_plane["AED"],
|
|
|
|
|
19: LVOT_plane["max_dist"],
|
|
|
|
|
20: LVOT_plane["min_dist"],
|
|
|
|
|
21: LVOT_plane["average_dist"],
|
|
|
|
|
//
|
|
|
|
|
22: nominal_aorta_plane["perimeter"],
|
|
|
|
|
23: nominal_aorta_plane["PED"],
|
|
|
|
|
24: nominal_aorta_plane["area"],
|
|
|
|
|
25: nominal_aorta_plane["AED"],
|
|
|
|
|
26: nominal_aorta_plane["max_dist"],
|
|
|
|
|
27: nominal_aorta_plane["min_dist"],
|
|
|
|
|
28: nominal_aorta_plane["average_dist"],
|
|
|
|
|
//
|
|
|
|
|
29: SOV_plane["perimeter"],
|
|
|
|
|
30: SOV_plane["PED"],
|
|
|
|
|
31: SOV_plane["area"],
|
|
|
|
|
32: SOV_plane["AED"],
|
|
|
|
|
33: SOV_plane["max_dist"],
|
|
|
|
|
34: SOV_plane["min_dist"],
|
|
|
|
|
35: SOV_plane["average_dist"],
|
|
|
|
|
//
|
|
|
|
|
38: calcification_analysis.map((i) => `HU${i.key}:${i.value}`).join(";"),
|
|
|
|
|
39: annulus_plane["horizontal_angle"],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 设置样式
|
|
|
|
|
worksheet.getRow(1).font = { bold: true };
|
|
|
|
|
// 保存到文件
|
|
|
|
|
await workbook.xlsx.writeFile(path.join(savePath));
|
|
|
|
|
};
|