Toggle navigation
Toggle navigation
This project
Loading...
Sign in
万朱浩
/
Venue-Ops
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
马一丁
2025-11-18 01:13:25 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
dffe1618d5fc5975e5befaf01ef1a346a03927ea
dffe1618
1 parent
fdd836bf
Add an "Export to PDF" Button and Define the Font for Exporting to PDF
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
39 additions
and
1 deletions
ReportEngine/renderers/html_renderer.py
ReportEngine/renderers/html_renderer.py
View file @
dffe161
...
...
@@ -10,6 +10,7 @@ import html
import
json
import
os
import
re
import
base64
from
pathlib
import
Path
from
typing
import
Any
,
Dict
,
List
from
loguru
import
logger
...
...
@@ -74,6 +75,7 @@ class HTMLRenderer:
self
.
toc_rendered
=
False
self
.
hero_kpi_signature
:
tuple
|
None
=
None
self
.
_lib_cache
:
Dict
[
str
,
str
]
=
{}
self
.
_pdf_font_base64
:
str
|
None
=
None
# 初始化图表验证和修复器
self
.
chart_validator
=
create_chart_validator
()
...
...
@@ -97,6 +99,11 @@ class HTMLRenderer:
"""获取第三方库文件的目录路径"""
return
Path
(
__file__
)
.
parent
/
"libs"
@staticmethod
def
_get_font_path
()
->
Path
:
"""返回PDF导出所需字体的路径"""
return
Path
(
__file__
)
.
parent
/
"assets"
/
"fonts"
/
"SourceHanSerifSC-Medium.otf"
def
_load_lib
(
self
,
filename
:
str
)
->
str
:
"""
加载指定的第三方库文件内容
...
...
@@ -123,6 +130,22 @@ class HTMLRenderer:
print
(
f
"警告: 读取库文件 {filename} 时出错: {e}"
)
return
""
def
_load_pdf_font_data
(
self
)
->
str
:
"""加载PDF字体的Base64数据,避免重复读取大型文件"""
if
self
.
_pdf_font_base64
is
not
None
:
return
self
.
_pdf_font_base64
font_path
=
self
.
_get_font_path
()
try
:
data
=
font_path
.
read_bytes
()
self
.
_pdf_font_base64
=
base64
.
b64encode
(
data
)
.
decode
(
"ascii"
)
return
self
.
_pdf_font_base64
except
FileNotFoundError
:
logger
.
warning
(
"PDF字体文件缺失:
%
s"
,
font_path
)
except
Exception
as
exc
:
logger
.
warning
(
"读取PDF字体文件失败:
%
s (
%
s)"
,
font_path
,
exc
)
self
.
_pdf_font_base64
=
""
return
self
.
_pdf_font_base64
# ====== 公共入口 ======
def
render
(
self
,
document_ir
:
Dict
[
str
,
Any
])
->
str
:
...
...
@@ -221,6 +244,8 @@ class HTMLRenderer:
str: head片段HTML。
"""
css
=
self
.
_build_css
(
theme_tokens
)
pdf_font_b64
=
self
.
_load_pdf_font_data
()
pdf_font_literal
=
json
.
dumps
(
pdf_font_b64
)
# 加载第三方库
chartjs
=
self
.
_load_lib
(
"chart.js"
)
...
...
@@ -263,6 +288,10 @@ class HTMLRenderer:
{css}
</style>
<script>
// 预载 PDF 字体 Base64 数据,后续由 jspdf addFileToVFS 使用
window.pdfFontData = {pdf_font_literal};
</script>
<script>
document.documentElement.classList.remove('no-js');
document.documentElement.classList.add('js-ready');
</script>
...
...
@@ -330,7 +359,7 @@ class HTMLRenderer:
<div class="header-actions">
<button id="theme-toggle" class="action-btn" type="button">🌗 主题切换</button>
<button id="print-btn" class="action-btn" type="button">🖨️ 打印</button>
<
!-- <button id="export-btn" class="action-btn" type="button">⬇️ 导出PDF</button> --
>
<
button id="export-btn" class="action-btn" type="button">⬇️ 导出PDF</button
>
</div>
</header>
"""
.
strip
()
...
...
@@ -2793,6 +2822,15 @@ function exportPdf() {
}
showExportOverlay('正在导出PDF,请稍候...');
const pdf = new jspdf.jsPDF('p', 'mm', 'a4');
try {
if (window.pdfFontData) {
pdf.addFileToVFS('SourceHanSerifSC-Medium.otf', window.pdfFontData);
pdf.addFont('SourceHanSerifSC-Medium.otf', 'SourceHanSerif', 'normal');
pdf.setFont('SourceHanSerif');
}
} catch (err) {
console.warn('Custom PDF font setup failed, fallback to default', err);
}
const pageWidth = pdf.internal.pageSize.getWidth();
const pxWidth = Math.max(target.scrollWidth, document.documentElement.scrollWidth);
const restoreButton = () => {
...
...
Please
register
or
login
to post a comment