From 3e301ba8648c9a738669fdbe4f6ee99f4fbbfe3a Mon Sep 17 00:00:00 2001 From: xunbu Date: Thu, 3 Jul 2025 18:52:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=A4=E4=BA=92=E5=BC=8F=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E4=B8=8B=E8=BD=BD=E9=9D=9E=E5=86=85=E5=B5=8C?= =?UTF-8?q?markdown=E3=80=81=E7=BC=93=E5=AD=98=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docutranslate/app.py | 37 ++++++++++++++++++++++++++++++--- docutranslate/static/index.html | 22 ++++++++++++++------ 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/docutranslate/app.py b/docutranslate/app.py index 35965be..b5b4b8d 100644 --- a/docutranslate/app.py +++ b/docutranslate/app.py @@ -28,6 +28,7 @@ current_state: Dict[str, Any] = { "error_flag": False, "download_ready": False, "markdown_content": None, + "markdown_zip_content": None, "html_content": None, "original_filename_stem": None, "task_start_time": 0, @@ -138,6 +139,7 @@ async def _perform_translation(params: Dict[str, Any], file_contents: bytes, ori ) md_content = ft.export_to_markdown() + md_zip_content = ft.export_to_unembed_markdown() try: await httpx_client.head("https://s4.zstatic.net/ajax/libs/KaTeX/0.16.9/contrib/auto-render.min.js", timeout=3) @@ -151,6 +153,7 @@ async def _perform_translation(params: Dict[str, Any], file_contents: bytes, ori current_state.update({ "markdown_content": md_content, + "markdown_zip_content": md_zip_content, "html_content": html_content, "status_message": f"翻译成功!用时 {duration:.2f} 秒。", "download_ready": True, @@ -168,6 +171,7 @@ async def _perform_translation(params: Dict[str, Any], file_contents: bytes, ori "error_flag": False, "download_ready": False, "markdown_content": None, + "md_zip_content": None, "html_content": None, "task_end_time": end_time, }) @@ -181,6 +185,7 @@ async def _perform_translation(params: Dict[str, Any], file_contents: bytes, ori "error_flag": True, "download_ready": False, "markdown_content": None, + "md_zip_content": None, "html_content": None, "task_end_time": end_time, }) @@ -255,6 +260,7 @@ async def handle_translate( "error_flag": False, "download_ready": False, "markdown_content": None, + "md_zip_content": None, "html_content": None, "original_filename_stem": Path(original_filename_for_init).stem, "task_start_time": time.time(), @@ -291,9 +297,9 @@ async def handle_translate( "code_ocr": code_ocr, "refine_markdown": refine_markdown, "convert_engin": convert_engin, "mineru_token": mineru_token, - "chunk_size":chunk_size, - "concurrent":concurrent, - "temperature":temperature, + "chunk_size": chunk_size, + "concurrent": concurrent, + "temperature": temperature, "custom_prompt_translate": custom_prompt_translate, } @@ -365,10 +371,16 @@ async def get_status(): "error_flag": current_state["error_flag"], "download_ready": current_state["download_ready"], "original_filename_stem": current_state["original_filename_stem"], + "markdown_url": f"/download/markdown/{current_state['original_filename_stem']}_translated.md" if current_state[ "download_ready"] and current_state[ "original_filename_stem"] else None, + "markdown_zip_url": f"/download/markdown_zip/{current_state['original_filename_stem']}_translated.md" if + current_state[ + "download_ready"] and + current_state[ + "original_filename_stem"] else None, "html_url": f"/download/html/{current_state['original_filename_stem']}_translated.html" if current_state[ "download_ready"] and current_state[ @@ -413,6 +425,25 @@ async def download_markdown(filename_with_ext: str): ) +@app.get("/download/markdown_zip/{filename_with_ext}") +async def download_markdown(filename_with_ext: str): + if not current_state["download_ready"] or not current_state["markdown_zip_content"] or not current_state[ + "original_filename_stem"]: + print("MarkdownZip 内容尚未准备好或不可用。") + raise HTTPException(status_code=404, detail="MarkdownZip 内容尚未准备好或不可用。") + + if Path(filename_with_ext).stem != f"{current_state['original_filename_stem']}_translated": + raise HTTPException(status_code=404, detail="请求的文件名与当前结果不符。") + + actual_filename = f"{current_state['original_filename_stem']}_translated.zip" + return StreamingResponse( + io.BytesIO(current_state["markdown_zip_content"]), + media_type="application/zip", + headers={ + "Content-Disposition": f"attachment; filename*=UTF-8''{quote(actual_filename, safe='', encoding='utf-8')}"} + ) + + @app.get("/download/html/{filename_with_ext}") async def download_html(filename_with_ext: str): if not current_state["download_ready"] or not current_state["html_content"] or not current_state[ diff --git a/docutranslate/static/index.html b/docutranslate/static/index.html index 51b6f1a..830db9c 100644 --- a/docutranslate/static/index.html +++ b/docutranslate/static/index.html @@ -114,6 +114,9 @@ display: none; margin-top: 1rem; } + .smaller-button-group > *{ + font-size: 0.9em; + } .hidden { display: none !important; @@ -444,12 +447,11 @@

-
-

翻译结果

-
- 下载 Markdown - 下载 HTML - +
@@ -528,11 +530,13 @@ const logArea = document.getElementById('logArea'); const statusMsg = document.getElementById('statusMessage'); const downloadBtns = document.getElementById('downloadButtons'); + const markdownZipLink = document.getElementById('downloadMarkdownZip'); const markdownLink = document.getElementById('downloadMarkdown'); const htmlLink = document.getElementById('downloadHtml'); const previewHtmlBtn = document.getElementById('previewHtml'); const downloadPdfBtn = document.getElementById('downloadPdf'); const printFrameEl = document.getElementById('printFrame'); + const customPromptTranslateArea=document.getElementById("custom_prompt_translate"); // Modal and preview elements const modal = document.getElementById('previewModal'); @@ -612,6 +616,7 @@ statusMsg.textContent = error.toString(); statusMsg.className = 'error-message'; } + customPromptTranslateArea.value=getFromStorage("custom_prompt_translate") } await init() @@ -794,6 +799,9 @@ setBilingualViewBtn.addEventListener('click', () => setPreviewDisplayMode('bilingual')); setTranslatedOnlyViewBtn.addEventListener('click', () => setPreviewDisplayMode('translationOnly')); + customPromptTranslateArea.addEventListener('input',()=>{ + saveToStorage("custom_prompt_translate",customPromptTranslateArea.value) + }) fileDropArea.addEventListener('click', () => fileInput.click()); fileInput.addEventListener('change', () => { @@ -888,6 +896,8 @@ isTranslating = false; if (status.download_ready && !status.error_flag) { + markdownZipLink.href = status.markdown_zip_url; + markdownZipLink.setAttribute('download', status.original_filename_stem + '_translated.zip'); markdownLink.href = status.markdown_url; markdownLink.setAttribute('download', status.original_filename_stem + '_translated.md'); htmlLink.href = status.html_url;