import html import shutil import tempfile import uuid from pathlib import Path from fastapi import FastAPI, File, Form, HTTPException, UploadFile from fastapi.responses import FileResponse, HTMLResponse from .processor import ProcessingError, run_processing APP_ROOT = Path(__file__).resolve().parent WORK_ROOT = Path(tempfile.gettempdir()) / "his_sur_data_deal_jobs" WORK_ROOT.mkdir(parents=True, exist_ok=True) app = FastAPI(title="检测数据处理") @app.get("/", response_class=HTMLResponse) def index() -> str: return """ 检测数据处理

检测数据处理

上传“待处理检测数据.zip”,处理完成后自动下载结果压缩包。
V1 适用于含有 Patients_info.csv、Tests_List、Tests_Detail_List 的批量数据;V2 适用于每个患者单独目录的数据。
""" @app.post("/process") async def process( file: UploadFile = File(...), mode: str = Form("auto"), data_type: str = Form("pat_no"), result_name: str = Form("Result"), show_not_match: str | None = Form(None), show_all_infos: str | None = Form(None), ) -> FileResponse: if not file.filename or not file.filename.lower().endswith(".zip"): raise HTTPException(status_code=400, detail="请上传 zip 文件。") job_dir = WORK_ROOT / uuid.uuid4().hex job_dir.mkdir(parents=True, exist_ok=True) upload_path = job_dir / "input.zip" try: with upload_path.open("wb") as out: shutil.copyfileobj(file.file, out) result_zip = run_processing( zip_path=upload_path, job_dir=job_dir, mode=mode, data_type=data_type, result_name=result_name, show_not_match=show_not_match == "true", show_all_infos=show_all_infos == "true", ) except ProcessingError as exc: safe_detail = html.escape(str(exc)) raise HTTPException(status_code=400, detail=safe_detail) from exc except Exception as exc: raise HTTPException(status_code=500, detail=f"处理失败:{exc}") from exc return FileResponse( result_zip, media_type="application/zip", filename="检测数据处理结果.zip", ) @app.get("/health") def health() -> dict[str, str]: return {"status": "ok"}