ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

前端实战:用纯HTML/CSS/JS构建CPA备考知识库系统——搜索+记忆卡+知识图谱+AI问答

前端实战:用纯HTML/CSS/JS构建CPA备考知识库系统——搜索+记忆卡+知识图谱+AI问答 前端实战用纯HTML/CSS/JS构建CPA备考知识库系统——搜索记忆卡知识图谱AI问答系统架构┌──────────────────────────────────────────────┐│ 四大功能模块 │├──────────────┬──────────────┬────────────────┤│ 知识检索 │ 记忆卡片 │ 知识图谱 ││ 173篇文档 │ 87张卡片 │ 30个概念节点 ││ 模糊搜索 │ 间隔复习 │ Canvas绘制 ││ 评分排序 │ 队列管理 │ 悬浮交互 │├──────────────┴──────────────┴────────────────┤│ AI智能问答RAG ││ DeepSeek API 知识库上下文注入 │└──────────────────────────────────────────────┘数据结构设计知识文档每篇文档是一个对象包含标题、内容、科目、来源、关键词javascriptconst CPA_DOCS [{id: “doc_001”,f: “长期股权投资.docx”, // 文件名c: “注册会计师·会计·长期股权投资”, // 分类sub: “会计”, // 科目t: “东奥·张志凤”, // 来源j: “基础阶段”, // 阶段tl: 15200, // 字数kw: [“长投”, “成本法”, “权益法”], // 关键词ft: “长期股权投资是指…” // 全文内容}// … 173篇];记忆卡片javascriptconst CPA_CARDS [{ q: “长期股权投资成本法转权益法的步骤”, a: “1.按原持股比例确认投资收益…” },{ q: “合并报表抵消分录的核心逻辑”, a: “母公司长期股权投资与子公司所有者权益抵消…” }// … 87张];知识图谱节点与连线javascriptvar CONCEPT_NODES [{ id: 0, name: “长期股权投资”, category: “会计” },{ id: 1, name: “合并报表”, category: “会计” },{ id: 6, name: “审计报告”, category: “审计” },{ id: 11, name: “增值税”, category: “税法” },{ id: 16, name: “战略分析”, category: “战略” },{ id: 21, name: “NPV”, category: “财管” },{ id: 25, name: “公司法”, category: “经济法” }// … 30个节点];var CONCEPT_LINKS [{ source: 0, target: 1, label: “会计” },{ source: 1, target: 2, label: “会计-税法” }];模糊搜索自定义评分算法CPA知识点的搜索需求很特殊——用户可能输入长股投来搜长期股权投资输入五力来搜波特五力模型。标准 indexOf 搞不定需要模糊匹配。第一步文本归一化javascriptfunction norm(s) {return (s || ‘’).toLowerCase().replace(/[\s-]/g, ‘’);}去掉空格、连字符、中文标点全部转小写。“长 股 投” 和 “长股投” 归一化后一致。第二步模糊匹配javascriptfunction fuzzy(text, q) {if (!q) return true;var t norm(text), n norm(q);// 完全包含 → 直接命中if (t.indexOf(n) 0) return true;// 逐字检查每个中文字都必须出现for (var i 0; i n.length; i) {var c n[i];if (c ‘\u4e00’ c ‘\u9fa5’ t.indexOf© 0) return false;}return true;}核心逻辑如果 norm(text) 包含 norm(query) 则直接命中否则对查询串逐字检查每个中文字符都必须出现在目标文本中。“长股投” 能匹配 “长期股权投资”因为长“股”投三个字都在。第三步评分排序javascriptfunction score(d, q) {var l q.toLowerCase(), s 0;if (norm(d.f).indexOf(l) 0) s 10; // 文件名命中 10if (norm(d.c).indexOf(l) 0) s 8; // 分类命中 8if (d.kw) for (var i 0; i d.kw.length; i) {if (norm(d.kw[i]).indexOf(l) 0) { s 6; break; } // 关键词命中 6}if (norm(d.ft || ‘’).indexOf(l) 0) s 2; // 全文命中 2return s;}不同字段命中得分不同文件名 分类 关键词 全文。搜索结果按得分降序排列最相关的排最前面。记忆卡片间隔复习队列数据结构javascriptvar reviewQueue []; // 待复习队列var reviewState { known: 0, maybe: 0, again: 0 };核心流程javascriptfunction initCards() {// 复制全部卡片到队列reviewQueue CPA_CARDS.map(function© { return { q: c.q, a: c.a }; });showCard();}function rateCard(t) {var c reviewQueue.shift(); // 取出当前卡片if (t ‘know’) {reviewState.known; // 记住了 → 移出队列} else if (t ‘again’) {reviewQueue.push©; // 不认识 → 放回队尾reviewState.again;} else {reviewQueue.push©; // 模糊 → 也放回队尾reviewState.maybe;}showCard(); // 显示下一张}三档评分记住了green→ 卡片移出队列不再出现模糊yellow→ 卡片放回队尾稍后再练不认识red→ 卡片放回队尾稍后再练这是简化的 Anki 算法——不做时间间隔调度只做队列循环。简单但有效全部记住即完成复习。知识图谱Canvas 环形布局节点环形排列javascriptfunction drawGraph() {var cvs document.getElementById(‘graphCanvas’);var ctx cvs.getContext(‘2d’);var dpr window.devicePixelRatio || 1;var rect cvs.getBoundingClientRect();cvs.width rect.width * dpr;cvs.height rect.height * dpr;ctx.scale(dpr, dpr);var W rect.width, H rect.height;// 环形布局每个节点均匀分布在圆周上var placed CONCEPT_NODES.map(function(n, i) {var a (i / CONCEPT_NODES.length) * 2 * Math.PI - Math.PI / 2;var r Math.min(W, H) * 0.35;return {x: W / 2 r * Math.cos(a),y: H / 2 r * Math.sin(a),color: NC[n.category] || ‘#95a5a6’,name: n.name,category: n.category};});30个概念节点均匀分布在圆周上角度 (索引/总数) × 2π - π/2起始角度为正上方。r min(W, H) * 0.35 确保节点不超出画布。高DPI适配javascriptvar dpr window.devicePixelRatio || 1;cvs.width rect.width * dpr;cvs.height rect.height * dpr;ctx.scale(dpr, dpr);Retina 屏幕下 devicePixelRatio 2如果不做适配Canvas 会被放大模糊。设置物理像素 CSS像素 × dpr再 scale(dpr, dpr)绘制清晰。悬浮高亮javascriptcvs.addEventListener(‘mousemove’, function(e) {var mx e.clientX - rect.left, my e.clientY - rect.top;hov -1;for (var i 0; i placed.length; i) {if (Math.hypot(mx - placed[i].x, my - placed[i].y) 16) {hov i;break;}}redraw(); // 重绘悬浮节点放大});鼠标移动时检测鼠标坐标与每个节点的距离Math.hypot小于16px则判定为悬浮。悬浮时节点半径从11变为16外圈光晕也放大。点击跳转搜索javascriptcvs.addEventListener(‘click’, function() {if (hov 0) {document.getElementById(‘searchInput’).value placed[hov].name;switchTab(‘search’, document.getElementById(‘tab-search’));doSearch();}});点击图谱节点 → 自动切到搜索页 → 用节点名称搜索 → 显示相关文档。知识图谱不只是好看还是导航工具。AI问答RAG 检索增强上下文注入javascriptasync function sendChat() {var msg inp.value.trim();if (!msg) return;addMsg(‘user’, msg);inp.value ‘’;addMsg(‘ai’, ‘正在思考…’);// 从知识库检索相关文档var relevant CPA_DOCS.filter(function(d) {return fuzzy(d.f ’ ’ (d.kw || []).join(’ ) ’ ’ (d.ft || ‘’), msg);}).slice(0, 5);// 构建上下文字符串var ctxStr relevant.map(function(d) {return ‘[来源’ (d.t || ‘东奥’) ‘]\n’ (d.ft || ‘’).slice(0, 800);}).join(‘\n\n’);var sysPrompt ‘你是CPA备考知识库助手。\n’ ‘1.结合知识库内容回答不要编造。\n’ ‘2.回答后注明来源。\n’ ‘3.控制在200字以内条理清晰。\n\n’ ‘知识库摘要\n’ ctxStr;// 调用DeepSeek APIvar resp await fetch(‘https://api.deepseek.com/chat/completions’, {method: ‘POST’,headers: {‘Authorization’: Bearer ’ apiKey,‘Content-Type’: ‘application/json’},body: JSON.stringify({model: ‘deepseek-chat’,messages: [{ role: ‘system’, content: sysPrompt },{ role: ‘user’, content: msg }],max_tokens: 600,temperature: 0.3})});核心思路用户提问 → 先用模糊搜索从知识库检索 Top 5 相关文档 → 截取每篇前800字 → 拼接成上下文 → 注入到 system prompt → 发送给大模型。temperature: 0.3 低温度保证回答稳定max_tokens: 600 控制回答长度。API Key 存 localStorage不上传任何服务器。暗黑模式CSS变量切换css:root {–bg: #f0f2f5;–card: #fff;–text: #1a1a2e;–primary: #4a6cf7;}[data-theme“dark”] {–bg: #0f0f23;–card: #1a1a3e;–text: #e0e0f0;–primary: #6b8aff;}javascriptfunction toggleTheme() {var d document.documentElement;var isDark d.getAttribute(‘data-theme’) ‘dark’;d.setAttribute(‘data-theme’, isDark ? ‘’ : ‘dark’);localStorage.setItem(‘cpa_theme’, isDark ? ‘light’ : ‘dark’);}所有颜色用 CSS 变量切换>CPA备考知识库大师智能交互版 · 173篇文档 · 87张记忆卡 · 5科全覆盖 知识检索 记忆卡片 知识图谱全部会计审计税法战略财管待复习:0已掌握:0▶ 点击下方按钮开始复习 记住了 模糊 不认识CPA核心概念知识图谱 · 点击节点搜索详情技术要点总结 模块 核心技术 难点 模糊搜索 逐字匹配 评分排序 中文模糊匹配需逐字检查Unicode范围 记忆卡片 队列循环 三档评分 简化Anki算法队列管理是关键 知识图谱 Canvas环形布局 DPI适配 高分屏适配 悬浮检测 AI问答 RAG上下文注入 DeepSeek API 知识库检索 → 截取 → 拼接prompt 暗黑模式 CSS变量 >
返回列表