From b26046349c91f6234d47bf1fd85bfa58824b6839 Mon Sep 17 00:00:00 2001 From: Hermes CI Fix Date: Mon, 13 Jul 2026 09:49:55 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A1=A5=E6=B3=A8=E5=86=8C=E7=BC=BA?= =?UTF-8?q?=E5=A4=B1API=E6=A8=A1=E5=9D=97+=E5=89=8D=E7=AB=AF=E8=B7=AF?= =?UTF-8?q?=E7=94=B1+ConnectionLines=E6=81=A2=E5=A4=8D=20-=20=E6=B3=A8?= =?UTF-8?q?=E5=86=8C4=E4=B8=AA=E5=90=8E=E7=AB=AF=E6=A8=A1=E5=9D=97:=20cust?= =?UTF-8?q?omer=5Fdashboard/deviation=5Fpush/budget=5Fgenerate/knowledge?= =?UTF-8?q?=5Farticles=20-=20=E4=BF=AE=E5=A4=8D=E6=94=B9=E5=96=84=E8=A1=8C?= =?UTF-8?q?=E5=8A=A8=E8=B7=AF=E7=94=B1=E6=8C=87=E5=90=91ActionPlanLibrary.?= =?UTF-8?q?vue(=E5=8E=9F=E6=8C=87=E5=90=91AlertList.vue)=20-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E3=E4=B8=AA=E8=B7=AF=E7=94=B1:=20/reports(=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=8A=A5=E8=A1=A8)=20/alignment(=E6=88=98=E7=95=A5?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E7=9C=8B=E6=9D=BF)=20/dupont-analysis=20-=20?= =?UTF-8?q?=E6=81=A2=E5=A4=8DConnectionLines.vue=E5=AE=8C=E6=95=B4?= =?UTF-8?q?=E7=89=88(288=E8=A1=8C,=20=E5=8E=9F=E8=A2=AB=E6=88=AA=E6=96=AD?= =?UTF-8?q?=E4=B8=BA123=E8=A1=8C)=20-=20=E4=BF=AE=E5=A4=8Dmaps.py=E7=BB=B4?= =?UTF-8?q?=E5=BA=A6=E9=94=AE=20finance(=E5=8E=9Ffinancial=E4=B8=8D?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E5=89=8D=E7=AB=AF)=20-=20=E8=A1=A5=E5=9B=9Em?= =?UTF-8?q?odels/=5F=5Finit=5F=5F.py=20knowledge=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/__pycache__/main.cpython-312.pyc | Bin 7292 -> 7481 bytes .../app/api/__pycache__/maps.cpython-312.pyc | Bin 15928 -> 15763 bytes backend/app/api/maps.py | 2 +- backend/app/main.py | 8 +- backend/app/models/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 15268 -> 15355 bytes .../components/strategy/ConnectionLines.vue | 339 +++++++++++++----- frontend/src/permission.ts | 11 +- frontend/src/router/index.ts | 5 +- 9 files changed, 273 insertions(+), 93 deletions(-) diff --git a/backend/app/__pycache__/main.cpython-312.pyc b/backend/app/__pycache__/main.cpython-312.pyc index e2981e8bc107f5542e0d550de57f1519c9f9fc4a..1ab30f568396d028e3c9ce172d2d542b963ec7c5 100644 GIT binary patch delta 2094 zcmaiz-)|d55XW!NXUDN?JB}UyO5%k4Hc68Ps1@wAO-0-!YDl33gbcwt`__rw^AGmU zM5qsSq*Q>2M9RW5RBe$^_#tG3#1nr&U&;eQI)T&&5``y(5CT<5Fnexo^I+Xc_w~%q zXLfeRd;iRR8*|)sIBXm|(S`N=J2xCbK5xA-@y%ReEIC#fPmUu_LQ${&(fU}9-2U2w53}GWa~W*h)L>_+*0>v zo&yuB%5ljkj^<1BeKZq{=3lR`wJLVy3BB3vq3`jwHbhsGFu@-56yJl4a=M#2ZFcn- z5?({1$B^(D5`IG>&?NN!@0*PK4>fbz^xtbp^cfQUhD6wq7%(ITn}pu~zS+3{p=M5- z{)Y{T5kq3skQg&0#+yVuny<8e8+9AU4^Z8b{8*3zIGz=x;I44+5KYd*7j{+u3V*fu z%xA&7rhEPl=jd!Bm(TK2KVAS0@0uIA=YhVi(;IE*!4~?N#@@F&eCEYR-tcgv%7iqc z*BEWdN;GP8SbgXM4O_3HAiZt<*{^k8DVDZnENx=VmM*EOG|7Qo+vyzOEl)vza=5>D^!c5`+g}}jeJ3_ZV)R|-TX;;>FDk1XRbHZ=;wiTzEF}XGCoVHz_FPr2lV&A$k>wb h7x?YOK2NM7~WZ}WW|;&%MY#OMDhEv@k1mrjV-%2wVkv$#5ULjN1-T^c3fG}i`iA( zP@1^ZfgXHtGW3#OTxcoA&>RGX@A%zl>{4=seOz{ltxBoxi z|D5@E?}c9vx*xjTl@hEo3v;QiTke4Ts^V7nuk%RKk$xoIndypjXSB!(u2-geGQE*L zE?1@dGoeTbNwS2iwpavMTtlfVTsZ(3rQ$Slm7of=xya(-FiFE)bXDG1kaRoYG{()cHTrP^&i#x%xy~lux#W*24nj$M!#|g(M0ikcMpP)52{Z(K49D#`leb%gVg64 zgzXtmV-xeUs$+U)DI3KkA2qIJ6J#DX&%$FY(oJu$_>*S^^_&BJdY*g?FERyC@Br-G z{ch*?^_?Hq{`zI@<+tl(FUhR8F+9i&&oh_>Fcg4hSiDfncQ9d8C)c8+kR=zvYPR^J z_Y=8}<**zC8-=vFANOsYse(BndkO zcnmkdiu9+iabx*$Rp^ltBFtDr)7n{z)hxP9pQx)e?yv1_fqjx-(8?eVVAU82vXnQC z{_<6}G42B0@CQ&kz3*>D!*ts}d4r!0nKQdqWk6Xa~C diff --git a/backend/app/api/__pycache__/maps.cpython-312.pyc b/backend/app/api/__pycache__/maps.cpython-312.pyc index 988bd34e9be485df6d9c1263afdad68d8c9232eb..9fec0546885a25e0f8fdfe3c946727d8310627da 100644 GIT binary patch delta 2748 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 OcSQcV?FOgERQwlt%Tv_= diff --git a/backend/app/api/maps.py b/backend/app/api/maps.py index 2d23f0b7..65199ffd 100644 --- a/backend/app/api/maps.py +++ b/backend/app/api/maps.py @@ -14,7 +14,7 @@ router = APIRouter(prefix="/api/cma/maps", tags=["战略地图"], # ── 四维度模板 ────────────────────────────── STRATEGIC_MAP_TEMPLATE = [ { - "key": "financial", + "key": "finance", "name": "财务层", "icon": "💰", "color": "#F56C6C", diff --git a/backend/app/main.py b/backend/app/main.py index a670dd39..daaf8d7a 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -5,7 +5,7 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from dotenv import load_dotenv from app.database import init_db -from app.api import auth, kpis, templates, maps, dashboard, data, alerts, ai_analysis, alert_rules, users, thresholds, notifications, permissions, action_plans, alignment, org, objectives, versions, budget, cost, predict, reports, security +from app.api import auth, kpis, templates, maps, dashboard, data, alerts, ai_analysis, alert_rules, users, thresholds, notifications, permissions, action_plans, alignment, org, objectives, versions, budget, cost, predict, reports, security, knowledge, bot_bridge, customer_dashboard, deviation_push, budget_generate, knowledge_articles from app.utils.cache import clear_all as clear_cache, delete as delete_cache from scripts.erp_sync import run_sync as run_erp_sync from app.auth_middleware import require_auth @@ -53,6 +53,12 @@ app.include_router(cost.router) app.include_router(predict.router) app.include_router(reports.router) app.include_router(security.router) +app.include_router(knowledge.router) +app.include_router(bot_bridge.router) +app.include_router(customer_dashboard.router) +app.include_router(deviation_push.router) +app.include_router(budget_generate.router) +app.include_router(knowledge_articles.router) @app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py index b94a5b79..15d5267b 100644 --- a/backend/app/models/__init__.py +++ b/backend/app/models/__init__.py @@ -4,6 +4,7 @@ from app.database import Base from app.models.budget_plan import BudgetPlan from app.models.cost_model import StandardCost, ActualCost, AbcActivity, AbcAllocation +from app.models.knowledge import KnowledgeEvent, KnowledgeSummary class User(Base): diff --git a/backend/app/models/__pycache__/__init__.cpython-312.pyc b/backend/app/models/__pycache__/__init__.cpython-312.pyc index 78becec0ef6931b32ab6fd74487f0a56a35ad3e7..f623d819dda4af48e9f33e4fb35d7b97fe62785a 100644 GIT binary patch delta 3316 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 - - + + + - - + + + + + + + - - - {{ arrow.from }} → {{ arrow.to }} - - - + - - + + + + 点击选中连线 - - - - - - ✕ 删除连线 + v-if="hoverIdx === idx" + :x="conn.mx" + :y="conn.my + 4" + text-anchor="middle" + fill="#fff" + font-size="11" + class="conn-hover-text" + > + 点击选中 + + + + + + ✕ 删除连线 + + - - diff --git a/frontend/src/permission.ts b/frontend/src/permission.ts index 0fd86854..0e0cd1e5 100644 --- a/frontend/src/permission.ts +++ b/frontend/src/permission.ts @@ -5,9 +5,9 @@ // 各角色可访问的路由列表 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'], - 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'], - business: ['/my-dashboard', '/dashboard', '/kpis', '/alerts', '/deviations', '/budget', '/action-plans', '/knowledge', '/guide', '/customer'], + 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'], + business: ['/my-dashboard', '/dashboard', '/kpis', '/alerts', '/deviations', '/budget', '/action-plans', '/knowledge', '/guide', '/customer', '/reports', '/alignment'], it: ['/my-dashboard', '/dashboard', '/kpis', '/alerts', '/data', '/org', '/users', '/permissions', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard'], } @@ -47,6 +47,11 @@ export const MENU_ITEMS: MenuItem[] = [ { path: '/predict', label: '预测模拟', icon: 'DataLine', roles: ['ceo', 'finance', 'it'] }, { path: '/budget', label: '预算管理', icon: 'Coin', roles: ['ceo', 'finance', 'business', 'it'] }, + // ── 高级分析 ── + { path: '/reports', label: '管理报表', icon: 'DataAnalysis', roles: ['ceo', 'finance', 'business'], group: '分析决策' }, + { path: '/alignment', label: '战略执行看板', icon: 'Opportunity', roles: ['ceo', 'finance', 'business', 'it'] }, + { path: '/dupont-analysis', label: '杜邦分析', icon: 'TrendCharts', roles: ['ceo', 'finance', 'it'] }, + // ── 行动管理 ── { path: '/alerts', label: '预警中心', icon: 'WarningFilled', roles: ['ceo', 'finance', 'business', 'it'], group: '行动管理' }, { path: '/action-plans', label: '改善行动', icon: 'Edit', roles: ['ceo', 'finance', 'business', 'it'] }, diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index f0b5ea08..68dd6b19 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -27,7 +27,10 @@ const routes = [ { path: 'deviations', name: 'DeviationDashboard', component: () => import('@/views/DeviationDashboard.vue'), meta: { title: '差异分析', roles: ['ceo', 'finance', 'business', 'it'] } }, { path: 'cost', name: 'CostDashboard', component: () => import('@/views/CostDashboard.vue'), meta: { title: '成本分析', roles: ['ceo', 'finance', 'it'] } }, { path: 'predict', name: 'PredictDashboard', component: () => import('@/views/PredictDashboard.vue'), meta: { title: '预测模拟', roles: ['ceo', 'finance', 'it'] } }, - { path: 'action-plans', name: 'ActionPlans', component: () => import('@/views/AlertList.vue'), meta: { title: '改善行动', roles: ['ceo', 'finance', 'business', 'it'], tab: 'plans' } }, + { path: 'action-plans', name: 'ActionPlans', component: () => import('@/views/ActionPlanLibrary.vue'), meta: { title: '改善行动', roles: ['ceo', 'finance', 'business', 'it'] } }, + { path: 'reports', name: 'ReportCenter', component: () => import('@/views/ReportCenter.vue'), meta: { title: '管理报表', roles: ['ceo', 'finance', 'business'] } }, + { path: 'alignment', name: 'KPIAlignment', component: () => import('@/views/KPIAlignment.vue'), meta: { title: '战略执行看板', roles: ['ceo', 'finance', 'business', 'it'] } }, + { path: 'dupont-analysis', name: 'DupontAnalysis', component: () => import('@/views/DupontAnalysis.vue'), meta: { title: '杜邦分析', roles: ['ceo', 'finance', 'it'] } }, ] }, ]