feat: 完善批量导入逻辑,8步冒烟全绿
This commit is contained in:
@@ -138,6 +138,9 @@ def import_episodes(
|
||||
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=msg)
|
||||
# 其他解析/校验错误
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=msg)
|
||||
except Exception as e:
|
||||
# 捕获 generate_error_excel 等意外错误,避免 500 扩散
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"导入失败:{str(e)}")
|
||||
|
||||
# 存储失败行(供后续下载)
|
||||
if result["errors"]:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"""
|
||||
|
||||
from datetime import date
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
@@ -22,6 +23,6 @@ class ImportResult(BaseModel):
|
||||
success_count: int # 成功数
|
||||
failed_count: int # 失败数
|
||||
errors: list[ImportError] # 失败行列表
|
||||
error_excel_url: str | None # 失败行 Excel 下载 URL
|
||||
error_excel_url: Optional[str] = None # 失败行 Excel 下载 URL(无可失败行时可不返回)
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
@@ -10,6 +10,7 @@ Excel 解析服务 — 批量导入核心逻辑
|
||||
- Phase 2 不支持重播行(is_rerun=是 → 报错标记为失败行)
|
||||
"""
|
||||
|
||||
import io
|
||||
import uuid
|
||||
from datetime import date
|
||||
from typing import Any
|
||||
@@ -121,8 +122,9 @@ class ExcelService:
|
||||
|
||||
def import_episodes(self, file_content: bytes) -> dict:
|
||||
"""解析 Excel,批量导入 episodes。返回 ImportResult 结构。"""
|
||||
# 1. 读取 Excel
|
||||
df = pd.read_excel(file_content, engine="openpyxl")
|
||||
# 1. 读取 Excel(pandas 2.x 要求 file-like object,用 BytesIO 包装 bytes)
|
||||
file_like = io.BytesIO(file_content)
|
||||
df = pd.read_excel(file_like, engine="openpyxl")
|
||||
rows = df.to_dict(orient="records")
|
||||
|
||||
# 2. 解析 air_date 并提取年份
|
||||
@@ -239,7 +241,6 @@ def generate_error_excel(errors: list[dict]) -> bytes:
|
||||
row_data = [err["row_number"], err["reason"]] + list(err["raw_data"].values())
|
||||
ws.append(row_data)
|
||||
|
||||
wb.add_named_style("error_header")
|
||||
output = io.BytesIO()
|
||||
wb.save(output)
|
||||
output.seek(0)
|
||||
|
||||
Reference in New Issue
Block a user