# ai_20261102 **Repository Path**: burns/ai_20261102 ## Basic Information - **Project Name**: ai_20261102 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-11-02 - **Last Updated**: 2026-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AI 术语库 · 离线知识库 一个 **Android 优先、全离线** 的 AI 术语知识库 App。收录 71 个 AI 核心术语,每个术语包含: - **定义**:一句话说清它是什么 - **概念描述**:它处在知识地图的什么位置 - **原理**:关键公式、流程与直觉 - **开源实现**:真实开源项目 + 可读代码示例 - **术语关系**:前置 / 包含 / 相关 / 衍生 / 对比,可点击跳转 - **正文内链**:例如 `[[transformer|Transformer]]`,点击直达对应术语 技术栈:**uni-app (Vue 3) + plus.sqlite + Canvas**。无后端、无远程 CDN、无在线字体,安装后全部内容在手机本地。 --- ## 1. 先纠正一个关键点 > 「OpenCode 是 uni-app 的原生增强,内置 sqlite」 这个说法不准确。**OpenCode 是编码 Agent,不是 uni-app 的运行时发行版**。本项目按标准 uni-app 项目实现,离线数据库使用 uni-app 自带的 HTML5+ 能力: - App 端:`plus.sqlite`,数据库文件位于 App 私有目录 `_doc/ai_terms.db` - H5 端:`plus.sqlite` 不可用,项目内置了 **localStorage 降级适配器**,接口完全一致,方便浏览器预览 - 打包 Android 后,H5 降级层不会被使用,自动走系统原生 SQLite 因此不需要额外原生插件,也不需要 HBuilderX 之外的“增强版 uni-app”。 --- ## 2. 功能一览 | 页面 | 能力 | | --- | --- | | 首页 | 统计、分类入口、今日随机术语、精选术语、最近浏览 | | 搜索 | 中文 / 英文 / 缩写 / 标签 / 定义全文检索,分类过滤,搜索历史 | | 分类 | 左侧 10 个知识域,右侧术语列表,独立滚动 | | 详情 | 定义、概念、原理、开源实现、参考资料、关系分组、同类推荐、代码高亮与复制 | | 关系图谱 | Canvas 径向图,点击节点切换中心,图例与关系明细 | | 收藏 | 本地收藏、浏览历史、清空历史 | 其他细节: - 代码块语法高亮完全本地实现,支持 Python / JavaScript / SQL / Shell / JSON - 术语内链解析器支持 `[[slug]]` 与 `[[slug|显示文字]]` - 收藏与历史持久化到 SQLite,内置内容升级时保留用户数据 - 无网络请求;`manifest.json` 已关闭 uni 统计 --- ## 3. 目录结构 ```text ai_20261102/ ├─ index.html ├─ package.json ├─ vite.config.js ├─ scripts/ │ ├─ validate-data.mjs # 数据完整性校验 │ └─ generate-icons.ps1 # 生成 App 图标(Windows) ├─ src/ │ ├─ main.js │ ├─ App.vue # 启动时初始化数据库 │ ├─ pages.json │ ├─ manifest.json │ ├─ components/ │ │ ├─ NavBar.vue │ │ ├─ TabBar.vue │ │ ├─ TermCard.vue │ │ ├─ TermContent.vue # 内链 / 粗体 / 列表 / 引用渲染 │ │ ├─ CodeBlock.vue # 代码高亮、行号、复制 │ │ └─ EmptyState.vue │ ├─ data/ │ │ ├─ categories.js # 10 个分类 + 关系类型 │ │ ├─ seed.js # 种子数据入口 / 版本号 │ │ └─ terms/ │ │ ├─ 01-foundations.js │ │ ├─ 02-math.js │ │ ├─ 03-architecture.js │ │ ├─ 04-llm.js │ │ ├─ 05-apps.js │ │ └─ 06-engineering.js │ ├─ pages/ │ │ ├─ index/index.vue │ │ ├─ search/search.vue │ │ ├─ categories/categories.vue │ │ ├─ detail/detail.vue │ │ ├─ graph/graph.vue │ │ └─ favorites/favorites.vue │ ├─ static/icons/ # 1024 图标 + Android 各密度图标 │ └─ utils/ │ ├─ db.js # 统一入口(App / H5 切换) │ ├─ db-app.js # plus.sqlite 实现 │ ├─ db-web.js # localStorage 预览实现 │ ├─ search-score.js # 统一搜索打分 │ ├─ content.js # 富文本 / 内链解析 │ ├─ highlight.js # 零依赖语法高亮 │ └─ format.js # 分类、关系、时间格式化 └─ dist/ # 构建产物(gitignore) ``` --- ## 4. 本地数据库设计 ### 4.1 表结构 ```sql ai_term ( slug TEXT PRIMARY KEY, name TEXT, name_en TEXT, abbr TEXT, aliases TEXT, -- aliases 为 JSON category_id TEXT, tags_json TEXT, difficulty INTEGER, definition TEXT, concept TEXT, principle TEXT, implementation TEXT, code_lang TEXT, code_title TEXT, code_source TEXT, code_snippet TEXT, refs_json TEXT, sort_order INTEGER ) term_relation ( id INTEGER PRIMARY KEY AUTOINCREMENT, from_slug TEXT, to_slug TEXT, relation_type TEXT, note TEXT, UNIQUE(from_slug, to_slug, relation_type) ) term_tag ( term_slug TEXT, tag TEXT, PRIMARY KEY(term_slug, tag) ) app_meta (key TEXT PRIMARY KEY, value TEXT) favorite (slug TEXT PRIMARY KEY, created_at TEXT) view_history (slug TEXT PRIMARY KEY, viewed_at TEXT) ``` 关系类型: | type | 正向显示 | 反向显示 | | --- | --- | --- | | `prerequisite` | 前置知识 | 后续概念 | | `contains` | 包含组件 | 所属体系 | | `related` | 相关概念 | 相关概念 | | `derived` | 衍生概念 | 来源概念 | | `contrast` | 对比概念 | 对比概念 | ### 4.2 首次启动与升级 `src/App.vue` 的 `onLaunch` 调用 `initDatabase()`: 1. 打开 `_doc/ai_terms.db` 2. 建表 / 建索引 3. 读取 `app_meta.seed_version` 4. 若与 `src/data/seed.js` 的 `SEED_VERSION` 不一致: - 清空 `ai_term`、`term_relation`、`term_tag` - 分批写入内置数据 - 更新 `seed_version` - **保留** `favorite` 与 `view_history` 5. 清理已删除术语对应的收藏与历史 修改内置内容后,把 `SEED_VERSION` 递增即可触发重建。 ### 4.3 数据库位置 ```text Android: /data/data//doc/ai_terms.db ``` 属于 App 私有目录。卸载 App 会删除数据库;清除应用数据也会重置。 --- ## 5. 运行与构建 ### 5.1 安装依赖 ```bash npm install ``` > Windows PowerShell 如果提示 `npm.ps1 cannot be loaded`,改用: > > ```powershell > & "C:\Program Files\nodejs\npm.cmd" install > ``` > > 或调整执行策略。项目本身不依赖 PowerShell 脚本。 ### 5.2 浏览器预览(H5) ```bash npm run dev:h5 ``` 默认地址以终端输出为准。H5 预览使用 `localStorage` 模拟数据库,功能与 App 一致,只是不产生 `.db` 文件。 生产构建: ```bash npm run build:h5 ``` 产物在 `dist/build/h5`。 ### 5.3 数据校验 ```bash npm run validate ``` 会检查: - slug 唯一且格式合法 - 分类是否存在 - 关系目标是否存在、是否自关联、是否重复 - 正文内链目标是否存在 - 各正文字段长度 - 无代码示例的术语(仅警告) 当前数据规模: ```text 术语: 71 分类: 10 关系: 331 内链: 118 ``` ### 5.4 重新生成 App 图标 Windows 环境可重新生成 1024 主图标、Android 各密度图标与 favicon: ```powershell powershell -ExecutionPolicy Bypass -File scripts/generate-icons.ps1 ``` 生成位置:`src/static/icons/`。脚本只使用系统自带的 `System.Drawing`,不下载任何资源。 ### 5.5 构建 App 资源 ```bash npm run build:app ``` 产物在 `dist/build/app`,这是离线打包所需的 App 资源,不是可直接安装的 APK。 --- ## 6. 打包 Android APK uni-app CLI 不直接产出签名 APK。任选一种方式: ### 方式 A:HBuilderX(推荐) 1. 用 HBuilderX 打开项目根目录(不是 `src`) 2. 打开 `manifest.json` → 基础配置,确认应用名称、包名、版本 3. 图标已生成在 `src/static/icons`,`manifest.json` 的 `distribute.icons.android` 已指向各密度 PNG;如需替换,直接覆盖 `icon-1024.png` 后重新运行图标脚本 4. 选择「发行」→「原生 App - 云打包」或「本地打包」 5. 选择 Android,配置证书,打包 > 云打包需要 DCloud 账号。离线打包需要 DCloud 离线 SDK + Android Studio,参考官方文档。 ### 方式 B:HBuilderX 本地打包 + Android Studio 1. `npm run build:app` 2. 用 DCloud 离线 SDK 的 Android 工程替换 `assets/apps//www` 3. 在 Android Studio 中配置包名、签名并生成 APK ### 6.1 严格离线 项目已做: - 无远程 API - 无 CDN 脚本 / 字体 / 图片 - 代码高亮本地实现 - `manifest.json` 中 `uniStatistics.enable = false` - H5 构建会移除 uni-app 运行时自带的 CDN 阴影图预加载(`vite.config.js` 中的 `stripUniCdnShadow`),确保产物零外网请求 如需进一步收紧,可在 `manifest.json` 的 Android 权限中**不要添加** `INTERNET` 权限。当前配置的权限数组为空。部分 HBuilderX 打包流程可能自动补充网络权限,打包后可用 `aapt dump permissions app.apk` 检查。 --- ## 7. 如何新增术语 在 `src/data/terms/*.js` 中追加对象,然后递增 `SEED_VERSION`。 ```js { slug: 'attention-sink', // 唯一,小写字母/数字/连字符 name: '注意力汇', en: 'Attention Sink', abbr: '', aliases: ['Attention Sink'], category: 'llm', // src/data/categories.js 中的 id tags: ['长上下文', '注意力'], difficulty: 2, // 1 入门 / 2 进阶 / 3 深入 definition: '……', concept: '……支持 [[transformer|Transformer]] 内链与 **粗体**。', principle: '……', implementation: '……', code: { lang: 'python', title: '代码标题', source: 'PyTorch', snippet: 'print("hello")' }, relations: [ ['attention', 'prerequisite', '先理解注意力机制'], ['context-window', 'related', '影响长上下文行为'] ], refs: ['论文或文档标题'] } ``` ### 正文支持的标记 | 写法 | 效果 | | --- | --- | | `[[transformer]]` | 内链,显示 slug | | `[[transformer|Transformer]]` | 内链,显示自定义文字 | | `**重点**` | 粗体 | | `` `code` `` | 行内代码 | | `- 列表项` | 无序列表(整段均为列表时) | | `> 引用` | 引用块 | | `### 小标题` | 小标题 | | 空行 | 分段 | 内链必须指向存在的 slug,否则 `npm run validate` 会报错。 ### 关系方向 关系是**有向**的,但详情页会同时展示正向与反向关系。例如: ```js // transformer 中 ['attention', 'prerequisite', '注意力是基础'] ``` 在 `transformer` 页面显示为「前置知识 → 注意力机制」;在 `attention` 页面显示为「后续概念 → Transformer」。 --- ## 8. 关键实现说明 ### 8.1 SQLite 适配器 `src/utils/db.js` 通过条件编译切换实现: ```js let active = webDb // #ifdef APP-PLUS active = appDb // #endif ``` `plus.sqlite` 的 SQL 不支持参数占位符,`db-app.js` 用 `q()` 做单引号转义。所有用户输入进入 SQL 前都会经过转义。 ### 8.2 搜索 SQL 先用 `instr(lower(field), keyword)` 做候选过滤,再在 JS 中按字段权重打分: ```text 名称 120 > 英文名 70 > 缩写 65 > 别名 55 > 标签 40 > 定义 26 > 概念 14 > 原理 12 > 实现 6 ``` 支持多关键词(空格分隔,要求全部命中)。搜索结果按相关度排序。 ### 8.3 内链渲染 `content.js` 先把正文拆成段落 / 列表 / 引用 / 标题,再解析行内 token。`TermContent.vue` 渲染 token,点击 `link` token 时发出 `term-click`,详情页用 `uni.navigateTo` 打开新术语。 ### 8.4 关系图谱 `graph.vue` 使用 `uni.createCanvasContext` 绘制直接关系: - 中心节点:当前术语 - 外围节点:最多 12 个直接关联 - 边颜色:关系类型 - 点击节点:以该节点为中心重新加载 - 下方同时提供分组关系列表,保证可访问性 ### 8.5 代码高亮 `highlight.js` 用正则分词,支持字符串、注释、数字、关键字、函数、内置名与运算符,输出 token 数组。`CodeBlock.vue` 负责行号、横向滚动与复制。没有引入 highlight.js / Prism,避免增大包体与远程资源依赖。 --- ## 9. 已知限制 - 内置 71 个术语是高质量精选,不是“所有 AI 术语”。可按第 7 节持续扩展。 - 关系图谱只展示**直接邻居**,不是全库大图。 - H5 预览用 localStorage,不是真正的 SQLite;只有 App 端会产生 `.db` 文件。 - 当前环境没有 Android 真机 / 模拟器,`plus.sqlite` 的建库、种子写入与升级流程已按官方 API 实现并完成静态审查,但尚未在真实 App 运行时回归。 - 参考资料仅作为文字引用展示,不提供在线跳转(保持离线)。 - 搜索基于 `instr` 子串匹配,未使用 FTS5;71 条数据规模下性能充足。 - 切换语言 / 深色模式尚未实现。 --- ## 10. 常见问题 **Q:H5 报 `plus is not defined`?** A:正常。H5 不会走 `db-app.js`,统一入口已切到 `db-web.js`。若你手动调用了 App 适配器,请改回 `db`。 **Q:App 启动提示数据库初始化失败?** A:确认运行在 App 环境,而不是 H5;确认 `manifest.json` 未被裁剪 HTML5+ 模块;查看控制台 `[db] init failed` 详情。 **Q:修改了术语但 App 里没变化?** A:递增 `src/data/seed.js` 的 `SEED_VERSION`,重新打包。首次启动会自动重建种子表。 **Q:收藏会丢吗?** A:种子升级只清空术语 / 关系 / 标签表,收藏与历史保留。卸载 App 或清除应用数据会丢失。 **Q:构建时 esbuild 安装脚本被拦截?** A:npm 11 的 allow-scripts 机制可能拦截 `esbuild` postinstall。执行 `npm approve-scripts esbuild` 或重新安装;若 `vite` 能正常启动则可忽略。 **Q:如何彻底重置数据库?** A:Android 设置中清除 App 数据,或卸载重装。开发期也可临时提高 `SEED_VERSION` 强制重建。 --- ## 11. 后续可以做什么 - 接入 FTS5 全文索引(App 端 SQLite 支持时) - 术语版本历史与更新时间 - 深色模式 / 字号调节 - 关系图谱全库视图与缩放拖拽 - 术语测验 / 闪卡复习 - 导入自定义术语 JSON - 导出收藏为 Markdown --- 内容与代码均为本地实现,可自由修改扩展。