diff --git a/software-copyright/01-writech-cloud-platform/自然写互动课堂教学管理云平台软件-源程序.pdf b/software-copyright/01-writech-cloud-platform/自然写互动课堂教学管理云平台软件-源程序.pdf new file mode 100644 index 0000000..95003e7 Binary files /dev/null and b/software-copyright/01-writech-cloud-platform/自然写互动课堂教学管理云平台软件-源程序.pdf differ diff --git a/software-copyright/01-writech-cloud-platform/自然写互动课堂教学管理云平台软件-鉴别材料.pdf b/software-copyright/01-writech-cloud-platform/自然写互动课堂教学管理云平台软件-鉴别材料.pdf new file mode 100644 index 0000000..a17e003 Binary files /dev/null and b/software-copyright/01-writech-cloud-platform/自然写互动课堂教学管理云平台软件-鉴别材料.pdf differ diff --git a/software-copyright/02-writech-ai-engine/自然写手写识别与AI分析引擎软件-源程序.pdf b/software-copyright/02-writech-ai-engine/自然写手写识别与AI分析引擎软件-源程序.pdf new file mode 100644 index 0000000..ea4274d Binary files /dev/null and b/software-copyright/02-writech-ai-engine/自然写手写识别与AI分析引擎软件-源程序.pdf differ diff --git a/software-copyright/02-writech-ai-engine/自然写手写识别与AI分析引擎软件-鉴别材料.pdf b/software-copyright/02-writech-ai-engine/自然写手写识别与AI分析引擎软件-鉴别材料.pdf new file mode 100644 index 0000000..ef9babc Binary files /dev/null and b/software-copyright/02-writech-ai-engine/自然写手写识别与AI分析引擎软件-鉴别材料.pdf differ diff --git a/software-copyright/03-writech-learning-analytics/自然写教学数据分析与学情诊断系统软件-源程序.pdf b/software-copyright/03-writech-learning-analytics/自然写教学数据分析与学情诊断系统软件-源程序.pdf new file mode 100644 index 0000000..cdbc731 Binary files /dev/null and b/software-copyright/03-writech-learning-analytics/自然写教学数据分析与学情诊断系统软件-源程序.pdf differ diff --git a/software-copyright/03-writech-learning-analytics/自然写教学数据分析与学情诊断系统软件-鉴别材料.pdf b/software-copyright/03-writech-learning-analytics/自然写教学数据分析与学情诊断系统软件-鉴别材料.pdf new file mode 100644 index 0000000..29c3412 Binary files /dev/null and b/software-copyright/03-writech-learning-analytics/自然写教学数据分析与学情诊断系统软件-鉴别材料.pdf differ diff --git a/software-copyright/04-writech-gateway/自然写教室智能网关管理软件-源程序.pdf b/software-copyright/04-writech-gateway/自然写教室智能网关管理软件-源程序.pdf new file mode 100644 index 0000000..760d7e2 Binary files /dev/null and b/software-copyright/04-writech-gateway/自然写教室智能网关管理软件-源程序.pdf differ diff --git a/software-copyright/04-writech-gateway/自然写教室智能网关管理软件-鉴别材料.pdf b/software-copyright/04-writech-gateway/自然写教室智能网关管理软件-鉴别材料.pdf new file mode 100644 index 0000000..e4826c4 Binary files /dev/null and b/software-copyright/04-writech-gateway/自然写教室智能网关管理软件-鉴别材料.pdf differ diff --git a/software-copyright/05-writech-edge-box/自然写教室智能算力盒边缘计算软件-源程序.pdf b/software-copyright/05-writech-edge-box/自然写教室智能算力盒边缘计算软件-源程序.pdf new file mode 100644 index 0000000..120092e Binary files /dev/null and b/software-copyright/05-writech-edge-box/自然写教室智能算力盒边缘计算软件-源程序.pdf differ diff --git a/software-copyright/05-writech-edge-box/自然写教室智能算力盒边缘计算软件-鉴别材料.pdf b/software-copyright/05-writech-edge-box/自然写教室智能算力盒边缘计算软件-鉴别材料.pdf new file mode 100644 index 0000000..668ca36 Binary files /dev/null and b/software-copyright/05-writech-edge-box/自然写教室智能算力盒边缘计算软件-鉴别材料.pdf differ diff --git a/software-copyright/06-writech-app-mobile/自然写互动课堂手机端应用软件-源程序.pdf b/software-copyright/06-writech-app-mobile/自然写互动课堂手机端应用软件-源程序.pdf new file mode 100644 index 0000000..bdd5b58 Binary files /dev/null and b/software-copyright/06-writech-app-mobile/自然写互动课堂手机端应用软件-源程序.pdf differ diff --git a/software-copyright/06-writech-app-mobile/自然写互动课堂手机端应用软件-鉴别材料.pdf b/software-copyright/06-writech-app-mobile/自然写互动课堂手机端应用软件-鉴别材料.pdf new file mode 100644 index 0000000..076ed6f Binary files /dev/null and b/software-copyright/06-writech-app-mobile/自然写互动课堂手机端应用软件-鉴别材料.pdf differ diff --git a/software-copyright/07-writech-app-tv/自然写互动课堂电视端应用软件-源程序.pdf b/software-copyright/07-writech-app-tv/自然写互动课堂电视端应用软件-源程序.pdf new file mode 100644 index 0000000..5781886 Binary files /dev/null and b/software-copyright/07-writech-app-tv/自然写互动课堂电视端应用软件-源程序.pdf differ diff --git a/software-copyright/07-writech-app-tv/自然写互动课堂电视端应用软件-鉴别材料.pdf b/software-copyright/07-writech-app-tv/自然写互动课堂电视端应用软件-鉴别材料.pdf new file mode 100644 index 0000000..499239d Binary files /dev/null and b/software-copyright/07-writech-app-tv/自然写互动课堂电视端应用软件-鉴别材料.pdf differ diff --git a/software-copyright/08-writech-app-pc/自然写互动课堂PC端应用软件-源程序.pdf b/software-copyright/08-writech-app-pc/自然写互动课堂PC端应用软件-源程序.pdf new file mode 100644 index 0000000..cfd3aa0 Binary files /dev/null and b/software-copyright/08-writech-app-pc/自然写互动课堂PC端应用软件-源程序.pdf differ diff --git a/software-copyright/08-writech-app-pc/自然写互动课堂PC端应用软件-鉴别材料.pdf b/software-copyright/08-writech-app-pc/自然写互动课堂PC端应用软件-鉴别材料.pdf new file mode 100644 index 0000000..ca8598a Binary files /dev/null and b/software-copyright/08-writech-app-pc/自然写互动课堂PC端应用软件-鉴别材料.pdf differ diff --git a/software-copyright/09-writech-app-board/自然写互动课堂智慧黑板端应用软件-源程序.pdf b/software-copyright/09-writech-app-board/自然写互动课堂智慧黑板端应用软件-源程序.pdf new file mode 100644 index 0000000..da7842f Binary files /dev/null and b/software-copyright/09-writech-app-board/自然写互动课堂智慧黑板端应用软件-源程序.pdf differ diff --git a/software-copyright/09-writech-app-board/自然写互动课堂智慧黑板端应用软件-鉴别材料.pdf b/software-copyright/09-writech-app-board/自然写互动课堂智慧黑板端应用软件-鉴别材料.pdf new file mode 100644 index 0000000..eaa647b Binary files /dev/null and b/software-copyright/09-writech-app-board/自然写互动课堂智慧黑板端应用软件-鉴别材料.pdf differ diff --git a/software-copyright/10-writech-app-pad/自然写互动课堂平板端应用软件-源程序.pdf b/software-copyright/10-writech-app-pad/自然写互动课堂平板端应用软件-源程序.pdf new file mode 100644 index 0000000..a98939f Binary files /dev/null and b/software-copyright/10-writech-app-pad/自然写互动课堂平板端应用软件-源程序.pdf differ diff --git a/software-copyright/10-writech-app-pad/自然写互动课堂平板端应用软件-鉴别材料.pdf b/software-copyright/10-writech-app-pad/自然写互动课堂平板端应用软件-鉴别材料.pdf new file mode 100644 index 0000000..d48ea05 Binary files /dev/null and b/software-copyright/10-writech-app-pad/自然写互动课堂平板端应用软件-鉴别材料.pdf differ diff --git a/software-copyright/11-writech-sdk/自然写互动课堂应用开发SDK软件-源程序.pdf b/software-copyright/11-writech-sdk/自然写互动课堂应用开发SDK软件-源程序.pdf new file mode 100644 index 0000000..a6cb45a Binary files /dev/null and b/software-copyright/11-writech-sdk/自然写互动课堂应用开发SDK软件-源程序.pdf differ diff --git a/software-copyright/11-writech-sdk/自然写互动课堂应用开发SDK软件-鉴别材料.pdf b/software-copyright/11-writech-sdk/自然写互动课堂应用开发SDK软件-鉴别材料.pdf new file mode 100644 index 0000000..8c4044e Binary files /dev/null and b/software-copyright/11-writech-sdk/自然写互动课堂应用开发SDK软件-鉴别材料.pdf differ diff --git a/software-copyright/12-writech-pen-firmware/自然写智能点阵笔嵌入式固件软件-源程序.pdf b/software-copyright/12-writech-pen-firmware/自然写智能点阵笔嵌入式固件软件-源程序.pdf new file mode 100644 index 0000000..bb3f058 Binary files /dev/null and b/software-copyright/12-writech-pen-firmware/自然写智能点阵笔嵌入式固件软件-源程序.pdf differ diff --git a/software-copyright/12-writech-pen-firmware/自然写智能点阵笔嵌入式固件软件-鉴别材料.pdf b/software-copyright/12-writech-pen-firmware/自然写智能点阵笔嵌入式固件软件-鉴别材料.pdf new file mode 100644 index 0000000..b6d666e Binary files /dev/null and b/software-copyright/12-writech-pen-firmware/自然写智能点阵笔嵌入式固件软件-鉴别材料.pdf differ diff --git a/software-copyright/13-writech-resource-platform/自然写教学资源管理与内容分发系统软件-源程序.pdf b/software-copyright/13-writech-resource-platform/自然写教学资源管理与内容分发系统软件-源程序.pdf new file mode 100644 index 0000000..39e21e4 Binary files /dev/null and b/software-copyright/13-writech-resource-platform/自然写教学资源管理与内容分发系统软件-源程序.pdf differ diff --git a/software-copyright/13-writech-resource-platform/自然写教学资源管理与内容分发系统软件-鉴别材料.pdf b/software-copyright/13-writech-resource-platform/自然写教学资源管理与内容分发系统软件-鉴别材料.pdf new file mode 100644 index 0000000..718d662 Binary files /dev/null and b/software-copyright/13-writech-resource-platform/自然写教学资源管理与内容分发系统软件-鉴别材料.pdf differ diff --git a/software-copyright/batch_md_to_pdf.py b/software-copyright/batch_md_to_pdf.py new file mode 100644 index 0000000..7d60883 --- /dev/null +++ b/software-copyright/batch_md_to_pdf.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python3 +""" +批量将 Markdown 转为 PDF —— 通过 Google Chrome Headless 浏览器渲染 +1. Markdown → HTML(含代码高亮、表格样式) +2. HTML → 写入临时文件 → Chrome --headless --print-to-pdf +""" +import glob +import os +import subprocess +import tempfile +import markdown +from markdown.extensions.tables import TableExtension +from markdown.extensions.fenced_code import FencedCodeExtension +from markdown.extensions.codehilite import CodeHiliteExtension +from markdown.extensions.toc import TocExtension + +# ─── 配置 ─── +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +DIRS = [f"{i:02d}-*" for i in range(1, 14)] +PATTERNS = ["*-鉴别材料.md", "*-源程序.md"] +CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" + +CSS = """ +@page { + size: A4; + margin: 20mm 18mm 20mm 18mm; +} +body { + font-family: "PingFang SC", "Microsoft YaHei", "STSong", "Noto Sans CJK SC", sans-serif; + font-size: 11pt; + line-height: 1.7; + color: #222; + max-width: 100%; + padding: 0 10px; + margin: 0; +} +h1 { font-size: 20pt; border-bottom: 2px solid #333; padding-bottom: 6px; margin-top: 24pt; } +h2 { font-size: 16pt; border-bottom: 1px solid #999; padding-bottom: 4px; margin-top: 20pt; } +h3 { font-size: 13pt; margin-top: 16pt; } +h4 { font-size: 12pt; margin-top: 12pt; } +table { + border-collapse: collapse; + width: 100%; + margin: 12px 0; + font-size: 10pt; + page-break-inside: auto; +} +th, td { + border: 1px solid #bbb; + padding: 6px 10px; + text-align: left; +} +th { background-color: #f0f0f0; font-weight: bold; } +tr:nth-child(even) { background-color: #fafafa; } +code { + font-family: "SF Mono", "Menlo", "Consolas", "Monaco", monospace; + font-size: 9.5pt; + background: #f5f5f5; + padding: 1px 4px; + border-radius: 3px; +} +pre { + background: #f6f8fa; + border: 1px solid #e1e4e8; + border-radius: 6px; + padding: 12px 16px; + overflow-x: auto; + font-size: 8.5pt; + line-height: 1.5; + page-break-inside: auto; + white-space: pre-wrap; + word-wrap: break-word; +} +pre code { + background: transparent; + padding: 0; + font-size: inherit; +} +blockquote { + border-left: 4px solid #dfe2e5; + padding: 4px 16px; + margin: 12px 0; + color: #555; + background: #f9f9f9; +} +img { max-width: 100%; } +hr { border: none; border-top: 1px solid #ddd; margin: 20px 0; } +.codehilite { background: #f6f8fa; border-radius: 6px; padding: 12px 16px; } +""" + +def md_to_html(md_path): + """将 Markdown 文件转换为完整的 HTML 页面""" + with open(md_path, 'r', encoding='utf-8') as f: + md_text = f.read() + + extensions = [ + TableExtension(), + FencedCodeExtension(), + CodeHiliteExtension(css_class='codehilite', guess_lang=False), + TocExtension(permalink=False), + ] + html_body = markdown.markdown(md_text, extensions=extensions) + + title = os.path.splitext(os.path.basename(md_path))[0] + html = f""" + + + +{title} + + + +{html_body} + +""" + return html + + +def html_to_pdf_chrome(html_content, pdf_path): + """使用 Google Chrome headless 将 HTML 转为 PDF""" + with tempfile.NamedTemporaryFile(suffix='.html', mode='w', encoding='utf-8', delete=False) as f: + f.write(html_content) + html_path = f.name + + try: + cmd = [ + CHROME, + '--headless', + '--disable-gpu', + '--no-sandbox', + '--disable-software-rasterizer', + '--run-all-compositor-stages-before-draw', + f'--print-to-pdf={pdf_path}', + '--no-pdf-header-footer', + html_path, + ] + proc = subprocess.run(cmd, capture_output=True, text=True, timeout=60) + return os.path.exists(pdf_path) and os.path.getsize(pdf_path) > 0 + except Exception as e: + print(f" Chrome 错误: {e}") + return False + finally: + os.unlink(html_path) + + +def main(): + # 收集所有目标文件 + md_files = [] + for dir_pattern in DIRS: + for pattern in PATTERNS: + found = sorted(glob.glob(os.path.join(BASE_DIR, dir_pattern, pattern))) + md_files.extend(found) + + if not md_files: + print("❌ 未找到目标 md 文件") + return + + print(f"找到 {len(md_files)} 个 Markdown 文件待转换") + print(f"使用 Chrome Headless 浏览器渲染\n") + + success = 0 + failed = 0 + for i, md_path in enumerate(md_files, 1): + rel = os.path.relpath(md_path, BASE_DIR) + pdf_name = os.path.splitext(os.path.basename(md_path))[0] + '.pdf' + pdf_path = os.path.join(os.path.dirname(md_path), pdf_name) + + print(f"[{i:2d}/{len(md_files)}] {rel}") + try: + html = md_to_html(md_path) + if html_to_pdf_chrome(html, pdf_path): + size_kb = os.path.getsize(pdf_path) / 1024 + print(f" ✅ → {pdf_name} ({size_kb:.0f} KB)") + success += 1 + else: + print(f" ❌ PDF 生成失败") + failed += 1 + except Exception as e: + print(f" ❌ 错误: {e}") + failed += 1 + + print(f"\n{'='*50}") + print(f"转换完成: {success} 成功, {failed} 失败, 共 {len(md_files)} 个文件") + + +if __name__ == '__main__': + main()