HTML生成图片和导出PDF功能设计与实现 - 图2

1、需求背景:

在教学场景中,学生作答教师布置的纸质作业是常见课后场景。但当前作业本没有覆盖到使用纸质作业布置的教师用户,并且无法收集混合布置(线上作业+线下作业)教师在线下布置时的学情数据。
经过调研,教师在使用纸质作业时主要会遇到批改久、统计难以及挑题麻烦的问题。
因此,作业本将向老师提供答题卡作答模式,支持教师将题目打印为纸质作业进行分发,通过学生扫描二维码线上作答回收学情数据。

2、功能流程

3、功能设计

3.1 纸质作业预览设计

预览是提供两种方式,一是默认的缩略方式预览,二是以模态框的形式放大至A4纸张大小进行预览。如下图
一方面为了让两种预览方式保持一致,另一方面为了方便快速生成PDF,选择了图片方式预览。

3.2 实现逻辑过程

主要逻辑步骤
第一步 会在页面创建隐藏的容器id为PreviewContainer,用来存储作业预览的模板页面。
第二步 根据老师添加作业数据生成预览模板页面
第三步 根据模板生成图片
第四步 根据图片生成PDF

详细逻辑设计如下

3.3 具体组件与方法设计

考虑逻辑解耦和复用。将不同功能逻辑放在不同文件中,以便复用。
为了方面扩展,颗粒度拆分的比较细,例如渲染作业描述、题干、选项分开实现,以便在后续过程可能会引入答案解析和其他。
生成图片和下载方法作为公共方法,以方便其他业务逻辑使用。
主要文件氛围三块生成预览模板的文件集合 previewTpl,操作方法文件action.ts和previewTask预览作业组件。

1)生成预览模板文件

该文件对外主要提供生成预览模板和更新模板的作用。内部有如下文件与方法

  • 渲染题目字符串的方法与样式
  • 对作业数据进行分页
  • 根据每页数据进行渲染页面真实DOM
  • 还有更多诸如图片加载与数据处理等其他辅助方法没有标识出来
  • 图片2所示里面的详细文件结构

这里有一个必须要注意点是一定要等到图片加载完了之后才能知道每道题的高度,由于A4纸每页高度是固定的,每页能承载多少道题必须要通过计算出来。
然后才加载每一页的数据进行渲染。

2)文件操作相关方法

该文件主要提供以下操作方法,具体方法见图4

生成图片方法目前是采用html2canvas,后续如果有其他更好的方式可容易替换

  • 根据图片生成PDF,生成PDF使用的是客户端下载方式jsPDF(前端生成PDF文档方案
  • 下载文件方法
  • 其他辅助方法

图34

3)PreviewTask预览作业模板组件

该组件主要提供给习题记录里面查看学情报告可以预览作业和下载作业PDF。
以弹窗的形式预览作业和点击下载。该文件里面主要是组装和调用前面两个文件里面方法。

// 参数
interface props {
visible: boolean;
closeDialog: () => {};
// 需要预览的数据
previewList: any [];
}

最终效果

4、其他后话

总的来说,设计逻辑比较清晰,上线后性能差强人意,但还是需要做进一步的性能优化。