diff --git a/backend/app/api/analysis_results.py b/backend/app/api/analysis_results.py index 36ec6df6..fc40f051 100644 --- a/backend/app/api/analysis_results.py +++ b/backend/app/api/analysis_results.py @@ -69,22 +69,23 @@ async def get_analysis_results( @router.post("/result") -async def create_analysis_result( - period: str = Query(..., description="期间 YYYY-MM"), - conclusion: str = Query(..., description="分析结论"), - data_source: Optional[str] = Query(None, description="数据来源"), - calculation_logic: Optional[str] = Query(None, description="计算逻辑"), - comparable_benchmark: Optional[str] = Query(None, description="可比基准"), - limitations: Optional[str] = Query(None, description="局限说明"), - kpi_code: Optional[str] = Query(None, description="关联KPI编码"), - kpi_name: Optional[str] = Query(None, description="关联KPI名称"), - has_actual: bool = Query(False, description="有实际值"), - has_target: bool = Query(False, description="有目标值"), - has_trend: bool = Query(False, description="有历史趋势"), - has_review: bool = Query(False, description="有人工复核"), - db: Session = Depends(get_db), -): +def create_analysis_result(data: dict = None, db: Session = Depends(get_db)): """提交分析结果(自动计算置信度)""" + if not data: + data = {} + period = data.get("period", "") + conclusion = data.get("conclusion", "") + data_source = data.get("data_source", "") + calculation_logic = data.get("calculation", "") + comparable_benchmark = data.get("comparable_benchmark") + limitations = data.get("limitations") + kpi_code = data.get("kpi_code") + kpi_name = data.get("kpi_name") + has_actual = data.get("has_actual", False) + has_target = data.get("has_target", False) + has_trend = data.get("has_trend", False) + has_review = data.get("has_review", False) + confidence = _calc_confidence(has_actual, has_target, has_trend, has_review) result = AnalysisResult( diff --git a/frontend/src/views/ActionPlanLibrary.vue b/frontend/src/views/ActionPlanLibrary.vue index e1a66289..7bf82958 100644 --- a/frontend/src/views/ActionPlanLibrary.vue +++ b/frontend/src/views/ActionPlanLibrary.vue @@ -437,7 +437,15 @@ async function loadUsers() { const r: any = await userApi.list() const d = r.data || [] if (Array.isArray(d)) { - userOptions.value = d.map((u: any) => u.name || u.username).filter(Boolean) + const seen = new Set() + userOptions.value = d + .map((u: any) => u.name || u.username) + .filter(Boolean) + .filter((name: string) => { + if (seen.has(name)) return false + seen.add(name) + return true + }) } } catch {} } diff --git a/frontend/src/views/AlertList.vue b/frontend/src/views/AlertList.vue index 7c82a8be..77f4fb37 100644 --- a/frontend/src/views/AlertList.vue +++ b/frontend/src/views/AlertList.vue @@ -631,7 +631,6 @@ async function loadAlerts() { } alerts.value = items } catch (e) {} - try { const u: any = await userApi.list(); users.value = u.data || [] } catch (e) {} loading.value = false } @@ -667,6 +666,10 @@ async function loadKpis() { try { const r: any = await kpiApi.list(); kpiOptions.value = r.data || [] } catch (e) {} } +async function loadUsers() { + try { const r: any = await userApi.list(); users.value = r.data || [] } catch (e) {} +} + // ── 风险矩阵 ── const riskEntity = ref('hanke') const riskData = ref(null) @@ -701,6 +704,7 @@ onMounted(() => { loadRules() loadPlans() loadKpis() + loadUsers() }) diff --git a/frontend/src/views/KPIDetail.vue b/frontend/src/views/KPIDetail.vue index 79eb9368..8738e465 100644 --- a/frontend/src/views/KPIDetail.vue +++ b/frontend/src/views/KPIDetail.vue @@ -43,8 +43,16 @@ - - + + + + + + + + + + @@ -265,7 +273,7 @@ import { useRoute, onBeforeRouteLeave } from 'vue-router' import { ElMessage, ElMessageBox } from 'element-plus' import VChart from 'vue-echarts' import 'echarts' -import { kpiApi, mapApi, kpiCausalityApi } from '../api/index' +import { kpiApi, mapApi, kpiCausalityApi, orgApi, userApi } from '../api/index' import api from '../api/index' const route = useRoute() @@ -287,6 +295,8 @@ const simulateCurrentValue = ref(null) const simulateResult = ref(null) const simulating = ref(false) const allKpis = ref([]) +const orgNodes = ref([]) +const userList = ref([]) const fullNetworkNodes = ref([]) const fullNetworkEdges = ref([]) const fullNetworkLoading = ref(false) @@ -381,6 +391,15 @@ const categoryOptions = computed(() => { .map(([value, label]) => ({ value, label })) }) +const orgDeptOptions = computed(() => { + const names = orgNodes.value.map(n => n.name).filter(Boolean) + return [...new Set(names)] +}) + +const userOptions = computed(() => { + return userList.value.map(u => u.name).filter(Boolean) +}) + function dimLabel(d: string) { return ({ finance: '财务', customer: '客户', process: '流程', learning: '学习' } as any)[d] || d } function catLabel(c: string) { return CAT_MAP[c] || c } function dimTagType(d: string) { return ({ finance: '', customer: 'success', process: 'warning', learning: 'info' } as any)[d] || '' } @@ -661,6 +680,16 @@ onMounted(async () => { const kr: any = await kpiApi.list({ page_size: 100 }) allKpis.value = kr.data || [] } catch(e) {} + // 加载部门列表 + try { + const or: any = await orgApi.nodes() + orgNodes.value = Array.isArray(or) ? or : or.data || [] + } catch(e) {} + // 加载用户列表 + try { + const ur: any = await userApi.list() + userList.value = Array.isArray(ur) ? ur : ur.data || [] + } catch(e) {} }) async function associateMap() { diff --git a/frontend/src/views/KPIList.vue b/frontend/src/views/KPIList.vue index 49748d9b..5ec74102 100644 --- a/frontend/src/views/KPIList.vue +++ b/frontend/src/views/KPIList.vue @@ -225,10 +225,10 @@ - + - + @@ -335,10 +335,10 @@ - + - + @@ -356,7 +356,7 @@