feat: Excel导入支持自定义列映射+智能列名检测

- 上传后自动读取Excel列名,下拉框选择映射
- 智能匹配: 科目/编码→kpi_code, 期间→period, 金额→actual_value
- 支持统一期间(文件无期间列时)
- 后端接受 kpi_col/period_col/value_col/default_period 参数
This commit is contained in:
Hermes CI Fix
2026-07-13 15:18:40 +08:00
parent 311f772ca9
commit da9aceb567
3 changed files with 89 additions and 12 deletions
+18 -8
View File
@@ -15,14 +15,24 @@ router = APIRouter(prefix="/api/cma/data", tags=["数据对接"],
)
@router.post("/import-excel")
async def import_excel(file: UploadFile = File(...), db: Session = Depends(get_db)):
async def import_excel(file: UploadFile = File(...),
kpi_col: str = Query("kpi_code", description="Excel中KPI编码列名"),
period_col: str = Query("period", description="Excel中期间列名"),
value_col: str = Query("actual_value", description="Excel中实际值列名"),
default_period: str = Query(None, description="如文件无期间列,统一使用此值"),
db: Session = Depends(get_db)):
content = await file.read()
df = pd.read_excel(io.BytesIO(content))
required = ["kpi_code", "period", "actual_value"]
if not all(c in df.columns for c in required):
raise HTTPException(400, f"Excel必须包含列: {required}")
required = [kpi_col, value_col]
if not default_period:
required.append(period_col)
missing = [c for c in required if c not in df.columns]
if missing:
raise HTTPException(400,
f"Excel缺少列: {missing}。当前文件列: {list(df.columns)}")
if len(df) == 0:
raise HTTPException(400, "Excel文件为空,没有数据行")
@@ -33,9 +43,9 @@ async def import_excel(file: UploadFile = File(...), db: Session = Depends(get_d
count = 0
skipped = []
for idx, row in df.iterrows():
kpi_code = str(row.get("kpi_code", "")).strip()
period = str(row.get("period", "")).strip()
value = row.get("actual_value")
kpi_code = str(row.get(kpi_col, "")).strip()
period = str(row.get(period_col, default_period or "")).strip() if period_col in df.columns else (default_period or "").strip()
value = row.get(value_col)
if not kpi_code or not period or pd.isna(value):
skipped.append(f"{idx+2}行: 缺少必填字段")