????
Current Path : C:/inetpub/vhost/sdoc.gdtsolutions.vn/package/app/controllers/baocao/ |
Current File : C:/inetpub/vhost/sdoc.gdtsolutions.vn/package/app/controllers/baocao/WordController.js |
var { Document, Table, Paragraph, TextRun, AlignmentType, Packer, PageOrientation, WidthType, TableCell, TableRow } = require('docx'); var path = require('path'); var fsPromises = require('fs').promises; var { exportPath } = require('../../appconfig'); var { formatDate, formatDateToFilename } = require('../../utils'); async function createReport(name, heading, data, config) { // Tiền xử lý dự liệu var pHead = new Paragraph({ children: [new TextRun({ text: heading, size: 36, color: '#cce0ff', bold: true, allCaps: true })], alignment: AlignmentType.CENTER, spacing: { after: 240 } }); const getTableHeader = (col) => new TableCell({ shading: { fill: '#cce0ff' }, children: [new Paragraph({ children: [new TextRun({ text: col['text'], bold: true })], alignment: AlignmentType.CENTER, })] }) const getTableRow = (rowData) => new TableRow({ children: config.map(colConf => new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: rowData[colConf.column] })], alignment: colConf['align'] })] })) }) const table = new Table({ margins: { top: 50, right: 50, bottom: 50, left: 50 }, rows: [ new TableRow({ tableHeader: true, children: config.map(getTableHeader) }), ...data.map(getTableRow) ] }); // Khởi tạo Word document var filename = `${name}_${formatDateToFilename()}.docx`; const doc = new Document({ author: 'GDT-AR', description: heading, title: 'Báo cáo', styles: { paragraphStyles: [{ id: 'Normal', name: 'Normal', basedOn: 'Normal', next: 'Normal', paragraph: { spacing: { line: 276 } }, run: { font: 'Times New Roman', size: 26 }, }] }, sections: [{ size: { orientation: PageOrientation.LANDSCAPE }, children: [pHead, table] }] }); const buffer = await Packer.toBuffer(doc); await fsPromises.writeFile(path.join(exportPath, filename), buffer); return filename; } module.exports.reportFond = function (data) { var config = [ { text: 'Phông số', column: 'FondNumber', align: AlignmentType.CENTER }, { text: 'Tên phông', column: 'FondName', align: AlignmentType.JUSTIFIED }, { text: 'Số hồ sơ', column: 'tongSoHS', align: AlignmentType.CENTER }, { text: 'Số văn bản', column: 'tongSoVB', align: AlignmentType.CENTER }, { text: 'Số trang', column: 'tongSoTrang', align: AlignmentType.CENTER } ]; return createReport('ReportFond', 'Báo cáo danh mục phông', data, config); } module.exports.reportFile = function (data) { var config = [ { text: 'STT', column: 'RowNum', align: AlignmentType.CENTER }, { text: 'Phông', column: 'FondName', align: AlignmentType.JUSTIFIED }, { text: 'Mục lục', column: 'FileCatalog', align: AlignmentType.CENTER }, { text: 'Hộp', column: 'BoxNumber', align: AlignmentType.CENTER }, { text: 'Hồ sơ số', column: 'FileNumber', align: AlignmentType.CENTER }, { text: 'Ký hiệu', column: 'FileNotation', align: AlignmentType.CENTER }, { text: 'Tiêu đề', column: 'Title', align: AlignmentType.JUSTIFIED }, { text: 'Thời gian', column: 'FileDate', align: AlignmentType.CENTER }, { text: 'Thời hạn bảo quản', column: 'ThoiHanBQ', align: AlignmentType.CENTER }, { text: 'Số trang', column: 'PageNumber', align: AlignmentType.CENTER }, { text: 'Ghi chú', column: 'Description', align: AlignmentType.JUSTIFIED } ]; for (var i = 0; i < data.length; i++) { data[i].FileDate = [formatDate(data[i].StartDate), formatDate(data[i].EndDate)].filter(f => f).join('\n'); data[i].ThoiHanBQ = data[i].Maintenance ? `${data[i].Maintenance} năm` : 'Vĩnh viễn'; } return createReport('ReportFile', 'Báo cáo danh mục hồ sơ', data, config); } /** @type {import('docx').IStylesOptions} */ const DOC_STYLE = { paragraphStyles: [ { id: 'Normal', name: 'Normal', basedOn: 'Normal', next: 'Normal', run: { font: 'Times New Roman', size: 24, }, paragraph: { alignment: AlignmentType.JUSTIFIED } }, { id: 'PageHeader', name: 'PageHeader', basedOn: 'Normal', next: 'Normal', paragraph: { spacing: { before: 0, after: 0 }, alignment: AlignmentType.CENTER }, run: { allCaps: true } }, { id: 'Indent', name: 'Indent', basedOn: 'Normal', next: 'Normal', paragraph: { indent: { firstLine: 720 }, spacing: { before: 120, after: 120, lineRule: 'Single' } }, run: { size: 28 } }, { id: 'TableHeader', name: 'TableHeader', basedOn: 'Normal', next: 'Normal', paragraph: { alignment: AlignmentType.CENTER }, run: { bold: true } } ] } module.exports.reportDoc = function (data) { var config = [ { text: 'STT', column: 'RowNum', align: AlignmentType.CENTER }, { text: 'Phông', column: 'FondName', align: AlignmentType.JUSTIFIED }, { text: 'Mục lục', column: 'FileCatalog', align: AlignmentType.CENTER }, { text: 'Hộp', column: 'BoxNumber', align: AlignmentType.CENTER }, { text: 'Hồ sơ số', column: 'FileNumber', align: AlignmentType.CENTER }, { text: 'Số, ký hiệu', column: 'Code', align: AlignmentType.CENTER }, { text: 'Ngày ban hành', column: 'NgayBanHanh', align: AlignmentType.CENTER }, { text: 'Tên loại', column: 'TypeName', align: AlignmentType.CENTER }, { text: 'Trích yếu', column: 'Subject', align: AlignmentType.JUSTIFIED }, { text: 'Số trang', column: 'PageAmount', align: AlignmentType.CENTER }, { text: 'Ghi chú', column: 'Description', align: AlignmentType.JUSTIFIED } ]; for (var i = 0; i < data.length; i++) { data[i].Code = [data[i].CodeNumber, data[i].CodeNotation].filter(f => f).join('/'); data[i].NgayBanHanh = formatDate(data[i].IssuedDate); } return createReport('ReportDoc', 'Báo cáo danh mục văn bản', data, config); } // Xuất chi tiết yêu cầu tài liệu module.exports.exportRequest = async function (data) { const exportedDate = data['DateCreated'] || new Date(); const doc = new Document({ creator: 'GDT-AR', description: 'Thông tin chi tiết yêu cầu sử dụng tài liệu', title: 'Khai thác tài liệu', styles: DOC_STYLE, }); const pageMargins = { top: 1134, right: 1134, bottom: 1134, left: 1701 }; /** Render bản ký số */ const signTable = new Table({ rows: [ new TableRow({ children: [new TableCell({ columnSpan: 3, children: [new Paragraph({ children: [new TextRun({ text: `Bình Định, ngày ${exportedDate.getDate()} tháng ${exportedDate.getMonth() + 1} năm ${exportedDate.getFullYear()}`, italics: true })], alignment: AlignmentType.RIGHT })] })] }), new TableRow({ children: [ new TableCell({ width: { size: 30, type: WidthType.PERCENTAGE }, children: [new Paragraph({ children: [new TextRun({ text: 'Xét duyệt của người đứng đầu lưu trữ lịch sử', bold: true, allCaps: true })], alignment: AlignmentType.CENTER })], }), new TableCell({ width: { size: 30, type: WidthType.PERCENTAGE }, children: [new Paragraph({ children: [new TextRun({ text: 'Ý kiến của phòng đọc', bold: true })], alignment: AlignmentType.CENTER })], }), new TableCell({ children: [ new Paragraph({ children: [new TextRun({ text: 'Người đăng ký', bold: true })], alignment: AlignmentType.CENTER }), new Paragraph({ children: [new TextRun({ text: '(Ký, họ và tên)', bold: true })], alignment: AlignmentType.CENTER }), ], }) ] }) ], borders: { top: { size: 0 }, right: { size: 0 }, bottom: { size: 0 }, left: { size: 0 }, insideHorizontal: { size: 0 }, insideVertical: { size: 0 } } }); doc.addSection({ children: [ new Paragraph({ text: 'Sở Nội vụ tỉnh Bình Định', style: 'PageHeader', pageBreakBefore: false }), new Paragraph({ children: [new TextRun({ text: 'Chi cục Văn thư - Lưu trữ', bold: true })], style: 'PageHeader', thematicBreak: true }), new Paragraph({ text: '' }), new Paragraph({ children: [new TextRun({ text: 'Phiếu đăng ký sử dụng tài liệu', bold: true })], style: 'PageHeader' }), new Paragraph({ children: [new TextRun({ text: 'Số:', bold: true }), new TextRun(' '), new TextRun(data['ReqNumber'].toString())], style: 'PageHeader' }), new Paragraph({ text: '', style: 'Indent' }), new Paragraph({ text: ' Kính gửi: Chi cục Văn thư - Lưu trữ tỉnh Bình Định', style: 'Indent' }), new Paragraph({ text: '', style: 'Indent' }), new Paragraph({ text: 'Họ và tên độc giả: ' + data['FullName'], style: 'Indent' }), new Paragraph({ text: 'Ngày, tháng, năm sinh: ' + (data['Birthday'] || ''), style: 'Indent' }), new Paragraph({ text: 'Quốc tịch: ' + data['Nationality'], style: 'Indent' }), new Paragraph({ text: 'Số Chứng minh nhân dân/Số Hộ chiếu: ' + data['IdNumber'], style: 'Indent' }), new Paragraph({ text: 'Cơ quan công tác: ' + (data['OrganName'] || '......'), style: 'Indent' }), new Paragraph({ text: 'Địa chỉ liên hệ: ' + (data['Address'] || '......'), style: 'Indent' }), new Paragraph({ text: 'Số điện thoại: ' + data['Telephone'], style: 'Indent' }), new Paragraph({ text: 'Mục đích sử dụng, khai thác tài liệu: ' + (data['Uses'] || '......'), style: 'Indent' }), new Paragraph({ text: 'Tôi xin thực hiện nghiêm túc nội quy, quy chế của cơ quan lưu trữ và những quy định của pháp luật hiện hành về bảo vệ, khai thác, sử dụng tài liệu lưu trữ.', style: 'Indent' }), new Paragraph({ text: '', style: 'Indent' }), signTable ], margins: pageMargins, properties: {} }); /** Render header cho bảng */ const getCell = (text, options = {}, shading) => new TableCell({ shading, children: [new Paragraph({ text, ...options })] }) /** Render mỗi văn bản trên 1 dòng */ const getTableDataRow = (doc) => { const code = [doc['CodeNumber'], doc['CodeNotation']].filter(f => f).join('/'); return new TableRow({ children: [ getCell(doc['rowNum'].toString(), { alignment: AlignmentType.CENTER }), getCell(doc['FondName'], { alignment: AlignmentType.CENTER }), getCell(code, { alignment: AlignmentType.CENTER }), getCell(doc['Subject'], { alignment: AlignmentType.CENTER }), getCell(doc['PageAmount'].toString(), { alignment: AlignmentType.CENTER }), getCell(doc['CopiedNumber'].toString(), { alignment: AlignmentType.CENTER }), getCell(doc['CertifiedNumber'].toString(), { alignment: AlignmentType.CENTER }), getCell(doc['Price'].toLocaleString('vi-VN') + ' đồng', { alignment: AlignmentType.CENTER }), getCell(doc['Description'] || '', { alignment: AlignmentType.CENTER }), ] }) } const HEADERS = ['STT', 'Tên phông', 'Số, ký hiệu', 'Trích yếu', 'Số trang', 'Số bản sao lưu', 'Số bản chứng thực', 'Giá tiền', 'Ghi chú']; const table = new Table({ margins: { marginUnitType: WidthType.DXA, top: 40, right: 40, bottom: 40, left: 40 }, width: { size: 100, type: WidthType.PERCENTAGE }, rows: [ new TableRow({ children: HEADERS.map(h => getCell(h, { style: 'TableHeader' }, { fill: '#cce0ff' })), tableHeader: true, }), ...data['Content'].map(getTableDataRow), new TableRow({ children: [ new TableCell({ children: [new Paragraph({ text: 'Tổng chi phí: ', alignment: AlignmentType.RIGHT, style: 'TableHeader' })], columnSpan: 7 }), new TableCell({ children: [new Paragraph({ text: data['Content'].map(x => x['Price']).reduce((a, b) => a + b, 0).toLocaleString('vi-VN') + ' đồng' })] }) ] }) ], }); doc.addSection({ size: { orientation: PageOrientation.PORTRAIT }, children: [ new Paragraph({ children: [new TextRun({ text: 'Danh sách văn bản đăng ký sử dụng', bold: true, allCaps: true })], alignment: AlignmentType.CENTER }), new Paragraph({ text: '' }), table ], margins: pageMargins }) // for (let i = 0; i < data['Content'].length; i++) { // let docInfo = data['Content'][i]; // let code = []; // if (docInfo['CodeNumber']) code.push(docInfo['CodeNumber']); // if (docInfo['CodeNotation']) code.push(docInfo['CodeNotation']); // table.getCell(i + 1, 0).add(new Paragraph({ text: docInfo['rowNum'].toString(), alignment: AlignmentType.CENTER })); // table.getCell(i + 1, 1).add(new Paragraph({ text: docInfo['FondName'], alignment: AlignmentType.CENTER })); // table.getCell(i + 1, 2).add(new Paragraph({ text: code.join('/'), alignment: AlignmentType.CENTER })); // table.getCell(i + 1, 3).add(new Paragraph({ text: docInfo['Subject'], alignment: AlignmentType.CENTER })); // table.getCell(i + 1, 4).add(new Paragraph({ text: docInfo['PageAmount'].toString(), alignment: AlignmentType.CENTER })); // table.getCell(i + 1, 5).add(new Paragraph({ text: docInfo['CopiedNumber'].toString(), alignment: AlignmentType.CENTER })); // table.getCell(i + 1, 6).add(new Paragraph({ text: docInfo['CertifiedNumber'].toString(), alignment: AlignmentType.CENTER })); // table.getCell(i + 1, 7).add(new Paragraph({ text: docInfo['Price'].toLocaleString('vi-VN') + ' đồng', alignment: AlignmentType.CENTER })); // table.getCell(i + 1, 8).add(new Paragraph({ text: docInfo['Description'] || '', alignment: AlignmentType.CENTER })); // } // table.getRow(data['Content'].length + 1).mergeCells(0, 6).add(new Paragraph({ // text: 'Tổng chi phí: ', alignment: AlignmentType.RIGHT, style: 'TableHeader' // })); // table.getCell(data['Content'].length + 1, 1).add(new Paragraph({ // text: data['Content'].map(x => x['Price']).reduce((a, b) => a + b, 0).toLocaleString('vi-VN') + ' đồng' // })); let buffer = await Packer.toBuffer(doc, true); await fsPromises.writeFile(path.join(exportPath, data['UUID'] + '.docx'), buffer, { flag: 'w+' }); }