返回顶部
🇺🇸 English
🇨🇳 简体中文
🇨🇳 繁體中文
🇺🇸 English
🇯🇵 日本語
🇰🇷 한국어
🇫🇷 Français
🇩🇪 Deutsch
🇪🇸 Español
🇷🇺 Русский
p

pdf-studio

Professional PDF document generator. Use when user needs to create reports, invoices, certificates, portfolios, or any publication-ready PDF. Supports images, tables, charts, TOC, headers/footers, and cross-platform fonts. Generates print-quality PDFs. PDF文档生成、专业报告、发票制作。

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 1.0.4
安全检测
已通过
86
下载量
0
收藏
概述
安装方式
版本历史

pdf-studio

# PDF Studio Professional PDF document generator that creates publication-ready PDFs with perfect typography and layout. ## Features - 📑 **Print Quality**: 300 DPI, CMYK support, bleed marks - 🎨 **Professional Layout**: Multi-column, headers/footers, page numbers - 🖼️ **Image Support**: Embedded images, captions, watermarks - 📊 **Tables & Charts**: Formatted tables, bar charts, pie charts - 📐 **Typography**: Professional fonts, kerning, ligatures - 🌍 **Multi-Language**: Chinese, English, Japanese, etc. - ✅ **Cross-Platform**: Windows, macOS, Linux - 📱 **PDF/A Compliant**: Archival quality ## Trigger Conditions - "生成PDF" / "Generate PDF" - "帮我做一份报告" / "Create a report" - "制作发票" / "Create an invoice" - "生成证书" / "Generate certificate" - "制作作品集" / "Create portfolio" - "pdf-studio" ## Document Types ### Business (商务) - 年度报告 - 商业计划书 - 发票/账单 - 合同/协议 - 产品手册 ### Academic (学术) - 论文排版 - 学位证书 - 研究报告 - 会议论文 ### Government (政府) - 公文 - 公告 - 证书 - 表格 ### Personal (个人) - 简历 - 作品集 - 证书 - 邀请函 --- ## Step 1: Understand Requirements ``` 请提供以下信息: 文档类型:(报告/发票/证书/简历/其他) 纸张大小:(A4/Letter/A3/自定义) 方向:(纵向/横向) 页边距:(默认/自定义) 字体要求:(默认/指定字体) 语言:(中文/英文) 特殊要求:(水印/页眉页脚/目录等) ``` --- ## Step 2: Generate PDF ### Using FPDF2 (Recommended for simplicity) ```bash # Install dependencies pip install fpdf2 pillow ``` ### Python Script Template (with Unicode Support) ```python python3 << 'PYEOF' import os from fpdf import FPDF from datetime import datetime class PDFGenerator: def __init__(self, config): self.config = config self.html_content = [] self.css_content = [] self.font_config = FontConfiguration() def add_page_setup(self, size='A4', orientation='portrait', margins=None): """Setup page dimensions""" if margins is None: margins = {'top': '2cm', 'right': '2cm', 'bottom': '2cm', 'left': '2cm'} page_size = { 'A4': '210mm 297mm', 'Letter': '216mm 279mm', 'A3': '297mm 420mm' }.get(size, size) self.css_content.append(f''' @page {{ size: {page_size} {orientation}; margin: {margins['top']} {margins['right']} {margins['bottom']} {margins['left']}; @top-center {{ content: "{self.config.get('header_text', '')}"; font-size: 9pt; color: #666; }} @bottom-center {{ content: "Page " counter(page) " of " counter(pages); font-size: 9pt; color: #666; }} @bottom-right {{ content: "{self.config.get('footer_text', '')}"; font-size: 9pt; color: #666; }} }} ''') def add_base_styles(self, font_family='Noto Serif SC', font_size='12pt'): """Add base CSS styles""" self.css_content.append(f''' body {{ font-family: '{font_family}', 'Noto Serif', serif; font-size: {font_size}; line-height: 1.8; color: #333; }} h1 {{ font-family: '{font_family.replace('Serif', 'Sans')}', 'Noto Sans', sans-serif; font-size: 24pt; color: #1a365d; border-bottom: 3px solid #3182ce; padding-bottom: 0.5em; margin-top: 1.5em; page-break-after: avoid; }} h2 {{ font-family: '{font_family.replace('Serif', 'Sans')}', 'Noto Sans', sans-serif; font-size: 18pt; color: #2c5282; border-left: 4px solid #3182ce; padding-left: 1em; margin-top: 1.2em; page-break-after: avoid; }} h3 {{ font-family: '{font_family.replace('Serif', 'Sans')}', 'Noto Sans', sans-serif; font-size: 14pt; color: #3182ce; margin-top: 1em; page-break-after: avoid; }} p {{ text-align: justify; text-indent: 2em; margin: 0.5em 0; }} table {{ width: 100%; border-collapse: collapse; margin: 1em 0; font-size: 10pt; page-break-inside: avoid; }} th {{ background-color: #3182ce; color: white; padding: 0.8em; text-align: left; font-weight: 600; }} td {{ border: 1px solid #e2e8f0; padding: 0.6em 0.8em; }} tr:nth-child(even) {{ background-color: #f7fafc; }} .cover {{ text-align: center; padding-top: 30%; page-break-after: always; }} .cover h1 {{ border: none; font-size: 28pt; }} .cover .subtitle {{ font-size: 14pt; color: #4a5568; margin-top: 1em; }} .cover .author {{ font-size: 12pt; margin-top: 2em; }} .cover .date {{ font-size: 12pt; color: #718096; margin-top: 1em; }} .toc {{ page-break-after: always; }} .toc a {{ color: #3182ce; text-decoration: none; }} .figure {{ text-align: center; margin: 1em 0; page-break-inside: avoid; }} .figure img {{ max-width: 100%; height: auto; }} .figure-caption {{ font-size: 10pt; color: #718096; margin-top: 0.5em; }} .code {{ background-color: #2d3748; color: #e2e8f0; padding: 1em; border-radius: 5px; font-family: 'Fira Code', 'Consolas', monospace; font-size: 9pt; white-space: pre-wrap; page-break-inside: avoid; }} .highlight {{ background-color: #ebf8ff; border: 1px solid #90cdf4; border-radius: 5px; padding: 1em; margin: 1em 0; }} .warning {{ background-color: #fffaf0; border: 1px solid #f6ad55; border-radius: 5px; padding: 1em; margin: 1em 0; }} blockquote {{ border-left: 4px solid #718096; background-color: #f7fafc; padding: 1em; margin: 1em 0; font-style: italic; }} ul, ol {{ margin: 0.5em 0; padding-left: 2em; }} li {{ margin-bottom: 0.3em; }} strong {{ color: #1a365d; }} .page-break {{ page-break-before: always; }} ''') def add_cover(self, title, subtitle='', author='', date=None): """Add cover page""" if date is None: date = datetime.now().strftime('%Y年%m月%d日') self.html_content.append(f''' <div class="cover"> <h1>{title}</h1> {f'<div class="subtitle">{subtitle}</div>' if subtitle else ''} {f'<div class="author">{author}</div>' if author else ''} <div class="date">{date}</div> </div> ''') def add_toc(self, title='目录'): """Add table of contents placeholder""" self.html_content.append(f''' <div class="toc"> <h1>{title}</h1> <p style="font-style: italic; color: #718096;"> (在支持目录生成的PDF阅读器中自动生成) </p> </div> ''') def add_heading(self, text, level=1): """Add heading""" self.html_content.append(f'<h{level}>{text}</h{level}>') def add_paragraph(self, text, indent=True): """Add paragraph""" if indent: self.html_content.append(f'<p>{text}</p>') else: self.html_content.append(f'<p style="text-indent: 0;">{text}</p>') def add_table(self, headers, rows, caption=None): """Add formatted table""" table_html = '<table>' # Header table_html += '<thead><tr>' for header in headers: table_html += f'<th>{header}</th>' table_html += '</tr></thead>' # Body table_html += '<tbody>' for row in rows: table_html += '<tr>' for cell in row: table_html += f'<td>{cell}</td>' table_html += '</tr>' table_html += '</tbody></table>' if caption: table_html = f'<div class="figure"><div class="figure-caption">{caption}</div>{table_html}</div>' self.html_content.append(table_html) def add_image(self, image_path, caption=None, width='80%'): """Add image with caption""" # Convert to data URI for embedding import base64 with open(image_path, 'rb') as f: img_data = base64.b64encode(f.read()).decode() ext = os.path.splitext(image_path)[1].lower() mime = { '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml' }.get(ext, 'image/png') img_html = f'<div class="figure">' img_html += f'<img src="data:{mime};base64,{img_data}" style="max-width: {width};">' if caption: img_html += f'<div class="figure-caption">{caption}</div>' img_html += '</div>' self.html_content.append(img_html) def add_code_block(self, code, language=''): """Add code block""" self.html_content.append(f'<div class="code">{code}</div>') def add_blockquote(self, text): """Add blockquote""" self.html_content.append(f'<blockquote>{text}</blockquote>') def add_list(self, items, ordered=False): """Add list""" tag = 'ol' if ordered else 'ul' list_html = f'<{tag}>' for item in items: list_html += f'<li>{item}</li>' list_html += f'</{tag}>' self.html_content.append(list_html) def add_page_break(self): """Add page break""" self.html_content.append('<div class="page-break"></div>') def render(self): """Render HTML and CSS""" html = f''' <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> {''.join(self.css_content)} </style> </head> <body> {''.join(self.html_content)} </body> </html> ''' return html def save(self, output_path): """Save to PDF""" html_content = self.render() css_content = '\n'.join(self.css_content) html = HTML(string=html_content) css = CSS(string=css_content, font_config=self.font_config) html.write_pdf(output_path, stylesheets=[css], font_config=self.font_config) return output_path # 示例使用 def create_sample_pdf(): config = { 'header_text': 'Sample Report', 'footer_text': 'Confidential' } pdf = PDFGenerator(config) pdf.add_page_setup('A4', 'portrait') pdf.add_base_styles('Noto Serif SC', '12pt') # 封面 pdf.add_cover( '2026年AI行业发展趋势报告', '从大模型到智能体时代的全面变革', 'AI研究院' ) # 目录 pdf.add_toc() # 内容 pdf.add_heading('一、市场概况', 1) pdf.add_paragraph('2026年,全球人工智能市场规模突破3.2万亿美元,年复合增长率达到47%。') pdf.add_paragraph('企业AI采用率从2025年的72%提升至89%,标志着AI技术正式进入全面普及阶段。') # 表格 pdf.add_heading('二、核心数据', 1) pdf.add_table( ['指标', '2025年', '2026年', '增长率'], [ ['全球市场规模', '$2.1万亿', '$3.2万亿', '52%'], ['企业采用率', '72%', '89%', '24%'], ['风险投资', '$790亿', '$1,280亿', '62%'] ], caption='表2-1:AI市场核心指标' ) # 列表 pdf.add_heading('三、技术趋势', 1) pdf.add_list([ '大模型能力持续提升', 'Agent技术走向成熟', '开源生态蓬勃发展' ]) return pdf # 生成示例PDF output_dir = os.environ.get('OPENCLAW_WORKSPACE', os.getcwd()) output_path = os.path.join(output_dir, 'sample-report.pdf') pdf = create_sample_pdf() pdf.save(output_path) print(f"✅ PDF已生成:{output_path}") PYEOF ``` --- ## Typography Settings (字体设置) ### Cross-Platform Fonts ```python FONTS = { 'chinese': { 'serif': 'Noto Serif SC', 'sans': 'Noto Sans SC', 'mono': 'Noto Sans Mono CJK SC' }, 'english': { 'serif': 'Liberation Serif', 'sans': 'Liberation Sans', 'mono': 'Fira Code' }, 'japanese': { 'serif': 'Noto Serif JP', 'sans': 'Noto Sans JP', 'mono': 'Noto Sans Mono CJK JP' } } ``` ### Font Features ```css body { font-feature-settings: "liga" 1, "kern" 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } ``` --- ## Page Layout (页面布局) ### Multi-Column Layout ```css .two-column { column-count: 2; column-gap: 2em; column-rule: 1px solid #e2e8f0; } ``` ### Margin Presets ```python MARGINS = { 'normal': {'top': '2.54cm', 'right': '2.54cm', 'bottom': '2.54cm', 'left': '2.54cm'}, 'narrow': {'top': '1.27cm', 'right': '1.27cm', 'bottom': '1.27cm', 'left': '1.27cm'}, 'wide': {'top': '2.54cm', 'right': '5.08cm', 'bottom': '2.54cm', 'left': '5.08cm'} } ``` --- ## Error Handling ``` 字体缺失 → 使用开源字体回退 图片格式不支持 → 转换为PNG/JPEG 内存不足 → 分页处理大文档 生成失败 → 输出HTML备选 ``` --- ## Security Notes (安全说明) - ✅ No network calls or external endpoints - ✅ No credentials or API keys required - ✅ Local file processing only - ✅ Open source dependencies (fpdf2, pillow from PyPI) - ✅ No data uploaded to external servers - ⚠️ Requires python3 and pip install - ⚠️ Review code before execution ## Notes - 使用FPDF2确保跨平台一致性 - 所有字体可嵌入PDF中 - 支持PDF/A归档标准 - 图片自动压缩优化 - 支持水印和页眉页脚

标签

skill ai

通过对话安装

该技能支持在以下平台通过对话安装:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 pdf-studio-1776052803 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 pdf-studio-1776052803 技能

通过命令行安装

skillhub install pdf-studio-1776052803

下载 Zip 包

⬇ 下载 pdf-studio v1.0.4

文件大小: 7.27 KB | 发布时间: 2026-4-14 09:47

v1.0.4 最新 2026-4-14 09:47
添加安全说明:明确无网络调用、无凭证请求、本地处理

Archiver·手机版·闲社网·闲社论坛·羊毛社区· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2025 闲社网·线报更新论坛·羊毛分享社区·http://xianshe.com

p2p_official_large
返回顶部