diff --git a/frontend/src/views/CMAKnowledge.vue b/frontend/src/views/CMAKnowledge.vue index b263704e..dfdce000 100644 --- a/frontend/src/views/CMAKnowledge.vue +++ b/frontend/src/views/CMAKnowledge.vue @@ -165,6 +165,7 @@ import { ref, computed } from "vue" import { ElMessage } from "element-plus" import { ethicsQuizApi } from "../api/index" +import api from "../api/index" // ── Tab ── const activeTab = ref("knowledge") @@ -475,6 +476,67 @@ const searchResults = computed(() => { return results }) +// ── 动态知识库:从API加载(2026-08-26新增,支持CMA案例/税务合规/方法论等) ── +const dynamicLoaded = ref(false) +const CAT_LABELS: Record = { + term: "术语解释", formula: "公式", practice: "实践", faq: "FAQ", + "CMA完整文档": "CMA完整文档", "管理会计方法": "管理会计方法", KPI设定: "KPI设定", + OKR: "OKR", "战略修正": "战略修正", 方法论: "方法论", "税务合规": "税务合规", + "CMA案例": "CMA案例", +} +const CAT_ICONS: Record = { + term: "📖", formula: "🧮", practice: "🛠️", faq: "❓", + "CMA完整文档": "📚", "管理会计方法": "📐", KPI设定: "🎯", + OKR: "⭕", "战略修正": "🎯", 方法论: "📊", "税务合规": "🧾", + "CMA案例": "📖", +} + +async function loadDynamicArticles() { + if (dynamicLoaded.value) return + try { + const r: any = await api.get('/knowledge-articles') + const list = Array.isArray(r.data) ? r.data : (r.data?.data || r.data?.items || []) + if (!Array.isArray(list) || list.length === 0) return + // 排除静态已有的基础分类(term/formula/practice/faq 保留静态内容) + const dynamic = list.filter((a: any) => !["term", "formula", "practice", "faq"].includes(a.category)) + if (dynamic.length === 0) return + // 按分类聚合 + const grouped: Record = {} + for (const a of dynamic) { + const key = a.category || "其他" + if (!grouped[key]) grouped[key] = [] + grouped[key].push({ + title: a.title, + summary: a.summary || "", + content: a.content || "", + id: a.id, + }) + } + // 合并到categories(已有分类追加,新分类新增) + const existingKeys = new Set(categories.value.map((c: any) => c.key)) + for (const [key, items] of Object.entries(grouped)) { + const existing = categories.value.find((c: any) => c.key === key) + if (existing) { + existing.items.push(...items) + } else { + categories.value.push({ + name: CAT_LABELS[key] || key, + icon: CAT_ICONS[key] || "📄", + key, + items, + }) + } + } + dynamicLoaded.value = true + } catch (e) { + console.error("加载动态知识库失败", e) + } +} + +// 页面加载时拉取动态知识库 +import { onMounted } from "vue" +onMounted(() => { loadDynamicArticles() }) + function catLabel(key: string) { const map: Record = { term: "术语", formula: "公式", practice: "实践", faq: "FAQ" } return map[key] || key