This commit is contained in:
MarkLo 2025-11-27 03:58:07 +08:00
parent 2065323a59
commit 44705c79a7
4 changed files with 250 additions and 64 deletions

View File

@ -21,83 +21,82 @@ import markdown
class PDFGenerator:
"""Generate PDF reports from markdown content"""
# Emoji to Unicode symbol mapping for PDF compatibility
# Emojis don't render well in PDFs, so we replace them with Unicode text symbols
# NOTE: Use ASCII brackets [] not full-width for better font compatibility
# NOTE: Avoid [文字] formats - use pure symbols only
# Emoji to safe ASCII character mapping for PDF compatibility
# STSong-Light font has issues with certain Unicode symbols
# Using ONLY ASCII characters to ensure perfect rendering
EMOJI_TO_UNICODE = {
# Status & Indicators
'': '',
'': '',
'⚠️': '',
'': '',
'🔔': '',
# Status & Indicators - ASCII only
'': '[OK]',
'': '[X]',
'⚠️': '[!]',
'': '*',
'🔔': 'o',
# Rating & Quality
'': '',
'🌟': '',
'💎': '',
'🏆': '',
# Rating & Quality - ASCII only
'': '*',
'🌟': '*',
'💎': '+',
'🏆': '#',
# Charts & Analytics - pure symbols only
'📊': '',
'📈': '',
'📉': '',
'📋': '',
'📌': '',
# Charts & Analytics - ASCII or empty
'📊': '',
'📈': '^',
'📉': 'v',
'📋': '-',
'📌': '*',
# Money & Business - symbols only
# Money & Business - ASCII currency letters
'💰': '$',
'💵': '$',
'💴': '¥',
'💶': '',
'💷': '£',
'💴': 'Y', # 日元
'💶': 'E', # 歐元
'💷': 'P', # 英鎊
'💸': '$',
'💹': '',
'💹': '^',
# Direction & Movement
'🚀': '↑↑',
'⬆️': '',
'⬇️': '',
'➡️': '',
'⬅️': '',
'🔼': '',
'🔽': '',
# Direction & Movement - ASCII arrows
'🚀': '^^',
'⬆️': '^',
'⬇️': 'v',
'➡️': '>',
'⬅️': '<',
'🔼': '^',
'🔽': 'v',
# Symbols
'🎯': '',
'🔥': '',
'💡': '',
'⚙️': '',
'🔧': '',
'🔨': '',
# Symbols - ASCII only
'🎯': 'o',
'🔥': '*',
'💡': '*',
'⚙️': '*',
'🔧': '>',
'🔨': '>',
# AI & Tech - symbols only
'🤖': '',
'💻': '',
'📱': '',
'🖥️': '',
# AI & Tech - remove or simple ASCII
'🤖': '',
'💻': '',
'📱': '',
'🖥️': '',
# People & Roles - symbols only
'👤': '',
'👥': '◇◇',
'🔬': '',
'📚': '',
# People & Roles - remove
'👤': '',
'👥': '',
'🔬': '',
'📚': '',
# Time - symbols only
'': '',
'📅': '',
'⏱️': '',
# Time - simple ASCII
'': 'o',
'📅': '-',
'⏱️': 'o',
# Other common emojis - symbols only
'': '',
'🎨': '',
'📝': '',
'📄': '',
'🗂️': '',
'🌐': '',
'🔗': '',
'💼': '',
# Other common emojis - ASCII or remove
'': '*',
'🎨': '',
'📝': '-',
'📄': '-',
'🗂️': '=',
'🌐': 'o',
'🔗': '~',
'💼': '',
}
"""Generate PDF reports from markdown content"""

93
safe_emoji_mapping.py Normal file
View File

@ -0,0 +1,93 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
最簡單的解決方案完全移除可能導致問題的 Unicode 符號
改用最安全的 ASCII 和基本中文字符
"""
# 問題分析:
# STSong-Light 對某些 Unicode 符號的支持不完整
# 可能將某些符號(如 ★ ※ ◈ 等)錯誤渲染為「煉」
# 解決方案:
# 1. 完全移除這些 Unicode 符號
# 2. 改用 ASCII 字符或簡單的中文文字
# 3. 如果必須使用符號,只使用最基本的 ASCII 符號
SAFE_EMOJI_MAPPING = {
# Status - 使用 ASCII
'': '[OK]',
'': '[X]',
'⚠️': '[!]',
'': '*',
'🔔': 'o',
# Rating - 使用 ASCII
'': '*',
'🌟': '*',
'💎': '+',
'🏆': '#',
# Charts - 使用簡單文字
'📊': '', # 完全移除
'📈': '^', # 向上
'📉': 'v', # 向下
'📋': '-',
'📌': '*',
# Money - 保留貨幣符號(這些是安全的)
'💰': '$',
'💵': '$',
'💴': 'Y', # 改用 ASCII Y 代替 ¥
'💶': 'E', # 改用 ASCII E 代替 €
'💷': 'P', # 改用 ASCII P 代替 £
'💸': '$',
'💹': '^',
# Direction - 使用 ASCII
'🚀': '^^',
'⬆️': '^',
'⬇️': 'v',
'➡️': '>',
'⬅️': '<',
'🔼': '^',
'🔽': 'v',
# Symbols - 純 ASCII
'🎯': 'o',
'🔥': '*',
'💡': '*',
'⚙️': '*',
'🔧': '>',
'🔨': '>',
# Tech - 全部移除或改 ASCII
'🤖': '',
'💻': '',
'📱': '',
'🖥️': '',
# People - 全部移除
'👤': '',
'👥': '',
'🔬': '',
'📚': '',
# Time - 純 ASCII
'': 'o',
'📅': '-',
'⏱️': 'o',
# Other - 純 ASCII 或移除
'': '*',
'🎨': '',
'📝': '-',
'📄': '-',
'🗂️': '=',
'🌐': 'o',
'🔗': '~',
'💼': '',
}
print("安全的 Emoji 映射(只使用 ASCII 和基本字符):")
print(SAFE_EMOJI_MAPPING)

38
test_ascii_pdf.py Normal file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
sys.path.insert(0, '/Users/yaolo/Desktop/TradingAgentsX')
from backend.app.services.pdf_generator import PDFGenerator
# 測試包含各種符號的內容
test_content = '''# 測試報告
## 市場分析
- 上漲趨勢 ^
- 技術指標 *
- 支撐位 o
## 風險評估
- 警告標記 [!]
- 確認標記 [OK]
- 否定標記 [X]
## 結論
純文字和 ASCII 符號測試不應該出現
'''
pdf_gen = PDFGenerator()
pdf_bytes = pdf_gen.generate_analyst_report_pdf(
analyst_name='ASCII 符號測試',
ticker='TEST',
analysis_date='2025-11-27',
report_content=test_content
)
with open('/tmp/test_ascii_only.pdf', 'wb') as f:
f.write(pdf_bytes)
print('✓ 已生成測試 PDF: /tmp/test_ascii_only.pdf')
print('請檢查 PDF 中是否還有「煉」字出現')
print('如果沒有「煉」,說明 ASCII-only 方案成功解決問題')

56
test_symbol_rendering.py Normal file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
測試找出哪個字符在 STSong-Light 中被渲染為
"""
import sys
sys.path.insert(0, '/Users/yaolo/Desktop/TradingAgentsX')
from backend.app.services.pdf_generator import PDFGenerator
import io
# 測試內容 - 包含我們使用的所有符號
test_symbols = {
'星號': '',
'菱形': '',
'方塊': '',
'小方': '',
'雙菱': '',
'空菱': '',
'雙圓': '',
'米字': '',
'時鐘': '',
'': '',
'無限': '',
'粗方': '',
'對號': '',
'叉號': '',
'警告': '',
'閃電': '',
}
print("測試每個符號在 PDF 中的渲染...\n")
pdf_gen = PDFGenerator()
for name, symbol in test_symbols.items():
test_content = f"測試{name}符號: {symbol}"
try:
pdf_bytes = pdf_gen.generate_analyst_report_pdf(
analyst_name=f"測試: {symbol}",
ticker="TEST",
analysis_date="2025-11-27",
report_content=test_content
)
# 保存測試 PDF
filename = f"/tmp/test_symbol_{name}.pdf"
with open(filename, 'wb') as f:
f.write(pdf_bytes)
print(f"{name} ({symbol}) - U+{ord(symbol):04X} - 已生成: {filename}")
except Exception as e:
print(f"{name} ({symbol}) - 錯誤: {e}")
print("\n請手動檢查 /tmp/test_symbol_*.pdf 文件,看看哪個符號顯示為「煉」")