协议书导出 Word

This commit is contained in:
bb_pan 2025-10-30 16:56:32 +08:00
parent 9f24743e4f
commit bc71705627
3 changed files with 691 additions and 3 deletions

View File

@ -41,10 +41,11 @@
"clipboard": "2.0.8", "clipboard": "2.0.8",
"core-js": "3.25.3", "core-js": "3.25.3",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"docx": "^9.5.1",
"echarts": "5.4.0", "echarts": "5.4.0",
"element-ui": "2.15.14", "element-ui": "2.15.14",
"exceljs": "^4.4.0", "exceljs": "^4.4.0",
"file-saver": "2.0.5", "file-saver": "^2.0.5",
"fuse.js": "6.4.3", "fuse.js": "6.4.3",
"highlight.js": "9.18.5", "highlight.js": "9.18.5",
"html2canvas": "^1.4.1", "html2canvas": "^1.4.1",

View File

@ -235,7 +235,8 @@
<div slot="footer" class="dialog-footer" style="text-align: center"> <div slot="footer" class="dialog-footer" style="text-align: center">
<el-button type="primary" @click="print"> </el-button> <el-button type="primary" @click="print"> </el-button>
<el-button type="success" @click="handleExportAgreement"> </el-button> <!-- <el-button type="success" @click="handleExportAgreement"> </el-button> -->
<el-button type="success" @click="exportWord"> </el-button>
<el-button @click="openPrint = false"> </el-button> <el-button @click="openPrint = false"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
@ -324,6 +325,20 @@ import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css' import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import printJS from 'print-js' import printJS from 'print-js'
import ExcelJS from 'exceljs' import ExcelJS from 'exceljs'
import {
Document,
Packer,
Paragraph,
TextRun,
Table,
TableRow,
TableCell,
AlignmentType,
WidthType,
BorderStyle,
PageOrientation
} from 'docx'
export default { export default {
name: 'ApplyHome', name: 'ApplyHome',
dicts: ['cost_status'], dicts: ['cost_status'],
@ -806,6 +821,335 @@ export default {
// this.download('material/agreementInfo/export', { // this.download('material/agreementInfo/export', {
// ...this.queryParams // ...this.queryParams
// }, `_${new Date().getTime()}.xlsx`) // }, `_${new Date().getTime()}.xlsx`)
},
async exportWord() {
const data = this.agreementContent
// ====== ======
const cellOpts = {
margins: { top: 300, bottom: 300, left: 40, right: 40 }, //
verticalAlign: 'center',
borders: {
top: { style: BorderStyle.SINGLE, size: 1 },
bottom: { style: BorderStyle.SINGLE, size: 1 },
left: { style: BorderStyle.SINGLE, size: 1 },
right: { style: BorderStyle.SINGLE, size: 1 }
}
}
const noBorder = {
top: { style: BorderStyle.NONE },
bottom: { style: BorderStyle.NONE },
left: { style: BorderStyle.NONE },
right: { style: BorderStyle.NONE }
}
// ====== ======
const doc = new Document({
sections: [
{
properties: {
page: {
size: { width: 11900, height: 16840, orientation: PageOrientation.PORTRAIT },
margin: { top: 720, right: 720, bottom: 720, left: 720 }
}
},
children: [
// ===== =====
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 100, after: 200 },
children: [new TextRun({ text: '机具设备有偿使用费结算协议书', bold: true, size: 32 })]
}),
// ===== =====
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
new TableCell({
width: { size: 70, type: WidthType.PERCENTAGE },
borders: noBorder,
children: [new Paragraph({ text: '' })]
}),
new TableCell({
width: { size: 30, type: WidthType.PERCENTAGE },
borders: noBorder,
children: [
new Paragraph({
alignment: AlignmentType.LEFT,
text: `协议号:${data.agreementCode || ''}`,
spacing: { before: 0, after: 0 },
margins: { top: 100, bottom: 100 }
})
]
})
]
}),
new TableRow({
children: [
new TableCell({
width: { size: 70, type: WidthType.PERCENTAGE },
borders: noBorder,
children: [new Paragraph({ text: '' })]
}),
new TableCell({
width: { size: 30, type: WidthType.PERCENTAGE },
borders: noBorder,
children: [
new Paragraph({
alignment: AlignmentType.LEFT,
text: `编号:`,
spacing: { before: 0, after: 0 },
margins: { top: 100, bottom: 100 }
})
]
})
]
})
]
}),
// === Paragraph ===
new Paragraph({
text: '',
spacing: { before: 100, after: 100 } //
}),
// ===== =====
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
//
new TableRow({
children: [
new TableCell({
...cellOpts,
width: { size: 25, type: WidthType.PERCENTAGE },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '工程名称:'
})
]
}),
new TableCell({
...cellOpts,
width: { size: 75, type: WidthType.PERCENTAGE },
columnSpan: 3,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: data.projectName
})
]
})
]
}),
// +
new TableRow({
children: [
new TableCell({
...cellOpts,
width: { size: 25, type: WidthType.PERCENTAGE },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '承租单位:'
})
]
}),
new TableCell({
...cellOpts,
width: { size: 40, type: WidthType.PERCENTAGE },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: data.unitName
})
]
}),
new TableCell({
...cellOpts,
width: { size: 10, type: WidthType.PERCENTAGE },
children: [
new Paragraph({ alignment: AlignmentType.CENTER, text: '日期:' })
]
}),
new TableCell({
...cellOpts,
width: { size: 25, type: WidthType.PERCENTAGE },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: data.applyTime
})
]
})
]
}),
//
new TableRow({
children: [
new TableCell({
...cellOpts,
columnSpan: 4,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '结算项目及金额(元)',
bold: true
})
]
})
]
}),
//
...[
['一、施工机具有偿使用费:', `${Number(data.leaseCost).toFixed(2)}`],
['二、施工机具维修费:', `${Number(data.repairCost).toFixed(2)}`],
['三、施工机具丢失费:', `${Number(data.loseCost).toFixed(2)}`],
['四、施工机具损坏赔偿费:', `${Number(data.scrapCost).toFixed(2)}`],
['五、施工机具租赁减免费:', `${Number(data.reductionCost).toFixed(2)}`]
].map(
([label, value]) =>
new TableRow({
children: [
new TableCell({
...cellOpts,
columnSpan: 2,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: label
})
]
}),
new TableCell({
...cellOpts,
columnSpan: 2,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: value
})
]
})
]
})
),
//
new TableRow({
children: [
new TableCell({
...cellOpts,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '费用合计金额(大写):'
})
]
}),
new TableCell({
...cellOpts,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: data.costAllUpper
})
]
}),
new TableCell({
...cellOpts,
columnSpan: 2,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: `${Number(data.costAll).toFixed(2)}`
})
]
})
]
}),
//
new TableRow({
children: [
new TableCell({
...cellOpts,
children: [
new Paragraph({ alignment: AlignmentType.CENTER, text: '说明:' })
]
}),
new TableCell({
...cellOpts,
columnSpan: 3,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '本协议一式两份,甲方一份,乙方一份,经双方签字后生效。'
})
]
})
]
}),
//
new TableRow({
children: [
new TableCell({
...cellOpts,
children: [
new Paragraph({ alignment: AlignmentType.CENTER, text: '备注:' })
]
}),
new TableCell({
...cellOpts,
columnSpan: 3,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '此费用仅为在机具设备分公司发生费用,未计从项目部领用机具费用。'
})
]
})
]
})
]
}),
//
new Paragraph({ text: '', spacing: { before: 200 } }),
// ===== =====
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: ['部门负责人:', '承租负责人:', '核算员:'].map(
text =>
new TableCell({
borders: noBorder,
children: [new Paragraph({ alignment: AlignmentType.LEFT, text })],
margins: { top: 200, bottom: 200 } //
})
)
})
]
})
]
}
]
})
const blob = await Packer.toBlob(doc)
saveAs(blob, `机具设备有偿使用费结算协议书-${data.agreementCode}.docx`)
} }
} }
} }

View File

@ -268,8 +268,9 @@
</div> </div>
<div slot="footer" class="dialog-footer" style="text-align: center"> <div slot="footer" class="dialog-footer" style="text-align: center">
<el-button @click="exportExcel">导出Excel</el-button> <!-- <el-button @click="exportExcel">导出Excel</el-button> -->
<el-button type="primary" @click="print"> </el-button> <el-button type="primary" @click="print"> </el-button>
<el-button type="success" @click="exportWord">导出</el-button>
<el-button @click="openPrint = false"> </el-button> <el-button @click="openPrint = false"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
@ -286,6 +287,19 @@ import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { formatTime } from '@/utils/bonus' import { formatTime } from '@/utils/bonus'
import { saveAs } from 'file-saver' import { saveAs } from 'file-saver'
import ExcelJS from 'exceljs' import ExcelJS from 'exceljs'
import {
Document,
Packer,
Paragraph,
TextRun,
Table,
TableRow,
TableCell,
AlignmentType,
WidthType,
BorderStyle,
PageOrientation
} from 'docx'
export default { export default {
name: 'ExamHome', name: 'ExamHome',
@ -657,6 +671,335 @@ export default {
// ======= ======= // ======= =======
const buf = await workbook.xlsx.writeBuffer() const buf = await workbook.xlsx.writeBuffer()
saveAs(new Blob([buf]), `机具设备有偿使用费结算协议书-${data.agreementCode}_${formatTime(new Date())}.xlsx`) saveAs(new Blob([buf]), `机具设备有偿使用费结算协议书-${data.agreementCode}_${formatTime(new Date())}.xlsx`)
},
async exportWord() {
const data = this.agreementContent
// ====== ======
const cellOpts = {
margins: { top: 300, bottom: 300, left: 40, right: 40 }, //
verticalAlign: 'center',
borders: {
top: { style: BorderStyle.SINGLE, size: 1 },
bottom: { style: BorderStyle.SINGLE, size: 1 },
left: { style: BorderStyle.SINGLE, size: 1 },
right: { style: BorderStyle.SINGLE, size: 1 }
}
}
const noBorder = {
top: { style: BorderStyle.NONE },
bottom: { style: BorderStyle.NONE },
left: { style: BorderStyle.NONE },
right: { style: BorderStyle.NONE }
}
// ====== ======
const doc = new Document({
sections: [
{
properties: {
page: {
size: { width: 11900, height: 16840, orientation: PageOrientation.PORTRAIT },
margin: { top: 720, right: 720, bottom: 720, left: 720 }
}
},
children: [
// ===== =====
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 100, after: 200 },
children: [new TextRun({ text: '机具设备有偿使用费结算协议书', bold: true, size: 32 })]
}),
// ===== =====
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
new TableCell({
width: { size: 70, type: WidthType.PERCENTAGE },
borders: noBorder,
children: [new Paragraph({ text: '' })]
}),
new TableCell({
width: { size: 30, type: WidthType.PERCENTAGE },
borders: noBorder,
children: [
new Paragraph({
alignment: AlignmentType.LEFT,
text: `协议号:${data.agreementCode || ''}`,
spacing: { before: 0, after: 0 }
})
],
margins: { top: 100, bottom: 100 } //
})
]
}),
new TableRow({
children: [
new TableCell({
width: { size: 70, type: WidthType.PERCENTAGE },
borders: noBorder,
children: [new Paragraph({ text: '' })]
}),
new TableCell({
width: { size: 30, type: WidthType.PERCENTAGE },
borders: noBorder,
children: [
new Paragraph({
alignment: AlignmentType.LEFT,
text: `编号:`,
spacing: { before: 0, after: 0 }
})
],
margins: { top: 100, bottom: 100 } //
})
]
})
]
}),
// === Paragraph ===
new Paragraph({
text: '',
spacing: { before: 100, after: 100 } //
}),
// ===== =====
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
//
new TableRow({
children: [
new TableCell({
...cellOpts,
width: { size: 25, type: WidthType.PERCENTAGE },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '工程名称:'
})
]
}),
new TableCell({
...cellOpts,
width: { size: 75, type: WidthType.PERCENTAGE },
columnSpan: 3,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: data.projectName
})
]
})
]
}),
// +
new TableRow({
children: [
new TableCell({
...cellOpts,
width: { size: 25, type: WidthType.PERCENTAGE },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '承租单位:'
})
]
}),
new TableCell({
...cellOpts,
width: { size: 40, type: WidthType.PERCENTAGE },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: data.unitName
})
]
}),
new TableCell({
...cellOpts,
width: { size: 10, type: WidthType.PERCENTAGE },
children: [
new Paragraph({ alignment: AlignmentType.CENTER, text: '日期:' })
]
}),
new TableCell({
...cellOpts,
width: { size: 25, type: WidthType.PERCENTAGE },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: data.applyTime
})
]
})
]
}),
//
new TableRow({
children: [
new TableCell({
...cellOpts,
columnSpan: 4,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '结算项目及金额(元)',
bold: true
})
]
})
]
}),
//
...[
['一、施工机具有偿使用费:', `${Number(data.leaseCost).toFixed(2)}`],
['二、施工机具维修费:', `${Number(data.repairCost).toFixed(2)}`],
['三、施工机具丢失费:', `${Number(data.loseCost).toFixed(2)}`],
['四、施工机具损坏赔偿费:', `${Number(data.scrapCost).toFixed(2)}`],
['五、施工机具租赁减免费:', `${Number(data.reductionCost).toFixed(2)}`]
].map(
([label, value]) =>
new TableRow({
children: [
new TableCell({
...cellOpts,
columnSpan: 2,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: label
})
]
}),
new TableCell({
...cellOpts,
columnSpan: 2,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: value
})
]
})
]
})
),
//
new TableRow({
children: [
new TableCell({
...cellOpts,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '费用合计金额(大写):'
})
]
}),
new TableCell({
...cellOpts,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: data.costAllUpper
})
]
}),
new TableCell({
...cellOpts,
columnSpan: 2,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: `${Number(data.costAll).toFixed(2)}`
})
]
})
]
}),
//
new TableRow({
children: [
new TableCell({
...cellOpts,
children: [
new Paragraph({ alignment: AlignmentType.CENTER, text: '说明:' })
]
}),
new TableCell({
...cellOpts,
columnSpan: 3,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '本协议一式两份,甲方一份,乙方一份,经双方签字后生效。'
})
]
})
]
}),
//
new TableRow({
children: [
new TableCell({
...cellOpts,
children: [
new Paragraph({ alignment: AlignmentType.CENTER, text: '备注:' })
]
}),
new TableCell({
...cellOpts,
columnSpan: 3,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
text: '此费用仅为在机具设备分公司发生费用,未计从项目部领用机具费用。'
})
]
})
]
})
]
}),
//
new Paragraph({ text: '', spacing: { before: 200 } }),
// ===== =====
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: ['部门负责人:', '承租负责人:', '核算员:'].map(
text =>
new TableCell({
borders: noBorder,
children: [new Paragraph({ alignment: AlignmentType.LEFT, text })],
margins: { top: 200, bottom: 200 } //
})
)
})
]
})
]
}
]
})
const blob = await Packer.toBlob(doc)
saveAs(blob, `机具设备有偿使用费结算协议书-${data.agreementCode}.docx`)
} }
} }
} }