Asp.net MVC Razor视图模版动态渲染PDF,Razor模版生成静态Html

Asp.net MVC Razor视图模版动态渲染PDF,Razor模版生成静态Html

1.前言

    上一篇文章我开源了轮子Asp.net Core 3.1 Razor视图模版动态渲染PDF,然后,很多小伙伴有很多私信找我了。那么我下面就简单的给大家说一下,关于小伙伴问的这些问题。

  • 我项目的电子签章部分代码可否开源?

  答:我项目电子签章也是使用第三方的电子签章,电子签章并不是自己实现的,项目里面的电子签章代码无非也是对接第三方的接口。这部分代码开源出去也没有什么意义。我们是使用数字广东的方案,如果您也是使用该数字签章,可以私下沟通我看看能不能帮助您。

  • 电子签章实现难不难,怎么实现自己的电子签章?

  答:电子签章要实现,估计不是太难,按照我的理解,当然我没有具体深入研究(如果这里我有妄自菲薄的意思,请谅解,毕竟我能力有限,只是按照我的理解来分析),我个人觉得电子签章应该就是利用数字证书给PDF签名,然后加密保护文档,然后校验文档的真伪,就要考虑怎么验证这个文档没有被删改,是当初我们签章的这个文档,而且这个签名不能被伪造。个人觉得不是很复杂,但是,电子签章的法律有效性却不是这么简单的。按照国家法律规定,利用的签名平台应该有资质的,国家认可的第三方签章平台,也就是说,私人自己制作的签章,打起官司来,很难得到法律支持。

  • 项目为什么CSS样式不起效?

  答:你是否使用了外链的CSS样式,因为渲染Razor视图是在后台渲染,无法找到外链的文件路径,就使用不了外链的CSS样式,内嵌和内联CSS样式都没啥问题的。

  • 用word或者excel模版他不香吗?为什么要搞个这个东西?

  答:无非是多一个方案,具体你使用什么完全是你自己说了算,你觉得其他方案好就用,你觉得本方案能帮助你就用,不好就不用,我又不收你半毛线,还是想说的是,你其他的方案,能有用CSS那么容易做出来漂亮的表单效果吗?

  • 图片支持吗?

  答:图片要转Base64编码,不支持外连接图片。

  • 前端预览PDF用什么插件?

  答:我目前不用插件,新一代浏览器都支持PDF直接预览,直接就能渲染成PDF呈现,当然你也可以自己集成PDF.JS.我大概看了下,集成也很方便。我之所以不集成,是考虑到我的项目有可能使用IE低版本的情况,PDF.JS可能不支持。所以干脆直接把PDF流推送给浏览器,浏览器要是能预览,就直接呈现,不能预览就下载。

  • 项目支持net Framework吗?为啥报错?

  答:这个问题问的有点多,所以本文后续就以这个再说一下本轮子在net45下的使用。还是那句话,有不对的,欢迎您指正,觉得对你有用的就用,无用的就直接忽视,我又不收你半毛线。

  • 可以用本项目生成静态Html吗?容易被搜索引擎抓取。

  答:可以,后面演示

  2.依赖项目

  <PackageReference Include="TuesPechkin" Version="2.1.1" />
  <PackageReference Include="TuesPechkin.Wkhtmltox.Win32" Version="0.12.2.1" />
  <PackageReference Include="RazorEngine" Version="3.9.3" />
  <PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
  <PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.3" />
  <PackageReference Include="Nito.AsyncEx" Version="4.0.1" />
  <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
  <Reference Include="Nito.AsyncEx.Concurrent" Version="4.0.1" />
  <Reference Include="Nito.AsyncEx.Enlightenment" Version="4.0.1" />

     3.核心代码

    TuesPechkin插件,首先说一下这个TuesPechkin插件,他其实是利用TuesPechkin.Wkhtmltox进程来转换的。这个插件使用还是要小心的,使用不当可能有线程安全问题,会使得当前工作进程挂起。在IIS下面使用也要注意使用32位的插件。具体使用请看作者的说明:https://github.com/tuespetre/TuesPechkin/blob/develop/README.md

 插件初始化代码:

  private static readonly IConverter PdfConverter = new ThreadSafeConverter(new RemotingToolset<PdfToolset>(
            new Win32EmbeddedDeployment(
                new TempFolderDeployment())));

  

 切记IIS和多线程一定要静态单例。使用

 Win32EmbeddedDeployment

ThreadSafeConverter
这两个类。其他的可能让你进程挂起的成为可能。
还要用到远程工具集的PDF工具集。


Razor 转Html代码,主要有两种方式:


第一种使用RazorEngine来转换:这个主要是传递Razor模版进去,转换。

   protected string RunCompileRazorTemplate(object model,string razorTemplateStr)
        {
            if(string.IsNullOrWhiteSpace(razorTemplateStr))
                throw new ArgumentException("Razor模版不能为空");

            var htmlString= Engine.Razor.RunCompile(razorTemplateStr, razorTemplateStr.GetHashCode().ToString(), null, model);
            return htmlString;
        }

第二种使用ViewEngine。这个主要是自动查找Asp.net MVC里面的View下面的Razor,目前我们项目就是使用这个。

var viewName = context.RouteData.Values["action"].ToString();
            var result = ViewEngines.Engines.FindView(context, viewName, null);
           
            IExportPdfByHtmlTemplate exportPdfByHtmlTemplate = new PdfByHtmlTemplateExporter ();
#endif
            if (result.View == null)
                throw new ArgumentException($"名称为:{viewName}的视图不存在,请检查!");
             context.HttpContext.Response.ContentType = "application/pdf";
            //context.HttpContext.Response.Headers.Add("Content-Disposition", "attachment; filename=test.pdf");                    
            var html = "";
            using (var stringWriter = new StringWriter())
            {

#if !NET45
                var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = Value };
                var viewContext = new ViewContext(context, result.View, viewDictionary, new TempDataDictionary(context.HttpContext, tempDataProvider), stringWriter, new HtmlHelperOptions());

                await result.View.RenderAsync(viewContext);
#else
                var viewDictionary = new ViewDataDictionary(new ModelStateDictionary()) { Model = Value };
                var viewContext = new ViewContext(context, result.View, viewDictionary, context.Controller.TempData, stringWriter);
                result.View.Render(viewContext, stringWriter);
                result.ViewEngine.ReleaseView(context, result.View);
#endif
                html = stringWriter.ToString();

            }

推送PDF流给客户端,预览PDF主要代码

          context.HttpContext.Response.ContentType = "application/pdf";
    context.HttpContext.Response.AddHeader("Content-Length", buff.Length.ToString());
            context.HttpContext.Response.AddHeader("Content-Disposition", "filename=电子签章PDF-"+DateTime.Now.ToString()+".pdf");
            context.HttpContext.Response.BinaryWrite(buff);
            context.HttpContext.Response.Flush();
            context.HttpContext.Response.Close();
            context.HttpContext.Response.End();

  

 这里要注意三个地方,不然一定会踩坑。

Content-Length要设置,不然谷歌浏览器可能无法下载预览的PDF。
Content-Disposition不能要attachment,否则可能直接下载不是预览。
ContentType 要设置"application/pdf"


Razor转静态Html

还有一部分人问我怎么利用本插件Razor模版动态生成静态Html,这样容易被百度爬虫录取。
其实这部分核心代码就是几句代码,非常简单。本项目直接用下面接口即可生成html字符转,自行保存就可以了。

 public interface IHtmlByRazorTemplateExporter
    {
        Task<string> ExportHtmlByRazorTemplateAsync<T>(T data, string htmlTemplate) where T : class;
        string ExportHtmlByRazorTemplate<T>(T data, string htmlTemplate) where T : class;
    }

  

核心:

   protected string RunCompileRazorTemplate(object model,string razorTemplateStr)
        {
            if(string.IsNullOrWhiteSpace(razorTemplateStr))
                throw new ArgumentException("Razor模版不能为空");

            var htmlString= Engine.Razor.RunCompile(razorTemplateStr, razorTemplateStr.GetHashCode().ToString(), null, model);
            return htmlString;
        }

  4.使用方式

  •  目前本项目已经打包成nuget,并上传,使用可以直接项目右键->管理NuGet程序包,查找,然后下载安装。

  •  也可以使用命令安装。install-package JESAI.HtmlTemplate.Pdf.net45
  • 或者直接fork本仓库自己打包,并根据自己情况修改使用。

自定打包可以修改项目目标框架。项目右键->属性->应用程序,目标框架,修改

如发现不能修改,可以,项目->右键->编辑项目文件

然后编译,就可以使用了。

具体使用

方式一:

 方式二:

 

Razor视图模版代码:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8" />
    <title></title>
</head>

<body>
    <table border="1" style="background-color:gray;width:800px;height:500px;">
        <tr>
            <td>姓名</td>
            <td>@Model.Name</td>
            <td>性别</td>
            <td>@Model.Sex</td>
        </tr>
        <tr>
            <td>年龄</td>
            <td>@Model.Age</td>
            <td>班级</td>
            <td>@Model.Class</td>
        </tr>
        <tr>
            <td>住址</td>
            <td>@Model.Address</td>
            <td>电话</td>
            <td>@Model.Tel</td>
        </tr>
        <tr>
            <td clospan="2">住址</td>
            <td>@Model.Des</td>
        </tr>
    </table>
    <img src="data:image/jpg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wAARCAEiASIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDvWOMUmaV+1NoAXNGaSigBcmkzRRQAuaTJpKWluAZNGSKQ+tHWl5DHZpCSDmkHXFBovdABJxShuP8A61NBpAecVnz63Cw4sc0Fj/kU1ulITxUSna40iTcfakDHJpuaTPJpyqaoLDwxyaCxxTQetBNJVPcC2o7cQKUE4phPQU6tIyuxASelKWIH/wBamjk5o6mjmv8AMBwJoJopOpq3pohCgmjJpDS0eQC5ozSUnWmAuTS5pKKYC5ozSUUAGTRk0UlAEo6UUg6CigBH7U2nP2ptABRRRQAUlLRSAKTNHSjrSGLTTxSg9jQaTd0Ah9aAcikzg03OD7Vzyq2dx2HHg5ppPOaCaYT2rmqVLMpIkzTc8UwNkfSkz8+M1lOrezKUSQNxSbvmNQeamcZPWllkVGwc9Kn2jsiuQnVuM0FskVCkimPIB5NCyKzE7sU/ae6hcpODlvpTieKhVjTi3zY9K1jVtH1JcdSTOBSjgUwHJ+lOzgV005rcloUnPFL0FNHAyaUc81rGTfqSKBS0lHWtdtEIOtLSZxRj1oAKWiiqAKKKKACkpaSgCQdBRQOgooAR+1Npz9qbQAUUUlIA6UtJmgil6ALTTx0pc+tFJ2YxOtJnHBoPqKaTmuapNp+ZSQp5FMJ7Gjdjg0xyAMk4rjqT5tUWkLuPSo3kVRnOSKia4U/L91h9361WmVxJ8xCgnGP5/hXPe6sbRp33J5Lna23JO7gDpUMczk4yBjuTgGo5JxEDGrBtvUgfeH1qCS4aWXIwiuenYHpSOiNPTYsTo8cjAv0Oc1JdKoK/OQdueap3MczOHb5iwzkd/epbmFmhgOSW2ZOefwpX0Hy/DqTxhVgAaX73zKRzj8KbGswUMCCrNgGoDC6WqqxIfBK9SMGmxpMpwcjaMjPGad9g5d9S95zxyfMjAAZzUsM3mKCTnNZyXTKgiaMYLcgjtVmPy2iBBCOfuhWPPvTuZyp2WqNBGBGFOcU5W3HNZ1uzCTEgIUc7u2PrVtZkdtqkYzjPrWqn0RhKnZlkfN9KfmolOBzxTgd30ruhPlXmYNDutLntTc54FOAxW8XfYkAKWkzijk1pdLRCDNFHSjNHqAtFJS1QCUUtJQBIOgooHQUUAI/am05+1NoAKKTFHNK4C4pORRmlpWT2ATINNPHSnEZphyPesaja3KQZBprc0Eg0xie9cFSpfRlpDWPHPSq7XKn922Pm4Bp0swAKgg+1U5YCqGR+g+8M8iuV6M6YQXUS4iELfMfcc/pTHkW63MP3ZA5TPJ9/8+9EM4nPk3B+UghM87T61JDbNFJ8oBPTPXj2qJSS1Oj4fi3IYInTLlwGHG3HJzVhbdtir5YDA8HHOKnkW2tITLM6xRIOWdsAVzeoeOrWOQw6ZbPdP0DH5VP0HU/pShCpWfuIwnX1Oj+ylkVSxIGevanm0UoowBjua4s3Pi3VvmVvscR6Afu//sqiPhXU7jm61Xcfdmb+dW6EF8dRL8TPmqPZHbm2QqFDLuHfNMktZCuSdx6evFcU3gqbOU1H80P+NOHhzW7P5rLVTkdAJGX/AOtQqVH7NX8GVzVV0OueNWnDGNV5x04xVaeBvOxCCyk4UZrnf7Z8TaUMX9t9rhHViuf/AB5f61q6V4p029bBY2tweAkvQ/Rv/wBVN0akVzLVd1qXCvZ2ZrC6WBBBjDYPmc5qSCNkbzOsGM56VA1r5ziR5Nq7gCT1NKLthMUYDC/LjGAP/r0oyW5o43Xu/M0UmEhxn6VMpz14rOjjaGUqeV6giryyAjrkiumm+rOWpFLYsDpRn0pgJI54pwPpXdGpdaaHO0KB60ufSkxnrTh0reKfoITHrS0UmarRCFopOtLimAlFLSUwJB0FFA6CigBH7U2nP2ptACUZpaMUtQEpOR0pcUnNRL0GGfUUhINBPqKacGuWpNopIa9QuxTkdakYnOAap3c+BjFcE2mzaEW3YrsDNIQcLyBntUMjhZsPnYDyVOd1SysTACzLw20A/e/z/hTIY4w6tHhz3BHesm7bHbHRXZLFAjY2KQ/8XpRq2q2uh2AluDk9I4x1c+3t71NNPDplhLdXDbY4xuP9APeuCiEniO+uNX1Riljbj7o6YHRR/X60qNJVLzn8K/qxyVJuTsiSODU/F1z9pvZDDZKflUdPoo7/AFrp7DTLPTowtrAqHu55Y/jRpUks2nxSSwpDuGUjX+FP4QffFW6zxGInN8myXRG1Omoq4tJRRXIahRRRQAtZGq+HbHUlZvLEM56SIMZPuO9a1FXCpKm+aLsKUVJWZx8N/qfhmdLbUAbiyPCOOcD/AGT/AENdRE1teQpdWcu6MrkY6kjqPb6U+6toby3eC4QPG4wQa5GF5/CWreXJ+90+4PU88ev+8K9GnKOI2Vp/g/8AgmOtJ+R2ds/nxNHlQpGVz3PtU9pKQdoGSDyT3qhGoBjlVw6yruRx0x61fdhGySbhhhyB3PrRG73NJpbLqX1yTzUoqtFLuTgciphk9TXdSlFbHDJMkyBRkmm5Apck9q6lK/X7jMXFFGD60Yq15IAzRzS0VQhKKWkpgSDoKKB0FFACP2pnNPftTc0AJk0ZozRkVPzAMiijikIFS2xgaYwHpTiPQ0w59a5Ksu6KRG2BnPSqUksBfDFvy75q42SpGQD71QNsXdtpVsfh3rzpW6HVTt1I5bVnkKhkGBn5T/n/ACamtYmHynOAcnjvVVrSRpWOzI3bTg5q6ZRZ2c1xMSEiQsc+gFc83fRG1SVo7nIeNL2XU9Vg0S0OQrAyY7ufX6Cprm0j8/T9Bg/1KDzp/cD1+pqp4Pge7vrzVp+XZiAT/ePJp0urCw8QapK1vLPIqqiKg4VQMkk9hXdJNS9jT+yvxf8Alc5opKPM+p1VB4GTxWJYWfiHxBbpcrcw6fZy8rs5cj/PuKujwDBIc3mqXs/r8wH881EMrm/idvxLeJS2Re3L/eH50bl/vD86oy/D7SUjZ/tN6oUEn5wf6Vm6R4R0fV0laG6v08s4Icr36HpV/wBlq9uf8P8AgjVaTi5KOiOh60Vmn4fQr/qdWvE/I/4UxvCOt2xzY68XH92ZT/8AXqZZVLpIlYldUalMinimLiJ1cxsUfH8J9KyHk8TaaCb3TEu4l6vbnn8h/hUHhy+jvNV1NoVZI5Ckmx+CGxg/rXNUwVSnGUprb/M0jWjJpI6Gs/XdOXU9Mlhx+8A3Rn0Yf49K0KWuSE3CSkt0atXVmcp4SvZrqzksZCS1r8y56hSen4H+dddDayPbhT6hl55964u3RtP8cyxRrhJw2AO4Zc/zFdfZwylWzEdpUjLDnP416ta3OpLZq5lBv2dr7M0LYxlFCtyR6VZVRj1qhZRSgAsoXB5HSry7u+K6KXL1Vznqqz0ZKOKWmDPrS4Fd0ZPojAdkUmRRgUcVV2AZoozRmn8xC0lLSVQEg6CigdBRQAj9qbTn7U3NABRgelJmjNTdAGBRgUZ9qTJ9Kl8gxCo96Yy/Wnkn0pjE+lcdXk7Fq5BMh8s4rO2SO+BuPPIB+taTkhSc4rPaTaxC7ssQMjj8K4ZWOulezIIxKJiikgluQvt71X8Wzm28LXIH3pSsf5nn+Rq0rNGzLtO7fznt/nNZfjjKeH4jjcFuV3DseDWdNJ1orzHiPhLOh2y2OlW1twJNm9hnnJ5NO1hUTSL5gFUtC2SBjPFc3oOreZr91canIsDmPYoc7QmCPlGa0PFGpwvpf2W0mjmmuWCBY2DHH4fgKJYeosQk+rT/AFEpx9mdX4TQp4X04H/niD+fNPv5tU3b7BYWCE7o26t/hVrSrZrPSrS2cgtDCqNj1A5qLUdKjvVYpNNazEY863faxHofUV9EcBi2njBTcvZ6nbG0ug20J1B9OaJvEOn6FDLGLF4pSSwRV2h/fPpRpvhLTbfUjK8895PGdzGY5APb8a3NS0211S1a3u4g6sMZHDL9DQO7SsZ2najrWpxLcR2lvbwNyvmklmFadvfeZcG1mTy51GSoORj1rnrPws0Df6Br14sCnHlq2dvtW9pumWun7mhUtLJ9+aQ7nf6mgRfrh4mDeONYxjhEHH0FdxXn+jSfafE2uXIHymXYD9CR/SuTHP8A2eX9dTWj8aN6iiivmD0Tl9TbyvHOnSL12rn82FdPZyyyXAySec//AF65m4CzeP7fIysMYLfgpP8AUV09lLl8jKryTwABxz/KvWfwwXkjGG03YmtZXkYsSSCfc1oqvJ5NUrRlY/LgZPTFXlZj6V001HqjCrvoPC+5pdopMn0oyfSu2PJ2OfUXAowKM+1Gfar90NRcUUmaXNVdCCkpaSmBIOgooHQUUAI/am05+1NoAKSjFGBS1AMikz7U6ipab6jGHPpTSD61ISKYT6Vz1Ix6saIm4BHWs9onM2dwHX04OK0W9+9Z97kEhQfp61501HojqpPWxXKqZmeUnpkE9z7VbhSKeMLIiSLncFYZwR/WqcqySJHzu2/dx2X1OKtxKtuwUyqW9B1rlqJ7m9RXiVdR8PaRdLPc3FmhkKl2cMVJOOvBrm/hzoiXNxJqlwmUgbbCD039z+H9a6fxLc/ZvDl9IGwTEUB924/rUHw6mik8MrGhG+KVg475JyP0Netl8pSg22efPc6iqupLKbRjAxEg+7g9TVuorncIWKLuYc49a9AgyJoddt7SFrN7aWVTmSFxgMPZvWq9rN4jurkpObKyVTyAhdiPY9Kdq8VkHilvNTu7BpCDlZiqn29BUR/sW7njhi1S5uphnYkVyzH9P60AXtS0+ZQLmxmW3uF5aRuknswqfRpbua1WS8I3nqBVePR7aELIEmD5yPNmZ/5nFasC7YxxigB0rMsTsi7mCkgepry3QdWj0ZrqDVY5oJ5JN5zGf1HWvVKyvE4tl0C+luYo5AkLbSyg4JGBj8SKyrUo1ocktioycXdGDH4h0mQcX0Y/3gR/Os3XfEyWqwjTZYp2LbpCPmAX0/GqL6DZr8P11XyyLzdnfuPI37cY6dK29O8NaPe6NZzCJk81UkfDn5iBgg+2SeleXUwlDDNTldo39tOasjP8LWss7XWs3uQ1wdsX+1zyR7dvwrqLYbYZQpByAOR7+tQ3EXllYYwqoigBAPlX0FTO48qOEjkjJKjH6fnUcznLma0OmMbQS7luziKgblA75FXFUDoahgGYyVb86nUkdRXbTUOqOOo22Owfajn0pdwpa6oxT2ZkJmjNLRV2fcQlLSYoxT1AWkoopgSDoKKB0FFACP2ptOftTaACkzRilpagJk+lJg+tLmjk1D18xiYApM56CnYFFQ6bfkFyJkJ61DNGm0s/b0qwx9OaiZckhvyriqRitjWLZmyXcrEqu1I+hwMcfWoYYWWRQfl9M8FvpV2WFYm8wfeHT2qrKWu5Tszu/hDdh71xzjfc7YSVtNih4tje88N3CW4LFGV8DklQefyrkrPXE0W8iv8ASGwsqBbi0fOAw64PoeoPUZru7ZyhcDAx1yefrR/Y+k3Uqzy2Fu0h53bcbvqB/WtcNilh4uMloc1alrdDtI8Z6RqSqrTC1m7xzHH5N0NdAjpIoZGVlPQqcivPvF9hp8t1b2NlZRjUbg7i6fKEUdyBx/8AqqEeE7i1w2narLC469VyfwNd6xtJJOelzFU5PY9CurS3vITFcwpLGequMiorLTLLTy5s7aOEv97YuM15/dN4psHtYv7YMjXEoiT5s8n1JFXGsPHgJUXgYeokT/CumFSNRc0XdENOLszvyAeozQSFGScAVwA0nxvIn77UxCo5JM2MfkKydI0q41+B7i91S4dFkKbdxbOMc5J9/SlVqxpR5p7DjFydkegah4l0jTlYz3sRYf8ALOM72P4CuF8SeItS1/T5jaWkkOlxkeY5HL88ZP17CtM+E9J+zmIROGI/1m87h/Srvh683wzaFqCoZbVdoyOJYuxxXF/aEZRbgtvyNJUZR3MnVda0seALfTradZJ3jRTGOqEEFifTkH8629Fglh8N2kfSRIslTweef60yDw5o1ndmZLNdw5AkYsF9wDUzLMZcnJGTgryDXPiMRHEWjFaG1Gk07sks2kjldmyFAywboR/n+lXIWjuJmP3TwFUjPakcx3CiF2Jkzy4/r61PDAITycjtVU4uJVSaer0ZOsYAAxjFPAI96auR71ICDXbBQfkzkbYmR3owO1Oxmk2+hrXlfXUkOR3oz7UcijNUvUBc0UYpMVWohaSiimBIOgooHQUUAI/am05+1NoASjFLRSsAUUmaMZ60r9gAn0pMZ60vSkwT7Cokr6PUYh9AKaU49akxjpTSewrOUEtZDTIJYhIu3v61RaExyccrnp/XPr71pMMfWo3gEindxnrXHKDkzeE+UyjGjq+2TbtHGRjfSWxIVyzYKjOPap3gYSkj7g4wRkGo5jGxeIJnkEMOo+lc06dzrUr6HOaEzah4h1PUpMkK3lR57DPT8h+taWrXclvcafDC+1p7gK3uoHI/lVDwcf8ARL0YwRctn8hSa9a6nPrNlLYQh1hQlXYjarE9/wBKiolLEuMtEl19DFaU9C/qgB1XRMjI+2D+VM8cam87xWWmXhWS3V7idoXPyBRwCR+P6Vny+Hby7jabVdSkldFLLHHwqnH+e1M8PWNxrOlJaxA2OnhcXEiKN90+fX0Fd+Eq06VFrmvb9TCsm5XtuGnavdw6e+iT3JWS7KuLuZ8BInUFiCep6ge5NM01Gg0LWo7GRl8md/LdTzgY7/QVF4mt5dMgi0trlLy2ypi34823APTjsf6VeuPDUtuXfRrtrfeMPC5yrf596MTVpyUfe0e3bR9RU4vVo2tOulvdPguV/wCWiAn2Pf8AWsvxCfsN3YasgOYZPLkx/Eh7fz/Ol8K217ZWUtrexFBHJmM5ByD1x/nvS+L8f8I/KT1Dpj868ymlDFcsdVe3yZ1S1p3ZreXJcz7UZifvAnjirMLLHG0YY7mHIXt/n+tR22JLdEUMH2qSx7HHQe1Wra1x83KsOprtp0ug5zVtRLez8og5BXuavrgr049KaF2jgfL3pwGOVrrguR2sck5OWrF2kdPypeDSg5oIzW/IrXjsZXE5HvSgg0ZI60YzVRv0AWjFJyKXNXdMQmKKWiiwBSUtJTAkHQUUDoKKAEftTac/am0AFJ1paKQBSfSilpbgIBS0UnWjbRAJnPTpR04FL0oA796izb8xiBcc96Y4zwKkJxTcYGT1rOaSXKhoiKjv1FVZbTLhv9rNXwvHNNI547Vi6do3e5pGbT0OH0Uppmtanpk7CNzN5kW7gMD6Z9sV0OD6Vz3jm5sruVNPt7f7RqeQA6dYx6H/AA7VhGx1PTxtvYL14+z28x+X+Yrkr4SNSXPzWb6GtOq0rWO6uMi2lOOiN/Ksrw0ouNDtojrLRKqfNChRWXk/xYziuVeew+0W6Nf6kIWYi4Eh5VfbHWuottc8KwWUNsWEqQrtUzW5ZvzxUrDSpQsk3fy9SZ1OZi6+mmR+H5F0/wAtlS4j8x1O4k57t3P41tVg6z4i8O3+mNYmWcRkgjyIsbSPrgVycZt5Z5lgGozx5/dBWAJH+1gH9KPqsqsPeurX3+XoEKnIz0G61Gzs1LXFzFHjsW5/LrXNX+or4mv7bSbLKRNJueR+NwA7D6ZrNttB1KZ8w6eIAf47g5I/P/CtBvDeo6aU1G0uxLewneV29fp68VdKlh6Ek3O8un9L/MqUqk1toegQ2qxxKMAFBgAelTLnqKzPDWtw65p/nKAk8fyzR/3T6j2NaxGDnsa75U7amDlfcUYIyKMY5HSjoc9qdWqXMrPdEDcZ5FKD2PWkIx06UuAaFdPTcBaTGOlAPrS1ekhCA0YpaSn6gFLRRTAKSiigCQdBRQOgooAR+1Npz9qbQAUUUUAFFFJSAKKKAKVuiAAKUnAopOpoemiAQdcmgDJz6UMQByQB6muTufEmorqbRWcMckUknkQq6nCtkgMze5Vjj0HWs3yrfYZ1NxcQ2sRluJUijH8TsFH61hav4ijTSrmTShNczBDtkjiYonqxbGOBzVmHSYt4nvj9tuupllGQP91eij6U/V7aS70i7toDiSSJlTtzjpXBPHRc1yrQtQdjzzw2+qyNM2laeLm4Y5kuH5xntkkCt4r4zjG9tPgYf3QV/wDiqXwf4lsNIsf7K1JHtJo3bLsvBJPfuD2rs4dV06dN0N9bOD6Sr/jXdLD0pvmlG4lOS0TOATxLAblrXWtOEMinaxK7sH3B5q5dSeGoIVnkSzYOMqEQMT+Are1XQfD+rs8s5hWd+s0UoDZ/ka4vUPDz+Hrtb6D7LqlonLI5BIHuuf1Fc88DC94NryTLVZ9TT0vUfD10SsMEEDDtLGq5Hsadd+KdPtW8mzQ3MhOAsQwufr3/AArH1yfS9bFkukWJXUJzh1QbQvsR0P19K7Dw9o2j+HbdZJ7m2a8x88zuo2+y56Cs4YGFT3p39GN15JWRipd+KrwbrXRhEp6GUYP/AI8RUhsfGhTcVtUwM4ytdTJ4k0WPO7U7Xj0kB/lXP6741imQ2Ggo91dTfIJFU4XPoOpP6V1LC0Ir4UR7Sb6nLeF9Qv18TC5toDM0ufOiiAUMvf2Hr9a9DXxBYghLxZ7Fjx/pMRVf++vu/rVLwrop0XTAkoX7TKd8pHb0XPtWwyq6FHUMp4IIyDXFPMFGXLFXiPkvqWEIYAgggjIIOQRSjj6VzV5I/hgiW0UNZTvsNuzELFIejL6Ke4H4VoeHNYGsWDSSNF5yyMhCAqGA6EA89xXbRqKpHmiQ1Y16TpQPSlrf4iROtHSjpS0AFFJ0paoAooooAKSlpKAJB0FFA6CigBH7U2nP2ptABRRRQAUUUUAFFFFLYBOtHSlqhrGqRaTYtdTDdggKm4KWJPv+tLYDK8aSutlbQYUxzS/Pu+6QoyAfbPJ+lc/eWd9oUscZZXhaVZUmwWCFMnpnPQkYzzng1cu9R1XxHbNFBp8IWKTOMhiCPqw4IJHTkGs68h1xfs0F5CVhDbEBnVtu4EYB6/TJ64riqyTkkpK3VFoda69qGm6o5u3eXzJD5sDZXGe43fdx+WB361rp4ytjqAR4ilmcL5pzuQnuR0x9D2rE8Qaml5DA89s8WpWzBXyABIvcEHkfTHrUurnTbuKHVNLnigk3DzrckKcnodvqDjpx3rB0oTs5R30/r9B3aNe91Hw9qt99lvIo5V+6Lk4AB9M5yPr0zWXPofhY6h9k+03ELHo/mDyycZxuI64NQ6xo2/S4dT06XzInC+ekvzFT6k9eD1z0+lQano/2fTI9RsXEtpLtMquoLxP/APtZBp04xSSjNrp8wZZfw74aS9W2Op3ALAESbl2c9BuxjOKkm8K+HonhjbVZg0wyjBlKnnHUDA5qPV9CgsooLuzYTWk43HfychSw+oJH8xUfiHRmsjBcCUTw3K/OwAU5C7jgDjnnH1pqTk1ao9Q+RLd+GNFtYFmj1eUYYxnywHZ2HUAD0pp0bwrbxK76hPcMwBCI4yc/hx+J4qLVNFmguoLbKSTSJGBkADDHaR/wFsY9j7VPrOkLa3NrptrK0kjKmA54DltpOOwIz09Kak3ZOo9RfIebTwfDZLcbHkc8LC0xDk5xg84H1rQg1rw/pNksthbBJJFGECEE+oLn078msi+0OI6xb6PZOZGAUzO33QeSTjoMLjj3FTato9u+uWul2LMrBF8xyc+pJPvt/mKhqErKUm+u/Qepp3HjS3W0EkFpK8hAGCRtVj2PfHvjmqGoeL7qXTALeJIJXAV33fMuepA7Dp3yM9Kh1e20+bUrbTbOSOKFAI3m3D727cxJ7kAfmcUmu3FhLcWdlZQl7G34Yxj7+WBbnv8AdxnuTRClSvG0fP5A2yq15qcFhZzyNIYS7SQq/wAw3dMgH5jjdkZPNXLWwm0LUdNbKrKxV2QAblDOqEMepyGPtkcUmr3OoalJaahFaNBbQSLHbwkDdIxPYHg/dHtxU8cOtRXw1K5sHldTvAkIcEgcE7SMYycADAznrWsJWabaXcR35HNIDWBo3imDUJ4beaLyZpiRHtbcrEdfQj8R+Nb9d611RAtJS0VQBRRRQAUUUUAFJS0lAEg6CigdBRQAj9qbTn7U2gAooooAKKKKACiiigArldW0yPVPENzbXssqbrZTashxheQ49Cc4z7Yrqqo6rp/26GNopPJuoG3wS4ztb0PqD0IrKrBzg1F2Y0eZyWcOmXxt7m6ZmjkZC6tjaB02nIBPPIJ49KuLHptygis7K/nlk4VndRux3G0Ennv+tdDJZ6VqNw0Gq6cltqLZO0sVEp/vIw4bP51g/wBn+JrKcm2tJF2oE3ROBlR0HB5x9K4vac2ktJLu7FWNmyv9X0u0DavapJAvCSPKol+mCfmP60xZvCWoTlpYUhmPLLKrR/njisJLyCG8dtca6upozgKX2Ej3zyPoMfjV2PUm1dmsLOK30mxAzNJkAlfQnjOfTvWbpW97bzWi/UdzTXw1aXBc2OqEwSdUBDj9CM/jmnS+EZArRQajIIZABIrqct9dpAP4ismeDTZ5V07RbXzpnOGunGGY4/hPYY5JA6dOoqfUYLfR7aKxtru5uNUmYL+7nYbPoM4HoM1H7y6Slr6L7w0LT+GNSihFtbaihtwwdRJkYYHOcYI/LGahvtD1ma1W0TYYoiSgEg2jIIIUkbhweAenrUmqi80extUOq3b3srfN+8DDA6gAj1IUfWn6lLrGmw2EI1Rnu7g4ffGhVeQOOPVhSjKo7NNO/l+I9COWz1/U545JYI7eWFVUOxAHDBs98kkD2FPHhfUWuFu31NftJyWb5sg4xkHvxx2x2p2ty6xpUlq39qtJbyyBHIgQOv04x0purPqGm6taJcavc/Ybg7C4CKUP1x7g/nQnNpcrSvfp/wAANCVPCLwOJrXVZ4rkgh5AvXPpz/PNPXwbaj55Lu4kmOd7uFbcT35HFVNWS70i/hkutQvbjT5Cd2JSrL6/dxnA59wDTNW00QRxana3El/Zkgsk0zOADx1z07eoNJOo7e/v5fgGnY0JdI8O2UOLqWNXXrI8+H+nHb2xUNvrmkWebbQ7U3Mz/wB07A593frVEafpU6fb/D1wLe7QZMBbk+ow3f8AMGq1xrGlXNu/2vTWjuFUbprUKA3ocHt7HNUqfNvd/wBdv8mFyXU2vrqVZvEFjc+Qh+RITtWP3zyCfckVj6lPpK4gtBfqGYb0l2gY9Rj+tWojr13YodP+2TW5yCm4hQM9Ac8jsR2xW1pumWlpppufElrCsoISMSYb5R0VVHuTxyTW/MqS1+5f5E7lXw/4cspLFtSvLyb5C33X2+VtPUn1GM+ldloM9xc6JaTXZJmdMkkYJGeCR7jBrPttOm1Py2u4fsmnRkGKyAAMmOhkx0H+z+db/SumhGorym9+nYTt0CiiiukkKKKKACiiigApKWkoAkHQUUDoKKAEftTac/am0AFFFFABRRRQAUUUUAFFFGKAIbq0t7yAw3UKTRn+Fxn8R6Gs06VeWhzpt+TH2gux5ij2DfeH61sUVE6cZq0lcd7HH3emQvdtPqui3W9m3M9tIZYyemcA5HQdqytR0bS9RvAtjfWtmgAxHKWRlOTn5Wx1yPyr0Xmo5oIpxiaGOQejqG/nWP1ezvCTX4jucLceGrjTbFp9Nu2uGBAxGh3sCRnlW5HGaq6foOtGeC8FoIXjIKh3Gd2fvFfT9a7aTw/pLnP2CND6xZT/ANBIpg8P2yj91c38X+7dP/Umo9jVStzJ+qC6PP8AdqN7qa3piluZoHBZly4XDZAIA45HQfl3p9/eapqOr/v4Jlu4ztit4xnYByT/AOgn3rvDoRBJTVNRT/topH6rTf7DnVzJFq1yshGC7RRsSPrto9lO+y/H/ILo4vWdXfW2tvOWS1tkBVpFXdiXH/6uOoGajvLvVNb0m1W4sppoYn3iVIyWdRwe2PXn9K7WXQriaFoZtUeSN+WVrWIgn16VImi3AjVG1i7CqMARpGmB+C0lRkkkktPP/gBc46wg13VdK8pI/Os0kKoJWCuCBgde3Pv0xUumeGtYWSaGbFtCU5/eEpJ2x8p+vWuu/sGM/f1DUnHfNyR/ICj/AIRvS2/1sEkx9ZZ3f+Zo9jVd0ml8gujjpfDMVtfRm91SxFv5hd137HGeoA5zVo6ToExxbpqN+2MYgDEEdhnAXH412FvpOnWvNvYW0Z9REM/nVznGO1X7CTtzTfy0C5zlhYanHbC3srWDSrfOSZX86Qk9TgcZ+prSs9Ht7af7TKz3V3j/AF85yR/ujov4Vo0YrWFGENYrUTbYUUUVqIKKKKACiiigAooooAKSlooAeOgooHQUUALS0lcDrHjLWbLVrq1gs4niikKqxjYkgfjQB39FeYr8QtZdtqWtszegRif50/8A4TzXv+fCH/v0/wDjQB6XSVwmheMNY1DWba0ubOJIpWwzCNgRwfU1c8S+JrnTdej06PyRBLEC7vkFCc8g5oA6+iuC+HOqmQ3kd9fM8jFPLWaXJPDZxk1R0rxYV8UXNze38yaeWcpEMsp7KMduOaAPTKSub/4TvQP+fqT/AL8t/hWxPcLPo0tzAx2vbl0bocFcg0AXKK8k8PeJtWsJpmjjm1AsoG2RnfZ71b8T6/qd3Yafct51hI7Sq0cbMmQNuCfzNAHqFLXnsHjq/uJbW307TXnVAolzl3kwOcY6fXmux1bVV0vR31GSB2VApMfAbkgY/WgDRpK4f/hZVp/0Dpv++xXM3Xi2+l11b6O4uBbpKHSBn4A7rgcetAHr9FcN/wALKtP+gdN/32K6Hw5r8fiC1lnigeERvsIYg54zQBsUUlcJrnirXbHWLq2tLNJII2wjGFjkYHcGgDvKK8wl8e69AQJraCMnpviYZ/WpB428SEAiwjIP/TB/8aAPSqK5nwfrep6w90NSt1hEQXZiMrnOc9fpWR4p8UXcuswadoNwQ8bYd0wQzenpgd//AK1AHe0VwXiLXdW0u70+8gvYruxwA3lY2u+PmDY9eo/+tVHWfE0tx4ot2s9QmtrMiIP8xUAHlsj15/SgD0yisZfFehMwUanDk9M5A/PFQ+LdWvtJ0+GbToRNI8m0goW4wTnigDforzNvG/iNFLPYxqo5JMDAD9abF488QTgmG1gkA67IWOP1oA9Oorzuz8YeIpr2CKWxRY3kVWPkMMAnnvXZ6zrVpoluk96XCO+wbFzzjP8ASgDRpK5f/hP9C/56T/8AfquR0rxM1v4nku7m9uWsi8pVSzMADnb8ufpQB6tS15JB4t1Oy1eSWPUftUEj5bzEO0g+i9V/CvT9L1G31WxS8tSxickAsuDwcdKALlFFFACUjsERmPQDNLWN4s1NNL0C5lLASSKY4h6seP06/hQB5n4d1tNF1mS+eFpgysu0NjqQc/pXV/8ACy4P+gZJ/wB/R/hUHw40eG4tru8u7eOVGYRxiRAw45JGfqK3/FWn6da+G7+WOxtkcRYVliUEEkDg496AJvDPiRPES3DJatAICo+Z927Of8K5rxB4dvdW8V3MtyjxWggLpKvzAhV6fXParXwvTGm3z+swH5D/AOvSeK38USapPbacZfsPlhtyKFAGOQWP0NAHG6XYXE1jc3tmWM8DBdqkZ2sGBIHUn6VI+kKk+nWDKReT4kn5/wBWrdAR2IUbj9al8M6dcTCfVLUNJLp7I6wouTIeffpxz3pfMmt7G61i9J+2X5aKDd1wf9Y/sMfKPqfSgDGuRGZ5XgQrB5hCZ7DsPyr16X7RH4LH2RA0wsl2qR1+QZ/HGa831mxOnaFpMbria4D3Dj0B2hf0H616yqmHSgqnBSDAI7YWgDyzSNP8T2MU01hb3FsjpmR2AT5Rz/FSagL3VtHtpDctqFxC7tIELO0aMFxnjgZBqC01DUNREsNzrz28ZXB8+VyHB6jjNT2dobAsbPxPaQF/veW8i5/JaALreKdW/soafaaZ9lbaqiWFGVuMc/U4rpbq31G88ASrq02y5ZN7s6HKqGB5Cjrgelctoural/wlNnavq811CZ1UssrFHH416qyhlKsAVIwQe9AHkFhrken6abCzsLe6uWlJW4kiDHBxgBSM/n+VdnpllqMnht3uNGsP7SxiLzI1UsPVhjAPt/Ks7U/Bd/b6oJ/DzpbRbMZMxDbsnPb6Vz1xP4httaGlSapP9pLqnE7bctjHP40AF7qd/aWk+marpsCySLgStAqSLz1BAwf88123w+s4rbRHkhnaaOeTcC0RQjAAI68/UVjweE/EFzeW66xdJdWayAyI87Nx3xxXewwx28KQwoEjQBVVRgACgAmfyoXkxnYpbHriuE/4WYv/AECz/wB/v/rV3xAIIIyD1BrOurLSLO2kuLizs44oxuZjCvA/KgDy3xT4h/4SG6gm+zmARIV2792ec56V0UXxISKJIxpZwihR++9PwrmLsNrup393bQrBBEjS7VUAKi8AcdzxXU/DWztbqyvjcW0MxWRcGRA2OPegDS0HxuNa1aKxFgYfMDHf5ucYBPTHtWd41k0vR5ZjYxIup3cexyvSND1bHZiOP889ZZto326SG0SzS7hJVlRFV1P86898a6cNK8Sxy2bEvcYmCv8ANtfOO/UZ9aAIdGvpvDlx9k1WxRoLgLMFmX7rY+Vvp61FcaXcRx32q6xCXBkXZh8LMznOVYdRj+lGtvrlxf2thrshDswKblTKhjjOV+nT2rX8di30rStO0K1diseZW3Nk+gz9SWoAw0sYLnVNJjtbd4lutpZWbePvkHBx6Cu88SeMRoGpLZmyM2Yw+7zNvUkYxj2qv8Ob6O70ZrOTBltJCVB5IVuQR+Oa6mextLh99xawSvjG54wxx+NAHnurePxqOl3NmNPMZmQpv83OM+2KzvC3itfD1tPEbMzmVw27zNuMDHoa0viBeWCPHpen21usqtumaKNQQey5A/E/hWHpuntZeLbGyukVmE0fmIwyOcHBH40AdN/wsxf+gWf+/wB/9at7WFtdX8MRX11YS3KiMXCwRuQckeo9AauXkOh2HlG7trKEStsVniUAn0zirklzaWdmJnlhhtkXhsgKB7UAef8AhWz8N66Wt57HyLxckIJnw6+3PUVzqR2Fr4leG8iLWKXDRsu4ghckA568dfwrTv8AVtMtdbmuvD9q0lxI37uR1+WNj1KJ3J9/yrJstOutX1aW2JIvG8xyHGCzjJIPoTzQBveIk8N6Vfw2tnYfayDmbE7cA9ACD1716Dotrb2elQRWsElvEV3iKQ/MueSD+deYeDrjTLDW86xGyupxG7/djf8A2h/XtXriOsiB0YMrDIIOQaAHUUUUAJ2rzPW9M8Qa/wCJzZ3SBVi+6yg+VGh/iz3z+fFemUtAGbFZHSNCNtpirvgiPlhxkM3XnHqf5155rHibWtcsTYNYBFdgW8qNstjoK9VooA5/wTpc2k6AkVymyaVzIynqueAD+ArZvv8AjxuP+uTfyNT0lAHAfDDcINT2gbvkxngZw1Q/8I7rWteI57nV4lRIBlR1jfHKovt6/j3r0QKq/dUD6CloA8odtV8XeILUzWnlrHtQhUISNAcknNepXXFnN/1zb+VS0UAeI6OGMsm3Sv7R+X7pD/J7/Ka1dsn/AEJ4/wC+Zv8AGvWFRE+6oX6CnUAeO6ICPGdnm1+yf6Qv7nn5PbnmvVNanurbSbmaxjMlyi5jULuyc+nernlpu3bF3euOadQB51/wkPjT/oGP/wCAjVi3Fv4iudZGqyaXcfaQ6vxbttyuMcfhXr9FAHnX/CQ+NP8AoGP/AOAjV1fha91S+0+STV4DBOJSqqYyny4HOD75raooAa+7Y2zG7HGema8w1OLxP4l1aSxnhKLC+GRfliT3J716jRQBzNv4Vj0/wveafbESXVxEd8p43tjgewritJuPEvh4TQ2unzL5jAsHty3I9DXrVLQB514P0rU7zxO2salbyRBdzlpE2bnIxgD8TR8Rre5m1uya2ikciIYKqTg7jXotFAHmE/h3xXe6jBd3sInkiK4LyoOAc44qbRdF1DXfFc99rERVLeXMgYcFh0Qeo6fh9a9IooA85Oi6roPjOM6THuhuGJTd9zZ1ZW9Mf4Vs+N9Q12zWKLTY8QT/ACeZEpaQN6e31rraKAOE8JeC5YbhdR1hf3indHATk5/vN7+1UPFml6rZ+Km1SytZZVLLLG6JvAYAcEfhXpVFAHk+pzeJvEhhtrmxlIRsqFgKDJ4ySa7LV/CS6j4esrFJFjuLRFCSHO3oA2a6eigDgNRsV8DWttd2NvDdyyMUkmnUllOMjbg8DrVDwNbXl54pbU3gZYv3ju+0hctngfnXppAPUA/WigDl/FHg2DWnN1autveH7xI+WT6+/vW1oulQ6NpsVnASQoyzE/ebuav0UAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQB//Z" />
</body>
</html>

  5.运行效果

 

  6.项目代码

 代码托管:https://gitee.com/Jesai/JESAI.HtmlTemplate.Pdf

猜你喜欢

转载自www.cnblogs.com/dengjiahai/p/12956165.html