如何使用 Node js 在 pdf 中创建图表

问题描述 投票:0回答:1

我使用 Nodejs 添加了代码结构。我使用 Nodejs 添加了数据来创建 pdf 报告。使用相同的数据值我需要创建一个 pdf 图表

    const Config = require('../constants/config');
    const _ = require("lodash");
    const xlsx = require('xlsx');
    const url = require('url');
    const { Tabletojson } = require('tabletojson');
    const puppeteer = require("puppeteer");
    const hbs = require('hbs');
    const fetch = require('node-fetch');
    const { BlobSASPermissions, BlobServiceClient, generateBlobSASQueryParameters, StorageSharedKeyCredential } =
    require("@azure/storage-blob");
    const { validateSchema } = require('../lib/validator');
    const { reportSchema } = require('../model/reportSchema');
    const moment = require('moment/moment');
    
    
    const signedURL = async (files, NameOfThefiles) => {
    const containerName = envConfig.sasContainerName;
    const cerds = new StorageSharedKeyCredential(envConfig.containerName, envConfig.containerSecret)
    const connectionString = envConfig.azureBlobConnectionString;
    const client = BlobServiceClient.fromConnectionString(connectionString);
    const containerClient = client.getContainerClient(containerName);
    const blobClient = containerClient.getBlobClient(NameOfThefiles)
    await containerClient.createIfNotExists({
    access: 'container'
    });
    const blockBlobClient = containerClient.getBlockBlobClient(NameOfThefiles);
    
    const startDate = new Date();
    const expiryDate = new Date(startDate);
    
    expiryDate.setMinutes(startDate.getMinutes() + parseInt(envConfig.azureBlobTimeout, 10));
    
    startDate.setMinutes(startDate.getMinutes());
    
    const blobSAS = generateBlobSASQueryParameters({
    containerName,
    blobName: NameOfThefiles,
    permissions: BlobSASPermissions.parse(envConfig.azureUploadPermission),
    startsOn: startDate,
    expiresOn: expiryDate
    }, cerds).toString()
    await blockBlobClient.uploadData(files);
    
    return {
    success: {
    data: {
    url: `${blobClient.url}?${blobSAS}`
    },
    successCode: "RSSCC-0001"
    },
    error: null
    }
    }
    const template = async (templateType, data) => {
    const filesUrl = new url.URL(`${ Config.protocol }${ Config.azureContainerBaseUrl }${ Config.azureBlobTemplateName }${
    templateType }.hbs`);
    const response = await fetch(filesUrl);
    const body = await response.text();
    const template = hbs.compile(body);
    const filter = data?.filters && data?.filters.map((item)=>{
    item.filterColumn = item?.filterColumn?.split("_").join(" ")
    item.filterValue = item.filterValue.map((filterValue)=>{
    return filterValue.split("_").join(" ")
    })
    return item
    })
    return template({ data: data.data, filters: filter });
    }
    
    
    
    const generatePdf = async (data, templateType) => {
    // Browser actions & buffer creator
    const html = await template(templateType, data);
    const browser = await puppeteer.launch({
    args: ["--no-sandbox", "--disable-setuid-sandbox"]
    });
    const page = await browser.newPage();
    await page.setContent(html);
    const pdf = await page.pdf({
    margin: {
    top: 80,
    bottom: 80,
    left: 30,
    right: 30,
    top: 80
    }
    });
    await browser.close();
    return pdf;
    };
    
    
    const ReportCreation = async (ParamsForGeneratedReport) => {
    let NameOfThefiles;
    let files;
    await validateSchema(reportSchema, ParamsForGeneratedReport);
    const date = moment(new Date()).format(envConfig.dateFormat);
    
    if (ParamsForGeneratedReport.filesType === envConfig.filesType.PDF){
    files = await generatePdf({
    data: ParamsForGeneratedReport.data,
    filters: ParamsForGeneratedReport.filters
    }, ParamsForGeneratedReport.templateType);
    NameOfThefiles = ParamsForGeneratedReport.NameOfThefiles ? `${ ParamsForGeneratedReport.NameOfThefiles }.${
    ParamsForGeneratedReport.filesType } ` : `${ ParamsForGeneratedReport.templateType }_${ date }.${
    ParamsForGeneratedReport.filesType } `
    return await signedURL(files, NameOfThefiles);
    }
    }
    
    module.exports = {
    ReportCreation
    }

上面的代码是我的代码的当前结构,我需要创建一个pdf格式的图表。我创建了一个 POC,用于在 pdf 中创建图表,如下代码所示。请帮助我使用nodejs库-jspdf将以下代码与我当前的结构集成,并在上面的代码中动态输入。

    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Line Chart</title>
        <!-- Include Chart.js library -->
    
        <canvas id="canvas" style="width:90vw">
        </canvas>
        <button id="saveExcel">Save xlsx</button> <button id="savePdf">Save pdf</button>
    
        <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/exceljs/4.4.0/exceljs.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
    </head>
    
    <body>
        <script>
            let chart = null,
                originalWidth, originalHeight;
            function TyLyReport() {
                const lineChartData = {
                    labels: ["Jan", "Feb", "Mar"],
                    datasets: [
                        {
                            label: 'Dataset 1',
                            borderColor: 'rgba(75, 192, 192, 1)',
                            backgroundColor: 'rgba(75, 192, 192, 0.2)',
                            data: [1000, 2000, 2500],
                            fill: false
                        },
                        {
                            label: 'Dataset 2',
                            borderColor: '#FF4848',
                            backgroundColor: 'rgba(255, 72, 72, 0.2)',
                            data: [1016, 1800, 2900],
                            fill: false
                        }
                    ]
                };
    
               chart = new Chart("canvas", {
                    type: 'line',
                    data: lineChartData,
                    options: {
                        responsive: false,
                        animation: false,
                        maintainAspectRatio: false,
                        devicePixelRatio: 1,
                        scales: {
                            y: {
                                beginAtZero: true
                            }
                        }
                    },
                    plugins: [
                        {
                            beforeDraw(chart) { // White background in the exported image
                                const { ctx, canvas } = chart;
                                ctx.save();
                                ctx.fillStyle = '#FFF';
                                ctx.fillRect(0, 0, canvas.offsetWidth, canvas.offsetHeight);
                                ctx.restore();
                            }
                        }
                    ]
                });
    
                originalWidth = canvas.offsetWidth;
                originalHeight = canvas.offsetHeight;
            }
    
            function getChartImageForWidth(widthPx) {
                chart.resize(widthPx, widthPx * originalHeight / originalWidth);
                const returnData = {
                    image: chart.canvas.toDataURL("image/png").split(';base64,')[1],
                    width: chart.canvas.offsetWidth,
                    height: chart.canvas.offsetHeight
                };
                chart.resize(originalWidth, originalHeight);
                return returnData;
            }
    
    
    
            function exportToPdf(marginPx) {  // the top, left and right margins of the image wrt the pdf page
                const doc = new jspdf.jsPDF({ unit: "px", hotfixes: ["px_scaling"] });
                const pdfWidth = doc.internal.pageSize.getWidth(); // to fit width
                const { image } = getChartImageForWidth(pdfWidth - 2 * marginPx);
                doc.addImage(image, marginPx, marginPx);
                doc.save('chart_image.pdf');
            }
    
            TyLyReport();
            document.querySelector('#savePdf').addEventListener('click', () => exportToPdf(40));
        </script>
    </body>
    
    </html>

这个 html 脚本是 POC,我已为其创建了一个 pdf 图表,我需要将相同的代码与我的代码的输入集成。您能帮忙将上面的代码与我的 Node js 代码集成吗?使用 html 代码,我可以创建 pdf 格式的图表,但需要集成到 Node js 代码中。我已经添加了下面的图片,因为需要在 pdf 中添加图表。我已经添加了基于该图表在 pdf 中创建的表格,应该在 pdf 中绘制

javascript node.js asynchronous async-await
1个回答
0
投票

您可以尝试使用 Node canvas 和 Chart js,除了 HTML 部分之外,它将与您提供的代码类似。

© www.soinside.com 2019 - 2024. All rights reserved.