fix: sync/barcode/memory overhaul + detailed logs + preview + result tracking
- Sync: fix GiteaSync constructor + add push()/pull() methods - Barcode: two-tab layout matching GUI (mapping + special rules) - Memory: spec→specification unification, manual add, confidence/price tracking - Processing: TaskLogHandler captures detailed logs (barcode mapping, unit conversion) - Preview: fullscreen dialog for file preview (image/Excel) in Orders/Tables/Images - Detail: per-file log filtering in file pages - Tasks: result files now per-task, add copy path button - Config: reactive edited state + save_config fix - Dashboard: sync task isolation, log limit 10 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, UploadFile, File, Depends, Query, Request
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.responses import FileResponse, JSONResponse
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ..auth.dependencies import get_current_user, get_current_user_flexible
|
||||
@@ -267,10 +267,13 @@ async def get_file_relations(
|
||||
status: Optional[str] = None,
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(50, ge=1, le=200),
|
||||
sort_by: Optional[str] = None,
|
||||
sort_order: str = "desc",
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
"""Query file relations with optional view filter."""
|
||||
items, total = query_file_relations(view=view, status=status, page=page, page_size=page_size)
|
||||
items, total = query_file_relations(view=view, status=status, page=page, page_size=page_size,
|
||||
sort_by=sort_by, sort_order=sort_order)
|
||||
return {"items": items, "total": total}
|
||||
|
||||
|
||||
@@ -299,3 +302,47 @@ async def delete_relations(
|
||||
"""Delete file relation records by IDs."""
|
||||
delete_file_relations(body.ids)
|
||||
return {"message": f"已删除 {len(body.ids)} 条关系记录"}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# File preview
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@router.get("/preview/{directory}/{filename:path}")
|
||||
async def preview_file(
|
||||
directory: str,
|
||||
filename: str,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
"""Preview file content: images served directly, Excel returned as JSON grid."""
|
||||
# Security: only allow specific directories
|
||||
if directory not in ("input", "output", "result"):
|
||||
raise HTTPException(403, "不允许访问该目录")
|
||||
|
||||
dir_map = {"input": _input_dir, "output": _output_dir, "result": _result_dir}
|
||||
file_path = dir_map[directory] / filename
|
||||
if not file_path.is_file():
|
||||
raise HTTPException(404, f"文件不存在: {filename}")
|
||||
|
||||
ext = file_path.suffix.lower()
|
||||
# Images: serve directly
|
||||
if ext in ('.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp'):
|
||||
return FileResponse(str(file_path))
|
||||
|
||||
# Excel: read and return as JSON grid
|
||||
if ext in ('.xls', '.xlsx'):
|
||||
try:
|
||||
import pandas as pd
|
||||
from fastapi.responses import JSONResponse
|
||||
df = pd.read_excel(str(file_path), header=None)
|
||||
# Fill NaN with empty string
|
||||
df = df.fillna('')
|
||||
rows = []
|
||||
for _, row in df.iterrows():
|
||||
rows.append([str(v) if v != '' else '' for v in row])
|
||||
# Limit to first 200 rows
|
||||
return JSONResponse({"type": "excel", "rows": rows[:200], "total_rows": len(rows)})
|
||||
except Exception as e:
|
||||
raise HTTPException(500, f"读取文件失败: {e}")
|
||||
|
||||
raise HTTPException(400, f"不支持预览的文件类型: {ext}")
|
||||
|
||||
Reference in New Issue
Block a user