diff --git a/README.md b/README.md index c038208..33ac320 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ V2:zip 解压后包含 `Patients_info.csv`,并按患者目录分别保存检 患者编号类型可选择自动识别。自动识别会读取 `Patients_info.csv` 中的 `pat_no`,并与 `Tests_List` 文件名或患者目录名比对:若更匹配 10 位补零编号,则使用 `pat_no`;若更匹配原始编号,则使用 `zhuyuanhao`。 -系统默认输出完整结果;处理完成后可在结果页通过“内容选择”立即切换预览内容,并同步影响右侧“导出此 Excel”的文件内容。可选择是否保留: +系统默认输出完整结果;处理完成后可在结果页通过“内容选择”立即切换预览内容,并同步影响右侧“导出此 Excel”的文件内容。结果页还可以按姓名、采样时间或检测原因选择升序/降序排序;“未检测到内容汇总”会在每个分组标题下单独排序,不会把不同检测原因的分组混在一起。可选择是否保留: - 基本工作表 - 未匹配检测内容项 diff --git a/app/main.py b/app/main.py index b5c66d0..8c0cc3c 100644 --- a/app/main.py +++ b/app/main.py @@ -23,6 +23,15 @@ WORK_ROOT.mkdir(parents=True, exist_ok=True) APP_TITLE = "\u68c0\u6d4b\u6570\u636e\u5904\u7406" UNMATCHED = "\u672a\u5339\u914d\u68c0\u6d4b\u5185\u5bb9" +SORT_OPTIONS = { + "name": "\u59d3\u540d", + "sample_time": "\u91c7\u6837\u65f6\u95f4", + "reason": "\u68c0\u6d4b\u539f\u56e0", +} +SORT_ORDERS = { + "asc": "\u5347\u5e8f", + "desc": "\u964d\u5e8f", +} app = FastAPI(title=APP_TITLE) @@ -117,16 +126,22 @@ def result_page( include_basic_sheets: bool = Query(True), include_unmatched_items: bool = Query(True), include_summary_sheet: bool = Query(True), + sort_by: str = Query("sample_time"), + sort_order: str = Query("asc"), ) -> str: job_dir = _get_job_dir(job_id) try: rows = _clean_preview_rows(preview_rows) + clean_sort_by = _clean_sort_by(sort_by) + clean_sort_order = _clean_sort_order(sort_order) result = summarize_job( job_dir, rows, include_basic_sheets=include_basic_sheets, include_unmatched_items=include_unmatched_items, include_summary_sheet=include_summary_sheet, + sort_by=clean_sort_by, + sort_order=clean_sort_order, ) except ProcessingError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc @@ -136,6 +151,8 @@ def result_page( include_basic_sheets=include_basic_sheets, include_unmatched_items=include_unmatched_items, include_summary_sheet=include_summary_sheet, + sort_by=clean_sort_by, + sort_order=clean_sort_order, ) @@ -145,6 +162,8 @@ def download_all( include_basic_sheets: bool = Query(True), include_unmatched_items: bool = Query(True), include_summary_sheet: bool = Query(True), + sort_by: str = Query("sample_time"), + sort_order: str = Query("asc"), ) -> FileResponse: job_dir = _get_job_dir(job_id) try: @@ -153,6 +172,8 @@ def download_all( include_basic_sheets=include_basic_sheets, include_unmatched_items=include_unmatched_items, include_summary_sheet=include_summary_sheet, + sort_by=_clean_sort_by(sort_by), + sort_order=_clean_sort_order(sort_order), ) except ProcessingError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc @@ -166,6 +187,8 @@ def download_file( include_basic_sheets: bool = Query(True), include_unmatched_items: bool = Query(True), include_summary_sheet: bool = Query(True), + sort_by: str = Query("sample_time"), + sort_order: str = Query("asc"), ) -> FileResponse: job_dir = _get_job_dir(job_id) try: @@ -175,6 +198,8 @@ def download_file( include_basic_sheets=include_basic_sheets, include_unmatched_items=include_unmatched_items, include_summary_sheet=include_summary_sheet, + sort_by=_clean_sort_by(sort_by), + sort_order=_clean_sort_order(sort_order), ) except ProcessingError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc @@ -207,12 +232,26 @@ def _checked(value: bool) -> str: return "checked" if value else "" +def _selected(value: str, current: str) -> str: + return "selected" if value == current else "" + + +def _clean_sort_by(sort_by: str) -> str: + return sort_by if sort_by in SORT_OPTIONS else "sample_time" + + +def _clean_sort_order(sort_order: str) -> str: + return sort_order if sort_order in SORT_ORDERS else "asc" + + def _render_result( result: ProcessingResult, preview_rows: int = 20, include_basic_sheets: bool = True, include_unmatched_items: bool = True, include_summary_sheet: bool = True, + sort_by: str = "sample_time", + sort_order: str = "asc", ) -> str: total_sheets = sum(len(file.sheets) for file in result.files) total_rows = sum(max(sheet.rows - 1, 0) for file in result.files for sheet in file.sheets) @@ -230,6 +269,16 @@ def _render_result( + + +