diff --git a/backend/package/yuxi/plugins/parser/unified.py b/backend/package/yuxi/plugins/parser/unified.py index a7b82ad6..77cbf488 100644 --- a/backend/package/yuxi/plugins/parser/unified.py +++ b/backend/package/yuxi/plugins/parser/unified.py @@ -131,6 +131,7 @@ def _convert_with_docling(file_path: Path, params: dict | None = None) -> str: for pic in doc.pictures: uri = str(pic.image.uri) if hasattr(pic, "image") and hasattr(pic.image, "uri") else "" if uri.startswith("data:"): + filename = "image" try: image_data, mime_type = _parse_data_uri(uri) filename = f"image_{int(time.time() * 1000000)}.{mime_type.split('/')[-1]}" @@ -138,7 +139,7 @@ def _convert_with_docling(file_path: Path, params: dict | None = None) -> str: replacements.append(f"![{filename}]({url})") except Exception as e: # noqa: BLE001 logger.error(f"上传图片失败 {filename}: {e}") - replacements.append("") + replacements.append(f"[图片: {filename}]") else: replacements.append("") diff --git a/backend/test/unit/plugins/test_parser_facade.py b/backend/test/unit/plugins/test_parser_facade.py index 21857308..e3d1d4ce 100644 --- a/backend/test/unit/plugins/test_parser_facade.py +++ b/backend/test/unit/plugins/test_parser_facade.py @@ -76,9 +76,10 @@ def test_convert_with_docling_reinserts_image_links_in_document_order( fake_doc = SimpleNamespace( pictures=[ SimpleNamespace(image=SimpleNamespace(uri=f"data:image/png;base64,{first_image}")), + SimpleNamespace(image=SimpleNamespace(uri="https://example.test/remote.png")), SimpleNamespace(image=SimpleNamespace(uri=f"data:image/png;base64,{second_image}")), ], - export_to_markdown=lambda: "before\n\nbetween\n\nafter", + export_to_markdown=lambda: "before\n\nremote\n\nbetween\n\nafter", ) fake_result = SimpleNamespace(status=SimpleNamespace(name="SUCCESS"), document=fake_doc) uploaded_images: list[bytes] = [] @@ -103,12 +104,44 @@ def test_convert_with_docling_reinserts_image_links_in_document_order( assert markdown == ( "before\n" "![image_1000000.png](https://example.test/1.png)\n" + "remote\n" + "\n" "between\n" "![image_2000000.png](https://example.test/2.png)\n" "after" ) +def test_convert_with_docling_keeps_image_placeholder_when_upload_fails( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +): + file_path = tmp_path / "parser_test.docx" + file_path.write_bytes(b"fake docx") + image = base64.b64encode(b"image data").decode() + fake_doc = SimpleNamespace( + pictures=[SimpleNamespace(image=SimpleNamespace(uri=f"data:image/png;base64,{image}"))], + export_to_markdown=lambda: "before\n\nafter", + ) + fake_result = SimpleNamespace(status=SimpleNamespace(name="SUCCESS"), document=fake_doc) + + class FakeConverter: + def convert(self, path: Path): + assert path == file_path + return fake_result + + def _raise_upload_error(*args, **kwargs): + raise RuntimeError("upload failed") + + monkeypatch.setattr(parser_unified, "_get_docling_converter", lambda: FakeConverter()) + monkeypatch.setattr(parser_unified, "_upload_image_to_minio", _raise_upload_error) + monkeypatch.setattr(parser_unified.time, "time", lambda: 1.0) + + markdown = parser_unified._convert_with_docling(file_path) + + assert markdown == "before\n[图片: image_1000000.png]\nafter" + + def test_parser_parse_png_file_returns_markdown_text_with_mocked_ocr( tmp_path: Path, monkeypatch: pytest.MonkeyPatch,