From 68e40ac9c5e05ccba0e4a5246a1f8b0166df0b83 Mon Sep 17 00:00:00 2001 From: Hermes CI Fix Date: Wed, 29 Jul 2026 18:12:11 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=87=AA=E5=8A=A8=E5=88=9B=E5=BB=BAKPI?= =?UTF-8?q?=E8=A1=A5=E5=85=A8target=5Fvalue/kpi=5Flevel+=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=E4=B8=AD=E6=96=87=E6=97=A5=E6=9C=9F=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=20-=20=E8=A1=A5NOT=20NULL=E5=AD=97=E6=AE=B5:=20target=5Fvalue?= =?UTF-8?q?=3D0,=20kpi=5Flevel=3D'operational'=20-=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=E6=94=AF=E6=8C=81=E4=B8=AD=E6=96=87=E6=97=A5=E6=9C=9F?= =?UTF-8?q?:=202026=E5=B9=B401=E6=9C=88=20/=202026=E5=B9=B401=E6=9C=88?= =?UTF-8?q?=E8=87=B32026=E5=B9=B405=E6=9C=88=20-=20=E7=A7=91=E7=9B=AE?= =?UTF-8?q?=E4=BD=99=E9=A2=9D=E8=A1=A8=E5=88=97=E5=90=8D=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E5=A2=9E=E5=BC=BA:=20=E4=BD=99=E9=A2=9D/=E6=9C=AC=E5=B9=B4?= =?UTF-8?q?=E7=B4=AF=E8=AE=A1/=E6=9C=AC=E6=9C=9F=E5=8F=91=E7=94=9F?= =?UTF-8?q?=E9=A2=9D=20-=20=E6=9C=9F=E9=97=B4=E5=88=97=E8=AF=86=E5=88=AB:?= =?UTF-8?q?=20=E5=B9=B4/=E6=9C=88=E5=BC=80=E5=A4=B4=E5=88=97=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/data.py | 24 ++++++++++++++++++------ frontend/src/permission.ts | 7 ++++--- frontend/src/router/index.ts | 1 + 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/backend/app/api/data.py b/backend/app/api/data.py index c51581ce..ec0fc18b 100644 --- a/backend/app/api/data.py +++ b/backend/app/api/data.py @@ -89,15 +89,20 @@ _SMART_MAP = { "period_patterns": [ re.compile(r'^(period|期间|月份?|年月|日期|会计期间)$', re.I), re.compile(r'^(报表期[间]?|所属期)$'), + re.compile(r'^年|^月'), # 以"年"或"月"开头的列 ], # 数值列匹配 "value_patterns": [ re.compile(r'^(actual_?value|数值|实际值|实际金额)$', re.I), - re.compile(r'^(本期金额|本月数|本期|期末余额|期末数)$'), - re.compile(r'^(金额|数据|value)$', re.I), + re.compile(r'^(本期金额|本月数|本期|期末余额|期末数|余额)$'), + re.compile(r'^(金额|数据|value|本年累计|本期发生[额]?)$', re.I), ], # 文件名→期间提取 - "period_in_filename": re.compile(r'[-_]?(\d{4})[-_]?(\d{1,2})'), + "period_in_filename_patterns": [ + re.compile(r'[-_]?(\d{4})[-_]?(\d{1,2})'), # 2026-06 / 2026_06 / 2606 + re.compile(r'(\d{4})年(\d{1,2})月(?:至(\d{4})年(\d{1,2})月)?'), # 2026年01月 / 2026年01月至2026年05月 + re.compile(r'(\d{4})(\d{2})'), # 202606 (纯数字6-8位) + ], # 文件名→报表类型 "statement_types": { "利润表": "PL", @@ -139,9 +144,14 @@ def _smart_detect_value_col(cols: list[str]) -> str | None: def _smart_extract_period_from_filename(filename: str) -> str | None: - m = _SMART_MAP["period_in_filename"].search(filename) - if m: - return f"{m.group(1)}-{int(m.group(2)):02d}" + for pat in _SMART_MAP["period_in_filename_patterns"]: + m = pat.search(filename) + if m: + groups = m.groups() + if len(groups) == 4 and groups[2]: # 2026年01月至2026年05月 → 取结束月 + return f"{groups[2]}-{int(groups[3]):02d}" + if len(groups) >= 2: # 2026-06 或 2026年01月 + return f"{int(groups[0])}-{int(groups[1]):02d}" return None @@ -255,6 +265,8 @@ async def import_excel_smart(file: UploadFile = File(...), db: Session = Depends data_owner="财务部", frequency="monthly", unit="元", + target_value=0, + kpi_level="operational", status="active", ) db.add(new_kpi) diff --git a/frontend/src/permission.ts b/frontend/src/permission.ts index 5da6dc70..5a4bc805 100644 --- a/frontend/src/permission.ts +++ b/frontend/src/permission.ts @@ -9,10 +9,10 @@ interface MenuItem { // ── 角色路由映射 ── export const ROLE_ROUTES: Record = { - ceo: ['/my-dashboard', '/dashboard', '/kpis', '/maps', '/maps-review', '/maps/canvas', '/maps/review', '/alerts', '/notifications', '/org', '/users', '/permissions', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard', '/reports', '/alignment', '/dupont-analysis'], - finance: ['/my-dashboard', '/dashboard', '/kpis', '/maps', '/maps-review', '/maps/canvas', '/maps/review', '/alerts', '/data', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard', '/reports', '/alignment', '/dupont-analysis'], + ceo: ['/my-dashboard', '/dashboard', '/kpis', '/maps', '/maps-review', '/maps/canvas', '/maps/review', '/alerts', '/notifications', '/org', '/users', '/permissions', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard', '/reports', '/alignment', '/dupont-analysis', '/analysis-confidence'], + finance: ['/my-dashboard', '/dashboard', '/kpis', '/maps', '/maps-review', '/maps/canvas', '/maps/review', '/alerts', '/data', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard', '/reports', '/alignment', '/dupont-analysis', '/analysis-confidence'], business: ['/my-dashboard', '/dashboard', '/kpis', '/alerts', '/budget', '/deviations', '/action-plans', '/knowledge', '/guide', '/customer'], - it: ['/my-dashboard', '/dashboard', '/kpis', '/alerts', '/data', '/org', '/users', '/permissions', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard'], + it: ['/my-dashboard', '/dashboard', '/kpis', '/alerts', '/data', '/org', '/users', '/permissions', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard', '/analysis-confidence'], } export const ROLE_ACTIONS: Record = { @@ -49,6 +49,7 @@ export const MENU_ITEMS: MenuItem[] = [ { path: '/predict', label: '预测模拟', icon: 'DataLine', roles: ['ceo', 'finance', 'it'], group: '🔴 A 复盘与改进' }, { path: '/mpm-calculator', label: 'MPM计算器', icon: 'Money', roles: ['ceo', 'finance', 'business'], group: '🔴 A 复盘与改进' }, { path: '/data-quality', label: '数据质量', icon: 'WarningFilled', roles: ['ceo', 'finance', 'it'], group: '🔴 A 复盘与改进' }, + { path: '/analysis-confidence', label: '分析置信度', icon: 'TrendCharts', roles: ['ceo', 'finance', 'it'], group: '🔴 A 复盘与改进' }, // ── GROUP 5: 基础数据与知识── { path: '/kpis', label: 'KPI字典', icon: 'Document', roles: ['ceo', 'finance', 'business', 'it'], group: '基础数据与知识' }, diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 676bf325..404a06fe 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -40,6 +40,7 @@ const routes = [ { path: 'subjects', name: 'SubjectManage', component: () => import('@/views/SubjectManage.vue'), meta: { title: '科目打标', roles: ['ceo', 'finance', 'business', 'it'] } }, { path: 'mpm-calculator', name: 'MpmCalculator', component: () => import('@/views/MpmCalculator.vue'), meta: { title: 'MPM计算器', roles: ['ceo', 'finance', 'business'] } }, { path: 'bot-kpis', name: 'BotKpis', component: () => import('@/views/BotKpiDashboard.vue'), meta: { title: 'Bot KPI看板', roles: ['ceo', 'finance', 'it'] } }, + { path: 'analysis-confidence', name: 'AnalysisConfidence', component: () => import('@/views/AnalysisConfidence.vue'), meta: { title: '分析置信度', roles: ['ceo', 'finance', 'it'] } }, ] }, ]