如何使用AngularJS从动态加载的数据生成PDF?

3
我使用Node.JS作为后端和AngularJS作为前端创建了类似ERP的系统。我需要打印发票,因此需要将发票下载为PDF格式。我已经使用Bootstrap CSS精心设计了整个发票,并找到了一个解决方案来打印它。下面是相关的代码。
$scope.downloadQuotation = function () {
        html2canvas(document.getElementById('printQuotation'), {
            onrendered: function (canvas) {
                var data = canvas.toDataURL();
                var docDefinition = {
                    content: [{
                        image: data,
                        width: 540
                    }]
                };
                pdfMake.createPdf(docDefinition).download("Quotation_'" + $scope.selectedQuotation.id + "'.pdf");
            }
        });
    };

我正在使用'html2canvas'和pdfMake来生成这个PDF文件。而'printQuotation'是HTML发票的div名称。其中有一个动态加载数据的项目表格以及其他一些信息,就像一张普通的发票一样。
有时候这种解决方案可以正常工作。但当显示大小改变时,我只得到一个空白的PDF文件。问题在于如果发票无法适应用户的电脑(笔记本电脑)屏幕,我们就会得到一个空白的PDF文件。所以请帮助我解决这个问题。
实际上,我并不需要这种方式。任何客户端或服务器端的解决方案都可以。我的服务器是NodeJs,我看到了很多解决方案并尝试过,但对我来说都不起作用。这是我需要转换为PDF的HTML页面。
<div class="widgets">
<button class="btn btn-success" ng-click="printQuotation()">Print Quotation</button>
<button class="btn btn-info" ng-click="downloadQuotation()">Download Quotation</button>
<a class="btn btn-warning" href="#/quotation/add">Create New Quotation</a>
<a class="btn btn-primary" href="#/quotation/view">Back to View All</a>
<br><br>
<div class="row" ba-panel id="printQuotation">
    <div style="min-width: 871px;overflow-x: scroll">
        <div class="">
            <hr>
            <div class="row">
                <div class="col-lg-6">
                    <p style="font-size: 18px;"><b>Quotation No : {{selectedQuotation.id}}</b></p>
                </div>
                <div class="col-lg-6" style="text-align: right">
                    <p style="font-size: 18px;"><b>Date : {{selectedQuotation.date | date:'yyyy-MM-dd'}}</b></p>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-6">
                    <p style="font-size: 18px;"><b>Mr / Messrs : {{selectedQuotation.customer_name}}</b></p>
                    <p style="font-size: 18px;">We have pleasure in submitting our offer for the following items
                        :</p>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-6">
                    <p style="font-size: 18px;"><b>Pump No : : {{selectedQuotation.pump_no}}</b></p>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-6">
                    <p style="font-size: 18px;"><b>Se No : {{selectedQuotation.se_no}}</b></p>
                </div>
                <div class="col-lg-6" style="text-align: right">
                    <p style="font-size: 18px;"><b>Type : {{selectedQuotation.type}}</b></p>
                </div>
            </div>
            <br><br>
            <table class="table table-hover">
                <thead>
                <tr class="black-muted-bg">
                    <th style="font-size: 18px;">ID</th>
                    <th style="font-size: 18px;">Description</th>
                    <th style="font-size: 18px;">Qty</th>
                    <th style="font-size: 18px;">Unit Rate (R.O)</th>
                    <th style="font-size: 18px;">Amount (R.O)</th>
                </tr>
                </thead>
                <tbody>
                <tr ng-repeat="item in selectedQuotationItems" class="no-top-border">
                    <td style="font-size: 18px;">{{item.item_id}}</td>
                    <td style="font-size: 18px;">{{item.item_name}}</td>
                    <td style="font-size: 18px;">{{item.qty}}</td>
                    <td style="font-size: 18px;">{{item.unit_rate | currency:"":2}}</td>
                    <td style="font-size: 18px;">{{item.qty * item.unit_rate | currency:"":2}}</td>
                </tr>
                </tbody>
            </table>
            <hr>
            <div class="row">
                <div class="col-lg-6">
                    <p style="font-size: 18px;"><b>Note : {{selectedQuotation.remark}}</b></p>
                </div>
                <div class="col-lg-6" style="text-align: right">
                    <p style="font-size: 18px;"><b>Total Amount : {{selectedQuotation.total_amount |
                        currency:"":2}}</b></p>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-6">

                </div>
                <div class="col-lg-6" style="text-align: right">
                    <p style="font-size: 18px;"><b>Discount : {{selectedQuotation.discount | currency:"":2}}</b></p>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-6">

                </div>
                <div class="col-lg-6" style="text-align: right">
                    <p style="font-size: 18px;"><b>Net Amount : {{selectedQuotation.net_amount | currency:"":2}}</b>
                    </p>
                </div>
            </div>
            <hr>
            <div class="row">
                <div class="col-lg-6">
                    <h3>PATROL INJECTOR SERVICES</h3>
                    <P style="font-size: 18px;">Specialist in all kinds of Diesel lnjection Pump & lnjectors</P>
                    <br>
                    <p>Prepared by : ................................</p>
                </div>
                <div class="col-lg-6" style="text-align: right">
                    <h3>For MUSCAT DIESEL PUMP SERVICES</h3>
                    <br>
                    <p style="font-size: 18px;">Authorized by : ................................</p>
                </div>
            </div>
        </div>
    </div>
</div>
<button class="btn btn-success" ng-click="printQuotation()">Print Quotation</button>
<button class="btn btn-info" ng-click="downloadQuotation()">Download Quotation</button>
<a class="btn btn-warning" href="#/quotation/add">Create New Quotation</a>
<a class="btn btn-primary" href="#/quotation/view">Back to View All</a>

请检查下面的div。我需要将该div内所有内容转换为PDF。

<div class="row" ba-panel id="printQuotation">

有什么建议吗?请提供示例代码或类似的东西。我陷入了这个问题中很长一段时间,没有任何解决方案。


你尝试过使用PDFKit吗?不要依赖客户端进行PDF生成,应该从服务器端完成。 - harish2704
我试过了兄弟,不行。我只是跟着一些例子做。你能发一个更好的给我吗? - Chanaka De Silva
据我所知,PDFKit是最佳的选择。如果您可以分享您尝试过的示例,我可以进行检查。 - harish2704
@harish2704 你好,我想创建这个。http://www.faceinfotech.com/ReportDemo.pdf 请查看并告诉我可能的方法。在顶部,我们必须留下3英寸的空间放置他们的信头和标志。有两种格式。他们有预印纸张。所有数据都通过MySQL数据库加载,也有项目表。 - Chanaka De Silva
@Nathanael 很好。有没有办法让报告更加丰富多彩?我的意思是添加一些类似于 CSS 的东西,或者添加一个漂亮的表格。 - Chanaka De Silva
显示剩余5条评论
2个回答

3

1
非常感谢您 :) 我会尝试这个并让您知道。非常感谢您的好意。 - Chanaka De Silva
你的解决方案很好用。我只需要做一些小改动。通过for循环加载项目。就像这样。:) 非常感谢你。 - Chanaka De Silva
无论如何,我们能用Jade来做这件事吗?我的意思是在Jade中创建模板并填充所有字段和表格。 - Chanaka De Silva

0
以下解决方案使用AWS Lambda和Serverless框架与NodeJS。
有一个名为serverless-chrome的Github库,它接近于您要寻找的功能。
它与AWS Lambda和NodeJS一起工作。它使用无服务器Chrome访问您的网站并截取屏幕截图或将整个网站保存为PDF文件并显示PDF文件。部署非常简单,使用Serverless框架。我在客户的AWS帐户上部署了Github库。
这是部署后获得的演示链接。
https://1wphj1kzch.execute-api.ap-southeast-1.amazonaws.com/dev/pdf?url=http://www.gmail.com

http://www.gmail.com 替换为您选择的网站链接。它会等待网站完全加载,然后进行截图。您可以部署此功能并使用生成的链接来截取并保存截图,或者您可以使用另一个 Lambda 函数并将 PDF 保存到 AWS 上的 S3 存储桶中。

最重要的是,如果您是 AWS 的新用户,每个月可以免费获得 400,000 次 Lambda 执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接