From a268c4e74d99caa4f7ae7a3b899960d759a21e2d Mon Sep 17 00:00:00 2001 From: Hermes CI Fix Date: Thu, 13 Aug 2026 01:17:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=99=BA=E8=83=BD=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E5=88=97=E6=A3=80=E6=B5=8B+=E5=90=8D=E7=A7=B0=E9=98=B2?= =?UTF-8?q?=E6=8A=A4=20=E2=80=94=20=E7=A7=91=E7=9B=AE=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E8=AF=AF=E5=BD=93=E5=90=8D=E7=A7=B0(EXT=5F069=E6=98=BE?= =?UTF-8?q?=E7=A4=BA1001.0/EXT=5F071=E6=98=BE=E7=A4=BAnan)=E6=A0=B9?= =?UTF-8?q?=E5=9B=A0=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - kpi_code_patterns 名称类列优先(科目名称/指标名称/name),编码类列兜底 - 修复科目余额表表头(科目编码|科目名称)检测失败fallback cols[0]导致名称存成编码 - 导入循环增加防护: NaN/空/纯数字名称跳过,不再创建垃圾KPI - 存量数据: 14个一级科目名称已按科目表修正,82个明细标记待财务核对,EXT_071标记未命名 --- backend/app/api/data.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/backend/app/api/data.py b/backend/app/api/data.py index e8efdfd7..8125eb1d 100644 --- a/backend/app/api/data.py +++ b/backend/app/api/data.py @@ -80,11 +80,11 @@ async def import_excel(file: UploadFile = File(...), # ── 智能导入(BOT自动识别,无需手动映射) ── _SMART_MAP = { - # KPI编码列匹配模式 → 标准kpi_code + # KPI名称/编码列匹配模式(顺序重要:名称类列优先,避免科目编码被当名称) "kpi_code_patterns": [ - re.compile(r'^(kpi_?code|指标编码|编码)$', re.I), - re.compile(r'^(科目|项目|账户|报表项目|项目名称)$'), - re.compile(r'^(指标名称?|kpi名称?|name)$', re.I), + re.compile(r'^(科目名称|项目名称|指标名称?|kpi名称?|name|名称)$', re.I), + re.compile(r'^(科目编码|科目代码|kpi_?code|指标编码|编码)$', re.I), + re.compile(r'^(科目|项目|账户|报表项目)$'), ], # 期间列匹配 "period_patterns": [ @@ -218,11 +218,19 @@ async def import_excel_smart( skipped_rows = [] for idx, row in df.iterrows(): - raw_kpi = str(row.get(kpi_col, "")).strip() + raw_kpi_raw = row.get(kpi_col, "") + raw_kpi = str(raw_kpi_raw).strip() raw_val = row.get(value_col) raw_period = str(row.get(period_col, period or "")).strip() if period_col else (period or "") - if not raw_kpi or pd.isna(raw_val): + # 名称防护:NaN/空/None 或 纯数字(疑似科目编码被误当名称)→ 跳过,避免创建垃圾KPI + if raw_kpi.lower() in ("nan", "none") or not raw_kpi: + skipped_rows.append(f"第{idx+2}行: KPI名称为空") + continue + if re.fullmatch(r"\d+(\.\d+)?", raw_kpi): + skipped_rows.append(f"第{idx+2}行: KPI名称疑似科目编码「{raw_kpi}」,跳过") + continue + if pd.isna(raw_val): skipped_rows.append(f"第{idx+2}行: 缺数据") continue if not raw_period: