feat/printTemplate (#1345)
Co-authored-by: root <root@huan.daoyoucloud.com> Reviewed-on: daoyoucloud/tachybase#1345 Reviewed-by: sealday <zhanglin@daoyoucloud.com> Co-authored-by: yoona <1486343814@qq.com> Co-committed-by: yoona <1486343814@qq.com>
This commit is contained in:
parent
eaa9bb0bd2
commit
73fdc790f4
@ -1,14 +1,14 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { PassThrough, Readable } from 'stream';
|
||||
import { Readable } from 'stream';
|
||||
import { Context } from '@tachybase/actions';
|
||||
import { Model } from '@tachybase/database';
|
||||
|
||||
import Docxtemplater from 'docxtemplater';
|
||||
// 导入 Docxtemplater 的 InspectModule 类
|
||||
import InspectModule from 'docxtemplater/js/inspect-module';
|
||||
import PizZip from 'pizzip';
|
||||
|
||||
import { getTemplateParams } from './template-params'; // 导入 getTemplateParams
|
||||
|
||||
export const generate = async (ctx: Context) => {
|
||||
const id = ctx.action.params.id;
|
||||
const repo = ctx.db.getRepository('templateManage');
|
||||
@ -22,47 +22,23 @@ export const generate = async (ctx: Context) => {
|
||||
|
||||
const rawTemplate = template.get();
|
||||
const templatePath = path.join(process.env.PWD, rawTemplate.template[0].get().url);
|
||||
|
||||
const data = rawTemplate.testData;
|
||||
|
||||
const outputPath = path.join(__dirname, './output.docx');
|
||||
|
||||
try {
|
||||
// 获取模板中的占位符
|
||||
const tags = (await getTemplateParams(templatePath)) as any;
|
||||
console.log('Template tags:', tags);
|
||||
|
||||
// 验证数据是否包含所有占位符
|
||||
const missingTags = tags.filter((tag) => !data.prototype.hasOwnProperty.call(tag.replace(/[{}]/g, '')));
|
||||
if (missingTags.length > 0) {
|
||||
// throw new Error(`Missing data for tags: ${missingTags.join(',')}`);
|
||||
console.log('Missing data for tags');
|
||||
}
|
||||
|
||||
// 生成定制的 docx 文件
|
||||
const buffer = generateDocxFromTemplate(templatePath, data);
|
||||
|
||||
// 创建一个可读流
|
||||
const readableStream = new Readable({
|
||||
read(size) {
|
||||
// 将Buffer数据push到可读流中
|
||||
this.push(buffer);
|
||||
// 标记流的末尾
|
||||
this.push(null);
|
||||
},
|
||||
});
|
||||
|
||||
ctx.withoutDataWrapping = true;
|
||||
// 设置响应类型为二进制流
|
||||
ctx.set('Content-Type', 'application/octet-stream');
|
||||
// 将可读流设置为响应体
|
||||
ctx.body = readableStream;
|
||||
|
||||
// // 确保生成的 docx 文件存在
|
||||
// if (!fs.existsSync(outputPath)) {
|
||||
// throw new Error('Generated DOCX file not found');
|
||||
// }
|
||||
// ctx.body = 'Word and PDF files generated';
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
ctx.status = 500;
|
||||
@ -70,6 +46,50 @@ export const generate = async (ctx: Context) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const getTags = async (ctx: Context) => {
|
||||
const id = ctx.action.params.id;
|
||||
const repo = ctx.db.getRepository('templateManage');
|
||||
const template: Model = await repo.findOne({
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
appends: ['template'],
|
||||
});
|
||||
const rawTemplate = template.get();
|
||||
const templatePath = path.join(process.env.PWD, rawTemplate.template[0].get().url);
|
||||
|
||||
try {
|
||||
const content = fs.readFileSync(templatePath, 'binary');
|
||||
const zip = new PizZip(content);
|
||||
const iModule = new InspectModule();
|
||||
const doc = new Docxtemplater(zip, { modules: [iModule] });
|
||||
|
||||
// 获取所有占位符
|
||||
const allTags = iModule.getAllTags();
|
||||
console.log('All tags in the document:', allTags);
|
||||
|
||||
// 将 tags 转换为 JSON 格式的字符串
|
||||
const tagsJson = JSON.stringify(allTags, null, 2);
|
||||
|
||||
// 创建一个可读流
|
||||
const readableStream = new Readable({
|
||||
read(size) {
|
||||
this.push(tagsJson); // 将 tagsJson 写入流中
|
||||
this.push(null); // 结束流
|
||||
},
|
||||
});
|
||||
|
||||
// 设置响应头和响应内容
|
||||
ctx.withoutDataWrapping = true;
|
||||
ctx.set('Content-Type', 'application/json');
|
||||
ctx.body = readableStream;
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
ctx.status = 500;
|
||||
ctx.body = 'Error generating tags: ' + error.message;
|
||||
}
|
||||
};
|
||||
|
||||
function generateDocxFromTemplate(templatePath, data): Buffer {
|
||||
try {
|
||||
const content = fs.readFileSync(templatePath, 'binary');
|
||||
@ -77,17 +97,11 @@ function generateDocxFromTemplate(templatePath, data): Buffer {
|
||||
const doc = new Docxtemplater(zip);
|
||||
|
||||
doc.setData(data);
|
||||
|
||||
try {
|
||||
doc.render();
|
||||
} catch (error) {
|
||||
console.error('Error rendering template:', error);
|
||||
throw error;
|
||||
}
|
||||
doc.render();
|
||||
|
||||
return doc.getZip().generate({ type: 'nodebuffer' });
|
||||
} catch (error) {
|
||||
console.error('Error generating DOCX from template:', error);
|
||||
throw error; // Ensure errors are propagated correctly
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Plugin } from '@tachybase/server';
|
||||
|
||||
import { generate } from './actions/printTemplates';
|
||||
import { generate, getTags } from './actions/printTemplates';
|
||||
|
||||
export class PluginPrintTemplateServer extends Plugin {
|
||||
async afterAdd() {}
|
||||
@ -13,6 +13,7 @@ export class PluginPrintTemplateServer extends Plugin {
|
||||
name: 'printTemplates',
|
||||
actions: {
|
||||
generate,
|
||||
getTags,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
644
pnpm-lock.yaml
644
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user