首次提交

This commit is contained in:
2026-05-26 10:10:32 +08:00
parent 02e1486d39
commit a6f7ad12da
45 changed files with 27435 additions and 0 deletions
+213
View File
@@ -0,0 +1,213 @@
import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path'
import {
AlignmentType,
BorderStyle,
Document,
Footer,
HeadingLevel,
Packer,
Paragraph,
Table,
TableCell,
TableRow,
TextRun,
WidthType,
} from 'docx'
const outputDir = path.resolve(process.cwd(), 'public/assets/templates')
function createInfoTable() {
const rows = [
['合同名称', '{contractName}'],
['合同编码', '{contractCode}'],
['合同类型', '{contractType}'],
['合同金额', '人民币 {contractAmountDisplay}'],
['有效期', '{effectivePeriod}'],
['付款方式', '{paymentMethod}'],
['合同相对方', '{counterpartySummary}'],
['附件情况', '{attachmentSummary}'],
]
return new Table({
width: {
size: 100,
type: WidthType.PERCENTAGE,
},
rows: rows.map(
([label, value]) =>
new TableRow({
children: [
new TableCell({
width: {
size: 22,
type: WidthType.PERCENTAGE,
},
children: [
new Paragraph({
children: [
new TextRun({
text: label,
bold: true,
}),
],
}),
],
}),
new TableCell({
width: {
size: 78,
type: WidthType.PERCENTAGE,
},
children: [
new Paragraph({
text: value,
}),
],
}),
],
}),
),
borders: {
top: { style: BorderStyle.SINGLE, size: 1, color: 'D9DDE7' },
bottom: { style: BorderStyle.SINGLE, size: 1, color: 'D9DDE7' },
left: { style: BorderStyle.SINGLE, size: 1, color: 'D9DDE7' },
right: { style: BorderStyle.SINGLE, size: 1, color: 'D9DDE7' },
insideHorizontal: { style: BorderStyle.SINGLE, size: 1, color: 'E5E7EB' },
insideVertical: { style: BorderStyle.SINGLE, size: 1, color: 'E5E7EB' },
},
})
}
function sectionTitle(text) {
return new Paragraph({
text,
heading: HeadingLevel.HEADING_2,
spacing: {
before: 280,
after: 160,
},
})
}
function clause(text) {
return new Paragraph({
text,
spacing: {
after: 160,
line: 360,
},
})
}
async function writeTemplate(filename, config) {
const doc = new Document({
sections: [
{
properties: {},
footers: {
default: new Footer({
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new TextRun({
text: `${config.title} - 模板演示文档`,
color: '6B7280',
size: 18,
}),
],
}),
],
}),
},
children: [
new Paragraph({
text: config.title,
heading: HeadingLevel.TITLE,
alignment: AlignmentType.CENTER,
spacing: {
after: 240,
},
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new TextRun({
text: '用于演示合同发起模块模板填充与导出',
italics: true,
color: '64748B',
}),
],
spacing: {
after: 280,
},
}),
sectionTitle('一、合同基础信息'),
createInfoTable(),
sectionTitle('二、合同正文示例'),
...config.clauses.map(clause),
sectionTitle('三、补充说明'),
clause('合同标的说明:{contractSubject}'),
clause('业务备注:{businessRemark}'),
clause('模板来源:{templateLabel}'),
new Paragraph({
spacing: {
before: 360,
after: 180,
},
children: [
new TextRun({
text: '甲方(业务方):__________________',
}),
],
}),
new Paragraph({
spacing: {
after: 180,
},
children: [
new TextRun({
text: '乙方(相对方):__________________',
}),
],
}),
new Paragraph({
children: [
new TextRun({
text: '签署日期:{signDate}',
}),
],
}),
],
},
],
})
const buffer = await Packer.toBuffer(doc)
await writeFile(path.join(outputDir, filename), buffer)
}
await mkdir(outputDir, { recursive: true })
await writeTemplate('purchase-contract-template.docx', {
title: '采购合同模板',
clauses: [
'甲乙双方经友好协商,就 {contractName} 项下采购合作事宜达成一致,并共同遵守本合同。',
'第一条 合作内容:乙方根据甲方需求提供 {contractSubject},具体交付内容以双方确认的技术资料和补充协议为准。',
'第二条 合同金额:本合同总金额为人民币 {contractAmountDisplay},付款方式采用 {paymentMethod}。',
'第三条 合同期限:本合同自 {effectiveStart} 起生效,至 {effectiveEnd} 止。',
],
})
await writeTemplate('sales-contract-template.docx', {
title: '销售合同模板',
clauses: [
'为明确双方权利义务,甲乙双方就 {contractName} 相关销售事项签订本合同。',
'第一条 销售范围:甲方向乙方提供 {contractSubject},合同编码为 {contractCode}。',
'第二条 金额与结算:本合同金额合计人民币 {contractAmountDisplay},采用 {paymentMethod} 完成结算。',
'第三条 生效与终止:本合同有效期为 {effectivePeriod},双方应按约履约。',
],
})
console.log(`Generated templates in ${outputDir}`)